forked from Ivasoft/traefik
Compare commits
20 Commits
v2.9.0-rc1
...
v2.9.0-rc4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52b6b057f0 | ||
|
|
7b3faef4b3 | ||
|
|
7758880f3f | ||
|
|
d04903edb2 | ||
|
|
a63d5c95a8 | ||
|
|
bb66950197 | ||
|
|
c4cc30ccc6 | ||
|
|
9cd54baca4 | ||
|
|
7ac687a0a9 | ||
|
|
83ae1021f6 | ||
|
|
67e3bc6380 | ||
|
|
4b291b2cf8 | ||
|
|
89870ad539 | ||
|
|
5bc03af75f | ||
|
|
30ec5c58fe | ||
|
|
a4b447256b | ||
|
|
1c9a7b8c61 | ||
|
|
d06573de6c | ||
|
|
6c2c561d8f | ||
|
|
e5309a4601 |
@@ -40,6 +40,8 @@ builds:
|
||||
goarch: arm64
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
|
||||
changelog:
|
||||
skip: true
|
||||
|
||||
@@ -64,7 +64,7 @@ blocks:
|
||||
- name: GH_VERSION
|
||||
value: 1.12.1
|
||||
- name: CODENAME
|
||||
value: "beaufort"
|
||||
value: "banon"
|
||||
- name: IN_DOCKER
|
||||
value: ""
|
||||
prologue:
|
||||
|
||||
45
CHANGELOG.md
45
CHANGELOG.md
@@ -1,5 +1,41 @@
|
||||
## [v2.9.0-rc1](https://github.com/traefik/traefik/tree/v2.9.0-rc1) (2022-09-14)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0-rc1...v2.9.0-rc1)
|
||||
## [v2.9.0-rc4](https://github.com/traefik/traefik/tree/v2.9.0-rc4) (2022-09-23)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc3...v2.9.0-rc4)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme]** Fix ACME panic ([#9365](https://github.com/traefik/traefik/pull/9365) by [ldez](https://github.com/ldez))
|
||||
|
||||
**Documentation:**
|
||||
- **[metrics]** Rework metrics overview page ([#9366](https://github.com/traefik/traefik/pull/9366) by [ddtmachado](https://github.com/ddtmachado))
|
||||
|
||||
**Misc:**
|
||||
- Merge current v2.8 into v2.9 ([#9371](https://github.com/traefik/traefik/pull/9371) by [ldez](https://github.com/ldez))
|
||||
- Merge current v2.8 into v2.9 ([#9367](https://github.com/traefik/traefik/pull/9367) by [ldez](https://github.com/ldez))
|
||||
- Merge current v2.8 into v2.9 ([#9350](https://github.com/traefik/traefik/pull/9350) by [ldez](https://github.com/ldez))
|
||||
|
||||
## [v2.8.6](https://github.com/traefik/traefik/tree/v2.8.6) (2022-09-23)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.5...v2.8.6)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[consulcatalog]** Fix UDP loadbalancer tags not being used with Consul Catalog ([#9357](https://github.com/traefik/traefik/pull/9357) by [t3hchipmunk](https://github.com/t3hchipmunk))
|
||||
- **[docker,rancher,ecs,provider]** Simplify AddServer algorithm ([#9358](https://github.com/traefik/traefik/pull/9358) by [ldez](https://github.com/ldez))
|
||||
- **[plugins]** Allow empty plugin configuration ([#9338](https://github.com/traefik/traefik/pull/9338) by [ldez](https://github.com/ldez))
|
||||
- **[rules]** Fix query parameter matching with equal ([#9369](https://github.com/traefik/traefik/pull/9369) by [ldez](https://github.com/ldez))
|
||||
- **[server]** Optimize websocket headers handling ([#9360](https://github.com/traefik/traefik/pull/9360) by [juliens](https://github.com/juliens))
|
||||
|
||||
**Documentation:**
|
||||
- **[ecs]** Add documentation for ECS constraints option ([#9354](https://github.com/traefik/traefik/pull/9354) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[k8s/gatewayapi]** Fix link to RouteNamespaces ([#9349](https://github.com/traefik/traefik/pull/9349) by [ldez](https://github.com/ldez))
|
||||
- Add documentation for json schema usage to validate config in the FAQ ([#9340](https://github.com/traefik/traefik/pull/9340) by [rtribotte](https://github.com/rtribotte))
|
||||
- Add a note on case insensitive regex matching ([#9322](https://github.com/traefik/traefik/pull/9322) by [NEwa-05](https://github.com/NEwa-05))
|
||||
|
||||
## [v2.9.0-rc3](https://github.com/traefik/traefik/tree/v2.9.0-rc3) (2022-09-16)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc2...v2.9.0-rc3)
|
||||
|
||||
**Misc:**
|
||||
- Merge current v2.8 into v2.9 ([#9343](https://github.com/traefik/traefik/pull/9343) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
## [v2.9.0-rc1](https://github.com/traefik/traefik/tree/v2.9.0-rc2) (2022-09-14)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0-rc1...v2.9.0-rc2)
|
||||
|
||||
**Enhancements:**
|
||||
- **[acme,tls]** ACME Default Certificate ([#9189](https://github.com/traefik/traefik/pull/9189) by [rtribotte](https://github.com/rtribotte))
|
||||
@@ -30,6 +66,11 @@
|
||||
- Merge current v2.8 into master ([#9146](https://github.com/traefik/traefik/pull/9146) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- Merge current v2.8 into master ([#9135](https://github.com/traefik/traefik/pull/9135) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
## [v2.9.0-rc1](https://github.com/traefik/traefik/tree/v2.9.0-rc1) (2022-09-14)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0-rc1...v2.9.0-rc1)
|
||||
|
||||
Release canceled.
|
||||
|
||||
## [v2.8.5](https://github.com/traefik/traefik/tree/v2.8.5) (2022-09-13)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.4...v2.8.5)
|
||||
|
||||
|
||||
@@ -157,3 +157,27 @@ By default, the following headers are automatically added when proxying requests
|
||||
|
||||
For more details,
|
||||
please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation.
|
||||
|
||||
## What does the "field not found" error mean?
|
||||
|
||||
```shell
|
||||
error: field not found, node: -badField-
|
||||
```
|
||||
|
||||
The "field not found" error occurs, when an unknown property is encountered in the dynamic or static configuration.
|
||||
|
||||
One easy way to check whether a configuration file is well-formed, is to validate it with:
|
||||
|
||||
- [JSON Schema of the static configuration](https://json.schemastore.org/traefik-v2.json)
|
||||
- [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json)
|
||||
|
||||
## Why are some resources (routers, middlewares, services...) not created/applied?
|
||||
|
||||
As a common tip, if a resource is dropped/not created by Traefik after the dynamic configuration was evaluated,
|
||||
one should look for an error in the logs.
|
||||
|
||||
If found, the error obviously confirms that something went wrong while creating the resource,
|
||||
and the message should help in figuring out the mistake(s) in the configuration, and how to fix it.
|
||||
|
||||
When using the file provider,
|
||||
one easy way to check if the dynamic configuration is well-formed is to validate it with the [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json).
|
||||
|
||||
@@ -445,7 +445,7 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
|
||||
### Kubernetes Gateway API Provider
|
||||
|
||||
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and
|
||||
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
|
||||
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
|
||||
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated.
|
||||
|
||||
## v2.6.0 to v2.6.1
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "Traefik Metrics Overview"
|
||||
description: "Traefik Proxy supports four metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started."
|
||||
description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started."
|
||||
---
|
||||
|
||||
# Metrics
|
||||
|
||||
Traefik supports 4 metrics backends:
|
||||
Traefik supports these metrics backends:
|
||||
|
||||
- [Datadog](./datadog.md)
|
||||
- [InfluxDB](./influxdb.md)
|
||||
@@ -15,569 +15,188 @@ Traefik supports 4 metrics backends:
|
||||
|
||||
## Global Metrics
|
||||
|
||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||
|-------------------------------------------------------------------------|---------|----------------------|------------|--------|
|
||||
| [Configuration reloads](#configuration-reloads) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Last Configuration Reload Success](#last-configuration-reload-success) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [TLS certificates expiration](#tls-certificates-expiration) | ✓ | ✓ | ✓ | ✓ |
|
||||
| Metric | Type | Description |
|
||||
|---------------------------------------------|---------|---------------------------------------------------------|
|
||||
| Config reload total | Count | The total count of configuration reloads. |
|
||||
| Config reload last success | Gauge | The timestamp of the last configuration reload success. |
|
||||
| TLS certificates not after | Gauge | The expiration date of certificates. |
|
||||
|
||||
### Configuration Reloads
|
||||
|
||||
The total count of configuration reloads.
|
||||
```prom tab="Prometheus"
|
||||
traefik_config_reloads_total
|
||||
traefik_config_last_reload_success
|
||||
traefik_tls_certs_not_after
|
||||
```
|
||||
|
||||
```dd tab="Datadog"
|
||||
config.reload.total
|
||||
config.reload.lastSuccessTimestamp
|
||||
tls.certs.notAfterTimestamp
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.config.reload.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_config_reloads_total
|
||||
traefik.config.reload.lastSuccessTimestamp
|
||||
traefik.tls.certs.notAfterTimestamp
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.config.reload.total
|
||||
```
|
||||
|
||||
### Last Configuration Reload Success
|
||||
|
||||
The timestamp of the last configuration reload success.
|
||||
|
||||
```dd tab="Datadog"
|
||||
config.reload.lastSuccessTimestamp
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.config.reload.lastSuccessTimestamp
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_config_last_reload_success
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.config.reload.lastSuccessTimestamp
|
||||
```
|
||||
|
||||
### TLS certificates expiration
|
||||
|
||||
The expiration date of certificates.
|
||||
|
||||
[Labels](#labels): `cn`, `sans`, `serial`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
tls.certs.notAfterTimestamp
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.tls.certs.notAfterTimestamp
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_tls_certs_not_after
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.tls.certs.notAfterTimestamp
|
||||
```
|
||||
|
||||
## EntryPoint Metrics
|
||||
|
||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||
|-----------------------------------------------------------|---------|----------------------|------------|--------|
|
||||
| [HTTP Requests Count](#http-requests-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [HTTPS Requests Count](#https-requests-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Request Duration Histogram](#request-duration-histogram) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Open Connections Count](#open-connections-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Requests Bytes Count](#requests-bytes-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Responses Bytes Count](#responses-bytes-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| Metric | Type | [Labels](#labels) | Description |
|
||||
|-----------------------|-----------|--------------------------------------------|---------------------------------------------------------------------|
|
||||
| Requests total | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. |
|
||||
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. |
|
||||
| Request duration | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. |
|
||||
| Open connections | Count | `method`, `protocol`, `entrypoint` | The current count of open connections on an entrypoint. |
|
||||
| Requests bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. |
|
||||
| Responses bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. |
|
||||
|
||||
### HTTP Requests Count
|
||||
|
||||
The total count of HTTP requests received by an entrypoint.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_requests_total
|
||||
traefik_entrypoint_requests_tls_total
|
||||
traefik_entrypoint_request_duration_seconds
|
||||
traefik_entrypoint_open_connections
|
||||
traefik_entrypoint_requests_bytes_total
|
||||
traefik_entrypoint_responses_bytes_total
|
||||
```
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.total
|
||||
entrypoint.request.tls.total
|
||||
entrypoint.request.duration
|
||||
entrypoint.connections.open
|
||||
entrypoint.requests.bytes.total
|
||||
entrypoint.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.requests.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_requests_total
|
||||
traefik.entrypoint.requests.tls.total
|
||||
traefik.entrypoint.request.duration
|
||||
traefik.entrypoint.connections.open
|
||||
traefik.entrypoint.requests.bytes.total
|
||||
traefik.entrypoint.responses.bytes.total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.request.total
|
||||
```
|
||||
|
||||
### HTTPS Requests Count
|
||||
|
||||
The total count of HTTPS requests received by an entrypoint.
|
||||
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.tls.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.requests.tls.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_requests_tls_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.request.tls.total
|
||||
```
|
||||
|
||||
### Request Duration Histogram
|
||||
|
||||
Request processing duration histogram on an entrypoint.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.duration
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.request.duration
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_request_duration_seconds
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.request.duration
|
||||
```
|
||||
|
||||
### Open Connections Count
|
||||
|
||||
The current count of open connections on an entrypoint.
|
||||
|
||||
[Labels](#labels): `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.connections.open
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.connections.open
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_open_connections
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.connections.open
|
||||
```
|
||||
|
||||
### Requests Bytes Count
|
||||
|
||||
The total size of HTTP requests in bytes handled by an entrypoint.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.requests.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.requests.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_requests_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.requests.bytes.total
|
||||
```
|
||||
|
||||
### Responses Bytes Count
|
||||
|
||||
The total size of HTTP responses in bytes handled by an entrypoint.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.entrypoint.responses.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_entrypoint_responses_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.entrypoint.responses.bytes.total
|
||||
```
|
||||
|
||||
## Router Metrics
|
||||
|
||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||
|-------------------------------------------------------------|---------|----------------------|------------|--------|
|
||||
| [HTTP Requests Count](#http-requests-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [HTTPS Requests Count](#https-requests-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Request Duration Histogram](#request-duration-histogram_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Open Connections Count](#open-connections-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Requests Bytes Count](#requests-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Responses Bytes Count](#responses-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
|
||||
| Metric | Type | [Labels](#labels) | Description |
|
||||
|-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------|
|
||||
| Requests total | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. |
|
||||
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. |
|
||||
| Request duration | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. |
|
||||
| Open connections | Count | `method`, `protocol`, `router`, `service` | The current count of open connections on a router. |
|
||||
| Requests bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. |
|
||||
| Responses bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. |
|
||||
|
||||
### HTTP Requests Count
|
||||
|
||||
The total count of HTTP requests handled by a router.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_requests_total
|
||||
traefik_router_requests_tls_total
|
||||
traefik_router_request_duration_seconds
|
||||
traefik_router_open_connections
|
||||
traefik_router_requests_bytes_total
|
||||
traefik_router_responses_bytes_total
|
||||
```
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.total
|
||||
router.request.tls.total
|
||||
router.request.duration
|
||||
router.connections.open
|
||||
router.requests.bytes.total
|
||||
router.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.requests.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_requests_total
|
||||
traefik.router.requests.tls.total
|
||||
traefik.router.request.duration
|
||||
traefik.router.connections.open
|
||||
traefik.router.requests.bytes.total
|
||||
traefik.router.responses.bytes.total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.request.total
|
||||
```
|
||||
|
||||
### HTTPS Requests Count
|
||||
|
||||
The total count of HTTPS requests handled by a router.
|
||||
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.tls.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.requests.tls.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_requests_tls_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.request.tls.total
|
||||
```
|
||||
|
||||
### Request Duration Histogram
|
||||
|
||||
Request processing duration histogram on a router.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.duration
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.request.duration
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_request_duration_seconds
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.request.duration
|
||||
```
|
||||
|
||||
### Open Connections Count
|
||||
|
||||
The current count of open connections on a router.
|
||||
|
||||
[Labels](#labels): `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.connections.open
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.connections.open
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_open_connections
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.connections.open
|
||||
```
|
||||
|
||||
### Requests Bytes Count
|
||||
|
||||
The total size of HTTP requests in bytes handled by a router.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.requests.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.requests.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_requests_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.requests.bytes.total
|
||||
```
|
||||
|
||||
### Responses Bytes Count
|
||||
|
||||
The total size of HTTP responses in bytes handled by a router.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.router.responses.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_router_responses_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.router.responses.bytes.total
|
||||
```
|
||||
|
||||
## Service Metrics
|
||||
|
||||
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|
||||
|-------------------------------------------------------------|---------|----------------------|------------|--------|
|
||||
| [HTTP Requests Count](#http-requests-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [HTTPS Requests Count](#https-requests-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Request Duration Histogram](#request-duration-histogram_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Open Connections Count](#open-connections-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Requests Retries Count](#requests-retries-count) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Service Server UP](#service-server-up) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Requests Bytes Count](#requests-bytes-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| [Responses outgoing traffic](#responses-bytes-count_2) | ✓ | ✓ | ✓ | ✓ |
|
||||
| Metric | Type | Labels | Description |
|
||||
|-----------------------|-----------|-----------------------------------------|-------------------------------------------------------------|
|
||||
| Requests total | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. |
|
||||
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. |
|
||||
| Request duration | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. |
|
||||
| Open connections | Count | `method`, `protocol`, `service` | The current count of open connections on a service. |
|
||||
| Retries total | Count | `service` | The count of requests retries on a service. |
|
||||
| Server UP | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. |
|
||||
| Requests bytes total | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. |
|
||||
| Responses bytes total | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. |
|
||||
|
||||
### HTTP Requests Count
|
||||
|
||||
The total count of HTTP requests processed on a service.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_requests_total
|
||||
traefik_service_requests_tls_total
|
||||
traefik_service_request_duration_seconds
|
||||
traefik_service_open_connections
|
||||
traefik_service_retries_total
|
||||
traefik_service_server_up
|
||||
traefik_service_requests_bytes_total
|
||||
traefik_service_responses_bytes_total
|
||||
```
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.request.total
|
||||
router.service.tls.total
|
||||
service.request.duration
|
||||
service.connections.open
|
||||
service.retries.total
|
||||
service.server.up
|
||||
service.requests.bytes.total
|
||||
service.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.requests.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_requests_total
|
||||
traefik.service.requests.tls.total
|
||||
traefik.service.request.duration
|
||||
traefik.service.connections.open
|
||||
traefik.service.retries.total
|
||||
traefik.service.server.up
|
||||
traefik.service.requests.bytes.total
|
||||
traefik.service.responses.bytes.total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.request.total
|
||||
```
|
||||
|
||||
### HTTPS Requests Count
|
||||
|
||||
The total count of HTTPS requests processed on a service.
|
||||
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.service.tls.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.requests.tls.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_requests_tls_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.request.tls.total
|
||||
```
|
||||
|
||||
### Request Duration Histogram
|
||||
|
||||
Request processing duration histogram on a service.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.request.duration
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.request.duration
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_request_duration_seconds
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.request.duration
|
||||
```
|
||||
|
||||
### Open Connections Count
|
||||
|
||||
The current count of open connections on a service.
|
||||
|
||||
[Labels](#labels): `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.connections.open
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.connections.open
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_open_connections
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.connections.open
|
||||
```
|
||||
|
||||
### Requests Retries Count
|
||||
|
||||
The count of requests retries on a service.
|
||||
|
||||
[Labels](#labels): `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.retries.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.retries.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_retries_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.retries.total
|
||||
```
|
||||
|
||||
### Service Server UP
|
||||
|
||||
Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server.
|
||||
|
||||
[Labels](#labels): `service`, `url`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.server.up
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.server.up
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_server_up
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.server.up
|
||||
```
|
||||
|
||||
### Requests Bytes Count
|
||||
|
||||
The total size of requests in bytes received by a service.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.requests.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.requests.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_requests_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.requests.bytes.total
|
||||
```
|
||||
|
||||
### Responses Bytes Count
|
||||
|
||||
The total size of responses in bytes returned by a service.
|
||||
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.responses.bytes.total
|
||||
```
|
||||
|
||||
```influxdb tab="InfluxDB / InfluxDB2"
|
||||
traefik.service.responses.bytes.total
|
||||
```
|
||||
|
||||
```prom tab="Prometheus"
|
||||
traefik_service_responses_bytes_total
|
||||
```
|
||||
|
||||
```statsd tab="StatsD"
|
||||
# Default prefix: "traefik"
|
||||
{prefix}.service.responses.bytes.total
|
||||
```
|
||||
|
||||
|
||||
@@ -169,6 +169,70 @@ providers:
|
||||
# ...
|
||||
```
|
||||
|
||||
### `constraints`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
The `constraints` option can be set to an expression that Traefik matches against the container labels (task),
|
||||
to determine whether to create any route for that container.
|
||||
If none of the container labels match the expression, no route for that container is created.
|
||||
If the expression is empty, all detected containers are included.
|
||||
|
||||
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
|
||||
as well as the usual boolean logic, as shown in examples below.
|
||||
|
||||
??? example "Constraints Expression Examples"
|
||||
|
||||
```toml
|
||||
# Includes only containers having a label with key `a.label.name` and value `foo`
|
||||
constraints = "Label(`a.label.name`, `foo`)"
|
||||
```
|
||||
|
||||
```toml
|
||||
# Excludes containers having any label with key `a.label.name` and value `foo`
|
||||
constraints = "!Label(`a.label.name`, `value`)"
|
||||
```
|
||||
|
||||
```toml
|
||||
# With logical AND.
|
||||
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
|
||||
```
|
||||
|
||||
```toml
|
||||
# With logical OR.
|
||||
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
|
||||
```
|
||||
|
||||
```toml
|
||||
# With logical AND and OR, with precedence set by parentheses.
|
||||
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
|
||||
```
|
||||
|
||||
```toml
|
||||
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
|
||||
constraints = "LabelRegex(`a.label.name`, `a.+`)"
|
||||
```
|
||||
|
||||
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
ecs:
|
||||
constraints: "Label(`a.label.name`,`foo`)"
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.ecs]
|
||||
constraints = "Label(`a.label.name`,`foo`)"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.ecs.constraints=Label(`a.label.name`,`foo`)
|
||||
# ...
|
||||
```
|
||||
|
||||
### `defaultRule`
|
||||
|
||||
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
|
||||
|
||||
@@ -213,6 +213,7 @@ you can do so in two different ways:
|
||||
List of providers that support these features:
|
||||
|
||||
- [Docker](./docker.md#exposedbydefault)
|
||||
- [ECS](./ecs.md#exposedbydefault)
|
||||
- [Consul Catalog](./consul-catalog.md#exposedbydefault)
|
||||
- [Nomad](./nomad.md#exposedbydefault)
|
||||
- [Rancher](./rancher.md#exposedbydefault)
|
||||
@@ -223,6 +224,7 @@ List of providers that support these features:
|
||||
List of providers that support constraints:
|
||||
|
||||
- [Docker](./docker.md#constraints)
|
||||
- [ECS](./ecs.md#constraints)
|
||||
- [Consul Catalog](./consul-catalog.md#constraints)
|
||||
- [Nomad](./nomad.md#constraints)
|
||||
- [Rancher](./rancher.md#constraints)
|
||||
|
||||
@@ -233,18 +233,18 @@ If the rule is verified, the router becomes active, calls middlewares, and then
|
||||
|
||||
The table below lists all the available matchers:
|
||||
|
||||
| Rule | Description |
|
||||
|------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| ```Headers(`key`, `value`)``` | Check if there is a key `key`defined in the headers, with the value `value` |
|
||||
| ```HeadersRegexp(`key`, `regexp`)``` | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
|
||||
| ```Host(`example.com`, ...)``` | Check if the request domain (host header value) targets one of the given `domains`. |
|
||||
| ```HostHeader(`example.com`, ...)``` | Same as `Host`, only exists for historical reasons. |
|
||||
| ```HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``` | Match the request domain. See "Regexp Syntax" below. |
|
||||
| ```Method(`GET`, ...)``` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`) |
|
||||
| ```Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)``` | Match exact request path. See "Regexp Syntax" below. |
|
||||
| ```PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)``` | Match request prefix path. See "Regexp Syntax" below. |
|
||||
| ```Query(`foo=bar`, `bar=baz`)``` | Match Query String parameters. It accepts a sequence of key=value pairs. |
|
||||
| ```ClientIP(`10.0.0.0/16`, `::1`)``` | Match if the request client IP is one of the given IP/CIDR. It accepts IPv4, IPv6 and CIDR formats. |
|
||||
| Rule | Description |
|
||||
|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| ```Headers(`key`, `value`)``` | Check if there is a key `key`defined in the headers, with the value `value` |
|
||||
| ```HeadersRegexp(`key`, `regexp`)``` | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
|
||||
| ```Host(`example.com`, ...)``` | Check if the request domain (host header value) targets one of the given `domains`. |
|
||||
| ```HostHeader(`example.com`, ...)``` | Same as `Host`, only exists for historical reasons. |
|
||||
| ```HostRegexp(`example.com`, `{subdomain:[a-z]+}.example.com`, ...)``` | Match the request domain. See "Regexp Syntax" below. |
|
||||
| ```Method(`GET`, ...)``` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`) |
|
||||
| ```Path(`/path`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`, ...)``` | Match exact request path. See "Regexp Syntax" below. |
|
||||
| ```PathPrefix(`/products/`, `/articles/{cat:[a-z]+}/{id:[0-9]+}`)``` | Match request prefix path. See "Regexp Syntax" below. |
|
||||
| ```Query(`foo=bar`, `bar=baz`)``` | Match Query String parameters. It accepts a sequence of key=value pairs. |
|
||||
| ```ClientIP(`10.0.0.0/16`, `::1`)``` | Match if the request client IP is one of the given IP/CIDR. It accepts IPv4, IPv6 and CIDR formats. |
|
||||
|
||||
!!! important "Non-ASCII Domain Names"
|
||||
|
||||
@@ -259,6 +259,7 @@ The table below lists all the available matchers:
|
||||
The regexp name (`name` in the above example) is an arbitrary value, that exists only for historical reasons.
|
||||
|
||||
Any `regexp` supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used.
|
||||
For example, here is a case insensitive path matcher syntax: ```Path(`/{path:(?i:Products)}`)```.
|
||||
|
||||
!!! info "Combining Matchers Using Operators and Parenthesis"
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ func headersRegexp(route *mux.Route, headers ...string) error {
|
||||
func query(route *mux.Route, query ...string) error {
|
||||
var queries []string
|
||||
for _, elem := range query {
|
||||
queries = append(queries, strings.Split(elem, "=")...)
|
||||
queries = append(queries, strings.SplitN(elem, "=", 2)...)
|
||||
}
|
||||
|
||||
route.Queries(queries...)
|
||||
|
||||
@@ -252,6 +252,14 @@ func Test_addRoute(t *testing.T) {
|
||||
"http://localhost/foo?bar=baz": http.StatusNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Query with multiple equals",
|
||||
rule: "Query(`foo=b=ar`)",
|
||||
expected: map[string]int{
|
||||
"http://localhost/foo?foo=b=ar": http.StatusOK,
|
||||
"http://localhost/foo?foo=bar": http.StatusNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Rule with simple path",
|
||||
rule: `Path("/a")`,
|
||||
|
||||
@@ -84,6 +84,9 @@ func (p middlewareBuilder) createConfig(config map[string]interface{}) (reflect.
|
||||
}
|
||||
|
||||
vConfig := results[0]
|
||||
if len(config) == 0 {
|
||||
return vConfig, nil
|
||||
}
|
||||
|
||||
cfg := &mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.StringToSliceHookFunc(","),
|
||||
|
||||
@@ -397,7 +397,7 @@ func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStor
|
||||
return
|
||||
}
|
||||
|
||||
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, tlsStore)
|
||||
err = p.addCertificateForDomain(dom, cert, tlsStore)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Error adding certificate for domain")
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
|
||||
err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Error adding certificate for domain")
|
||||
}
|
||||
@@ -468,7 +468,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
|
||||
err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Error adding certificate for domain")
|
||||
}
|
||||
@@ -535,7 +535,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
|
||||
domain.SANs = validDomains[1:]
|
||||
}
|
||||
|
||||
err = p.addCertificateForDomain(domain, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
|
||||
err = p.addCertificateForDomain(domain, cert, traefiktls.DefaultTLSStoreName)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Error adding certificate for domain")
|
||||
}
|
||||
@@ -660,11 +660,15 @@ func (p *Provider) removeResolvingDomains(resolvingDomains []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) addCertificateForDomain(domain types.Domain, certificate, key []byte, tlsStore string) error {
|
||||
func (p *Provider) addCertificateForDomain(domain types.Domain, crt *certificate.Resource, tlsStore string) error {
|
||||
if crt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
p.certificatesMu.Lock()
|
||||
defer p.certificatesMu.Unlock()
|
||||
|
||||
cert := Certificate{Certificate: certificate, Key: key, Domain: domain}
|
||||
cert := Certificate{Certificate: crt.Certificate, Key: crt.PrivateKey, Domain: domain}
|
||||
|
||||
certUpdated := false
|
||||
for _, domainsCertificate := range p.certificates {
|
||||
@@ -828,7 +832,7 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat
|
||||
continue
|
||||
}
|
||||
|
||||
err = p.addCertificateForDomain(cert.Domain, renewedCert.Certificate, renewedCert.PrivateKey, cert.Store)
|
||||
err = p.addCertificateForDomain(cert.Domain, renewedCert, cert.Store)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Error adding certificate for domain")
|
||||
}
|
||||
|
||||
@@ -195,29 +195,27 @@ func (p *Provider) addServerTCP(item itemData, loadBalancer *dynamic.TCPServersL
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
port = loadBalancer.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
if item.Port != "" && port == "" {
|
||||
port = item.Port
|
||||
}
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
if item.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
port = item.Port
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -230,21 +228,23 @@ func (p *Provider) addServerUDP(item itemData, loadBalancer *dynamic.UDPServersL
|
||||
loadBalancer.Servers = []dynamic.UDPServer{{}}
|
||||
}
|
||||
|
||||
var port string
|
||||
if item.Port != "" {
|
||||
if item.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
port = item.Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
if item.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -253,11 +253,6 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
port = loadBalancer.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.Server{}
|
||||
server.SetDefaults()
|
||||
@@ -265,17 +260,19 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
|
||||
loadBalancer.Servers = []dynamic.Server{server}
|
||||
}
|
||||
|
||||
if item.Port != "" && port == "" {
|
||||
port = item.Port
|
||||
if item.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
port = item.Port
|
||||
}
|
||||
|
||||
if item.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
scheme := loadBalancer.Servers[0].Scheme
|
||||
|
||||
@@ -2220,7 +2220,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||
Labels: map[string]string{
|
||||
"traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)",
|
||||
"traefik.tcp.routers.foo.tls.options": "foo",
|
||||
"traefik.tcp.services.foo.loadbalancer.server.port": "80",
|
||||
"traefik.tcp.services.foo.loadbalancer.server.port": "8080",
|
||||
},
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
@@ -2244,7 +2244,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: "127.0.0.1:80",
|
||||
Address: "127.0.0.1:8080",
|
||||
},
|
||||
},
|
||||
TerminationDelay: Int(100),
|
||||
@@ -2858,6 +2858,57 @@ func Test_buildConfiguration(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "UDP service with labels only",
|
||||
ConnectAware: true,
|
||||
items: []itemData{
|
||||
{
|
||||
ID: "1",
|
||||
Node: "Node1",
|
||||
Datacenter: "dc1",
|
||||
Name: "Test",
|
||||
Namespace: "ns",
|
||||
Labels: map[string]string{
|
||||
"traefik.udp.routers.test-udp-label.service": "test-udp-label-service",
|
||||
"traefik.udp.routers.test-udp-label.entryPoints": "udp",
|
||||
"traefik.udp.services.test-udp-label-service.loadBalancer.server.port": "21116",
|
||||
},
|
||||
Address: "127.0.0.1",
|
||||
Port: "80",
|
||||
Status: api.HealthPassing,
|
||||
},
|
||||
},
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{},
|
||||
Middlewares: map[string]*dynamic.TCPMiddleware{},
|
||||
Services: map[string]*dynamic.TCPService{},
|
||||
},
|
||||
UDP: &dynamic.UDPConfiguration{
|
||||
Routers: map[string]*dynamic.UDPRouter{
|
||||
"test-udp-label": {
|
||||
EntryPoints: []string{"udp"},
|
||||
Service: "test-udp-label-service",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.UDPService{
|
||||
"test-udp-label-service": {
|
||||
LoadBalancer: &dynamic.UDPServersLoadBalancer{
|
||||
Servers: []dynamic.UDPServer{
|
||||
{Address: "127.0.0.1:21116"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{},
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Services: map[string]*dynamic.Service{},
|
||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
||||
@@ -196,28 +196,24 @@ func (p *Provider) addServerTCP(ctx context.Context, container dockerData, loadB
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(ctx, container, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.TCPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.TCPServer{server}
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -226,28 +222,24 @@ func (p *Provider) addServerUDP(ctx context.Context, container dockerData, loadB
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.UDPServer{{}}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(ctx, container, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.UDPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.UDPServer{server}
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -256,17 +248,6 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
}
|
||||
|
||||
ip, port, err := p.getIPPort(ctx, container, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.Server{}
|
||||
server.SetDefaults()
|
||||
@@ -274,6 +255,14 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
|
||||
loadBalancer.Servers = []dynamic.Server{server}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(ctx, container, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ func (p *Provider) filterInstance(ctx context.Context, instance ecsInstance) boo
|
||||
|
||||
matches, err := constraints.MatchLabels(instance.Labels, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
logger.Errorf("Error matching constraint expression: %v", err)
|
||||
return false
|
||||
}
|
||||
if !matches {
|
||||
@@ -201,28 +201,24 @@ func (p *Provider) addServerTCP(instance ecsInstance, loadBalancer *dynamic.TCPS
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(instance, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.TCPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.TCPServer{server}
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -231,28 +227,24 @@ func (p *Provider) addServerUDP(instance ecsInstance, loadBalancer *dynamic.UDPS
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.UDPServer{{}}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(instance, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.UDPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.UDPServer{server}
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -261,17 +253,6 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
var serverPort string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
}
|
||||
|
||||
ip, port, err := p.getIPPort(instance, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.Server{}
|
||||
server.SetDefaults()
|
||||
@@ -279,6 +260,14 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
|
||||
loadBalancer.Servers = []dynamic.Server{server}
|
||||
}
|
||||
|
||||
serverPort := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
ip, port, err := p.getIPPort(instance, serverPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
@@ -175,29 +175,27 @@ func (p *Provider) addServerTCP(i item, lb *dynamic.TCPServersLoadBalancer) erro
|
||||
return errors.New("load-balancer is missing")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(lb.Servers) > 0 {
|
||||
port = lb.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(lb.Servers) == 0 {
|
||||
lb.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
if i.Port != 0 && port == "" {
|
||||
port = strconv.Itoa(i.Port)
|
||||
}
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
if i.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := lb.Servers[0].Port
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" && i.Port > 0 {
|
||||
port = strconv.Itoa(i.Port)
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -206,29 +204,27 @@ func (p *Provider) addServerUDP(i item, lb *dynamic.UDPServersLoadBalancer) erro
|
||||
return errors.New("load-balancer is missing")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(lb.Servers) > 0 {
|
||||
port = lb.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(lb.Servers) == 0 {
|
||||
lb.Servers = []dynamic.UDPServer{{}}
|
||||
}
|
||||
|
||||
if i.Port != 0 && port == "" {
|
||||
port = strconv.Itoa(i.Port)
|
||||
}
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
if i.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := lb.Servers[0].Port
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" && i.Port > 0 {
|
||||
port = strconv.Itoa(i.Port)
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -237,11 +233,6 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
|
||||
return errors.New("load-balancer is missing")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(lb.Servers) > 0 {
|
||||
port = lb.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(lb.Servers) == 0 {
|
||||
server := dynamic.Server{}
|
||||
server.SetDefaults()
|
||||
@@ -249,19 +240,21 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
|
||||
lb.Servers = []dynamic.Server{server}
|
||||
}
|
||||
|
||||
if i.Port != 0 && port == "" {
|
||||
if i.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
port := lb.Servers[0].Port
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" && i.Port > 0 {
|
||||
port = strconv.Itoa(i.Port)
|
||||
}
|
||||
lb.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
}
|
||||
|
||||
if i.Address == "" {
|
||||
return errors.New("address is missing")
|
||||
}
|
||||
|
||||
scheme := lb.Servers[0].Scheme
|
||||
lb.Servers[0].Scheme = ""
|
||||
lb.Servers[0].URL = fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(i.Address, port))
|
||||
|
||||
@@ -160,7 +160,7 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
|
||||
|
||||
matches, err := constraints.MatchLabels(service.Labels, p.Constraints)
|
||||
if err != nil {
|
||||
logger.Errorf("Error matching constraints expression: %v", err)
|
||||
logger.Errorf("Error matching constraint expression: %v", err)
|
||||
return false
|
||||
}
|
||||
if !matches {
|
||||
@@ -185,23 +185,19 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
|
||||
func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error {
|
||||
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
|
||||
|
||||
serverPort := ""
|
||||
|
||||
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
if loadBalancer == nil {
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
port := getServicePort(service)
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.TCPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.TCPServer{server}
|
||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
if serverPort != "" {
|
||||
port = serverPort
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
port = getServicePort(service)
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
@@ -216,29 +212,26 @@ func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBa
|
||||
}
|
||||
|
||||
loadBalancer.Servers = servers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error {
|
||||
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
|
||||
|
||||
serverPort := ""
|
||||
|
||||
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
|
||||
serverPort = loadBalancer.Servers[0].Port
|
||||
if loadBalancer == nil {
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
port := getServicePort(service)
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.UDPServer{}
|
||||
|
||||
loadBalancer.Servers = []dynamic.UDPServer{server}
|
||||
loadBalancer.Servers = []dynamic.UDPServer{{}}
|
||||
}
|
||||
|
||||
if serverPort != "" {
|
||||
port = serverPort
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
port = getServicePort(service)
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
@@ -253,14 +246,16 @@ func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBa
|
||||
}
|
||||
|
||||
loadBalancer.Servers = servers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error {
|
||||
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
|
||||
|
||||
serverPort := getLBServerPort(loadBalancer)
|
||||
port := getServicePort(service)
|
||||
if loadBalancer == nil {
|
||||
return errors.New("load-balancer is not defined")
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
server := dynamic.Server{}
|
||||
@@ -269,9 +264,11 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
|
||||
loadBalancer.Servers = []dynamic.Server{server}
|
||||
}
|
||||
|
||||
if serverPort != "" {
|
||||
port = serverPort
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
port := loadBalancer.Servers[0].Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
port = getServicePort(service)
|
||||
}
|
||||
|
||||
if port == "" {
|
||||
@@ -286,14 +283,8 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
|
||||
}
|
||||
|
||||
loadBalancer.Servers = servers
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLBServerPort(loadBalancer *dynamic.ServersLoadBalancer) string {
|
||||
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
|
||||
return loadBalancer.Servers[0].Port
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func getServicePort(data rancherData) string {
|
||||
|
||||
@@ -2,7 +2,6 @@ package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/traefik/traefik/v2/pkg/plugins"
|
||||
@@ -30,9 +29,5 @@ func findPluginConfig(rawConfig map[string]dynamic.PluginConf) (string, map[stri
|
||||
return "", nil, errors.New("missing plugin type")
|
||||
}
|
||||
|
||||
if len(rawPluginConfig) == 0 {
|
||||
return "", nil, fmt.Errorf("missing plugin configuration: %s", pluginType)
|
||||
}
|
||||
|
||||
return pluginType, rawPluginConfig, nil
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
ptypes "github.com/traefik/paerser/types"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"golang.org/x/net/http/httpguts"
|
||||
)
|
||||
|
||||
// StatusClientClosedRequest non-standard HTTP status code for client disconnection.
|
||||
@@ -67,16 +68,18 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
|
||||
// some servers need Sec-WebSocket-Key, Sec-WebSocket-Extensions, Sec-WebSocket-Accept,
|
||||
// Sec-WebSocket-Protocol and Sec-WebSocket-Version to be case-sensitive.
|
||||
// https://tools.ietf.org/html/rfc6455#page-20
|
||||
outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
|
||||
outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"]
|
||||
outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"]
|
||||
outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
|
||||
outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
|
||||
delete(outReq.Header, "Sec-Websocket-Key")
|
||||
delete(outReq.Header, "Sec-Websocket-Extensions")
|
||||
delete(outReq.Header, "Sec-Websocket-Accept")
|
||||
delete(outReq.Header, "Sec-Websocket-Protocol")
|
||||
delete(outReq.Header, "Sec-Websocket-Version")
|
||||
if isWebSocketUpgrade(outReq) {
|
||||
outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
|
||||
outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"]
|
||||
outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"]
|
||||
outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
|
||||
outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
|
||||
delete(outReq.Header, "Sec-Websocket-Key")
|
||||
delete(outReq.Header, "Sec-Websocket-Extensions")
|
||||
delete(outReq.Header, "Sec-Websocket-Accept")
|
||||
delete(outReq.Header, "Sec-Websocket-Protocol")
|
||||
delete(outReq.Header, "Sec-Websocket-Version")
|
||||
}
|
||||
},
|
||||
Transport: roundTripper,
|
||||
FlushInterval: time.Duration(flushInterval),
|
||||
@@ -112,6 +115,14 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
|
||||
return proxy, nil
|
||||
}
|
||||
|
||||
func isWebSocketUpgrade(req *http.Request) bool {
|
||||
if !httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.EqualFold(req.Header.Get("Upgrade"), "websocket")
|
||||
}
|
||||
|
||||
func statusText(statusCode int) string {
|
||||
if statusCode == StatusClientClosedRequest {
|
||||
return StatusClientClosedRequestText
|
||||
|
||||
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example new bugfix v2.8.5
|
||||
# example new bugfix v2.8.6
|
||||
CurrentRef = "v2.8"
|
||||
PreviousRef = "v2.8.4"
|
||||
PreviousRef = "v2.8.5"
|
||||
BaseBranch = "v2.8"
|
||||
FutureCurrentRefName = "v2.8.5"
|
||||
FutureCurrentRefName = "v2.8.6"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
||||
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example RC2 of v2.8.0
|
||||
CurrentRef = "v2.8"
|
||||
PreviousRef = "v2.8.0-rc1"
|
||||
BaseBranch = "v2.8"
|
||||
FutureCurrentRefName = "v2.8.0-rc2"
|
||||
# example RC4 of v2.9.0
|
||||
CurrentRef = "v2.9"
|
||||
PreviousRef = "v2.9.0-rc3"
|
||||
BaseBranch = "v2.9"
|
||||
FutureCurrentRefName = "v2.9.0-rc4"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
||||
Reference in New Issue
Block a user