Merge branch v3.1 into master

This commit is contained in:
kevinpollet 2024-08-06 16:38:39 +02:00
commit b611f967b7
No known key found for this signature in database
GPG key ID: 0C9A5DDD1B292453
36 changed files with 2917 additions and 2537 deletions

View file

@ -213,6 +213,7 @@ issues:
- 'Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' - 'Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked'
- "should have a package comment, unless it's in another file for this package" - "should have a package comment, unless it's in another file for this package"
- 'fmt.Sprintf can be replaced with string' - 'fmt.Sprintf can be replaced with string'
- 'SA1019: dockertypes.ContainerNode is deprecated'
exclude-rules: exclude-rules:
- path: '(.+)_test.go' - path: '(.+)_test.go'
linters: linters:

View file

@ -1,3 +1,33 @@
## [v3.1.2](https://github.com/traefik/traefik/tree/v3.1.2) (2024-08-06)
[All Commits](https://github.com/traefik/traefik/compare/v3.1.1...v3.1.2)
**Bug fixes:**
- **[k8s,k8s/gatewayapi]** Include status addresses when comparing Gateway statuses ([#10972](https://github.com/traefik/traefik/pull/10972) by [kevinpollet](https://github.com/kevinpollet))
- **[k8s/ingress,k8s/crd,k8s]** Allow to disable Kubernetes cluster scope resources discovery ([#10946](https://github.com/traefik/traefik/pull/10946) by [rtribotte](https://github.com/rtribotte))
- **[logs]** Change logs output from stderr to stdout ([#10973](https://github.com/traefik/traefik/pull/10973) by [rtribotte](https://github.com/rtribotte))
- Fix grafana dashboard to work with scrape interval greater than 15s ([#10954](https://github.com/traefik/traefik/pull/10954) by [swiffer](https://github.com/swiffer))
**Documentation:**
- **[accesslogs]** Add Access logs section to the migration guide ([#10947](https://github.com/traefik/traefik/pull/10947) by [lbenguigui](https://github.com/lbenguigui))
- **[http]** Fix missing codeblock ending in HTTP discover documentation ([#10967](https://github.com/traefik/traefik/pull/10967) by [djcode](https://github.com/djcode))
- **[http]** Fix yaml config example for HTTP provider headers ([#10966](https://github.com/traefik/traefik/pull/10966) by [djcode](https://github.com/djcode))
- **[k8s,k8s/gatewayapi]** Use Standard channel by default with Gateway API ([#10974](https://github.com/traefik/traefik/pull/10974) by [mloiseleur](https://github.com/mloiseleur))
**Misc:**
- Merge branch v2.11 into v3.1 ([#10978](https://github.com/traefik/traefik/pull/10978) by [rtribotte](https://github.com/rtribotte))
- Merge v2.11 into v3.1 ([#10956](https://github.com/traefik/traefik/pull/10956) by [mmatur](https://github.com/mmatur))
## [v2.11.8](https://github.com/traefik/traefik/tree/v2.11.8) (2024-08-06)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.7...v2.11.8)
**Bug fixes:**
- **[docker]** Update to github.com/docker/docker v27.1.1 ([#10955](https://github.com/traefik/traefik/pull/10955) by [rtribotte](https://github.com/rtribotte))
- **[webui]** Upgrade webui dependencies ([#10961](https://github.com/traefik/traefik/pull/10961) by [mmatur](https://github.com/mmatur))
**Documentation:**
- Fix embedded youtube video ([#10958](https://github.com/traefik/traefik/pull/10958) by [mmatur](https://github.com/mmatur))
- Updated index.md to include video ([#10944](https://github.com/traefik/traefik/pull/10944) by [tomatokoolaid](https://github.com/tomatokoolaid))
## [v3.1.1](https://github.com/traefik/traefik/tree/v3.1.1) (2024-07-30) ## [v3.1.1](https://github.com/traefik/traefik/tree/v3.1.1) (2024-07-30)
[All Commits](https://github.com/traefik/traefik/compare/v3.1.0...v3.1.1) [All Commits](https://github.com/traefik/traefik/compare/v3.1.0...v3.1.1)

View file

@ -46,7 +46,7 @@ func setupLogger(staticConfiguration *static.Configuration) {
} }
func getLogWriter(staticConfiguration *static.Configuration) io.Writer { func getLogWriter(staticConfiguration *static.Configuration) io.Writer {
var w io.Writer = os.Stderr var w io.Writer = os.Stdout
if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 {
_, _ = os.OpenFile(staticConfiguration.Log.FilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666) _, _ = os.OpenFile(staticConfiguration.Log.FilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)

View file

@ -1028,7 +1028,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "5xx over [$interval]", "title": "5xx over $interval",
"type": "timeseries" "type": "timeseries"
}, },
{ {
@ -1128,7 +1128,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Other codes over [$interval]", "title": "Other codes over $interval",
"type": "timeseries" "type": "timeseries"
}, },
{ {

View file

@ -242,7 +242,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[1m])) by (entrypoint)", "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[$interval])) by (entrypoint)",
"legendFormat": "{{entrypoint}}", "legendFormat": "{{entrypoint}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -340,7 +340,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "(sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"0.3\",code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method) + \n sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"1.2\",code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method)) / 2 / \n sum(rate(traefik_entrypoint_request_duration_seconds_count{code=\"200\",entrypoint=~\"$entrypoint\"}[5m])) by (method)\n", "expr": "(sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"0.3\",code=\"200\",entrypoint=~\"$entrypoint\"}[$interval])) by (method) + \n sum(rate(traefik_entrypoint_request_duration_seconds_bucket{le=\"1.2\",code=\"200\",entrypoint=~\"$entrypoint\"}[$interval])) by (method)) / 2 / \n sum(rate(traefik_entrypoint_request_duration_seconds_count{code=\"200\",entrypoint=~\"$entrypoint\"}[$interval])) by (method)\n",
"legendFormat": "{{method}}", "legendFormat": "{{method}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -408,7 +408,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "sum(rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[1m])) by (method, code)", "expr": "sum(rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[$interval])) by (method, code)",
"legendFormat": "{{method}}[{{code}}]", "legendFormat": "{{method}}[{{code}}]",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -606,7 +606,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "[{{code}}] on {{service}}", "legendFormat": "[{{code}}] on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -710,7 +710,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"1.2\",service=~\"$service.*\"}[5m])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[5m]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)", "expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"1.2\",service=~\"$service.*\"}[$interval])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[$interval]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)",
"legendFormat": "{{service}}", "legendFormat": "{{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -804,7 +804,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"0.3\",service=~\"$service.*\"}[5m])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[5m]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)", "expr": "label_replace(\n 1 - (sum by (service)\n (rate(traefik_service_request_duration_seconds_bucket{le=\"0.3\",service=~\"$service.*\"}[$interval])) / sum by (service) \n (rate(traefik_service_request_duration_seconds_count{service=~\"$service.*\"}[$interval]))\n ) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\"\n)",
"legendFormat": "{{service}}", "legendFormat": "{{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -916,13 +916,13 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"2..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"2..\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}}[{{code}}] on {{service}}", "legendFormat": "{{method}}[{{code}}] on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"title": "2xx over 5 min", "title": "2xx over $interval",
"type": "timeseries" "type": "timeseries"
}, },
{ {
@ -1015,13 +1015,13 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code=~\"5..\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}}[{{code}}] on {{service}}", "legendFormat": "{{method}}[{{code}}] on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"title": "5xx over 5 min", "title": "5xx over $interval",
"type": "timeseries" "type": "timeseries"
}, },
{ {
@ -1114,13 +1114,13 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code!~\"2..|5..\",protocol=\"http\"}[5m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,method,code) \n (rate(traefik_service_requests_total{service=~\"$service.*\",code!~\"2..|5..\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}}[{{code}}] on {{service}}", "legendFormat": "{{method}}[{{code}}] on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"title": "Other codes over 5 min", "title": "Other codes over $interval",
"type": "timeseries" "type": "timeseries"
}, },
{ {
@ -1213,7 +1213,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_requests_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_requests_bytes_total{service=~\"$service.*\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}} on {{service}}", "legendFormat": "{{method}} on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -1312,7 +1312,7 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)", "expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[$interval])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}} on {{service}}", "legendFormat": "{{method}} on {{service}}",
"range": true, "range": true,
"refId": "A" "refId": "A"
@ -1448,6 +1448,69 @@
"skipUrlSync": false, "skipUrlSync": false,
"type": "datasource" "type": "datasource"
}, },
{
"auto": true,
"auto_count": 30,
"auto_min": "1m",
"current": {
"selected": false,
"text": "auto",
"value": "$__auto_interval_interval"
},
"hide": 0,
"name": "interval",
"options": [
{
"selected": true,
"text": "auto",
"value": "$__auto_interval_interval"
},
{
"selected": false,
"text": "1m",
"value": "1m"
},
{
"selected": false,
"text": "5m",
"value": "5m"
},
{
"selected": false,
"text": "10m",
"value": "10m"
},
{
"selected": false,
"text": "30m",
"value": "30m"
},
{
"selected": false,
"text": "1h",
"value": "1h"
},
{
"selected": false,
"text": "2h",
"value": "2h"
},
{
"selected": false,
"text": "4h",
"value": "4h"
},
{
"selected": false,
"text": "8h",
"value": "8h"
}
],
"query": "1m,5m,10m,30m,1h,2h,4h,8h",
"refresh": 2,
"skipUrlSync": false,
"type": "interval"
},
{ {
"current": {}, "current": {},
"datasource": { "datasource": {

View file

@ -7,16 +7,22 @@ description: "Traefik Proxy, an open source Edge Router, auto-discovers configur
![Architecture](assets/img/traefik-architecture.png) ![Architecture](assets/img/traefik-architecture.png)
Traefik is an [open-source](https://github.com/traefik/traefik) *Edge Router* that makes publishing your services a fun and easy experience. Traefik is an [open-source](https://github.com/traefik/traefik) *Application Proxy* that makes publishing your services a fun and easy experience.
It receives requests on behalf of your system and finds out which components are responsible for handling them. It receives requests on behalf of your system and identifies which components are responsible for handling them, and routes them securely.
What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services. What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services.
The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request. The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request.
Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.)
With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions).
With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state.
And if your needs change, you can add API gateway and API management capabilities seamlessly to your existing Traefik deployments. It takes less than a minute, theres no rip-and-replace, and all your configurations are preserved. See how it works in this video:
<div style="text-align: center;">
<iframe src="https://www.youtube.com/embed/zriUO5YPgFg?modestbranding=1&rel=0&controls=1" width="560" height="315" title="Upgrade Traefik Proxy to API Gateway and API Management in Seconds // Traefik Labs" frameborder="0" allowfullscreen></iframe>
</div>
Developing Traefik, our main goal is to make it effortless to use, and we're sure you'll enjoy it. Developing Traefik, our main goal is to make it effortless to use, and we're sure you'll enjoy it.
@ -26,4 +32,4 @@ Developing Traefik, our main goal is to make it effortless to use, and we're sur
Join our user friendly and active [Community Forum](https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the Traefik community. Join our user friendly and active [Community Forum](https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the Traefik community.
Using Traefik OSS in Production? Add enterprise-grade API Gateway and API Management capabilities to your existing deployments seamlessly. No rip and replace. No learning curve. Learn more from [this short video](https://info.traefik.io/traefik-upgrade-walkthrough) Using Traefik OSS in Production? Consider our enterprise-grade [API Gateway](https://traefik.io/traefik-hub-api-gateway/), [API Management](https://traefik.io/traefik-hub/), and [Commercial Support](https://info.traefik.io/request-commercial-support) solutions.

View file

@ -591,6 +591,11 @@ Please take a look at the observability documentation for more information:
- [Metrics](../observability/metrics/overview.md#addinternals) - [Metrics](../observability/metrics/overview.md#addinternals)
- [Tracing](../observability/tracing/overview.md#addinternals) - [Tracing](../observability/tracing/overview.md#addinternals)
#### Access logs
In v3, the `ServiceURL` field is not an object anymore but a string representation.
An update may be required if you index access logs.
## Dynamic Configuration Changes ## Dynamic Configuration Changes
### Router Rule Matchers ### Router Rule Matchers

View file

@ -455,7 +455,7 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
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/) of the specification and 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/) of the specification and
[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. [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. Therefore, the RBAC and CRD definitions must be updated.
## v2.6.0 to v2.6.1 ## v2.6.0 to v2.6.1

View file

@ -10,9 +10,11 @@ description: "Learn the steps needed to migrate to new Traefik Proxy v3 versions
### Kubernetes Provider RBACs ### Kubernetes Provider RBACs
Starting with v3.1, the Kubernetes Providers now use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (Kubernetes >=v1.21) to discover service endpoint addresses. Starting with v3.1, the Kubernetes Providers now use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (Kubernetes >=v1.21) to discover service endpoint addresses.
It also brings NodePort load-balancing which requires Nodes resources lookup.
Therefore, in the corresponding RBACs (see [KubernetesIngress](../routing/providers/kubernetes-ingress.md#configuration-example), [KubernetesCRD](../reference/dynamic-configuration/kubernetes-crd.md#rbac), and [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs), Therefore, in the corresponding RBACs (see [KubernetesIngress](../routing/providers/kubernetes-ingress.md#configuration-example), [KubernetesCRD](../reference/dynamic-configuration/kubernetes-crd.md#rbac), and [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway-rbac.yml) provider RBACs):
the `endpoints` right has to be removed and the following `endpointslices` right has to be added.
- the `endpoints` right has to be removed and the following `endpointslices` right has to be added:
```yaml ```yaml
... ...
@ -26,6 +28,21 @@ the `endpoints` right has to be removed and the following `endpointslices` right
... ...
``` ```
- the `nodes` right has to be added:
```yaml
...
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
...
```
#### Gateway API: KubernetesGateway Provider #### Gateway API: KubernetesGateway Provider
In v3.1, the KubernetesGateway Provider is no longer an experimental feature. In v3.1, the KubernetesGateway Provider is no longer an experimental feature.
@ -51,3 +68,10 @@ It can be enabled without the associated `experimental.kubernetesgateway` option
The `kubernetesgateway` option should be removed from the experimental section of the static configuration. The `kubernetesgateway` option should be removed from the experimental section of the static configuration.
To configure `kubernetesgateway`, please check out the [KubernetesGateway Provider documentation](../providers/kubernetes-gateway.md). To configure `kubernetesgateway`, please check out the [KubernetesGateway Provider documentation](../providers/kubernetes-gateway.md).
## v3.1.0 to v3.1.1
### IngressClass Lookup
The Kubernetes Ingress provider option `disableIngressClassLookup` has been deprecated in v3.1.1, and will be removed in the next major version.
Please use the `disableClusterScopeResources` option instead to avoid cluster scope resources discovery (IngressClass, Nodes).

View file

@ -84,8 +84,9 @@ Defines custom headers to be sent to the endpoint.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
providers: providers:
headers: http:
name: value headers:
name: value
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -95,6 +96,7 @@ providers:
```bash tab="CLI" ```bash tab="CLI"
--providers.http.headers.name=value --providers.http.headers.name=value
```
### `tls` ### `tls`

View file

@ -8,7 +8,7 @@ description: "Learn how to use the Kubernetes Gateway API as a provider for conf
The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/) The Kubernetes Gateway provider is a Traefik implementation of the [Gateway API](https://gateway-api.sigs.k8s.io/)
specification from the Kubernetes Special Interest Groups (SIGs). specification from the Kubernetes Special Interest Groups (SIGs).
This provider supports version [v1.1.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0) of the Gateway API specification. This provider supports Standard version [v1.1.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0) of the Gateway API specification.
It fully supports all HTTP core and some extended features, as well as the `TCPRoute` and `TLSRoute` resources from the [Experimental channel](https://gateway-api.sigs.k8s.io/concepts/versioning/?h=#release-channels). It fully supports all HTTP core and some extended features, as well as the `TCPRoute` and `TLSRoute` resources from the [Experimental channel](https://gateway-api.sigs.k8s.io/concepts/versioning/?h=#release-channels).
@ -26,10 +26,10 @@ For more details, check out the conformance [report](https://github.com/kubernet
1. Install/update the Kubernetes Gateway API CRDs. 1. Install/update the Kubernetes Gateway API CRDs.
```bash ```bash
# Install Gateway API CRDs from the Experimental channel. # Install Gateway API CRDs from the Standard channel.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/experimental-install.yaml kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
``` ```
2. Install/update the Traefik [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac). 2. Install/update the Traefik [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac).
```bash ```bash
@ -38,7 +38,7 @@ For more details, check out the conformance [report](https://github.com/kubernet
``` ```
3. Deploy Traefik and enable the `kubernetesGateway` provider in the static configuration as detailed below: 3. Deploy Traefik and enable the `kubernetesGateway` provider in the static configuration as detailed below:
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
providers: providers:
kubernetesGateway: {} kubernetesGateway: {}
@ -269,6 +269,15 @@ providers:
--providers.kubernetesgateway.experimentalchannel=true --providers.kubernetesgateway.experimentalchannel=true
``` ```
!!! info "Experimental Channel"
When enabling experimental channel resources support, the experimental CRDs (Custom Resource Definitions) needs to be deployed too.
```bash
# Install Gateway API CRDs from the Experimental channel.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/experimental-install.yaml
```
### `labelselector` ### `labelselector`
_Optional, Default: ""_ _Optional, Default: ""_

View file

@ -287,6 +287,11 @@ providers:
_Optional, Default: false_ _Optional, Default: false_
??? warning "Deprecated"
The Kubernetes Ingress provider option `disableIngressClassLookup` has been deprecated in v3.1, and will be removed in the next major version.
Please use the `disableClusterScopeResources` option instead.
If the parameter is set to `true`, If the parameter is set to `true`,
Traefik will not discover IngressClasses in the cluster. Traefik will not discover IngressClasses in the cluster.
By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up. By doing so, it alleviates the requirement of giving Traefik the rights to look IngressClasses up.
@ -312,6 +317,33 @@ providers:
--providers.kubernetesingress.disableingressclasslookup=true --providers.kubernetesingress.disableingressclasslookup=true
``` ```
### `disableClusterScopeResources`
_Optional, Default: false_
When this parameter is set to `true`,
Traefik will not discover cluster scope resources (`IngressClass` and `Nodes`).
By doing so, it alleviates the requirement of giving Traefik the rights to look up for cluster resources.
Furthermore, Traefik will not handle Ingresses with IngressClass references, therefore such Ingresses will be ignored (please note that annotations are not affected by this option).
This will also prevent from using the `NodePortLB` options on services.
```yaml tab="File (YAML)"
providers:
kubernetesIngress:
disableClusterScopeResources: true
# ...
```
```toml tab="File (TOML)"
[providers.kubernetesIngress]
disableClusterScopeResources = true
# ...
```
```bash tab="CLI"
--providers.kubernetesingress.disableClusterScopeResources=true
```
### `ingressEndpoint` ### `ingressEndpoint`
#### `hostname` #### `hostname`

View file

@ -732,6 +732,9 @@ Allow ExternalName services. (Default: ```false```)
`--providers.kubernetescrd.certauthfilepath`: `--providers.kubernetescrd.certauthfilepath`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`--providers.kubernetescrd.disableclusterscoperesources`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`--providers.kubernetescrd.endpoint`: `--providers.kubernetescrd.endpoint`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).
@ -804,8 +807,11 @@ Allow ExternalName services. (Default: ```false```)
`--providers.kubernetesingress.certauthfilepath`: `--providers.kubernetesingress.certauthfilepath`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`--providers.kubernetesingress.disableclusterscoperesources`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`--providers.kubernetesingress.disableingressclasslookup`: `--providers.kubernetesingress.disableingressclasslookup`:
Disables the lookup of IngressClasses. (Default: ```false```) Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources). (Default: ```false```)
`--providers.kubernetesingress.endpoint`: `--providers.kubernetesingress.endpoint`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).

View file

@ -732,6 +732,9 @@ Allow ExternalName services. (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESCRD_CERTAUTHFILEPATH`: `TRAEFIK_PROVIDERS_KUBERNETESCRD_CERTAUTHFILEPATH`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`TRAEFIK_PROVIDERS_KUBERNETESCRD_DISABLECLUSTERSCOPERESOURCES`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESCRD_ENDPOINT`: `TRAEFIK_PROVIDERS_KUBERNETESCRD_ENDPOINT`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).
@ -804,8 +807,11 @@ Allow ExternalName services. (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_CERTAUTHFILEPATH`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_CERTAUTHFILEPATH`:
Kubernetes certificate authority file path (not needed for in-cluster client). Kubernetes certificate authority file path (not needed for in-cluster client).
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLECLUSTERSCOPERESOURCES`:
Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLEINGRESSCLASSLOOKUP`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_DISABLEINGRESSCLASSLOOKUP`:
Disables the lookup of IngressClasses. (Default: ```false```) Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources). (Default: ```false```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_ENDPOINT`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_ENDPOINT`:
Kubernetes server endpoint (required for external cluster client). Kubernetes server endpoint (required for external cluster client).

View file

@ -128,6 +128,7 @@
allowEmptyServices = true allowEmptyServices = true
allowExternalNameServices = true allowExternalNameServices = true
disableIngressClassLookup = true disableIngressClassLookup = true
disableClusterScopeResources = true
nativeLBByDefault = true nativeLBByDefault = true
[providers.kubernetesIngress.ingressEndpoint] [providers.kubernetesIngress.ingressEndpoint]
ip = "foobar" ip = "foobar"
@ -145,6 +146,7 @@
throttleDuration = "42s" throttleDuration = "42s"
allowEmptyServices = true allowEmptyServices = true
nativeLBByDefault = true nativeLBByDefault = true
disableClusterScopeResources = true
[providers.kubernetesGateway] [providers.kubernetesGateway]
endpoint = "foobar" endpoint = "foobar"
token = "foobar" token = "foobar"

View file

@ -145,6 +145,7 @@ providers:
allowEmptyServices: true allowEmptyServices: true
allowExternalNameServices: true allowExternalNameServices: true
disableIngressClassLookup: true disableIngressClassLookup: true
disableClusterScopeResources: true
nativeLBByDefault: true nativeLBByDefault: true
kubernetesCRD: kubernetesCRD:
endpoint: foobar endpoint: foobar
@ -160,6 +161,7 @@ providers:
throttleDuration: 42s throttleDuration: 42s
allowEmptyServices: true allowEmptyServices: true
nativeLBByDefault: true nativeLBByDefault: true
disableClusterScopeResources: true
kubernetesGateway: kubernetesGateway:
endpoint: foobar endpoint: foobar
token: foobar token: foobar

20
go.mod
View file

@ -12,8 +12,8 @@ require (
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd // No tag on the repo. github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd // No tag on the repo.
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // No tag on the repo. github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // No tag on the repo.
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/docker/cli v24.0.9+incompatible github.com/docker/cli v27.1.1+incompatible
github.com/docker/docker v27.0.3+incompatible github.com/docker/docker v27.1.1+incompatible
github.com/docker/go-connections v0.5.0 github.com/docker/go-connections v0.5.0
github.com/fatih/structs v1.1.0 github.com/fatih/structs v1.1.0
github.com/fsnotify/fsnotify v1.7.0 github.com/fsnotify/fsnotify v1.7.0
@ -22,7 +22,7 @@ require (
github.com/go-kit/log v0.2.1 github.com/go-kit/log v0.2.1
github.com/golang/protobuf v1.5.4 github.com/golang/protobuf v1.5.4
github.com/google/go-github/v28 v28.1.1 github.com/google/go-github/v28 v28.1.1
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
github.com/hashicorp/consul/api v1.26.1 github.com/hashicorp/consul/api v1.26.1
github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-hclog v1.6.3
@ -34,7 +34,7 @@ require (
github.com/influxdata/influxdb-client-go/v2 v2.7.0 github.com/influxdata/influxdb-client-go/v2 v2.7.0
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // No tag on the repo. github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // No tag on the repo.
github.com/juliens/wasm-goexport v0.0.6 github.com/juliens/wasm-goexport v0.0.6
github.com/klauspost/compress v1.17.4 github.com/klauspost/compress v1.17.9
github.com/kvtools/consul v1.0.2 github.com/kvtools/consul v1.0.2
github.com/kvtools/etcdv3 v1.0.2 github.com/kvtools/etcdv3 v1.0.2
github.com/kvtools/redis v1.1.0 github.com/kvtools/redis v1.1.0
@ -129,7 +129,7 @@ require (
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.11.5 // indirect github.com/Microsoft/hcsshim v0.11.7 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/VividCortex/gohistogram v1.0.0 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
@ -157,9 +157,9 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/civo/civogo v0.3.11 // indirect github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/cloudflare-go v0.97.0 // indirect github.com/cloudflare/cloudflare-go v0.97.0 // indirect
github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/containerd v1.7.20 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect
@ -194,7 +194,7 @@ require (
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/goccy/go-json v0.10.3 // indirect github.com/goccy/go-json v0.10.3 // indirect
github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/flock v0.12.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
@ -255,7 +255,7 @@ require (
github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect github.com/moby/sys/user v0.2.0 // indirect
github.com/moby/term v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
@ -287,7 +287,7 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/otp v1.4.0 // indirect github.com/pquerna/otp v1.4.0 // indirect
github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect
github.com/rs/cors v1.7.0 // indirect github.com/rs/cors v1.7.0 // indirect

35
go.sum
View file

@ -82,8 +82,8 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exYU38= github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
@ -192,12 +192,12 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ=
github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0=
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd h1:0n+lFLh5zU0l6KSk3KpnDwfbPGAR44aRLgTbCnhRBHU= github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd h1:0n+lFLh5zU0l6KSk3KpnDwfbPGAR44aRLgTbCnhRBHU=
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd/go.mod h1:BbQgeDS5i0tNvypwEoF1oNjOJw8knRAE1DnVvjDstcQ= github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd/go.mod h1:BbQgeDS5i0tNvypwEoF1oNjOJw8knRAE1DnVvjDstcQ=
github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTEzDZc1Fhmd0Pq06c+O9+KkAyExw0eVmu/NOqaHU= github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTEzDZc1Fhmd0Pq06c+O9+KkAyExw0eVmu/NOqaHU=
@ -247,10 +247,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY= github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8= github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
github.com/docker/cli v24.0.9+incompatible h1:OxbimnP/z+qVjDLpq9wbeFU3Nc30XhSe+LkwYQisD50= github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE=
github.com/docker/cli v24.0.9+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@ -377,8 +377,9 @@ github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGF
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/flock v0.12.0 h1:xHW8t8GPAiGtqz7KxiSqfOEXwpOaqhpYZrTE2MQBgXY=
github.com/gofrs/flock v0.12.0/go.mod h1:FirDy1Ing0mI2+kB6wk+vyyAH+e6xiE+EYA0jnzV9jc=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -599,8 +600,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@ -742,8 +743,8 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM=
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -872,8 +873,8 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=

View file

@ -204,16 +204,17 @@ func (c *configuration) deprecationNotice(logger zerolog.Logger) bool {
} }
type providers struct { type providers struct {
Docker *docker `json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" label:"allowEmpty" file:"allowEmpty"` Docker *docker `json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" label:"allowEmpty" file:"allowEmpty"`
Swarm *swarm `json:"swarm,omitempty" toml:"swarm,omitempty" yaml:"swarm,omitempty" label:"allowEmpty" file:"allowEmpty"` Swarm *swarm `json:"swarm,omitempty" toml:"swarm,omitempty" yaml:"swarm,omitempty" label:"allowEmpty" file:"allowEmpty"`
Consul *consul `json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" label:"allowEmpty" file:"allowEmpty"` Consul *consul `json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" label:"allowEmpty" file:"allowEmpty"`
ConsulCatalog *consulCatalog `json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty"` ConsulCatalog *consulCatalog `json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty"`
Nomad *nomad `json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty"` Nomad *nomad `json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty"`
Marathon map[string]any `json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" label:"allowEmpty" file:"allowEmpty"` Marathon map[string]any `json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" label:"allowEmpty" file:"allowEmpty"`
Rancher map[string]any `json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" label:"allowEmpty" file:"allowEmpty"` Rancher map[string]any `json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" label:"allowEmpty" file:"allowEmpty"`
ETCD *etcd `json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" label:"allowEmpty" file:"allowEmpty"` ETCD *etcd `json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" label:"allowEmpty" file:"allowEmpty"`
Redis *redis `json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" label:"allowEmpty" file:"allowEmpty"` Redis *redis `json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" label:"allowEmpty" file:"allowEmpty"`
HTTP *http `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" label:"allowEmpty" file:"allowEmpty"` HTTP *http `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" label:"allowEmpty" file:"allowEmpty"`
KubernetesIngress *ingress `json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" file:"allowEmpty"`
} }
func (p *providers) deprecationNotice(logger zerolog.Logger) bool { func (p *providers) deprecationNotice(logger zerolog.Logger) bool {
@ -243,6 +244,7 @@ func (p *providers) deprecationNotice(logger zerolog.Logger) bool {
etcdIncompatible := p.ETCD.deprecationNotice(logger) etcdIncompatible := p.ETCD.deprecationNotice(logger)
redisIncompatible := p.Redis.deprecationNotice(logger) redisIncompatible := p.Redis.deprecationNotice(logger)
httpIncompatible := p.HTTP.deprecationNotice(logger) httpIncompatible := p.HTTP.deprecationNotice(logger)
p.KubernetesIngress.deprecationNotice(logger)
return incompatible || return incompatible ||
dockerIncompatible || dockerIncompatible ||
consulIncompatible || consulIncompatible ||
@ -457,6 +459,22 @@ func (h *http) deprecationNotice(logger zerolog.Logger) bool {
return incompatible return incompatible
} }
type ingress struct {
DisableIngressClassLookup *bool `json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty"`
}
func (i *ingress) deprecationNotice(logger zerolog.Logger) {
if i == nil {
return
}
if i.DisableIngressClassLookup != nil {
logger.Error().Msg("Kubernetes Ingress provider `disableIngressClassLookup` option has been deprecated in v3.1, and will be removed in the next major version." +
"Please use the `disableClusterScopeResources` option instead." +
"For more information please read the migration guide: https://doc.traefik.io/traefik/v3.1/migration/v3/#ingressclasslookup")
}
}
type experimental struct { type experimental struct {
HTTP3 *bool `json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty"` HTTP3 *bool `json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty"`
KubernetesGateway *bool `json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty"` KubernetesGateway *bool `json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty"`

View file

@ -1,22 +1,22 @@
package docker package docker
import ( import (
docker "github.com/docker/docker/api/types" dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
) )
func containerJSON(ops ...func(*docker.ContainerJSON)) docker.ContainerJSON { func containerJSON(ops ...func(*dockertypes.ContainerJSON)) dockertypes.ContainerJSON {
c := &docker.ContainerJSON{ c := &dockertypes.ContainerJSON{
ContainerJSONBase: &docker.ContainerJSONBase{ ContainerJSONBase: &dockertypes.ContainerJSONBase{
Name: "fake", Name: "fake",
HostConfig: &container.HostConfig{}, HostConfig: &container.HostConfig{},
}, },
Config: &container.Config{}, Config: &container.Config{},
NetworkSettings: &docker.NetworkSettings{ NetworkSettings: &dockertypes.NetworkSettings{
NetworkSettingsBase: docker.NetworkSettingsBase{}, NetworkSettingsBase: dockertypes.NetworkSettingsBase{},
}, },
} }
@ -27,34 +27,34 @@ func containerJSON(ops ...func(*docker.ContainerJSON)) docker.ContainerJSON {
return *c return *c
} }
func name(name string) func(*docker.ContainerJSON) { func name(name string) func(*dockertypes.ContainerJSON) {
return func(c *docker.ContainerJSON) { return func(c *dockertypes.ContainerJSON) {
c.ContainerJSONBase.Name = name c.ContainerJSONBase.Name = name
} }
} }
func networkMode(mode string) func(*docker.ContainerJSON) { func networkMode(mode string) func(*dockertypes.ContainerJSON) {
return func(c *docker.ContainerJSON) { return func(c *dockertypes.ContainerJSON) {
c.ContainerJSONBase.HostConfig.NetworkMode = container.NetworkMode(mode) c.ContainerJSONBase.HostConfig.NetworkMode = container.NetworkMode(mode)
} }
} }
func nodeIP(ip string) func(*docker.ContainerJSON) { func nodeIP(ip string) func(*dockertypes.ContainerJSON) {
return func(c *docker.ContainerJSON) { return func(c *dockertypes.ContainerJSON) {
c.ContainerJSONBase.Node = &docker.ContainerNode{ c.ContainerJSONBase.Node = &dockertypes.ContainerNode{
IPAddress: ip, IPAddress: ip,
} }
} }
} }
func ports(portMap nat.PortMap) func(*docker.ContainerJSON) { func ports(portMap nat.PortMap) func(*dockertypes.ContainerJSON) {
return func(c *docker.ContainerJSON) { return func(c *dockertypes.ContainerJSON) {
c.NetworkSettings.NetworkSettingsBase.Ports = portMap c.NetworkSettings.NetworkSettingsBase.Ports = portMap
} }
} }
func withNetwork(name string, ops ...func(*network.EndpointSettings)) func(*docker.ContainerJSON) { func withNetwork(name string, ops ...func(*network.EndpointSettings)) func(*dockertypes.ContainerJSON) {
return func(c *docker.ContainerJSON) { return func(c *dockertypes.ContainerJSON) {
if c.NetworkSettings.Networks == nil { if c.NetworkSettings.Networks == nil {
c.NetworkSettings.Networks = map[string]*network.EndpointSettings{} c.NetworkSettings.Networks = map[string]*network.EndpointSettings{}
} }

View file

@ -7,6 +7,7 @@ import (
"time" "time"
docker "github.com/docker/docker/api/types" docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -3972,12 +3973,12 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) {
testCases := []struct { testCases := []struct {
service swarm.Service service swarm.Service
expected string expected string
networks map[string]*docker.NetworkResource networks map[string]*network.Summary
}{ }{
{ {
service: swarmService(withEndpointSpec(modeDNSSR)), service: swarmService(withEndpointSpec(modeDNSSR)),
expected: "", expected: "",
networks: map[string]*docker.NetworkResource{}, networks: map[string]*network.Summary{},
}, },
{ {
service: swarmService( service: swarmService(
@ -3985,7 +3986,7 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) {
withEndpoint(virtualIP("1", "10.11.12.13/24")), withEndpoint(virtualIP("1", "10.11.12.13/24")),
), ),
expected: "10.11.12.13", expected: "10.11.12.13",
networks: map[string]*docker.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "foo", Name: "foo",
}, },
@ -4003,7 +4004,7 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) {
), ),
), ),
expected: "10.11.12.99", expected: "10.11.12.99",
networks: map[string]*docker.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "foonet", Name: "foonet",
}, },

View file

@ -6,7 +6,7 @@ import (
"testing" "testing"
"time" "time"
dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -18,7 +18,7 @@ func TestListTasks(t *testing.T) {
tasks []swarm.Task tasks []swarm.Task
isGlobalSVC bool isGlobalSVC bool
expectedTasks []string expectedTasks []string
networks map[string]*dockertypes.NetworkResource networks map[string]*network.Summary
}{ }{
{ {
service: swarmService(serviceName("container")), service: swarmService(serviceName("container")),
@ -53,7 +53,7 @@ func TestListTasks(t *testing.T) {
"container.1", "container.1",
"container.4", "container.4",
}, },
networks: map[string]*dockertypes.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "foo", Name: "foo",
}, },
@ -91,7 +91,7 @@ func TestSwarmProvider_listServices(t *testing.T) {
services []swarm.Service services []swarm.Service
tasks []swarm.Task tasks []swarm.Task
dockerVersion string dockerVersion string
networks []dockertypes.NetworkResource networks []network.Summary
expectedServices []string expectedServices []string
}{ }{
{ {
@ -117,7 +117,7 @@ func TestSwarmProvider_listServices(t *testing.T) {
withEndpointSpec(modeDNSSR)), withEndpointSpec(modeDNSSR)),
}, },
dockerVersion: "1.30", dockerVersion: "1.30",
networks: []dockertypes.NetworkResource{}, networks: []network.Summary{},
expectedServices: []string{}, expectedServices: []string{},
}, },
{ {
@ -143,7 +143,7 @@ func TestSwarmProvider_listServices(t *testing.T) {
withEndpointSpec(modeDNSSR)), withEndpointSpec(modeDNSSR)),
}, },
dockerVersion: "1.30", dockerVersion: "1.30",
networks: []dockertypes.NetworkResource{ networks: []network.Summary{
{ {
Name: "network_name", Name: "network_name",
ID: "yk6l57rfwizjzxxzftn4amaot", ID: "yk6l57rfwizjzxxzftn4amaot",
@ -198,7 +198,7 @@ func TestSwarmProvider_listServices(t *testing.T) {
), ),
}, },
dockerVersion: "1.30", dockerVersion: "1.30",
networks: []dockertypes.NetworkResource{ networks: []network.Summary{
{ {
Name: "network_name", Name: "network_name",
ID: "yk6l57rfwizjzxxzftn4amaot", ID: "yk6l57rfwizjzxxzftn4amaot",
@ -255,7 +255,7 @@ func TestSwarmProvider_parseService_task(t *testing.T) {
tasks []swarm.Task tasks []swarm.Task
isGlobalSVC bool isGlobalSVC bool
expected map[string]dockerData expected map[string]dockerData
networks map[string]*dockertypes.NetworkResource networks map[string]*network.Summary
}{ }{
{ {
service: swarmService(serviceName("container")), service: swarmService(serviceName("container")),
@ -276,7 +276,7 @@ func TestSwarmProvider_parseService_task(t *testing.T) {
Name: "container.3", Name: "container.3",
}, },
}, },
networks: map[string]*dockertypes.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "foo", Name: "foo",
}, },
@ -301,7 +301,7 @@ func TestSwarmProvider_parseService_task(t *testing.T) {
Name: "container.id3", Name: "container.id3",
}, },
}, },
networks: map[string]*dockertypes.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "foo", Name: "foo",
}, },
@ -339,7 +339,7 @@ func TestSwarmProvider_parseService_task(t *testing.T) {
}, },
}, },
}, },
networks: map[string]*dockertypes.NetworkResource{ networks: map[string]*network.Summary{
"1": { "1": {
Name: "vlan", Name: "vlan",
}, },

View file

@ -57,10 +57,12 @@ type clientWrapper struct {
csCrd traefikclientset.Interface csCrd traefikclientset.Interface
csKube kclientset.Interface csKube kclientset.Interface
factoryClusterScope kinformers.SharedInformerFactory clusterScopeFactory kinformers.SharedInformerFactory
factoriesCrd map[string]traefikinformers.SharedInformerFactory disableClusterScopeInformer bool
factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory factoriesCrd map[string]traefikinformers.SharedInformerFactory
factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory
labelSelector string labelSelector string
@ -237,18 +239,11 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
c.factoriesSecret[ns] = factorySecret c.factoriesSecret[ns] = factorySecret
} }
c.factoryClusterScope = kinformers.NewSharedInformerFactory(c.csKube, resyncPeriod)
_, err := c.factoryClusterScope.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
for _, ns := range namespaces { for _, ns := range namespaces {
c.factoriesCrd[ns].Start(stopCh) c.factoriesCrd[ns].Start(stopCh)
c.factoriesKube[ns].Start(stopCh) c.factoriesKube[ns].Start(stopCh)
c.factoriesSecret[ns].Start(stopCh) c.factoriesSecret[ns].Start(stopCh)
} }
c.factoryClusterScope.Start(stopCh)
for _, ns := range namespaces { for _, ns := range namespaces {
for t, ok := range c.factoriesCrd[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesCrd[ns].WaitForCacheSync(stopCh) {
@ -270,9 +265,19 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
} }
for t, ok := range c.factoryClusterScope.WaitForCacheSync(stopCh) { if !c.disableClusterScopeInformer {
if !ok { c.clusterScopeFactory = kinformers.NewSharedInformerFactory(c.csKube, resyncPeriod)
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String()) _, err := c.clusterScopeFactory.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.clusterScopeFactory.Start(stopCh)
for t, ok := range c.clusterScopeFactory.WaitForCacheSync(stopCh) {
if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
}
} }
} }
@ -474,7 +479,7 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
} }
func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) { func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) {
nodes, err := c.factoryClusterScope.Core().V1().Nodes().Lister().List(labels.Everything()) nodes, err := c.clusterScopeFactory.Core().V1().Nodes().Lister().List(labels.Everything())
exist, err := translateNotFoundError(err) exist, err := translateNotFoundError(err)
return nodes, exist, err return nodes, exist, err
} }

View file

@ -50,17 +50,18 @@ const (
// Provider holds configurations of the provider. // Provider holds configurations of the provider.
type Provider struct { type Provider struct {
Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` Endpoint string `description:"Kubernetes server endpoint (required for external cluster client)." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` Token types.FileOrContent `description:"Kubernetes bearer token (not needed for in-cluster client). It accepts either a token value or a file path to the token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"`
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"` CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"` Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
AllowCrossNamespace bool `description:"Allow cross namespace resource reference." json:"allowCrossNamespace,omitempty" toml:"allowCrossNamespace,omitempty" yaml:"allowCrossNamespace,omitempty" export:"true"` AllowCrossNamespace bool `description:"Allow cross namespace resource reference." json:"allowCrossNamespace,omitempty" toml:"allowCrossNamespace,omitempty" yaml:"allowCrossNamespace,omitempty" export:"true"`
AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"`
LabelSelector string `description:"Kubernetes label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"` LabelSelector string `description:"Kubernetes label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"` IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"`
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
AllowEmptyServices bool `description:"Allow the creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow the creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"`
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"` NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
lastConfiguration safe.Safe lastConfiguration safe.Safe
@ -112,6 +113,7 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) {
} }
client.labelSelector = p.LabelSelector client.labelSelector = p.LabelSelector
client.disableClusterScopeInformer = p.DisableClusterScopeResources
return client, nil return client, nil
} }

View file

@ -51,11 +51,12 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
} }
cb := configBuilder{ cb := configBuilder{
client: client, client: client,
allowCrossNamespace: p.AllowCrossNamespace, allowCrossNamespace: p.AllowCrossNamespace,
allowExternalNameServices: p.AllowExternalNameServices, allowExternalNameServices: p.AllowExternalNameServices,
allowEmptyServices: p.AllowEmptyServices, allowEmptyServices: p.AllowEmptyServices,
NativeLBByDefault: p.NativeLBByDefault, nativeLBByDefault: p.NativeLBByDefault,
disableClusterScopeResources: p.DisableClusterScopeResources,
} }
for _, route := range ingressRoute.Spec.Routes { for _, route := range ingressRoute.Spec.Routes {
@ -199,11 +200,12 @@ func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace str
} }
type configBuilder struct { type configBuilder struct {
client Client client Client
allowCrossNamespace bool allowCrossNamespace bool
allowExternalNameServices bool allowExternalNameServices bool
allowEmptyServices bool allowEmptyServices bool
NativeLBByDefault bool nativeLBByDefault bool
disableClusterScopeResources bool
} }
// buildTraefikService creates the configuration for the traefik service defined in tService, // buildTraefikService creates the configuration for the traefik service defined in tService,
@ -428,7 +430,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, hostPort)}}, nil return []dynamic.Server{{URL: fmt.Sprintf("%s://%s", protocol, hostPort)}}, nil
} }
nativeLB := c.NativeLBByDefault nativeLB := c.nativeLBByDefault
if svc.NativeLB != nil { if svc.NativeLB != nil {
nativeLB = *svc.NativeLB nativeLB = *svc.NativeLB
} }
@ -448,6 +450,10 @@ func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.L
var servers []dynamic.Server var servers []dynamic.Server
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if c.disableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := c.client.GetNodes() nodes, nodesExists, nodesErr := c.client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -239,6 +239,10 @@ func (p *Provider) loadTCPServers(client Client, namespace string, svc traefikv1
var servers []dynamic.TCPServer var servers []dynamic.TCPServer
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -7446,10 +7446,10 @@ func TestNativeLB(t *testing.T) {
func TestNodePortLB(t *testing.T) { func TestNodePortLB(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingressClass string paths []string
paths []string disableClusterScope bool
expected *dynamic.Configuration expected *dynamic.Configuration
}{ }{
{ {
desc: "Empty", desc: "Empty",
@ -7594,6 +7594,90 @@ func TestNodePortLB(t *testing.T) {
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
}, },
{
desc: "HTTP with node port LB, cluster scope resources disabled",
paths: []string{"services.yml", "with_node_port_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "TCP with native Service LB, cluster scope resources disabled",
paths: []string{"tcp/services.yml", "tcp/with_node_port_service_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{
"default-test.route-fdd3e9338e47a45efefc": {
EntryPoints: []string{"foo"},
Service: "default-test.route-fdd3e9338e47a45efefc",
Rule: "HostSNI(`foo.com`)",
},
},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "UDP with native Service LB, cluster scope resources disabled",
paths: []string{"udp/services.yml", "udp/with_node_port_service_lb.yml"},
disableClusterScope: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{
"default-test.route-0": {
EntryPoints: []string{"foo"},
Service: "default-test.route-0",
},
},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
ServersTransports: map[string]*dynamic.TCPServersTransport{},
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{},
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
} }
for _, test := range testCases { for _, test := range testCases {
@ -7617,7 +7701,9 @@ func TestNodePortLB(t *testing.T) {
<-eventCh <-eventCh
} }
p := Provider{} p := Provider{
DisableClusterScopeResources: test.disableClusterScope,
}
conf := p.loadConfigurationFromCRD(context.Background(), client) conf := p.loadConfigurationFromCRD(context.Background(), client)
assert.Equal(t, test.expected, conf) assert.Equal(t, test.expected, conf)

View file

@ -123,6 +123,10 @@ func (p *Provider) loadUDPServers(client Client, namespace string, svc traefikv1
var servers []dynamic.UDPServer var servers []dynamic.UDPServer
if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB { if service.Spec.Type == corev1.ServiceTypeNodePort && svc.NodePortLB {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -684,32 +684,9 @@ func translateNotFoundError(err error) (bool, error) {
} }
func gatewayStatusEqual(statusA, statusB gatev1.GatewayStatus) bool { func gatewayStatusEqual(statusA, statusB gatev1.GatewayStatus) bool {
if len(statusA.Listeners) != len(statusB.Listeners) { return reflect.DeepEqual(statusA.Addresses, statusB.Addresses) &&
return false listenersStatusEqual(statusA.Listeners, statusB.Listeners) &&
} conditionsEqual(statusA.Conditions, statusB.Conditions)
if !conditionsEqual(statusA.Conditions, statusB.Conditions) {
return false
}
listenerMatches := 0
for _, newListener := range statusB.Listeners {
for _, oldListener := range statusA.Listeners {
if newListener.Name == oldListener.Name {
if !conditionsEqual(newListener.Conditions, oldListener.Conditions) {
return false
}
if newListener.AttachedRoutes != oldListener.AttachedRoutes {
return false
}
listenerMatches++
}
}
}
return listenerMatches == len(statusA.Listeners)
} }
func routeParentStatusesEqual(routeParentStatusesA, routeParentStatusesB []gatev1alpha2.RouteParentStatus) bool { func routeParentStatusesEqual(routeParentStatusesA, routeParentStatusesB []gatev1alpha2.RouteParentStatus) bool {
@ -737,15 +714,17 @@ func routeParentStatusesEqual(routeParentStatusesA, routeParentStatusesB []gatev
} }
func routeParentStatusEqual(sA, sB gatev1alpha2.RouteParentStatus) bool { func routeParentStatusEqual(sA, sB gatev1alpha2.RouteParentStatus) bool {
if !reflect.DeepEqual(sA.ParentRef, sB.ParentRef) { return sA.ControllerName == sB.ControllerName &&
return false reflect.DeepEqual(sA.ParentRef, sB.ParentRef) &&
} conditionsEqual(sA.Conditions, sB.Conditions)
}
if sA.ControllerName != sB.ControllerName { func listenersStatusEqual(listenerA, listenerB []gatev1.ListenerStatus) bool {
return false return slices.EqualFunc(listenerA, listenerB, func(lA gatev1.ListenerStatus, lB gatev1.ListenerStatus) bool {
} return lA.Name == lB.Name &&
lA.AttachedRoutes == lB.AttachedRoutes &&
return conditionsEqual(sA.Conditions, sB.Conditions) conditionsEqual(lA.Conditions, lB.Conditions)
})
} }
func conditionsEqual(conditionsA, conditionsB []metav1.Condition) bool { func conditionsEqual(conditionsA, conditionsB []metav1.Condition) bool {

View file

@ -49,14 +49,14 @@ type Client interface {
type clientWrapper struct { type clientWrapper struct {
clientset kclientset.Interface clientset kclientset.Interface
factoryClusterScope kinformers.SharedInformerFactory clusterScopeFactory kinformers.SharedInformerFactory
factoriesKube map[string]kinformers.SharedInformerFactory factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]kinformers.SharedInformerFactory factoriesSecret map[string]kinformers.SharedInformerFactory
factoriesIngress map[string]kinformers.SharedInformerFactory factoriesIngress map[string]kinformers.SharedInformerFactory
clusterFactory kinformers.SharedInformerFactory
ingressLabelSelector string ingressLabelSelector string
isNamespaceAll bool isNamespaceAll bool
disableIngressClassInformer bool disableIngressClassInformer bool // Deprecated.
disableClusterScopeInformer bool
watchedNamespaces []string watchedNamespaces []string
serverVersion *version.Version serverVersion *version.Version
} }
@ -201,58 +201,52 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
c.factoriesSecret[ns] = factorySecret c.factoriesSecret[ns] = factorySecret
} }
c.factoryClusterScope = kinformers.NewSharedInformerFactory(c.clientset, resyncPeriod)
_, err = c.factoryClusterScope.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
for _, ns := range namespaces { for _, ns := range namespaces {
c.factoriesIngress[ns].Start(stopCh) c.factoriesIngress[ns].Start(stopCh)
c.factoriesKube[ns].Start(stopCh) c.factoriesKube[ns].Start(stopCh)
c.factoriesSecret[ns].Start(stopCh) c.factoriesSecret[ns].Start(stopCh)
} }
c.factoryClusterScope.Start(stopCh)
for _, ns := range namespaces { for _, ns := range namespaces {
for typ, ok := range c.factoriesIngress[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesIngress[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
for typ, ok := range c.factoriesKube[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesKube[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
for typ, ok := range c.factoriesSecret[ns].WaitForCacheSync(stopCh) { for t, ok := range c.factoriesSecret[ns].WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", typ, ns) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s in namespace %q", t.String(), ns)
} }
} }
} }
for t, ok := range c.factoryClusterScope.WaitForCacheSync(stopCh) { if !c.disableIngressClassInformer || !c.disableClusterScopeInformer {
if !ok { c.clusterScopeFactory = kinformers.NewSharedInformerFactory(c.clientset, resyncPeriod)
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
}
}
if !c.disableIngressClassInformer { _, err = c.clusterScopeFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler)
c.clusterFactory = kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod)
_, err = c.clusterFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.clusterFactory.Start(stopCh) if !c.disableClusterScopeInformer {
_, err = c.clusterScopeFactory.Core().V1().Nodes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
}
for typ, ok := range c.clusterFactory.WaitForCacheSync(stopCh) { c.clusterScopeFactory.Start(stopCh)
for t, ok := range c.clusterScopeFactory.WaitForCacheSync(stopCh) {
if !ok { if !ok {
return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", typ) return nil, fmt.Errorf("timed out waiting for controller caches to sync %s", t.String())
} }
} }
} }
@ -370,18 +364,18 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
} }
func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) { func (c *clientWrapper) GetNodes() ([]*corev1.Node, bool, error) {
nodes, err := c.factoryClusterScope.Core().V1().Nodes().Lister().List(labels.Everything()) nodes, err := c.clusterScopeFactory.Core().V1().Nodes().Lister().List(labels.Everything())
exist, err := translateNotFoundError(err) exist, err := translateNotFoundError(err)
return nodes, exist, err return nodes, exist, err
} }
func (c *clientWrapper) GetIngressClasses() ([]*netv1.IngressClass, error) { func (c *clientWrapper) GetIngressClasses() ([]*netv1.IngressClass, error) {
if c.clusterFactory == nil { if c.clusterScopeFactory == nil {
return nil, errors.New("cluster factory not loaded") return nil, errors.New("cluster factory not loaded")
} }
var ics []*netv1.IngressClass var ics []*netv1.IngressClass
ingressClasses, err := c.clusterFactory.Networking().V1().IngressClasses().Lister().List(labels.Everything()) ingressClasses, err := c.clusterScopeFactory.Networking().V1().IngressClasses().Lister().List(labels.Everything())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -0,0 +1,45 @@
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ""
namespace: testing
spec:
rules:
- host: traefik.tchouk
http:
paths:
- path: /bar
backend:
service:
name: service1
port:
number: 8080
pathType: Prefix
---
kind: Service
apiVersion: v1
metadata:
name: service1
namespace: testing
annotations:
traefik.ingress.kubernetes.io/service.nodeportlb: "true"
spec:
ports:
- port: 8080
nodePort: 32456
clusterIP: 10.0.0.1
type: NodePort
externalName: traefik.wtf
---
kind: Node
apiVersion: v1
metadata:
name: traefik-node
status:
addresses:
- type: InternalIP
address: 172.16.4.4

View file

@ -51,8 +51,10 @@ type Provider struct {
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"` ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"` AllowEmptyServices bool `description:"Allow creation of services without endpoints." json:"allowEmptyServices,omitempty" toml:"allowEmptyServices,omitempty" yaml:"allowEmptyServices,omitempty" export:"true"`
AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"` AllowExternalNameServices bool `description:"Allow ExternalName services." json:"allowExternalNameServices,omitempty" toml:"allowExternalNameServices,omitempty" yaml:"allowExternalNameServices,omitempty" export:"true"`
DisableIngressClassLookup bool `description:"Disables the lookup of IngressClasses." json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty" export:"true"` // Deprecated: please use DisableClusterScopeResources.
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"` DisableIngressClassLookup bool `description:"Disables the lookup of IngressClasses (Deprecated, please use DisableClusterScopeResources)." json:"disableIngressClassLookup,omitempty" toml:"disableIngressClassLookup,omitempty" yaml:"disableIngressClassLookup,omitempty" export:"true"`
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
lastConfiguration safe.Safe lastConfiguration safe.Safe
@ -114,7 +116,8 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) {
} }
cl.ingressLabelSelector = p.LabelSelector cl.ingressLabelSelector = p.LabelSelector
cl.disableIngressClassInformer = p.DisableIngressClassLookup cl.disableIngressClassInformer = p.DisableIngressClassLookup || p.DisableClusterScopeResources
cl.disableClusterScopeInformer = p.DisableClusterScopeResources
return cl, nil return cl, nil
} }
@ -212,7 +215,6 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{}, Services: map[string]*dynamic.Service{},
}, },
TCP: &dynamic.TCPConfiguration{},
} }
var ingressClasses []*netv1.IngressClass var ingressClasses []*netv1.IngressClass
@ -591,6 +593,10 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
} }
if svcConfig.Service.NodePortLB && service.Spec.Type == corev1.ServiceTypeNodePort { if svcConfig.Service.NodePortLB && service.Spec.Type == corev1.ServiceTypeNodePort {
if p.DisableClusterScopeResources {
return nil, errors.New("nodes lookup is disabled")
}
nodes, nodesExists, nodesErr := client.GetNodes() nodes, nodesExists, nodesErr := client.GetNodes()
if nodesErr != nil { if nodesErr != nil {
return nil, nodesErr return nil, nodesErr

View file

@ -35,7 +35,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Empty ingresses", desc: "Empty ingresses",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -46,7 +45,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule host only", desc: "Ingress one rule host only",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -57,7 +55,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path", desc: "Ingress with a basic rule on one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -90,7 +87,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with annotations", desc: "Ingress with annotations",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -148,7 +144,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two different rules with one path", desc: "Ingress with two different rules with one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -185,7 +180,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with conflicting routers on host", desc: "Ingress with conflicting routers on host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -222,7 +216,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with conflicting routers on path", desc: "Ingress with conflicting routers on path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -259,7 +252,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with two paths", desc: "Ingress one rule with two paths",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -296,7 +288,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with one path and one host", desc: "Ingress one rule with one path and one host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -329,7 +320,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with one host without path", desc: "Ingress with one host without path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -359,7 +349,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress one rule with one host and two paths", desc: "Ingress one rule with one host and two paths",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -396,7 +385,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress Two rules with one host and one path", desc: "Ingress Two rules with one host and one path",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -433,7 +421,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two services", desc: "Ingress with two services",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -487,7 +474,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with one service without endpoints subset", desc: "Ingress with one service without endpoints subset",
allowEmptyServices: true, allowEmptyServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -512,7 +498,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with one service without endpoint", desc: "Ingress with one service without endpoint",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -523,7 +508,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Single Service Ingress (without any rules)", desc: "Single Service Ingress (without any rules)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -558,7 +542,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port value in backend and no pod replica", desc: "Ingress with port value in backend and no pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -591,7 +574,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port name in backend and no pod replica", desc: "Ingress with port name in backend and no pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -624,7 +606,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port name in backend and 2 pod replica", desc: "Ingress with port name in backend and 2 pod replica",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -657,7 +638,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with two paths using same service and different port name", desc: "Ingress with two paths using same service and different port name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -710,7 +690,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a named port matching subset of service pods", desc: "Ingress with a named port matching subset of service pods",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -743,7 +722,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "2 ingresses in different namespace with same service name", desc: "2 ingresses in different namespace with same service name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -796,7 +774,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with unknown service port name", desc: "Ingress with unknown service port name",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -807,7 +784,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with unknown service port", desc: "Ingress with unknown service port",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -818,7 +794,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with port invalid for one service", desc: "Ingress with port invalid for one service",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -848,7 +823,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "TLS support", desc: "TLS support",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -889,7 +863,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (port == 443)", desc: "Ingress with a basic rule on one path with https (port == 443)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -922,7 +895,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (portname == https)", desc: "Ingress with a basic rule on one path with https (portname == https)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -955,7 +927,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with a basic rule on one path with https (portname starts with https)", desc: "Ingress with a basic rule on one path with https (portname starts with https)",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
@ -989,7 +960,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Double Single Service Ingress", desc: "Double Single Service Ingress",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1024,7 +994,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with default traefik ingressClass", desc: "Ingress with default traefik ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1054,7 +1023,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress without provider traefik ingressClass and unknown annotation", desc: "Ingress without provider traefik ingressClass and unknown annotation",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1066,7 +1034,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with non matching provider traefik ingressClass and annotation", desc: "Ingress with non matching provider traefik ingressClass and annotation",
ingressClass: "tchouk", ingressClass: "tchouk",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1078,7 +1045,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass without annotation", desc: "Ingress with ingressClass without annotation",
ingressClass: "tchouk", ingressClass: "tchouk",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1090,7 +1056,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass without annotation", desc: "Ingress with ingressClass without annotation",
ingressClass: "toto", ingressClass: "toto",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1101,7 +1066,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with wildcard host", desc: "Ingress with wildcard host",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1133,7 +1097,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with multiple ingressClasses", desc: "Ingress with multiple ingressClasses",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1168,7 +1131,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClasses filter", desc: "Ingress with ingressClasses filter",
ingressClass: "traefik-lb2", ingressClass: "traefik-lb2",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1198,7 +1160,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with prefix pathType", desc: "Ingress with prefix pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1228,7 +1189,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with empty pathType", desc: "Ingress with empty pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1258,7 +1218,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with exact pathType", desc: "Ingress with exact pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1288,7 +1247,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with implementationSpecific pathType", desc: "Ingress with implementationSpecific pathType",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1318,7 +1276,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with ingress annotation", desc: "Ingress with ingress annotation",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1351,7 +1308,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingress annotation", desc: "Ingress with ingress annotation",
disableIngressClassLookup: true, disableIngressClassLookup: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1381,7 +1337,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with ingressClass", desc: "Ingress with ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1414,7 +1369,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
desc: "Ingress with ingressClass", desc: "Ingress with ingressClass",
disableIngressClassLookup: true, disableIngressClassLookup: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1425,7 +1379,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with named port", desc: "Ingress with named port",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1455,7 +1408,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with missing ingressClass", desc: "Ingress with missing ingressClass",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1466,7 +1418,6 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
{ {
desc: "Ingress with defaultbackend", desc: "Ingress with defaultbackend",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1524,7 +1475,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
{ {
desc: "Ingress with service with externalName", desc: "Ingress with service with externalName",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -1536,7 +1486,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
desc: "Ingress with service with externalName enabled", desc: "Ingress with service with externalName enabled",
allowExternalNameServices: true, allowExternalNameServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1566,7 +1515,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
{ {
desc: "Ingress with IPv6 endpoints", desc: "Ingress with IPv6 endpoints",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1597,7 +1545,6 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
desc: "Ingress with IPv6 endpoints externalname enabled", desc: "Ingress with IPv6 endpoints externalname enabled",
allowExternalNameServices: true, allowExternalNameServices: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1650,7 +1597,6 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
{ {
desc: "Ingress with native service lb", desc: "Ingress with native service lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1693,14 +1639,13 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) { func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingressClass string clusterScopeDisabled bool
expected *dynamic.Configuration expected *dynamic.Configuration
}{ }{
{ {
desc: "Ingress with node port lb", desc: "Ingress with node port lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1725,6 +1670,17 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
}, },
}, },
}, },
{
desc: "Ingress with node port lb cluster scope disabled",
clusterScopeDisabled: true,
expected: &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{},
Services: map[string]*dynamic.Service{},
},
},
},
} }
for _, test := range testCases { for _, test := range testCases {
@ -1733,7 +1689,7 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
clientMock := newClientMock(generateTestFilename(test.desc)) clientMock := newClientMock(generateTestFilename(test.desc))
p := Provider{IngressClass: test.ingressClass} p := Provider{DisableClusterScopeResources: test.clusterScopeDisabled}
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock) conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
assert.Equal(t, test.expected, conf) assert.Equal(t, test.expected, conf)
@ -1927,7 +1883,6 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
{ {
desc: "Ingress with native service lb", desc: "Ingress with native service lb",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{
@ -1955,7 +1910,6 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
{ {
desc: "Ingress with native lb by default", desc: "Ingress with native lb by default",
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{ Routers: map[string]*dynamic.Router{

View file

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example new bugfix v3.1.1 # example new bugfix v3.1.2
CurrentRef = "v3.1" CurrentRef = "v3.1"
PreviousRef = "v3.1.0" PreviousRef = "v3.1.1"
BaseBranch = "v3.1" BaseBranch = "v3.1"
FutureCurrentRefName = "v3.1.1" FutureCurrentRefName = "v3.1.2"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10

View file

@ -7,7 +7,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"transfer": "node dev/scripts/transfer.js", "transfer": "node dev/scripts/transfer.js",
"lint": "eslint --ext .js,.vue src", "lint": "eslint src/**/*.{js,vue}",
"dev": "APP_ENV=development quasar dev", "dev": "APP_ENV=development quasar dev",
"build-quasar": "quasar build", "build-quasar": "quasar build",
"build-staging": "NODE_ENV=production APP_ENV=development yarn build-quasar", "build-staging": "NODE_ENV=production APP_ENV=development yarn build-quasar",
@ -18,8 +18,8 @@
"test:unit:ci": "vitest run" "test:unit:ci": "vitest run"
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.16.9", "@quasar/extras": "^1.16.12",
"axios": "^1.6.7", "axios": "^1.7.2",
"bowser": "^2.11.0", "bowser": "^2.11.0",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"core-js": "^3.35.1", "core-js": "^3.35.1",
@ -27,7 +27,7 @@
"iframe-resizer": "^4.3.9", "iframe-resizer": "^4.3.9",
"lodash.isequal": "4.5.0", "lodash.isequal": "4.5.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"quasar": "^2.14.3", "quasar": "^2.16.6",
"query-string": "^8.1.0", "query-string": "^8.1.0",
"vh-check": "^2.0.5", "vh-check": "^2.0.5",
"vue": "^3.0.0", "vue": "^3.0.0",
@ -39,8 +39,8 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.9", "@babel/core": "^7.23.9",
"@babel/eslint-parser": "^7.23.10", "@babel/eslint-parser": "^7.23.10",
"@quasar/app-vite": "^1.4.3", "@quasar/app-vite": "^2.0.0-beta.15",
"@quasar/babel-preset-app": "^2.0.2", "@quasar/babel-preset-app": "^2.0.3",
"@quasar/quasar-app-extension-testing-unit-vitest": "^1.0.0", "@quasar/quasar-app-extension-testing-unit-vitest": "^1.0.0",
"@vue/test-utils": "^2.4.4", "@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.2", "autoprefixer": "^10.4.2",
@ -51,7 +51,7 @@
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^9.0.0", "eslint-plugin-vue": "^9.0.0",
"postcss": "^8.4.14", "postcss": "^8.4.14",
"vitest": "^1.3.1" "vitest": "^1.6.0"
}, },
"engines": { "engines": {
"node": "^20 || ^18 || ^16", "node": "^20 || ^18 || ^16",

File diff suppressed because it is too large Load diff