Merge branch v3.0 into master

This commit is contained in:
Fernandez Ludovic 2023-04-26 14:04:43 +02:00
commit 619045eb4b
67 changed files with 1862 additions and 1203 deletions

View file

@ -3,11 +3,11 @@ PLEASE READ THIS MESSAGE.
Documentation fixes or enhancements: Documentation fixes or enhancements:
- for Traefik v2: use branch v2.10 - for Traefik v2: use branch v2.10
- for Traefik v3: use branch master - for Traefik v3: use branch v3.0
Bug fixes: Bug fixes:
- for Traefik v2: use branch v2.10 - for Traefik v2: use branch v2.10
- for Traefik v3: use branch master - for Traefik v3: use branch v3.0
Enhancements: Enhancements:
- for Traefik v2: we only accept bug fixes - for Traefik v2: we only accept bug fixes

View file

@ -7,7 +7,7 @@ on:
- v* - v*
env: env:
STRUCTOR_VERSION: v1.13.1 STRUCTOR_VERSION: v1.13.2
MIXTUS_VERSION: v0.4.1 MIXTUS_VERSION: v0.4.1
jobs: jobs:

View file

@ -7,7 +7,7 @@ on:
env: env:
GO_VERSION: '1.20' GO_VERSION: '1.20'
GOLANGCI_LINT_VERSION: v1.51.2 GOLANGCI_LINT_VERSION: v1.52.2
MISSSPELL_VERSION: v0.4.0 MISSSPELL_VERSION: v0.4.0
IN_DOCKER: "" IN_DOCKER: ""

View file

@ -6,9 +6,10 @@ run:
linters-settings: linters-settings:
govet: govet:
check-shadowing: false enable-all: true
golint: disable:
min-confidence: 0 - shadow
- fieldalignment
gocyclo: gocyclo:
min-complexity: 14 min-complexity: 14
goconst: goconst:
@ -33,16 +34,85 @@ linters-settings:
keywords: keywords:
- FIXME - FIXME
importas: importas:
corev1: k8s.io/api/core/v1 no-unaliased: true
networkingv1beta1: k8s.io/api/networking/v1beta1 alias:
extensionsv1beta1: k8s.io/api/extensions/v1beta1 - alias: composeapi
metav1: k8s.io/apimachinery/pkg/apis/meta/v1 pkg: github.com/docker/compose/v2/pkg/api
kubeerror: k8s.io/apimachinery/pkg/api/errors
composeapi: github.com/docker/compose/v2/pkg/api # Standard Kubernetes rewrites:
- alias: corev1
pkg: "k8s.io/api/core/v1"
- alias: netv1
pkg: "k8s.io/api/networking/v1"
- alias: netv1beta1
pkg: "k8s.io/api/networking/v1beta1"
- alias: admv1
pkg: "k8s.io/api/admission/v1"
- alias: admv1beta1
pkg: "k8s.io/api/admission/v1beta1"
- alias: extv1beta1
pkg: "k8s.io/api/extensions/v1beta1"
- alias: metav1
pkg: "k8s.io/apimachinery/pkg/apis/meta/v1"
- alias: ktypes
pkg: "k8s.io/apimachinery/pkg/types"
- alias: kerror
pkg: "k8s.io/apimachinery/pkg/api/errors"
- alias: kclientset
pkg: "k8s.io/client-go/kubernetes"
- alias: kinformers
pkg: "k8s.io/client-go/informers"
- alias: ktesting
pkg: "k8s.io/client-go/testing"
- alias: kschema
pkg: "k8s.io/apimachinery/pkg/runtime/schema"
- alias: kscheme
pkg: "k8s.io/client-go/kubernetes/scheme"
- alias: kversion
pkg: "k8s.io/apimachinery/pkg/version"
- alias: kubefake
pkg: "k8s.io/client-go/kubernetes/fake"
- alias: discoveryfake
pkg: "k8s.io/client-go/discovery/fake"
# Kubernetes Gateway rewrites:
- alias: gateclientset
pkg: "sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned"
- alias: gateinformers
pkg: "sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions"
- alias: gatev1alpha2
pkg: "sigs.k8s.io/gateway-api/apis/v1alpha2"
# Traefik Kubernetes rewrites:
- alias: containousv1alpha1
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1"
- alias: traefikv1alpha1
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
- alias: traefikclientset
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned"
- alias: traefikinformers
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions"
- alias: traefikscheme
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme"
- alias: traefikcrdfake
pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake"
tagalign:
align: false
sort: true
order:
- description
- json
- toml
- yaml
- yml
- label
- label-slice-as-struct
- file
- kv
- export
revive: revive:
rules: rules:
- name: struct-tag - name: struct-tag
rules:
- name: blank-imports - name: blank-imports
- name: context-as-argument - name: context-as-argument
- name: context-keys-type - name: context-keys-type
@ -51,11 +121,13 @@ linters-settings:
- name: error-strings - name: error-strings
- name: error-naming - name: error-naming
- name: exported - name: exported
disabled: true
- name: if-return - name: if-return
- name: increment-decrement - name: increment-decrement
- name: var-naming - name: var-naming
- name: var-declaration - name: var-declaration
- name: package-comments - name: package-comments
disabled: true
- name: range - name: range
- name: receiver-naming - name: receiver-naming
- name: time-naming - name: time-naming
@ -65,6 +137,7 @@ linters-settings:
- name: empty-block - name: empty-block
- name: superfluous-else - name: superfluous-else
- name: unused-parameter - name: unused-parameter
disabled: true
- name: unreachable-code - name: unreachable-code
- name: redefines-builtin-id - name: redefines-builtin-id
gomoddirectives: gomoddirectives:
@ -183,3 +256,7 @@ issues:
text: "Function 'loadConfigurationFromCRD' has too many statements" text: "Function 'loadConfigurationFromCRD' has too many statements"
linters: linters:
- funlen - funlen
- path: pkg/provider/kubernetes/gateway/client_mock_test.go
text: 'unusedwrite: unused write to field'
linters:
- govet

View file

@ -25,7 +25,7 @@ global_job_config:
- export "PATH=${GOPATH}/bin:${PATH}" - export "PATH=${GOPATH}/bin:${PATH}"
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin" - mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
- export GOPROXY=https://proxy.golang.org,direct - export GOPROXY=https://proxy.golang.org,direct
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.50.0 - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.52.2
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin" - curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
- checkout - checkout
- cache restore traefik-$(checksum go.sum) - cache restore traefik-$(checksum go.sum)

View file

@ -1,3 +1,60 @@
## [v2.10.0](https://github.com/traefik/traefik/tree/v2.10.0) (2023-04-24)
[All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc1...v2.10.0)
**Enhancements:**
- **[docker]** Expose ContainerName in Docker provider ([#9770](https://github.com/traefik/traefik/pull/9770) by [quinot](https://github.com/quinot))
- **[hub]** Remove hub configuration out of experimental ([#9792](https://github.com/traefik/traefik/pull/9792) by [mpl](https://github.com/mpl))
- **[k8s/crd]** Introduce traefik.io API Group CRDs ([#9765](https://github.com/traefik/traefik/pull/9765) by [rtribotte](https://github.com/rtribotte))
- **[k8s/ingress,k8s/crd,k8s]** Native Kubernetes service load-balancing ([#9740](https://github.com/traefik/traefik/pull/9740) by [rtribotte](https://github.com/rtribotte))
- **[middleware,metrics]** Add prometheus metric requests_total with headers ([#9783](https://github.com/traefik/traefik/pull/9783) by [rtribotte](https://github.com/rtribotte))
- **[nomad]** Support multiple namespaces in the Nomad Provider ([#9794](https://github.com/traefik/traefik/pull/9794) by [rtribotte](https://github.com/rtribotte))
- **[tracing]** Add support to send DataDog traces via Unix Socket ([#9714](https://github.com/traefik/traefik/pull/9714) by [der-eismann](https://github.com/der-eismann))
- **[webui]** Modify the Hub Button ([#9851](https://github.com/traefik/traefik/pull/9851) by [mdeliatf](https://github.com/mdeliatf))
- **[webui]** Display period setting of the RateLimit middleware in the webui ([#9822](https://github.com/traefik/traefik/pull/9822) by [smatyas](https://github.com/smatyas))
**Bug fixes:**
- **[docker]** Only warn about missing docker network when network_mode is not host or container ([#9799](https://github.com/traefik/traefik/pull/9799) by [sentriz](https://github.com/sentriz))
- **[k8s/ingress,k8s]** Bump k8s.io/client-go from v0.22.1 to v0.26.3 ([#9808](https://github.com/traefik/traefik/pull/9808) by [ldez](https://github.com/ldez))
- **[plugins]** Improve DeepCopy of PluginConf ([#9846](https://github.com/traefik/traefik/pull/9846) by [ldez](https://github.com/ldez))
- **[plugins]** Update Yaegi to v0.15.1 ([#9815](https://github.com/traefik/traefik/pull/9815) by [ldez](https://github.com/ldez))
- **[server]** Update vulcand/oxy to 03de175b3822 ([#9849](https://github.com/traefik/traefik/pull/9849) by [longit644](https://github.com/longit644))
**Documentation:**
- Prepare release v2.10.0-rc1 ([#9802](https://github.com/traefik/traefik/pull/9802) by [ldez](https://github.com/ldez))
- Fix order of log levels ([#9791](https://github.com/traefik/traefik/pull/9791) by [svx](https://github.com/svx))
- **[docker]** Update wording - add link descriptions ([#9816](https://github.com/traefik/traefik/pull/9816) by [svx](https://github.com/svx))
- **[middleware]** Add accessControlAllowHeaders example ([#9810](https://github.com/traefik/traefik/pull/9810) by [yingshaoxo](https://github.com/yingshaoxo))
- **[tls]** More details on Kubernetes options for mTLS ([#9835](https://github.com/traefik/traefik/pull/9835) by [mloiseleur](https://github.com/mloiseleur))
- Prepare release v2.10.0-rc2 ([#9830](https://github.com/traefik/traefik/pull/9830) by [mpl](https://github.com/mpl))
- Update Call To Actions ([#9824](https://github.com/traefik/traefik/pull/9824) by [svx](https://github.com/svx))
- Improve concepts page ([#9813](https://github.com/traefik/traefik/pull/9813) by [svx](https://github.com/svx))
- Update wording ([#9811](https://github.com/traefik/traefik/pull/9811) by [svx](https://github.com/svx))
**Misc:**
- Merge branch v2.9 into v2.10 ([#9798](https://github.com/traefik/traefik/pull/9798) by [ldez](https://github.com/ldez))
- Merge branch v2.9 into v2.10 ([#9829](https://github.com/traefik/traefik/pull/9829) by [mpl](https://github.com/mpl))
## [v2.10.0-rc2](https://github.com/traefik/traefik/tree/v2.10.0-rc2) (2023-04-07)
[All Commits](https://github.com/traefik/traefik/compare/v2.10.0-rc1...v2.10.0-rc2)
**Enhancements:**
- **[webui]** Display period setting of the RateLimit middleware in the webui ([#9822](https://github.com/traefik/traefik/pull/9822) by [smatyas](https://github.com/smatyas))
**Bug fixes:**
- **[docker]** Only warn about missing docker network when network_mode is not host or container ([#9799](https://github.com/traefik/traefik/pull/9799) by [sentriz](https://github.com/sentriz))
- **[k8s/ingress,k8s]** chore: bump k8s.io/client-go from v0.22.1 to v0.26.3 ([#9808](https://github.com/traefik/traefik/pull/9808) by [ldez](https://github.com/ldez))
- **[plugins]** Update Yaegi to v0.15.1 ([#9815](https://github.com/traefik/traefik/pull/9815) by [ldez](https://github.com/ldez))
**Documentation:**
- **[docker]** Update wording - add link descriptions ([#9816](https://github.com/traefik/traefik/pull/9816) by [svx](https://github.com/svx))
- **[middleware]** Add accessControlAllowHeaders example ([#9810](https://github.com/traefik/traefik/pull/9810) by [yingshaoxo](https://github.com/yingshaoxo))
- Update Call To Actions ([#9824](https://github.com/traefik/traefik/pull/9824) by [svx](https://github.com/svx))
- Improve concepts page ([#9813](https://github.com/traefik/traefik/pull/9813) by [svx](https://github.com/svx))
- Update wording ([#9811](https://github.com/traefik/traefik/pull/9811) by [svx](https://github.com/svx))
## [v2.9.10](https://github.com/traefik/traefik/tree/v2.9.10) (2023-04-06)
[All Commits](https://github.com/traefik/traefik/compare/v2.9.9...v2.9.10)
## [v2.10.0-rc1](https://github.com/traefik/traefik/tree/v2.10.0-rc1) (2023-03-22) ## [v2.10.0-rc1](https://github.com/traefik/traefik/tree/v2.10.0-rc1) (2023-03-22)
[All Commits](https://github.com/traefik/traefik/compare/b3f162a8a61d89beaa9edc8adc12cc4cb3e1de0f...v2.10.0-rc1) [All Commits](https://github.com/traefik/traefik/compare/b3f162a8a61d89beaa9edc8adc12cc4cb3e1de0f...v2.10.0-rc1)

View file

@ -189,7 +189,7 @@ generate-genconf:
.PHONY: release-packages .PHONY: release-packages
release-packages: generate-webui build-dev-image release-packages: generate-webui build-dev-image
rm -rf dist rm -rf dist
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish -p 4 --timeout="90m" $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish -p 2 --timeout="90m"
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \ $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \
--exclude-vcs \ --exclude-vcs \
--exclude .idea \ --exclude .idea \

View file

@ -13,7 +13,7 @@ RUN mkdir -p /usr/local/bin \
| tar -xzC /usr/local/bin --transform 's#^.+/##x' | tar -xzC /usr/local/bin --transform 's#^.+/##x'
# Download golangci-lint binary to bin folder in $GOPATH # Download golangci-lint binary to bin folder in $GOPATH
RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.50.0 RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.52.2
# Download misspell binary to bin folder in $GOPATH # Download misspell binary to bin folder in $GOPATH
RUN curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.4.0 RUN curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.4.0

View file

@ -11,7 +11,7 @@ Understanding How Traefik is Being Used
## Configuration Example ## Configuration Example
Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways. Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways.
For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us so we can benefit from your experience and use cases. For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us, so we can benefit from your experience and use cases.
!!! example "Enabling Data Collection" !!! example "Enabling Data Collection"
@ -34,9 +34,7 @@ For this very reason, the sendAnonymousUsage option is mandatory: we want you to
## Collected Data ## Collected Data
This feature comes from the public proposal [here](https://github.com/traefik/traefik/issues/2369). This feature comes from this [public proposal](https://github.com/traefik/traefik/issues/2369).
This feature is activated when using Traefik Pilot to better understand the community's need, and also to get information about plug-ins popularity.
In order to help us learn more about how Traefik is being used and improve it, we collect anonymous usage statistics from running instances. In order to help us learn more about how Traefik is being used and improve it, we collect anonymous usage statistics from running instances.
Those data help us prioritize our developments and focus on what's important for our users (for example, which provider is popular, and which is not). Those data help us prioritize our developments and focus on what's important for our users (for example, which provider is popular, and which is not).
@ -47,7 +45,7 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
- the Traefik version number - the Traefik version number
- a hash of the configuration - a hash of the configuration
- an **anonymized version** of the static configuration (token, user name, password, URL, IP, domain, email, etc, are removed). - an **anonymized version** of the static configuration (token, username, password, URL, IP, domain, email, etc., are removed).
!!! info !!! info
@ -101,4 +99,4 @@ providers:
If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/traefik/traefik/blob/master/pkg/collector/collector.go) If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/traefik/traefik/blob/master/pkg/collector/collector.go)
By default we anonymize all configuration fields, except fields tagged with `export=true`. By default, we anonymize all configuration fields, except fields tagged with `export=true`.

View file

@ -11,7 +11,7 @@ Note: the document is a work in progress.
Welcome to the Traefik Community. Welcome to the Traefik Community.
This document describes how to be part of the core team This document describes how to be part of the core team
as well as various responsibilities together with various responsibilities
and guidelines for Traefik maintainers. and guidelines for Traefik maintainers.
We are strongly promoting a philosophy of openness and sharing, We are strongly promoting a philosophy of openness and sharing,
and firmly standing against the elitist closed approach. and firmly standing against the elitist closed approach.
@ -20,7 +20,7 @@ and wants to be part of that journey!
## Onboarding Process ## Onboarding Process
If you consider joining our community please drop us a line using Twitter or leave a note in the issue. If you consider joining our community, please drop us a line using Twitter or leave a note in the issue.
We will schedule a quick call to meet you and learn more about your motivation. We will schedule a quick call to meet you and learn more about your motivation.
During the call, the team will discuss the process of becoming a maintainer. During the call, the team will discuss the process of becoming a maintainer.
We will be happy to answer any questions and explain all your doubts. We will be happy to answer any questions and explain all your doubts.
@ -53,7 +53,7 @@ but we can suggest you start with activities such as:
Each of the issues that are labeled as bug/possible bug/confirmed requires a reproducible use case. Each of the issues that are labeled as bug/possible bug/confirmed requires a reproducible use case.
You can help in creating a reproducible use case if it has not been added to the issue You can help in creating a reproducible use case if it has not been added to the issue
or use the sample code provided by the reporter. or use the sample code provided by the reporter.
Typically, a simple docker compose should be enough to reproduce the issue. Typically, a simple Docker Compose should be enough to reproduce the issue.
- Code contribution. - Code contribution.
- Documentation contribution. - Documentation contribution.
- Technical documentation is one of the most important components of the product. - Technical documentation is one of the most important components of the product.
@ -61,7 +61,7 @@ but we can suggest you start with activities such as:
using the official documentation, using the official documentation,
is a game changer. is a game changer.
- You will be listed on our Maintainers GitHub page - You will be listed on our Maintainers GitHub page
as well as on our website in the section [maintainers](maintainers.md). and on our website in the section [maintainers](maintainers.md).
- We will be promoting you on social channels (mostly on Twitter). - We will be promoting you on social channels (mostly on Twitter).
## Governance ## Governance
@ -114,7 +114,7 @@ maintainers' activity and involvement will be reviewed on a regular basis.
- Be open-minded and respectful with other maintainers and other community members. - Be open-minded and respectful with other maintainers and other community members.
- Keep the communication public - - Keep the communication public -
if anyone tries to communicate with you directly, if anyone tries to communicate with you directly,
ask him politely to move the conversation to a public communication channel. ask politely to move the conversation to a public communication channel.
- Stay away from defensive comments. - Stay away from defensive comments.
- Please try to express your thoughts clearly enough - Please try to express your thoughts clearly enough
and note that some of us are not native English speakers. and note that some of us are not native English speakers.
@ -122,7 +122,7 @@ maintainers' activity and involvement will be reviewed on a regular basis.
none of us is able to predict your thoughts. none of us is able to predict your thoughts.
- There are a lot of use cases of using Traefik - There are a lot of use cases of using Traefik
and even more issues that are difficult to reproduce. and even more issues that are difficult to reproduce.
If the issue cant be replicated due to a lack of reproducible case (a simple docker compose should be enough) - If the issue cant be replicated due to a lack of reproducible case (a simple Docker Compose should be enough) -
set your time limits while working on the issue set your time limits while working on the issue
and express clearly that you were not able to replicate it. and express clearly that you were not able to replicate it.
You can come back later to that case. You can come back later to that case.

View file

@ -12,7 +12,7 @@ Issues are perfect for requesting a feature/enhancement or reporting a suspected
We use the [GitHub issue tracker](https://github.com/traefik/traefik/issues) to keep track of issues in Traefik. We use the [GitHub issue tracker](https://github.com/traefik/traefik/issues) to keep track of issues in Traefik.
The process of sorting and checking the issues is a daunting task, and requires a lot of work (more than an hour a day ... just for sorting). The process of sorting and checking the issues is a daunting task, and requires a lot of work (more than an hour a day ... just for sorting).
To help us (and other community members) quickly and easily understand what you need, To help us (and other community members) quickly and effortlessly understand what you need,
be sure to follow the guidelines below. be sure to follow the guidelines below.
!!! important "Getting Help Vs Reporting an Issue" !!! important "Getting Help Vs Reporting an Issue"
@ -40,9 +40,10 @@ Follow the [issue template](https://github.com/traefik/traefik/blob/master/.gith
Do your best to explain what you're looking for, and why it would improve Traefik for everyone. Do your best to explain what you're looking for, and why it would improve Traefik for everyone.
Be detailed and share the use-case(s) to allow us to see the value of your feature request as quickly as possible. Be detailed and share the use-case(s) to allow us to see the value of your feature request as quickly as possible.
Features with a lot of positive interaction (claps, +1s, conversation about how this would impact them) indicate higher community interest and help us to prioritize. Features with a lot of positive interaction (claps, +1s, conversation about how this would impact them) indicate higher community interest and help us to prioritize.
If you are interested in creating a PR for your feature request, let us know in the the issue so we can work with you. If you are interested in creating a PR for your feature request, let us know in the issue, so we can work with you.
It can take a lot of work to make sure a PR can integrate with our existing code and planning with the team ahead of time can make sure that your PR can be accepted and merged quickly. It can take a lot of work to make sure a PR can integrate with our existing code and planning with the team ahead of time can make sure that your PR can be accepted and merged quickly.
## Issues or Possible Bug Reports ## Issues or Possible Bug Reports
@ -50,13 +51,13 @@ It can take a lot of work to make sure a PR can integrate with our existing code
Follow the [issue template](https://github.com/traefik/traefik/blob/master/.github/ISSUE_TEMPLATE/bug_report.yml) as much as possible. Follow the [issue template](https://github.com/traefik/traefik/blob/master/.github/ISSUE_TEMPLATE/bug_report.yml) as much as possible.
Explain the conditions in which you encountered the issue; what is your context? Explain the conditions in which you encountered the issue; what is your context?
Share any logs you may have and make sure to share the steps it takes to reproduce your issue or bug. Share any logs you may have, and make sure to share the steps it takes to reproduce your issue or bug.
Remain as clear and concise as possible. Remain as clear and concise as possible.
Take time to polish the format of your message so we'll enjoy reading it and working on it. Take time to polish the format of your message, so we'll enjoy reading it and working on it.
Help your readers focus on what matters and help them understand the structure of your message (see the [GitHub Markdown Syntax](https://docs.github.com/en/get-started/writing-on-github)). Help your readers focus on what matters and help them understand the structure of your message (see the [GitHub Markdown Syntax](https://docs.github.com/en/get-started/writing-on-github)).
## International English ## International English
Every maintainer / Traefik user is not a native English speaker, so if you feel sometimes that some messages sound rude, remember that it probably is a language barrier problem from someone willing to help you. Every maintainer / Traefik user is not a native English speaker, so if you sometimes feel that some messages sound rude, remember that it probably is a language barrier problem from someone willing to help you.

View file

@ -20,7 +20,7 @@ or the list of [confirmed bugs](https://github.com/traefik/traefik/labels/kind%2
We wish we could review every pull request right away. We wish we could review every pull request right away.
Unfortunately, our team has to prioritize pull requests (PRs) for review Unfortunately, our team has to prioritize pull requests (PRs) for review
(but we are welcoming new [maintainers](https://github.com/traefik/traefik/blob/master/docs/content/contributing/maintainers-guidelines.md) to speed this up, (but we are welcoming new [maintainers](https://github.com/traefik/traefik/blob/master/docs/content/contributing/maintainers-guidelines.md) to speed this up,
so if you are interested, check it out and apply). if you are interested, check it out and apply).
The PRs we are able to handle fastest are: The PRs we are able to handle fastest are:
@ -38,11 +38,11 @@ and tell us you are interested in writing the PR.
If an issue already exists, definitely comment on it to tell us you are interested in creating a PR. If an issue already exists, definitely comment on it to tell us you are interested in creating a PR.
This will allow us to communicate directly and let you know if it is something we would accept. This will allow us to communicate directly and let you know if it is something we would accept.
It also allows us to make sure you have all the information you need during the design phase It also allows us to make sure you have all the information you need during the design phase
so that it can be reviewed and merged quickly. so that it can be reviewed and merged quickly.
If you have questions about the Triage process, Read more about the [Triage process](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md) in the docs.
[read more here](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md).
## The Pull Request Submit Process ## The Pull Request Submit Process
@ -63,8 +63,8 @@ Merging a PR requires the following steps to be completed before it is merged au
## Pull Request Review Cycle ## Pull Request Review Cycle
You can read about our Triage Process [here](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md), Learn about our [Triage Process](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md),
but in short, it looks like this: in short, it looks like this:
* We triage every new PR or comment before entering it into the review process. * We triage every new PR or comment before entering it into the review process.
* We ensure that all prerequisites for review have been met. * We ensure that all prerequisites for review have been met.
@ -132,12 +132,12 @@ Part of this goal is maintaining a lean codebase and ensuring code velocity.
unfortunately, this means that sometimes we will not be able to merge a pull request. unfortunately, this means that sometimes we will not be able to merge a pull request.
Because we respect the work you did, you will always be told why we are closing your pull request. Because we respect the work you did, you will always be told why we are closing your pull request.
If you do not agree with our decision, do not worry; closed pull requests are easy to recreate, If you do not agree with our decision, do not worry; closed pull requests are effortless to recreate,
and little work is lost by closing a pull request that subsequently needs to be reopened. and little work is lost by closing a pull request that subsequently needs to be reopened.
Your pull request might be closed if: Your pull request might be closed if:
* Your PR's design conflicts with our existing codebase in such a way that Merging is not an option * Your PR's design conflicts with our existing codebase in such a way that merging is not an option
and the work needed to make your pull request usable is too high. and the work needed to make your pull request usable is too high.
* To prevent this, make sure you created an issue first * To prevent this, make sure you created an issue first
and think about including Traefik Proxy maintainers in your design phase to minimize conflicts. and think about including Traefik Proxy maintainers in your design phase to minimize conflicts.
@ -152,7 +152,7 @@ A few factors affect how long your pull request might wait for review.
We must prioritize which PRs we focus on. We must prioritize which PRs we focus on.
Our first priority is PRs we have identified as having high community engagement and broad applicability. Our first priority is PRs we have identified as having high community engagement and broad applicability.
We put our top priorities on our roadmap and you can identify them by the `contributor/wanted` tag. We put our top priorities on our roadmap, and you can identify them by the `contributor/wanted` tag.
These PRs will enter our review process the fastest. These PRs will enter our review process the fastest.
Our second priority is bug fixes. Our second priority is bug fixes.
@ -160,7 +160,7 @@ Especially for bugs that have already been tagged with `bug/confirmed`.
These reviews enter the process quickly. These reviews enter the process quickly.
If your PR does not meet the criteria above, If your PR does not meet the criteria above,
it will take longer for us to review as any PRs that do meet the criteria above will be prioritized. it will take longer for us to review, as any PRs that do meet the criteria above will be prioritized.
Additionally, during the last few weeks of a milestone, we stop reviewing PRs to reduce churn and stabilize. Additionally, during the last few weeks of a milestone, we stop reviewing PRs to reduce churn and stabilize.
We will resume after the release. We will resume after the release.
@ -186,7 +186,7 @@ The most common failures to follow best practices are:
Please remember that we are working internationally, cross-culturally, and with different use-cases. Please remember that we are working internationally, cross-culturally, and with different use-cases.
Your reviewer will not intuitively understand the problem the same way you do or solve it the same way you would. Your reviewer will not intuitively understand the problem the same way you do or solve it the same way you would.
This is why every change you make must be explained and your strategy for coding must also be explained. This is why every change you make must be explained, and your strategy for coding must also be explained.
* Your tests were inadequate or absent. * Your tests were inadequate or absent.
* If you do not know how to test your PR, please ask! * If you do not know how to test your PR, please ask!
@ -228,4 +228,4 @@ but you should answer reasonable comments with an explanation.
No document can take the place of common sense and good taste. No document can take the place of common sense and good taste.
Use your best judgment, while you put a bit of thought into how your work can be made easier to review. Use your best judgment, while you put a bit of thought into how your work can be made easier to review.
If you do these things your pull requests will get merged with less friction. If you do these things, your pull requests will get merged with less friction.

View file

@ -1,19 +1,34 @@
--- ---
title: "Traefik Concepts Documentation" title: Concepts
description: "Get started with Traefik Proxy. Read the technical documentation for an introduction into the key concepts behind our open source edge router." description: Traefik - base concepts and main features
--- ---
# Concepts # Concepts
Everything You Need to Know This page explains the base concepts of Traefik.
{: .subtitle }
---
## Introduction
Traefik is based on the concept of EntryPoints, Routers, Middelwares and Services.
The main features include dynamic configuration, automatic service discovery, and support for multiple backends and protocols.
1. [EntryPoints](../routing/entrypoints.md "Link to docs about EntryPoints"): EntryPoints are the network entry points into Traefik. They define the port which will receive the packets, and whether to listen for TCP or UDP.
2. [Routers](../routing/routers/index.md "Link to docs about routers"): A router is in charge of connecting incoming requests to the services that can handle them.
3. [Middlewares](../middlewares/overview.md "Link to docs about middlewares"): Attached to the routers, middlewares can modify the requests or responses before they are sent to your service
4. [Services](../routing/services/index.md "Link to docs about services"): Services are responsible for configuring how to reach the actual services that will eventually handle the incoming requests.
## Edge Router ## Edge Router
Traefik is an _Edge Router_, it means that it's the door to your platform, and that it intercepts and routes every incoming request: Traefik is an *Edge Router*, it means that it's the door to your platform, and that it intercepts and routes every incoming request:
it knows all the logic and every rule that determine which services handle which requests (based on the [path](../routing/routers/index.md#rule), the [host](../routing/routers/index.md#rule), [headers](../routing/routers/index.md#rule), [and so on](../routing/routers/index.md#rule) ...). it knows all the logic and every [rule](../routing/routers/index.md#rule "Link to docs about routing rules") that determine which services handle which requests (based on the *path*, the *host*, *headers*, etc.).
![The Door to Your Infrastructure](../assets/img/traefik-concepts-1.png) ![The Door to Your Infrastructure](../assets/img/traefik-concepts-1.png "Picture explaining the infrastructure")
## Auto Service Discovery ## Auto Service Discovery
@ -21,7 +36,7 @@ Where traditionally edge routers (or reverse proxies) need a configuration file
Deploying your services, you attach information that tells Traefik the characteristics of the requests the services can handle. Deploying your services, you attach information that tells Traefik the characteristics of the requests the services can handle.
![Decentralized Configuration](../assets/img/traefik-concepts-2.png) ![Decentralized Configuration](../assets/img/traefik-concepts-2.png "Picture about Decentralized Configuration")
It means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time. It means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time.
Similarly, when a service is removed from the infrastructure, the corresponding route is deleted accordingly. Similarly, when a service is removed from the infrastructure, the corresponding route is deleted accordingly.
@ -30,14 +45,16 @@ You no longer need to create and synchronize configuration files cluttered with
!!! info "Many different rules" !!! info "Many different rules"
In the example above, we used the request [path](../routing/routers/index.md#rule) to determine which service was in charge, but of course you can use many other different [rules](../routing/routers/index.md#rule). In the example above, we used the request [path rule](../routing/routers/index.md#rule "Link to docs about routing rules") to determine which service was in charge.
Certainly, you can use many other different [rules](../routing/routers/index.md#rule "Link to docs about routing rules").
!!! info "Updating the requests" !!! info "Updating the requests"
In the [middleware](../middlewares/overview.md) section, you can learn about how to update the requests before forwarding them to the services. In the [middleware](../middlewares/overview.md "Link to middleware documentation") section, you can learn about how to update the requests before forwarding them to the services.
!!! question "How does Traefik discover the services?" !!! question "How does Traefik discover the services?"
Traefik is able to use your cluster API to discover the services and read the attached information. In Traefik, these connectors are called [providers](../providers/overview.md) because they _provide_ the configuration to Traefik. To learn more about them, read the [provider overview](../providers/overview.md) section. Traefik is able to use your cluster API to discover the services and read the attached information.
In Traefik, these connectors are called [providers](../providers/overview.md "Link to overview about Traefik providers") because they *provide* the configuration to Traefik.
{!traefik-for-business-applications.md!} {!traefik-for-business-applications.md!}

View file

@ -309,7 +309,7 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
For complete details, refer to your provider's _Additional configuration_ link. For complete details, refer to your provider's _Additional configuration_ link.
| Provider Name | Provider Code | Environment Variables | | | Provider Name | Provider Code | Environment Variables | |
|----------------------------------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| |--------------------------------------------------------------------------|--------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) | | [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) |
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) | | [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) |
| [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) | | [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) |
@ -349,7 +349,7 @@ For complete details, refer to your provider's _Additional configuration_ link.
| [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) | | [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) |
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) | | [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) |
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) | | [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) |
| [GoDaddy](https://godaddy.com/) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) | | [GoDaddy](https://www.godaddy.com) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) |
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) | | [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) |
| [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) | | [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) |
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) | | [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) |
@ -404,7 +404,7 @@ For complete details, refer to your provider's _Additional configuration_ link.
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) | | [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) | | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) | | [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
| [UKFast SafeDNS](https://www.ans.co.uk/cloud-and-infrastructure/dedicated-servers/dns-management/) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) | | [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) | | [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) |
| [Variomedia](https://www.variomedia.de/) | `variomedia` | `VARIOMEDIA_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia) | | [Variomedia](https://www.variomedia.de/) | `variomedia` | `VARIOMEDIA_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia) |
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) | | [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |

View file

@ -501,15 +501,17 @@ spec:
Traefik supports mutual authentication, through the `clientAuth` section. Traefik supports mutual authentication, through the `clientAuth` section.
For authentication policies that require verification of the client certificate, the certificate authority for the certificate should be set in `clientAuth.caFiles`. For authentication policies that require verification of the client certificate, the certificate authority for the certificates should be set in `clientAuth.caFiles`.
In Kubernetes environment, CA certificate can be set in `clientAuth.secretNames`. See [TLSOption resource](../../routing/providers/kubernetes-crd#kind-tlsoption) for more details.
The `clientAuth.clientAuthType` option governs the behaviour as follows: The `clientAuth.clientAuthType` option governs the behaviour as follows:
- `NoClientCert`: disregards any client certificate. - `NoClientCert`: disregards any client certificate.
- `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided. - `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided.
- `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `clientAuth.caFiles`. - `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`.
- `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `clientAuth.caFiles`. Otherwise proceeds without any certificate. - `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`. Otherwise proceeds without any certificate.
- `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `clientAuth.caFiles`. - `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Dynamic configuration # Dynamic configuration

View file

@ -2,15 +2,10 @@
!!! question "Using Traefik for Business Applications?" !!! question "Using Traefik for Business Applications?"
If you are using Traefik for commercial applications, If you are using Traefik in your organization, consider [Traefik Enterprise](https://traefik.io/traefik-enterprise/). You can use it as your:
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
You can use it as your:
- [API Gateway](https://traefik.io/solutions/api-gateway/)
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/) - [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
- [Docker Swarm Ingress Controller](https://traefik.io/solutions/docker-swarm-ingress/) - [Docker Swarm Ingress Controller](https://traefik.io/solutions/docker-swarm-ingress/)
- [API Gateway](https://traefik.io/solutions/api-gateway/)
Traefik Enterprise enables centralized access management, Traefik Enterprise simplifies the discovery, security, and deployment of APIs and microservices across any environment. See it in action in [this short video walkthrough](https://info.traefik.io/watch-traefikee-demo).
distributed Let's Encrypt,
and other advanced capabilities.
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).

View file

@ -24,10 +24,8 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo
!!! info !!! info
Join our user friendly and active [Community Forum](https://community.traefik.io) 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 for commercial applications? Using Traefik in your organization? Consider [Traefik Enterprise](https://traefik.io/traefik-enterprise/ "Lino to Traefik Enterprise"), our unified API Gateway and Ingress that simplifies the discovery, security, and deployment of APIs and microservices across any environment.
Consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/) of Traefik as your [Kubernetes Ingress](https://traefik.io/solutions/kubernetes-ingress/),
your [Docker Swarm Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/), See it in action in [this short video walkthrough](https://info.traefik.io/watch-traefikee-demo "Link to video walkthrough").
or your [API gateway](https://traefik.io/solutions/api-gateway/).
Get started with a [free 30-day trial](https://info.traefik.io/get-traefik-enterprise-free-for-30-days).

View file

@ -167,10 +167,13 @@ CORS (Cross-Origin Resource Sharing) headers can be added and configured in a ma
This functionality allows for more advanced security features to quickly be set. This functionality allows for more advanced security features to quickly be set.
If CORS headers are set, then the middleware does not pass preflight requests to any service, If CORS headers are set, then the middleware does not pass preflight requests to any service,
instead the response will be generated and sent back to the client directly. instead the response will be generated and sent back to the client directly.
Please note that the example below is by no means authoritative or exhaustive,
and should not be used as is for production.
```yaml tab="Docker" ```yaml tab="Docker"
labels: labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true" - "traefik.http.middlewares.testheader.headers.addvaryheader=true"
@ -187,6 +190,7 @@ spec:
- "GET" - "GET"
- "OPTIONS" - "OPTIONS"
- "PUT" - "PUT"
accessControlAllowHeaders: "*"
accessControlAllowOriginList: accessControlAllowOriginList:
- "https://foo.bar.org" - "https://foo.bar.org"
- "https://example.org" - "https://example.org"
@ -196,6 +200,7 @@ spec:
```yaml tab="Consul Catalog" ```yaml tab="Consul Catalog"
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true" - "traefik.http.middlewares.testheader.headers.addvaryheader=true"
@ -210,6 +215,7 @@ http:
- GET - GET
- OPTIONS - OPTIONS
- PUT - PUT
accessControlAllowHeaders: "*"
accessControlAllowOriginList: accessControlAllowOriginList:
- https://foo.bar.org - https://foo.bar.org
- https://example.org - https://example.org
@ -221,6 +227,7 @@ http:
[http.middlewares] [http.middlewares]
[http.middlewares.testHeader.headers] [http.middlewares.testHeader.headers]
accessControlAllowMethods= ["GET", "OPTIONS", "PUT"] accessControlAllowMethods= ["GET", "OPTIONS", "PUT"]
accessControlAllowHeaders= "*"
accessControlAllowOriginList = ["https://foo.bar.org","https://example.org"] accessControlAllowOriginList = ["https://foo.bar.org","https://example.org"]
accessControlMaxAge = 100 accessControlMaxAge = 100
addVaryHeader = true addVaryHeader = true

View file

@ -506,8 +506,6 @@ In `v2.9`, Traefik Pilot support has been removed.
In `v2.10`, the `namespace` option of the Nomad provider is deprecated, please use the `namespaces` options instead. In `v2.10`, the `namespace` option of the Nomad provider is deprecated, please use the `namespaces` options instead.
## v2.10
### Kubernetes CRDs ### Kubernetes CRDs
In `v2.10`, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. In `v2.10`, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead.
@ -517,6 +515,14 @@ it means that for the same kind, namespace and name, the provider will only keep
In addition, the Kubernetes CRDs API Version `traefik.io/v1alpha1` will not be supported in Traefik v3 itself. In addition, the Kubernetes CRDs API Version `traefik.io/v1alpha1` will not be supported in Traefik v3 itself.
Please note that it is a requirement to update the CRDs and the RBAC in the cluster before upgrading Traefik.
To do so, please apply the required [CRDs](https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml) and [RBAC](https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml) manifests for v2.10:
```bash
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
```
### Traefik Hub ### Traefik Hub
In `v2.10`, Traefik Hub is GA and the `experimental.hub` flag is deprecated. In `v2.10`, Traefik Hub is GA and the `experimental.hub` flag is deprecated.

View file

@ -1,12 +1,12 @@
--- ---
title: "Traefik Docker Documentation" title: "Traefik Docker Documentation"
description: "This guide covers a basic docker-compose file exposing a simple service using the docker provider in Traefik Proxy. Read the technical documentation." description: "This guide covers a Docker Compose file exposing a service using the Docker provider in Traefik Proxy. Read the technical documentation."
--- ---
# Docker-compose basic example # Docker Compose example
In this section we quickly go over a basic docker-compose file exposing a simple service using the docker provider. In this section, we quickly go over a Docker Compose file exposing a service using the Docker provider.
This will also be used as a starting point for the other docker-compose guides. This will also be used as a starting point for the other Docker Compose guides.
## Setup ## Setup
@ -19,9 +19,9 @@ This will also be used as a starting point for the other docker-compose guides.
??? Networking ??? Networking
The Traefik container has to be attached to the same network as the containers to be exposed. The Traefik container has to be attached to the same network as the containers to be exposed.
If no networks are specified in the docker-compose file, Docker creates a default one that allows Traefik to reach the containers defined in the same file. If no networks are specified in the Docker Compose file, Docker creates a default one that allows Traefik to reach the containers defined in the same file.
You can [customize the network](https://docs.docker.com/compose/networking/#specify-custom-networks) as described in the example below. You can [customize the network](https://docs.docker.com/compose/networking/#specify-custom-networks "Link to docs about custom networks with Docker Compose") as described in the example below.
You can use a [pre-existing network](https://docs.docker.com/compose/networking/#use-a-pre-existing-network) too. You can use a [pre-existing network](https://docs.docker.com/compose/networking/#use-a-pre-existing-network "Link to Docker Compose networking docs") too.
```yaml ```yaml
version: "3.3" version: "3.3"
@ -69,9 +69,9 @@ This will also be used as a starting point for the other docker-compose guides.
## Details ## Details
- As an example we use [whoami](https://github.com/traefik/whoami) (a tiny Go server that prints os information and HTTP request to output) which was used to define our `simple-service` container. - As an example, we use [whoami](https://github.com/traefik/whoami "Link to the GitHub repo of whoami") (a tiny Go server that prints OS information and HTTP request to output) which was used to define our `simple-service` container.
- We define an entry point, along with the exposure of the matching port within docker-compose, which basically allow us to "open and accept" HTTP traffic: - We define an entry point, along with the exposure of the matching port within Docker Compose, which allow us to "open and accept" HTTP traffic:
```yaml ```yaml
command: command:
@ -106,7 +106,7 @@ ports:
```yaml ```yaml
traefik: traefik:
command: command:
# Enabling docker provider # Enabling Docker provider
- "--providers.docker=true" - "--providers.docker=true"
# Do not expose containers unless explicitly told so # Do not expose containers unless explicitly told so
- "--providers.docker.exposedbydefault=false" - "--providers.docker.exposedbydefault=false"

View file

@ -22,7 +22,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \
--alt_ignore="/traefikproxy-vertical-logo-color.svg/" \ --alt_ignore="/traefikproxy-vertical-logo-color.svg/" \
--http_status_ignore="0,500,501,503" \ --http_status_ignore="0,500,501,503" \
--file_ignore="/404.html/" \ --file_ignore="/404.html/" \
--url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/,/www.wedos.com/,/www.reg.ru/" \ --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/,/www.wedos.com/,/www.reg.ru/,/www.godaddy.com/,/internetbs.net/" \
'{}' 1>/dev/null '{}' 1>/dev/null
## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration ## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration

46
go.mod
View file

@ -55,8 +55,8 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pires/go-proxyproto v0.6.1 github.com/pires/go-proxyproto v0.6.1
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835 github.com/prometheus/client_golang v1.14.0
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.3.0
github.com/quic-go/quic-go v0.33.0 github.com/quic-go/quic-go v0.33.0
github.com/rs/zerolog v1.28.0 github.com/rs/zerolog v1.28.0
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
@ -65,13 +65,13 @@ require (
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2 github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2
github.com/traefik/paerser v0.2.0 github.com/traefik/paerser v0.2.0
github.com/traefik/yaegi v0.15.0 github.com/traefik/yaegi v0.15.1
github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/uber/jaeger-lib v2.2.0+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible
github.com/unrolled/render v1.0.2 github.com/unrolled/render v1.0.2
github.com/unrolled/secure v1.0.9 github.com/unrolled/secure v1.0.9
github.com/vdemeester/shakers v0.1.0 github.com/vdemeester/shakers v0.1.0
github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040 github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822
github.com/vulcand/predicate v1.2.0 github.com/vulcand/predicate v1.2.0
go.elastic.co/apm v1.13.1 go.elastic.co/apm v1.13.1
go.elastic.co/apm/module/apmot v1.13.1 go.elastic.co/apm/module/apmot v1.13.1
@ -97,11 +97,11 @@ require (
gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 gopkg.in/DataDog/dd-trace-go.v1 v1.43.1
gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/fsnotify.v1 v1.4.7
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.25.0 k8s.io/api v0.26.3
k8s.io/apiextensions-apiserver v0.25.0 k8s.io/apiextensions-apiserver v0.26.3
k8s.io/apimachinery v0.25.0 k8s.io/apimachinery v0.26.3
k8s.io/client-go v0.25.0 k8s.io/client-go v0.26.3
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed k8s.io/utils v0.0.0-20230313181309-38a27ef9d749
mvdan.cc/xurls/v2 v2.1.0 mvdan.cc/xurls/v2 v2.1.0
sigs.k8s.io/gateway-api v0.4.0 sigs.k8s.io/gateway-api v0.4.0
) )
@ -131,8 +131,6 @@ require (
github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/Microsoft/hcsshim v0.8.24 // indirect github.com/Microsoft/hcsshim v0.8.24 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/Shopify/sarama v1.23.1 // indirect github.com/Shopify/sarama v1.23.1 // indirect
github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/VividCortex/gohistogram v1.0.0 // indirect
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
@ -175,11 +173,11 @@ require (
github.com/elastic/go-licenser v0.3.1 // indirect github.com/elastic/go-licenser v0.3.1 // indirect
github.com/elastic/go-sysinfo v1.1.1 // indirect github.com/elastic/go-sysinfo v1.1.1 // indirect
github.com/elastic/go-windows v1.0.0 // indirect github.com/elastic/go-windows v1.0.0 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/exoscale/egoscale v0.90.0 // indirect github.com/exoscale/egoscale v0.90.0 // indirect
github.com/fatih/color v1.13.0 // indirect github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-errors/errors v1.0.1 // indirect github.com/go-errors/errors v1.0.1 // indirect
@ -188,7 +186,7 @@ require (
github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.19.14 // indirect github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect
@ -236,7 +234,7 @@ require (
github.com/huandu/xstrings v1.3.3 // indirect github.com/huandu/xstrings v1.3.3 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/imdario/mergo v0.3.12 // indirect github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea // indirect github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea // indirect
@ -289,7 +287,7 @@ require (
github.com/nrdcg/goinwx v0.8.1 // indirect github.com/nrdcg/goinwx v0.8.1 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/porkbun v0.1.1 // indirect github.com/nrdcg/porkbun v0.1.1 // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect github.com/onsi/ginkgo/v2 v2.4.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.4 // indirect github.com/opencontainers/runc v1.1.4 // indirect
@ -299,8 +297,8 @@ require (
github.com/philhofer/fwd v1.1.1 // indirect github.com/philhofer/fwd v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pquerna/otp v1.3.0 // indirect github.com/pquerna/otp v1.3.0 // indirect
github.com/prometheus/common v0.35.0 // indirect github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.8.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
@ -318,7 +316,7 @@ require (
github.com/softlayer/softlayer-go v1.0.6 // indirect github.com/softlayer/softlayer-go v1.0.6 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.4.0 // indirect github.com/spf13/cobra v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/objx v0.5.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
@ -340,9 +338,9 @@ require (
github.com/zeebo/errs v1.2.2 // indirect github.com/zeebo/errs v1.2.2 // indirect
go.elastic.co/apm/module/apmhttp v1.13.1 // indirect go.elastic.co/apm/module/apmhttp v1.13.1 // indirect
go.elastic.co/fastjson v1.1.0 // indirect go.elastic.co/fastjson v1.1.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.4 // indirect go.etcd.io/etcd/api/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/v3 v3.5.4 // indirect go.etcd.io/etcd/client/v3 v3.5.5 // indirect
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect
@ -371,8 +369,8 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect
k8s.io/klog/v2 v2.70.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
nhooyr.io/websocket v1.8.7 // indirect nhooyr.io/websocket v1.8.7 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect

91
go.sum
View file

@ -192,10 +192,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
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=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
@ -495,7 +493,7 @@ github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobe
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
@ -625,8 +623,8 @@ github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/El
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -666,8 +664,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
@ -729,8 +727,9 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
@ -1127,8 +1126,9 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg= github.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg=
github.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU= github.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
@ -1489,8 +1489,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -1504,7 +1504,7 @@ github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1614,16 +1614,17 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835 h1:sYuFGkrz0PtewSFk0Bg7p7jjiiklc6FUIWz+mFGQfD0= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835/go.mod h1:RjnYTcBFM8s+WRft6oBqj4p5OgXJASPw5UFiI7w+GSs= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
@ -1637,8 +1638,8 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE= github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -1654,8 +1655,9 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
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/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY= github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY=
@ -1765,8 +1767,8 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@ -1839,8 +1841,8 @@ github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 h1:y/1cL5AL2oRcfz
github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c=
github.com/traefik/paerser v0.2.0 h1:zqCLGSXoNlcBd+mzqSCLjon/I6phqIjeJL2xFB2ysgQ= github.com/traefik/paerser v0.2.0 h1:zqCLGSXoNlcBd+mzqSCLjon/I6phqIjeJL2xFB2ysgQ=
github.com/traefik/paerser v0.2.0/go.mod h1:afzaVcgF8A+MpTnPG4wBr4whjanCSYA6vK5RwaYVtRc= github.com/traefik/paerser v0.2.0/go.mod h1:afzaVcgF8A+MpTnPG4wBr4whjanCSYA6vK5RwaYVtRc=
github.com/traefik/yaegi v0.15.0 h1:ScDDfQXTT75rKvcsMcP84rOxHsZ8b6NiQJyGocGDB7g= github.com/traefik/yaegi v0.15.1 h1:YA5SbaL6HZA0Exh9T/oArRHqGN2HQ+zgmCY7dkoTXu4=
github.com/traefik/yaegi v0.15.0/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0= github.com/traefik/yaegi v0.15.1/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0=
github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8= github.com/transip/gotransip/v6 v6.17.0 h1:2RCyqYqz5+Ej8z96EyE4sf6tQrrfEBaFDO0LliSl6+8=
github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/transip/gotransip/v6 v6.17.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
@ -1887,8 +1889,8 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040 h1:L+nLher4530BUkyOpxxBsl2SLbrD4fSlDH5rGZ8DRBM= github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822 h1:DXLWOIMPcQV+bxCFhBYSY5AIGP4DGvXH6qkwsg82YYY=
github.com/vulcand/oxy/v2 v2.0.0-20230227135449-a0e9f7ff1040/go.mod h1:A2voDnpONyqdplUDK0lt5y4XHLiBXPBw7iQES8+ZWRw= github.com/vulcand/oxy/v2 v2.0.0-20230417082832-03de175b3822/go.mod h1:A2voDnpONyqdplUDK0lt5y4XHLiBXPBw7iQES8+ZWRw=
github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50=
github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
@ -1950,14 +1952,14 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -2385,6 +2387,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -2819,11 +2822,11 @@ k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU=
k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg=
k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY=
k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU=
k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE=
k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE=
k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE=
k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ=
k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.0.0-20190806215851-162a2dabc72f/go.mod h1:+ntn62igV2hyNj7/0brOvXSMONE2KxcePkSxK7/9FFQ= k8s.io/apimachinery v0.0.0-20190806215851-162a2dabc72f/go.mod h1:+ntn62igV2hyNj7/0brOvXSMONE2KxcePkSxK7/9FFQ=
k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
@ -2834,8 +2837,8 @@ k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MA
k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=
k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k=
k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
@ -2849,8 +2852,8 @@ k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA=
k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU=
k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk=
k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s=
k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ=
k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo=
k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
@ -2877,16 +2880,16 @@ k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
@ -2894,8 +2897,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA= mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=
mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E= mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E=

View file

@ -220,8 +220,8 @@ func (r *ResponseForwarding) SetDefaults() {
// Server holds the server configuration. // Server holds the server configuration.
type Server struct { type Server struct {
URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"` URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"`
Scheme string `toml:"-" json:"-" yaml:"-" file:"-"` Scheme string `json:"-" toml:"-" yaml:"-" file:"-"`
Port string `toml:"-" json:"-" yaml:"-" file:"-"` Port string `json:"-" toml:"-" yaml:"-" file:"-"`
} }
// SetDefaults Default values for a Server. // SetDefaults Default values for a Server.
@ -282,7 +282,7 @@ type Spiffe struct {
// IDs defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). // IDs defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain).
IDs []string `description:"Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain)." json:"ids,omitempty" toml:"ids,omitempty" yaml:"ids,omitempty"` IDs []string `description:"Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain)." json:"ids,omitempty" toml:"ids,omitempty" yaml:"ids,omitempty"`
// TrustDomain defines the allowed SPIFFE trust domain. // TrustDomain defines the allowed SPIFFE trust domain.
TrustDomain string `description:"Defines the allowed SPIFFE trust domain." json:"trustDomain,omitempty" yaml:"trustDomain,omitempty" toml:"trustDomain,omitempty"` TrustDomain string `description:"Defines the allowed SPIFFE trust domain." json:"trustDomain,omitempty" toml:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -1,22 +1,26 @@
package dynamic package dynamic
import "k8s.io/apimachinery/pkg/runtime" import (
"encoding/json"
"fmt"
"reflect"
)
// +k8s:deepcopy-gen=false // +k8s:deepcopy-gen=false
// PluginConf holds the plugin configuration. // PluginConf holds the plugin configuration.
type PluginConf map[string]interface{} type PluginConf map[string]any
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is a deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PluginConf) DeepCopyInto(out *PluginConf) { func (in *PluginConf) DeepCopyInto(out *PluginConf) {
if in == nil { if in == nil {
*out = nil *out = nil
} else { } else {
*out = runtime.DeepCopyJSON(*in) *out = deepCopyJSON(*in)
} }
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginConf. // DeepCopy is a deepcopy function, copying the receiver, creating a new PluginConf.
func (in *PluginConf) DeepCopy() *PluginConf { func (in *PluginConf) DeepCopy() *PluginConf {
if in == nil { if in == nil {
return nil return nil
@ -25,3 +29,49 @@ func (in *PluginConf) DeepCopy() *PluginConf {
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
// inspired by https://github.com/kubernetes/apimachinery/blob/53ecdf01b997ca93c7db7615dfe7b27ad8391983/pkg/runtime/converter.go#L607
func deepCopyJSON(x map[string]any) map[string]any {
return deepCopyJSONValue(x).(map[string]any)
}
func deepCopyJSONValue(x any) any {
switch x := x.(type) {
case map[string]any:
if x == nil {
// Typed nil - an any that contains a type map[string]any with a value of nil
return x
}
clone := make(map[string]any, len(x))
for k, v := range x {
clone[k] = deepCopyJSONValue(v)
}
return clone
case []any:
if x == nil {
// Typed nil - an any that contains a type []any with a value of nil
return x
}
clone := make([]any, len(x))
for i, v := range x {
clone[i] = deepCopyJSONValue(v)
}
return clone
case string, int64, bool, float64, nil, json.Number:
return x
default:
v := reflect.ValueOf(x)
if v.NumMethod() == 0 {
panic(fmt.Errorf("cannot deep copy %T", x))
}
method := v.MethodByName("DeepCopy")
if method.Kind() == reflect.Invalid {
panic(fmt.Errorf("cannot deep copy %T", x))
}
call := method.Call(nil)
return call[0].Interface()
}
}

View file

@ -0,0 +1,75 @@
package dynamic
import (
"testing"
"github.com/stretchr/testify/assert"
)
type FakeConfig struct {
Name string `json:"name"`
}
// DeepCopyInto is a deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FakeConfig) DeepCopyInto(out *FakeConfig) {
*out = *in
}
// DeepCopy is a deepcopy function, copying the receiver, creating a new AddPrefix.
func (in *FakeConfig) DeepCopy() *FakeConfig {
if in == nil {
return nil
}
out := new(FakeConfig)
in.DeepCopyInto(out)
return out
}
type Foo struct {
Name string
}
func TestPluginConf_DeepCopy_mapOfStruct(t *testing.T) {
f := &FakeConfig{Name: "bir"}
p := PluginConf{
"fii": f,
}
clone := p.DeepCopy()
assert.Equal(t, &p, clone)
f.Name = "bur"
assert.NotEqual(t, &p, clone)
}
func TestPluginConf_DeepCopy_map(t *testing.T) {
m := map[string]interface{}{
"name": "bar",
}
p := PluginConf{
"config": map[string]interface{}{
"foo": m,
},
}
clone := p.DeepCopy()
assert.Equal(t, &p, clone)
p["one"] = "a"
m["two"] = "b"
assert.NotEqual(t, &p, clone)
}
func TestPluginConf_DeepCopy_panic(t *testing.T) {
p := &PluginConf{
"config": map[string]interface{}{
"foo": &Foo{Name: "gigi"},
},
}
assert.Panics(t, func() {
p.DeepCopy()
})
}

View file

@ -101,7 +101,7 @@ func (l *TCPServersLoadBalancer) Mergeable(loadBalancer *TCPServersLoadBalancer)
// TCPServer holds a TCP Server configuration. // TCPServer holds a TCP Server configuration.
type TCPServer struct { type TCPServer struct {
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"` Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
Port string `toml:"-" json:"-" yaml:"-"` Port string `json:"-" toml:"-" yaml:"-"`
TLS bool `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"` TLS bool `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"`
} }

View file

@ -78,5 +78,5 @@ func (l *UDPServersLoadBalancer) Mergeable(loadBalancer *UDPServersLoadBalancer)
// UDPServer defines a UDP server configuration. // UDPServer defines a UDP server configuration.
type UDPServer struct { type UDPServer struct {
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"` Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
Port string `toml:"-" json:"-" yaml:"-" file:"-"` Port string `json:"-" toml:"-" yaml:"-" file:"-"`
} }

View file

@ -114,7 +114,7 @@ type ServersTransport struct {
// Spiffe holds the SPIFFE configuration. // Spiffe holds the SPIFFE configuration.
type Spiffe struct { type Spiffe struct {
IDs []string `description:"Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain)." json:"ids,omitempty" toml:"ids,omitempty" yaml:"ids,omitempty"` IDs []string `description:"Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain)." json:"ids,omitempty" toml:"ids,omitempty" yaml:"ids,omitempty"`
TrustDomain string `description:"Defines the allowed SPIFFE trust domain." json:"trustDomain,omitempty" yaml:"trustDomain,omitempty" toml:"trustDomain,omitempty"` TrustDomain string `description:"Defines the allowed SPIFFE trust domain." json:"trustDomain,omitempty" toml:"trustDomain,omitempty" yaml:"trustDomain,omitempty"`
} }
// TCPServersTransport options to configure communication between Traefik and the servers. // TCPServersTransport options to configure communication between Traefik and the servers.
@ -191,13 +191,13 @@ func (a *LifeCycle) SetDefaults() {
type Tracing struct { type Tracing struct {
ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"` ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"` SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"`
Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Elastic *elastic.Config `description:"Settings for Elastic." json:"elastic,omitempty" toml:"elastic,omitempty" yaml:"elastic,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Elastic *elastic.Config `description:"Settings for Elastic." json:"elastic,omitempty" toml:"elastic,omitempty" yaml:"elastic,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
OpenTelemetry *opentelemetry.Config `description:"Settings for OpenTelemetry." json:"openTelemetry,omitempty" toml:"openTelemetry,omitempty" yaml:"openTelemetry,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` OpenTelemetry *opentelemetry.Config `description:"Settings for OpenTelemetry." json:"openTelemetry,omitempty" toml:"openTelemetry,omitempty" yaml:"openTelemetry,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
} }
// SetDefaults sets the default values. // SetDefaults sets the default values.
@ -210,12 +210,12 @@ func (t *Tracing) SetDefaults() {
type Providers struct { type Providers struct {
ProvidersThrottleDuration ptypes.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"` ProvidersThrottleDuration ptypes.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"`
Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"` File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"`
KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Rest *rest.Provider ` description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
ConsulCatalog *consulcatalog.ProviderBuilder `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` ConsulCatalog *consulcatalog.ProviderBuilder `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Nomad *nomad.ProviderBuilder `description:"Enable Nomad backend with default settings." json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Nomad *nomad.ProviderBuilder `description:"Enable Nomad backend with default settings." json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Ecs *ecs.Provider `description:"Enable AWS ECS backend with default settings." json:"ecs,omitempty" toml:"ecs,omitempty" yaml:"ecs,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Ecs *ecs.Provider `description:"Enable AWS ECS backend with default settings." json:"ecs,omitempty" toml:"ecs,omitempty" yaml:"ecs,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`

View file

@ -310,6 +310,7 @@ func (p *Provider) getIPPort(ctx context.Context, container dockerData, serverPo
func (p Provider) getIPAddress(ctx context.Context, container dockerData) string { func (p Provider) getIPAddress(ctx context.Context, container dockerData) string {
logger := log.Ctx(ctx) logger := log.Ctx(ctx)
netNotFound := false
if container.ExtraConf.Docker.Network != "" { if container.ExtraConf.Docker.Network != "" {
settings := container.NetworkSettings settings := container.NetworkSettings
if settings.Networks != nil { if settings.Networks != nil {
@ -318,7 +319,8 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string
return network.Addr return network.Addr
} }
logger.Warn().Msgf("Could not find network named '%s' for container '%s'! Maybe you're missing the project's prefix in the label? Defaulting to first available network.", container.ExtraConf.Docker.Network, container.Name) netNotFound = true
logger.Warn().Msgf("Could not find network named %q for container %q. Maybe you're missing the project's prefix in the label?", container.ExtraConf.Docker.Network, container.Name)
} }
} }
@ -367,6 +369,9 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string
} }
for _, network := range container.NetworkSettings.Networks { for _, network := range container.NetworkSettings.Networks {
if netNotFound {
logger.Warn().Msgf("Defaulting to first available network (%q) for container %q.", network, container.Name)
}
return network.Addr return network.Addr
} }

View file

@ -9,17 +9,17 @@ import (
"time" "time"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" traefikclientset "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions" traefikinformers "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
"github.com/traefik/traefik/v3/pkg/version" "github.com/traefik/traefik/v3/pkg/version"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
kubeerror "k8s.io/apimachinery/pkg/api/errors" kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" kinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes" kclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )
@ -31,17 +31,17 @@ const resyncPeriod = 10 * time.Minute
// The stores can then be accessed via the Get* functions. // The stores can then be accessed via the Get* functions.
type Client interface { type Client interface {
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
GetIngressRoutes() []*v1alpha1.IngressRoute GetIngressRoutes() []*traefikv1alpha1.IngressRoute
GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP
GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP
GetMiddlewares() []*v1alpha1.Middleware GetMiddlewares() []*traefikv1alpha1.Middleware
GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP GetMiddlewareTCPs() []*traefikv1alpha1.MiddlewareTCP
GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) GetTraefikService(namespace, name string) (*traefikv1alpha1.TraefikService, bool, error)
GetTraefikServices() []*v1alpha1.TraefikService GetTraefikServices() []*traefikv1alpha1.TraefikService
GetTLSOptions() []*v1alpha1.TLSOption GetTLSOptions() []*traefikv1alpha1.TLSOption
GetServersTransports() []*v1alpha1.ServersTransport GetServersTransports() []*traefikv1alpha1.ServersTransport
GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP GetServersTransportTCPs() []*traefikv1alpha1.ServersTransportTCP
GetTLSStores() []*v1alpha1.TLSStore GetTLSStores() []*traefikv1alpha1.TLSStore
GetService(namespace, name string) (*corev1.Service, bool, error) GetService(namespace, name string) (*corev1.Service, bool, error)
GetSecret(namespace, name string) (*corev1.Secret, bool, error) GetSecret(namespace, name string) (*corev1.Secret, bool, error)
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
@ -49,12 +49,12 @@ type Client interface {
// TODO: add tests for the clientWrapper (and its methods) itself. // TODO: add tests for the clientWrapper (and its methods) itself.
type clientWrapper struct { type clientWrapper struct {
csCrd versioned.Interface csCrd traefikclientset.Interface
csKube kubernetes.Interface csKube kclientset.Interface
factoriesCrd map[string]externalversions.SharedInformerFactory factoriesCrd map[string]traefikinformers.SharedInformerFactory
factoriesKube map[string]informers.SharedInformerFactory factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]informers.SharedInformerFactory factoriesSecret map[string]kinformers.SharedInformerFactory
labelSelector string labelSelector string
@ -71,12 +71,12 @@ func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
runtime.GOARCH, runtime.GOARCH,
) )
csCrd, err := versioned.NewForConfig(c) csCrd, err := traefikclientset.NewForConfig(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
csKube, err := kubernetes.NewForConfig(c) csKube, err := kclientset.NewForConfig(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -84,13 +84,13 @@ func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
return newClientImpl(csKube, csCrd), nil return newClientImpl(csKube, csCrd), nil
} }
func newClientImpl(csKube kubernetes.Interface, csCrd versioned.Interface) *clientWrapper { func newClientImpl(csKube kclientset.Interface, csCrd traefikclientset.Interface) *clientWrapper {
return &clientWrapper{ return &clientWrapper{
csCrd: csCrd, csCrd: csCrd,
csKube: csKube, csKube: csKube,
factoriesCrd: make(map[string]externalversions.SharedInformerFactory), factoriesCrd: make(map[string]traefikinformers.SharedInformerFactory),
factoriesKube: make(map[string]informers.SharedInformerFactory), factoriesKube: make(map[string]kinformers.SharedInformerFactory),
factoriesSecret: make(map[string]informers.SharedInformerFactory), factoriesSecret: make(map[string]kinformers.SharedInformerFactory),
} }
} }
@ -163,24 +163,63 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
for _, ns := range namespaces { for _, ns := range namespaces {
factoryCrd := externalversions.NewSharedInformerFactoryWithOptions(c.csCrd, resyncPeriod, externalversions.WithNamespace(ns), externalversions.WithTweakListOptions(matchesLabelSelector)) factoryCrd := traefikinformers.NewSharedInformerFactoryWithOptions(c.csCrd, resyncPeriod, traefikinformers.WithNamespace(ns), traefikinformers.WithTweakListOptions(matchesLabelSelector))
factoryCrd.Traefik().V1alpha1().IngressRoutes().Informer().AddEventHandler(eventHandler) _, err := factoryCrd.Traefik().V1alpha1().IngressRoutes().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().Middlewares().Informer().AddEventHandler(eventHandler) if err != nil {
factoryCrd.Traefik().V1alpha1().MiddlewareTCPs().Informer().AddEventHandler(eventHandler) return nil, err
factoryCrd.Traefik().V1alpha1().IngressRouteTCPs().Informer().AddEventHandler(eventHandler) }
factoryCrd.Traefik().V1alpha1().IngressRouteUDPs().Informer().AddEventHandler(eventHandler) _, err = factoryCrd.Traefik().V1alpha1().Middlewares().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler) if err != nil {
factoryCrd.Traefik().V1alpha1().ServersTransports().Informer().AddEventHandler(eventHandler) return nil, err
factoryCrd.Traefik().V1alpha1().ServersTransportTCPs().Informer().AddEventHandler(eventHandler) }
factoryCrd.Traefik().V1alpha1().TLSStores().Informer().AddEventHandler(eventHandler) _, err = factoryCrd.Traefik().V1alpha1().MiddlewareTCPs().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().TraefikServices().Informer().AddEventHandler(eventHandler) if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().IngressRouteTCPs().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().IngressRouteUDPs().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().ServersTransports().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().ServersTransportTCPs().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().TLSStores().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryCrd.Traefik().V1alpha1().TraefikServices().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
factoryKube := informers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, informers.WithNamespace(ns)) factoryKube := kinformers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, kinformers.WithNamespace(ns))
factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler) _, err = factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler) if err != nil {
return nil, err
}
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
factorySecret := informers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, informers.WithNamespace(ns), informers.WithTweakListOptions(notOwnedByHelm)) factorySecret := kinformers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, kinformers.WithNamespace(ns), kinformers.WithTweakListOptions(notOwnedByHelm))
factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler) _, err = factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.factoriesCrd[ns] = factoryCrd c.factoriesCrd[ns] = factoryCrd
c.factoriesKube[ns] = factoryKube c.factoriesKube[ns] = factoryKube
@ -216,8 +255,8 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
return eventCh, nil return eventCh, nil
} }
func (c *clientWrapper) GetIngressRoutes() []*v1alpha1.IngressRoute { func (c *clientWrapper) GetIngressRoutes() []*traefikv1alpha1.IngressRoute {
var result []*v1alpha1.IngressRoute var result []*traefikv1alpha1.IngressRoute
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
ings, err := factory.Traefik().V1alpha1().IngressRoutes().Lister().List(labels.Everything()) ings, err := factory.Traefik().V1alpha1().IngressRoutes().Lister().List(labels.Everything())
@ -230,8 +269,8 @@ func (c *clientWrapper) GetIngressRoutes() []*v1alpha1.IngressRoute {
return result return result
} }
func (c *clientWrapper) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP { func (c *clientWrapper) GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP {
var result []*v1alpha1.IngressRouteTCP var result []*traefikv1alpha1.IngressRouteTCP
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
ings, err := factory.Traefik().V1alpha1().IngressRouteTCPs().Lister().List(labels.Everything()) ings, err := factory.Traefik().V1alpha1().IngressRouteTCPs().Lister().List(labels.Everything())
@ -244,8 +283,8 @@ func (c *clientWrapper) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP {
return result return result
} }
func (c *clientWrapper) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP { func (c *clientWrapper) GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP {
var result []*v1alpha1.IngressRouteUDP var result []*traefikv1alpha1.IngressRouteUDP
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
ings, err := factory.Traefik().V1alpha1().IngressRouteUDPs().Lister().List(labels.Everything()) ings, err := factory.Traefik().V1alpha1().IngressRouteUDPs().Lister().List(labels.Everything())
@ -258,8 +297,8 @@ func (c *clientWrapper) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP {
return result return result
} }
func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware { func (c *clientWrapper) GetMiddlewares() []*traefikv1alpha1.Middleware {
var result []*v1alpha1.Middleware var result []*traefikv1alpha1.Middleware
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
middlewares, err := factory.Traefik().V1alpha1().Middlewares().Lister().List(labels.Everything()) middlewares, err := factory.Traefik().V1alpha1().Middlewares().Lister().List(labels.Everything())
@ -272,8 +311,8 @@ func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware {
return result return result
} }
func (c *clientWrapper) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP { func (c *clientWrapper) GetMiddlewareTCPs() []*traefikv1alpha1.MiddlewareTCP {
var result []*v1alpha1.MiddlewareTCP var result []*traefikv1alpha1.MiddlewareTCP
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
middlewares, err := factory.Traefik().V1alpha1().MiddlewareTCPs().Lister().List(labels.Everything()) middlewares, err := factory.Traefik().V1alpha1().MiddlewareTCPs().Lister().List(labels.Everything())
@ -287,7 +326,7 @@ func (c *clientWrapper) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP {
} }
// GetTraefikService returns the named service from the given namespace. // GetTraefikService returns the named service from the given namespace.
func (c *clientWrapper) GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) { func (c *clientWrapper) GetTraefikService(namespace, name string) (*traefikv1alpha1.TraefikService, bool, error) {
if !c.isWatchedNamespace(namespace) { if !c.isWatchedNamespace(namespace) {
return nil, false, fmt.Errorf("failed to get service %s/%s: namespace is not within watched namespaces", namespace, name) return nil, false, fmt.Errorf("failed to get service %s/%s: namespace is not within watched namespaces", namespace, name)
} }
@ -298,8 +337,8 @@ func (c *clientWrapper) GetTraefikService(namespace, name string) (*v1alpha1.Tra
return service, exist, err return service, exist, err
} }
func (c *clientWrapper) GetTraefikServices() []*v1alpha1.TraefikService { func (c *clientWrapper) GetTraefikServices() []*traefikv1alpha1.TraefikService {
var result []*v1alpha1.TraefikService var result []*traefikv1alpha1.TraefikService
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
traefikServices, err := factory.Traefik().V1alpha1().TraefikServices().Lister().List(labels.Everything()) traefikServices, err := factory.Traefik().V1alpha1().TraefikServices().Lister().List(labels.Everything())
@ -313,8 +352,8 @@ func (c *clientWrapper) GetTraefikServices() []*v1alpha1.TraefikService {
} }
// GetServersTransports returns all ServersTransport. // GetServersTransports returns all ServersTransport.
func (c *clientWrapper) GetServersTransports() []*v1alpha1.ServersTransport { func (c *clientWrapper) GetServersTransports() []*traefikv1alpha1.ServersTransport {
var result []*v1alpha1.ServersTransport var result []*traefikv1alpha1.ServersTransport
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
serversTransports, err := factory.Traefik().V1alpha1().ServersTransports().Lister().List(labels.Everything()) serversTransports, err := factory.Traefik().V1alpha1().ServersTransports().Lister().List(labels.Everything())
@ -328,8 +367,8 @@ func (c *clientWrapper) GetServersTransports() []*v1alpha1.ServersTransport {
} }
// GetServersTransportTCPs returns all ServersTransportTCP. // GetServersTransportTCPs returns all ServersTransportTCP.
func (c *clientWrapper) GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP { func (c *clientWrapper) GetServersTransportTCPs() []*traefikv1alpha1.ServersTransportTCP {
var result []*v1alpha1.ServersTransportTCP var result []*traefikv1alpha1.ServersTransportTCP
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
serversTransports, err := factory.Traefik().V1alpha1().ServersTransportTCPs().Lister().List(labels.Everything()) serversTransports, err := factory.Traefik().V1alpha1().ServersTransportTCPs().Lister().List(labels.Everything())
@ -343,8 +382,8 @@ func (c *clientWrapper) GetServersTransportTCPs() []*v1alpha1.ServersTransportTC
} }
// GetTLSOptions returns all TLS options. // GetTLSOptions returns all TLS options.
func (c *clientWrapper) GetTLSOptions() []*v1alpha1.TLSOption { func (c *clientWrapper) GetTLSOptions() []*traefikv1alpha1.TLSOption {
var result []*v1alpha1.TLSOption var result []*traefikv1alpha1.TLSOption
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
options, err := factory.Traefik().V1alpha1().TLSOptions().Lister().List(labels.Everything()) options, err := factory.Traefik().V1alpha1().TLSOptions().Lister().List(labels.Everything())
@ -358,8 +397,8 @@ func (c *clientWrapper) GetTLSOptions() []*v1alpha1.TLSOption {
} }
// GetTLSStores returns all TLS stores. // GetTLSStores returns all TLS stores.
func (c *clientWrapper) GetTLSStores() []*v1alpha1.TLSStore { func (c *clientWrapper) GetTLSStores() []*traefikv1alpha1.TLSStore {
var result []*v1alpha1.TLSStore var result []*traefikv1alpha1.TLSStore
for ns, factory := range c.factoriesCrd { for ns, factory := range c.factoriesCrd {
stores, err := factory.Traefik().V1alpha1().TLSStores().Lister().List(labels.Everything()) stores, err := factory.Traefik().V1alpha1().TLSStores().Lister().List(labels.Everything())
@ -435,7 +474,7 @@ func (c *clientWrapper) isWatchedNamespace(ns string) bool {
// translateNotFoundError will translate a "not found" error to a boolean return // translateNotFoundError will translate a "not found" error to a boolean return
// value which indicates if the resource exists and a nil error. // value which indicates if the resource exists and a nil error.
func translateNotFoundError(err error) (bool, error) { func translateNotFoundError(err error) (bool, error) {
if kubeerror.IsNotFound(err) { if kerror.IsNotFound(err) {
return false, nil return false, nil
} }
return err == nil, err return err == nil, err

View file

@ -5,17 +5,17 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes/scheme" kscheme "k8s.io/client-go/kubernetes/scheme"
) )
var _ Client = (*clientMock)(nil) var _ Client = (*clientMock)(nil)
func init() { func init() {
// required by k8s.MustParseYaml // required by k8s.MustParseYaml
err := v1alpha1.AddToScheme(scheme.Scheme) err := traefikv1alpha1.AddToScheme(kscheme.Scheme)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -30,16 +30,16 @@ type clientMock struct {
apiSecretError error apiSecretError error
apiEndpointsError error apiEndpointsError error
ingressRoutes []*v1alpha1.IngressRoute ingressRoutes []*traefikv1alpha1.IngressRoute
ingressRouteTCPs []*v1alpha1.IngressRouteTCP ingressRouteTCPs []*traefikv1alpha1.IngressRouteTCP
ingressRouteUDPs []*v1alpha1.IngressRouteUDP ingressRouteUDPs []*traefikv1alpha1.IngressRouteUDP
middlewares []*v1alpha1.Middleware middlewares []*traefikv1alpha1.Middleware
middlewareTCPs []*v1alpha1.MiddlewareTCP middlewareTCPs []*traefikv1alpha1.MiddlewareTCP
tlsOptions []*v1alpha1.TLSOption tlsOptions []*traefikv1alpha1.TLSOption
tlsStores []*v1alpha1.TLSStore tlsStores []*traefikv1alpha1.TLSStore
traefikServices []*v1alpha1.TraefikService traefikServices []*traefikv1alpha1.TraefikService
serversTransports []*v1alpha1.ServersTransport serversTransports []*traefikv1alpha1.ServersTransport
serversTransportTCPs []*v1alpha1.ServersTransportTCP serversTransportTCPs []*traefikv1alpha1.ServersTransportTCP
watchChan chan interface{} watchChan chan interface{}
} }
@ -60,25 +60,25 @@ func newClientMock(paths ...string) clientMock {
c.services = append(c.services, o) c.services = append(c.services, o)
case *corev1.Endpoints: case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o) c.endpoints = append(c.endpoints, o)
case *v1alpha1.IngressRoute: case *traefikv1alpha1.IngressRoute:
c.ingressRoutes = append(c.ingressRoutes, o) c.ingressRoutes = append(c.ingressRoutes, o)
case *v1alpha1.IngressRouteTCP: case *traefikv1alpha1.IngressRouteTCP:
c.ingressRouteTCPs = append(c.ingressRouteTCPs, o) c.ingressRouteTCPs = append(c.ingressRouteTCPs, o)
case *v1alpha1.IngressRouteUDP: case *traefikv1alpha1.IngressRouteUDP:
c.ingressRouteUDPs = append(c.ingressRouteUDPs, o) c.ingressRouteUDPs = append(c.ingressRouteUDPs, o)
case *v1alpha1.Middleware: case *traefikv1alpha1.Middleware:
c.middlewares = append(c.middlewares, o) c.middlewares = append(c.middlewares, o)
case *v1alpha1.MiddlewareTCP: case *traefikv1alpha1.MiddlewareTCP:
c.middlewareTCPs = append(c.middlewareTCPs, o) c.middlewareTCPs = append(c.middlewareTCPs, o)
case *v1alpha1.TraefikService: case *traefikv1alpha1.TraefikService:
c.traefikServices = append(c.traefikServices, o) c.traefikServices = append(c.traefikServices, o)
case *v1alpha1.TLSOption: case *traefikv1alpha1.TLSOption:
c.tlsOptions = append(c.tlsOptions, o) c.tlsOptions = append(c.tlsOptions, o)
case *v1alpha1.ServersTransport: case *traefikv1alpha1.ServersTransport:
c.serversTransports = append(c.serversTransports, o) c.serversTransports = append(c.serversTransports, o)
case *v1alpha1.ServersTransportTCP: case *traefikv1alpha1.ServersTransportTCP:
c.serversTransportTCPs = append(c.serversTransportTCPs, o) c.serversTransportTCPs = append(c.serversTransportTCPs, o)
case *v1alpha1.TLSStore: case *traefikv1alpha1.TLSStore:
c.tlsStores = append(c.tlsStores, o) c.tlsStores = append(c.tlsStores, o)
case *corev1.Secret: case *corev1.Secret:
c.secrets = append(c.secrets, o) c.secrets = append(c.secrets, o)
@ -91,27 +91,27 @@ func newClientMock(paths ...string) clientMock {
return c return c
} }
func (c clientMock) GetIngressRoutes() []*v1alpha1.IngressRoute { func (c clientMock) GetIngressRoutes() []*traefikv1alpha1.IngressRoute {
return c.ingressRoutes return c.ingressRoutes
} }
func (c clientMock) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP { func (c clientMock) GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP {
return c.ingressRouteTCPs return c.ingressRouteTCPs
} }
func (c clientMock) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP { func (c clientMock) GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP {
return c.ingressRouteUDPs return c.ingressRouteUDPs
} }
func (c clientMock) GetMiddlewares() []*v1alpha1.Middleware { func (c clientMock) GetMiddlewares() []*traefikv1alpha1.Middleware {
return c.middlewares return c.middlewares
} }
func (c clientMock) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP { func (c clientMock) GetMiddlewareTCPs() []*traefikv1alpha1.MiddlewareTCP {
return c.middlewareTCPs return c.middlewareTCPs
} }
func (c clientMock) GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) { func (c clientMock) GetTraefikService(namespace, name string) (*traefikv1alpha1.TraefikService, bool, error) {
for _, svc := range c.traefikServices { for _, svc := range c.traefikServices {
if svc.Namespace == namespace && svc.Name == name { if svc.Namespace == namespace && svc.Name == name {
return svc, true, nil return svc, true, nil
@ -121,27 +121,27 @@ func (c clientMock) GetTraefikService(namespace, name string) (*v1alpha1.Traefik
return nil, false, nil return nil, false, nil
} }
func (c clientMock) GetTraefikServices() []*v1alpha1.TraefikService { func (c clientMock) GetTraefikServices() []*traefikv1alpha1.TraefikService {
return c.traefikServices return c.traefikServices
} }
func (c clientMock) GetTLSOptions() []*v1alpha1.TLSOption { func (c clientMock) GetTLSOptions() []*traefikv1alpha1.TLSOption {
return c.tlsOptions return c.tlsOptions
} }
func (c clientMock) GetTLSStores() []*v1alpha1.TLSStore { func (c clientMock) GetTLSStores() []*traefikv1alpha1.TLSStore {
return c.tlsStores return c.tlsStores
} }
func (c clientMock) GetServersTransports() []*v1alpha1.ServersTransport { func (c clientMock) GetServersTransports() []*traefikv1alpha1.ServersTransport {
return c.serversTransports return c.serversTransports
} }
func (c clientMock) GetServersTransportTCPs() []*v1alpha1.ServersTransportTCP { func (c clientMock) GetServersTransportTCPs() []*traefikv1alpha1.ServersTransportTCP {
return c.serversTransportTCPs return c.serversTransportTCPs
} }
func (c clientMock) GetTLSOption(namespace, name string) (*v1alpha1.TLSOption, bool, error) { func (c clientMock) GetTLSOption(namespace, name string) (*traefikv1alpha1.TLSOption, bool, error) {
for _, option := range c.tlsOptions { for _, option := range c.tlsOptions {
if option.Namespace == namespace && option.Name == name { if option.Namespace == namespace && option.Name == name {
return option, true, nil return option, true, nil

View file

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
crdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" traefikcrdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubefake "k8s.io/client-go/kubernetes/fake" kubefake "k8s.io/client-go/kubernetes/fake"
@ -30,7 +30,7 @@ func TestClientIgnoresHelmOwnedSecrets(t *testing.T) {
} }
kubeClient := kubefake.NewSimpleClientset(helmSecret, secret) kubeClient := kubefake.NewSimpleClientset(helmSecret, secret)
crdClient := crdfake.NewSimpleClientset() crdClient := traefikcrdfake.NewSimpleClientset()
client := newClientImpl(kubeClient, crdClient) client := newClientImpl(kubeClient, crdClient)

View file

@ -25,7 +25,7 @@ import (
"github.com/traefik/traefik/v3/pkg/job" "github.com/traefik/traefik/v3/pkg/job"
"github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/provider" "github.com/traefik/traefik/v3/pkg/provider"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/safe" "github.com/traefik/traefik/v3/pkg/safe"
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/types"
@ -598,7 +598,7 @@ func getSecretValue(c Client, ns, urn string) (string, error) {
return string(secretValue), nil return string(secretValue), nil
} }
func createCircuitBreakerMiddleware(circuitBreaker *v1alpha1.CircuitBreaker) (*dynamic.CircuitBreaker, error) { func createCircuitBreakerMiddleware(circuitBreaker *traefikv1alpha1.CircuitBreaker) (*dynamic.CircuitBreaker, error) {
if circuitBreaker == nil { if circuitBreaker == nil {
return nil, nil return nil, nil
} }
@ -627,7 +627,7 @@ func createCircuitBreakerMiddleware(circuitBreaker *v1alpha1.CircuitBreaker) (*d
return cb, nil return cb, nil
} }
func createRateLimitMiddleware(rateLimit *v1alpha1.RateLimit) (*dynamic.RateLimit, error) { func createRateLimitMiddleware(rateLimit *traefikv1alpha1.RateLimit) (*dynamic.RateLimit, error) {
if rateLimit == nil { if rateLimit == nil {
return nil, nil return nil, nil
} }
@ -653,7 +653,7 @@ func createRateLimitMiddleware(rateLimit *v1alpha1.RateLimit) (*dynamic.RateLimi
return rl, nil return rl, nil
} }
func createRetryMiddleware(retry *v1alpha1.Retry) (*dynamic.Retry, error) { func createRetryMiddleware(retry *traefikv1alpha1.Retry) (*dynamic.Retry, error) {
if retry == nil { if retry == nil {
return nil, nil return nil, nil
} }
@ -668,7 +668,7 @@ func createRetryMiddleware(retry *v1alpha1.Retry) (*dynamic.Retry, error) {
return r, nil return r, nil
} }
func (p *Provider) createErrorPageMiddleware(client Client, namespace string, errorPage *v1alpha1.ErrorPage) (*dynamic.ErrorPage, *dynamic.Service, error) { func (p *Provider) createErrorPageMiddleware(client Client, namespace string, errorPage *traefikv1alpha1.ErrorPage) (*dynamic.ErrorPage, *dynamic.Service, error) {
if errorPage == nil { if errorPage == nil {
return nil, nil, nil return nil, nil, nil
} }
@ -693,7 +693,7 @@ func (p *Provider) createErrorPageMiddleware(client Client, namespace string, er
return errorPageMiddleware, balancerServerHTTP, nil return errorPageMiddleware, balancerServerHTTP, nil
} }
func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alpha1.ForwardAuth) (*dynamic.ForwardAuth, error) { func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traefikv1alpha1.ForwardAuth) (*dynamic.ForwardAuth, error) {
if auth == nil { if auth == nil {
return nil, nil return nil, nil
} }
@ -784,7 +784,7 @@ func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string,
return getCertificateBlocks(secret, namespace, secretName) return getCertificateBlocks(secret, namespace, secretName)
} }
func createBasicAuthMiddleware(client Client, namespace string, basicAuth *v1alpha1.BasicAuth) (*dynamic.BasicAuth, error) { func createBasicAuthMiddleware(client Client, namespace string, basicAuth *traefikv1alpha1.BasicAuth) (*dynamic.BasicAuth, error) {
if basicAuth == nil { if basicAuth == nil {
return nil, nil return nil, nil
} }
@ -831,7 +831,7 @@ func createBasicAuthMiddleware(client Client, namespace string, basicAuth *v1alp
}, nil }, nil
} }
func createDigestAuthMiddleware(client Client, namespace string, digestAuth *v1alpha1.DigestAuth) (*dynamic.DigestAuth, error) { func createDigestAuthMiddleware(client Client, namespace string, digestAuth *traefikv1alpha1.DigestAuth) (*dynamic.DigestAuth, error) {
if digestAuth == nil { if digestAuth == nil {
return nil, nil return nil, nil
} }
@ -906,7 +906,7 @@ func loadAuthCredentials(secret *corev1.Secret) ([]string, error) {
return credentials, nil return credentials, nil
} }
func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain { func createChainMiddleware(ctx context.Context, namespace string, chain *traefikv1alpha1.Chain) *dynamic.Chain {
if chain == nil { if chain == nil {
return nil return nil
} }
@ -1071,7 +1071,7 @@ func buildTLSStores(ctx context.Context, client Client) (map[string]tls.Store, m
} }
// buildCertificates loads TLSStore certificates from secrets and sets them into tlsConfigs. // buildCertificates loads TLSStore certificates from secrets and sets them into tlsConfigs.
func buildCertificates(client Client, tlsStore, namespace string, certificates []v1alpha1.Certificate, tlsConfigs map[string]*tls.CertAndStores) error { func buildCertificates(client Client, tlsStore, namespace string, certificates []traefikv1alpha1.Certificate, tlsConfigs map[string]*tls.CertAndStores) error {
for _, c := range certificates { for _, c := range certificates {
configKey := namespace + "/" + c.SecretName configKey := namespace + "/" + c.SecretName
if _, tlsExists := tlsConfigs[configKey]; !tlsExists { if _, tlsExists := tlsConfigs[configKey]; !tlsExists {

View file

@ -12,7 +12,7 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/provider" "github.com/traefik/traefik/v3/pkg/provider"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
@ -84,8 +84,8 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
serviceName := normalized serviceName := normalized
if len(route.Services) > 1 { if len(route.Services) > 1 {
spec := v1alpha1.TraefikServiceSpec{ spec := traefikv1alpha1.TraefikServiceSpec{
Weighted: &v1alpha1.WeightedRoundRobin{ Weighted: &traefikv1alpha1.WeightedRoundRobin{
Services: route.Services, Services: route.Services,
}, },
} }
@ -155,7 +155,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
return conf return conf
} }
func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace string, middlewares []v1alpha1.MiddlewareRef) ([]string, error) { func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace string, middlewares []traefikv1alpha1.MiddlewareRef) ([]string, error) {
var mds []string var mds []string
for _, mi := range middlewares { for _, mi := range middlewares {
@ -203,7 +203,7 @@ type configBuilder struct {
// buildTraefikService creates the configuration for the traefik service defined in tService, // buildTraefikService creates the configuration for the traefik service defined in tService,
// and adds it to the given conf map. // and adds it to the given conf map.
func (c configBuilder) buildTraefikService(ctx context.Context, tService *v1alpha1.TraefikService, conf map[string]*dynamic.Service) error { func (c configBuilder) buildTraefikService(ctx context.Context, tService *traefikv1alpha1.TraefikService, conf map[string]*dynamic.Service) error {
id := provider.Normalize(makeID(tService.Namespace, tService.Name)) id := provider.Normalize(makeID(tService.Namespace, tService.Name))
if tService.Spec.Weighted != nil { if tService.Spec.Weighted != nil {
@ -217,7 +217,7 @@ func (c configBuilder) buildTraefikService(ctx context.Context, tService *v1alph
// buildServicesLB creates the configuration for the load-balancer of services named id, and defined in tService. // buildServicesLB creates the configuration for the load-balancer of services named id, and defined in tService.
// It adds it to the given conf map. // It adds it to the given conf map.
func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tService v1alpha1.TraefikServiceSpec, id string, conf map[string]*dynamic.Service) error { func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tService traefikv1alpha1.TraefikServiceSpec, id string, conf map[string]*dynamic.Service) error {
var wrrServices []dynamic.WRRService var wrrServices []dynamic.WRRService
for _, service := range tService.Weighted.Services { for _, service := range tService.Weighted.Services {
@ -252,7 +252,7 @@ func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tS
// buildMirroring creates the configuration for the mirroring service named id, and defined by tService. // buildMirroring creates the configuration for the mirroring service named id, and defined by tService.
// It adds it to the given conf map. // It adds it to the given conf map.
func (c configBuilder) buildMirroring(ctx context.Context, tService *v1alpha1.TraefikService, id string, conf map[string]*dynamic.Service) error { func (c configBuilder) buildMirroring(ctx context.Context, tService *traefikv1alpha1.TraefikService, id string, conf map[string]*dynamic.Service) error {
fullNameMain, k8sService, err := c.nameAndService(ctx, tService.Namespace, tService.Spec.Mirroring.LoadBalancerSpec) fullNameMain, k8sService, err := c.nameAndService(ctx, tService.Namespace, tService.Spec.Mirroring.LoadBalancerSpec)
if err != nil { if err != nil {
return err return err
@ -291,7 +291,7 @@ func (c configBuilder) buildMirroring(ctx context.Context, tService *v1alpha1.Tr
} }
// buildServersLB creates the configuration for the load-balancer of servers defined by svc. // buildServersLB creates the configuration for the load-balancer of servers defined by svc.
func (c configBuilder) buildServersLB(namespace string, svc v1alpha1.LoadBalancerSpec) (*dynamic.Service, error) { func (c configBuilder) buildServersLB(namespace string, svc traefikv1alpha1.LoadBalancerSpec) (*dynamic.Service, error) {
servers, err := c.loadServers(namespace, svc) servers, err := c.loadServers(namespace, svc)
if err != nil { if err != nil {
return nil, err return nil, err
@ -344,7 +344,7 @@ func (c *configBuilder) makeServersTransportKey(parentNamespace string, serversT
return provider.Normalize(makeID(parentNamespace, serversTransportName)), nil return provider.Normalize(makeID(parentNamespace, serversTransportName)), nil
} }
func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) { func (c configBuilder) loadServers(parentNamespace string, svc traefikv1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) {
strategy := svc.Strategy strategy := svc.Strategy
if strategy == "" { if strategy == "" {
strategy = roundRobinStrategy strategy = roundRobinStrategy
@ -452,7 +452,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBala
// In addition, if the service is a Kubernetes one, // In addition, if the service is a Kubernetes one,
// it generates and returns the configuration part for such a service, // it generates and returns the configuration part for such a service,
// so that the caller can add it to the global config map. // so that the caller can add it to the global config map.
func (c configBuilder) nameAndService(ctx context.Context, parentNamespace string, service v1alpha1.LoadBalancerSpec) (string, *dynamic.Service, error) { func (c configBuilder) nameAndService(ctx context.Context, parentNamespace string, service traefikv1alpha1.LoadBalancerSpec) (string, *dynamic.Service, error) {
svcCtx := log.Ctx(ctx).With().Str(logs.ServiceName, service.Name).Logger().WithContext(ctx) svcCtx := log.Ctx(ctx).With().Str(logs.ServiceName, service.Name).Logger().WithContext(ctx)
namespace := namespaceOrFallback(service, parentNamespace) namespace := namespaceOrFallback(service, parentNamespace)
@ -487,7 +487,7 @@ func splitSvcNameProvider(name string) (string, string) {
return svc, pvd return svc, pvd
} }
func fullServiceName(ctx context.Context, namespace string, service v1alpha1.LoadBalancerSpec, port intstr.IntOrString) string { func fullServiceName(ctx context.Context, namespace string, service traefikv1alpha1.LoadBalancerSpec, port intstr.IntOrString) string {
if (port.Type == intstr.Int && port.IntVal != 0) || (port.Type == intstr.String && port.StrVal != "") { if (port.Type == intstr.Int && port.IntVal != 0) || (port.Type == intstr.String && port.StrVal != "") {
return provider.Normalize(fmt.Sprintf("%s-%s-%s", namespace, service.Name, &port)) return provider.Normalize(fmt.Sprintf("%s-%s-%s", namespace, service.Name, &port))
} }
@ -508,7 +508,7 @@ func fullServiceName(ctx context.Context, namespace string, service v1alpha1.Loa
return provider.Normalize(name) + providerNamespaceSeparator + pName return provider.Normalize(name) + providerNamespaceSeparator + pName
} }
func namespaceOrFallback(lb v1alpha1.LoadBalancerSpec, fallback string) string { func namespaceOrFallback(lb traefikv1alpha1.LoadBalancerSpec, fallback string) string {
if lb.Namespace != "" { if lb.Namespace != "" {
return lb.Namespace return lb.Namespace
} }
@ -516,7 +516,7 @@ func namespaceOrFallback(lb v1alpha1.LoadBalancerSpec, fallback string) string {
} }
// getTLSHTTP mutates tlsConfigs. // getTLSHTTP mutates tlsConfigs.
func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { func getTLSHTTP(ctx context.Context, ingressRoute *traefikv1alpha1.IngressRoute, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
if ingressRoute.Spec.TLS == nil { if ingressRoute.Spec.TLS == nil {
return nil return nil
} }

View file

@ -12,7 +12,7 @@ import (
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/logs"
"github.com/traefik/traefik/v3/pkg/provider" "github.com/traefik/traefik/v3/pkg/provider"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@ -144,7 +144,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
return conf return conf
} }
func (p *Provider) makeMiddlewareTCPKeys(ctx context.Context, ingRouteTCPNamespace string, middlewares []v1alpha1.ObjectReference) ([]string, error) { func (p *Provider) makeMiddlewareTCPKeys(ctx context.Context, ingRouteTCPNamespace string, middlewares []traefikv1alpha1.ObjectReference) ([]string, error) {
var mds []string var mds []string
for _, mi := range middlewares { for _, mi := range middlewares {
@ -173,7 +173,7 @@ func (p *Provider) makeMiddlewareTCPKeys(ctx context.Context, ingRouteTCPNamespa
return mds, nil return mds, nil
} }
func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace string, service v1alpha1.ServiceTCP) (*dynamic.TCPService, error) { func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace string, service traefikv1alpha1.ServiceTCP) (*dynamic.TCPService, error) {
ns := parentNamespace ns := parentNamespace
if len(service.Namespace) > 0 { if len(service.Namespace) > 0 {
if !isNamespaceAllowed(p.AllowCrossNamespace, parentNamespace, service.Namespace) { if !isNamespaceAllowed(p.AllowCrossNamespace, parentNamespace, service.Namespace) {
@ -213,7 +213,7 @@ func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace st
return tcpService, nil return tcpService, nil
} }
func (p *Provider) loadTCPServers(client Client, namespace string, svc v1alpha1.ServiceTCP) ([]dynamic.TCPServer, error) { func (p *Provider) loadTCPServers(client Client, namespace string, svc traefikv1alpha1.ServiceTCP) ([]dynamic.TCPServer, error) {
service, exists, err := client.GetService(namespace, svc.Name) service, exists, err := client.GetService(namespace, svc.Name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -304,7 +304,7 @@ func (p *Provider) makeTCPServersTransportKey(parentNamespace string, serversTra
} }
// getTLSTCP mutates tlsConfigs. // getTLSTCP mutates tlsConfigs.
func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { func getTLSTCP(ctx context.Context, ingressRoute *traefikv1alpha1.IngressRouteTCP, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
if ingressRoute.Spec.TLS == nil { if ingressRoute.Spec.TLS == nil {
return nil return nil
} }

View file

@ -14,8 +14,8 @@ import (
ptypes "github.com/traefik/paerser/types" ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/provider" "github.com/traefik/traefik/v3/pkg/provider"
crdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" traefikcrdfake "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/types"
@ -6400,25 +6400,25 @@ func TestCrossNamespace(t *testing.T) {
switch o := obj.(type) { switch o := obj.(type) {
case *corev1.Service, *corev1.Endpoints, *corev1.Secret: case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
k8sObjects = append(k8sObjects, o) k8sObjects = append(k8sObjects, o)
case *v1alpha1.IngressRoute: case *traefikv1alpha1.IngressRoute:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteTCP: case *traefikv1alpha1.IngressRouteTCP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteUDP: case *traefikv1alpha1.IngressRouteUDP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.Middleware: case *traefikv1alpha1.Middleware:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.MiddlewareTCP: case *traefikv1alpha1.MiddlewareTCP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TraefikService: case *traefikv1alpha1.TraefikService:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSOption: case *traefikv1alpha1.TLSOption:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSStore: case *traefikv1alpha1.TLSStore:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.ServersTransport: case *traefikv1alpha1.ServersTransport:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.ServersTransportTCP: case *traefikv1alpha1.ServersTransportTCP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
default: default:
} }
@ -6426,7 +6426,7 @@ func TestCrossNamespace(t *testing.T) {
} }
kubeClient := kubefake.NewSimpleClientset(k8sObjects...) kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
crdClient := crdfake.NewSimpleClientset(crdObjects...) crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
client := newClientImpl(kubeClient, crdClient) client := newClientImpl(kubeClient, crdClient)
@ -6707,19 +6707,19 @@ func TestExternalNameService(t *testing.T) {
switch o := obj.(type) { switch o := obj.(type) {
case *corev1.Service, *corev1.Endpoints, *corev1.Secret: case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
k8sObjects = append(k8sObjects, o) k8sObjects = append(k8sObjects, o)
case *v1alpha1.IngressRoute: case *traefikv1alpha1.IngressRoute:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteTCP: case *traefikv1alpha1.IngressRouteTCP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteUDP: case *traefikv1alpha1.IngressRouteUDP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.Middleware: case *traefikv1alpha1.Middleware:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TraefikService: case *traefikv1alpha1.TraefikService:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSOption: case *traefikv1alpha1.TLSOption:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSStore: case *traefikv1alpha1.TLSStore:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
default: default:
} }
@ -6727,7 +6727,7 @@ func TestExternalNameService(t *testing.T) {
} }
kubeClient := kubefake.NewSimpleClientset(k8sObjects...) kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
crdClient := crdfake.NewSimpleClientset(crdObjects...) crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
client := newClientImpl(kubeClient, crdClient) client := newClientImpl(kubeClient, crdClient)
@ -6920,19 +6920,19 @@ func TestNativeLB(t *testing.T) {
switch o := obj.(type) { switch o := obj.(type) {
case *corev1.Service, *corev1.Endpoints, *corev1.Secret: case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
k8sObjects = append(k8sObjects, o) k8sObjects = append(k8sObjects, o)
case *v1alpha1.IngressRoute: case *traefikv1alpha1.IngressRoute:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteTCP: case *traefikv1alpha1.IngressRouteTCP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.IngressRouteUDP: case *traefikv1alpha1.IngressRouteUDP:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.Middleware: case *traefikv1alpha1.Middleware:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TraefikService: case *traefikv1alpha1.TraefikService:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSOption: case *traefikv1alpha1.TLSOption:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSStore: case *traefikv1alpha1.TLSStore:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
default: default:
} }
@ -6940,7 +6940,7 @@ func TestNativeLB(t *testing.T) {
} }
kubeClient := kubefake.NewSimpleClientset(k8sObjects...) kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
crdClient := crdfake.NewSimpleClientset(crdObjects...) crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
client := newClientImpl(kubeClient, crdClient) client := newClientImpl(kubeClient, crdClient)
@ -6964,7 +6964,6 @@ func TestNativeLB(t *testing.T) {
func TestCreateBasicAuthCredentials(t *testing.T) { func TestCreateBasicAuthCredentials(t *testing.T) {
var k8sObjects []runtime.Object var k8sObjects []runtime.Object
var crdObjects []runtime.Object
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/basic_auth_secrets.yml")) yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/basic_auth_secrets.yml"))
if err != nil { if err != nil {
panic(err) panic(err)
@ -6980,7 +6979,7 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
} }
kubeClient := kubefake.NewSimpleClientset(k8sObjects...) kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
crdClient := crdfake.NewSimpleClientset(crdObjects...) crdClient := traefikcrdfake.NewSimpleClientset()
client := newClientImpl(kubeClient, crdClient) client := newClientImpl(kubeClient, crdClient)
@ -6989,13 +6988,13 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
eventCh, err := client.WatchAll([]string{"default"}, stopCh) eventCh, err := client.WatchAll([]string{"default"}, stopCh)
require.NoError(t, err) require.NoError(t, err)
if k8sObjects != nil || crdObjects != nil { if len(k8sObjects) != 0 {
// just wait for the first event // just wait for the first event
<-eventCh <-eventCh
} }
// Testing for username/password components in basic-auth secret // Testing for username/password components in basic-auth secret
basicAuth, secretErr := createBasicAuthMiddleware(client, "default", &v1alpha1.BasicAuth{Secret: "basic-auth-secret"}) basicAuth, secretErr := createBasicAuthMiddleware(client, "default", &traefikv1alpha1.BasicAuth{Secret: "basic-auth-secret"})
require.NoError(t, secretErr) require.NoError(t, secretErr)
require.Len(t, basicAuth.Users, 1) require.Len(t, basicAuth.Users, 1)
@ -7010,7 +7009,7 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
assert.True(t, auth.CheckSecret("password", hashedPassword)) assert.True(t, auth.CheckSecret("password", hashedPassword))
// Testing for username/password components in htpasswd secret // Testing for username/password components in htpasswd secret
basicAuth, secretErr = createBasicAuthMiddleware(client, "default", &v1alpha1.BasicAuth{Secret: "auth-secret"}) basicAuth, secretErr = createBasicAuthMiddleware(client, "default", &traefikv1alpha1.BasicAuth{Secret: "auth-secret"})
require.NoError(t, secretErr) require.NoError(t, secretErr)
require.Len(t, basicAuth.Users, 2) require.Len(t, basicAuth.Users, 2)

View file

@ -9,7 +9,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@ -78,7 +78,7 @@ func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client
return conf return conf
} }
func (p *Provider) createLoadBalancerServerUDP(client Client, parentNamespace string, service v1alpha1.ServiceUDP) (*dynamic.UDPService, error) { func (p *Provider) createLoadBalancerServerUDP(client Client, parentNamespace string, service traefikv1alpha1.ServiceUDP) (*dynamic.UDPService, error) {
ns := parentNamespace ns := parentNamespace
if len(service.Namespace) > 0 { if len(service.Namespace) > 0 {
if !isNamespaceAllowed(p.AllowCrossNamespace, parentNamespace, service.Namespace) { if !isNamespaceAllowed(p.AllowCrossNamespace, parentNamespace, service.Namespace) {
@ -102,7 +102,7 @@ func (p *Provider) createLoadBalancerServerUDP(client Client, parentNamespace st
return udpService, nil return udpService, nil
} }
func (p *Provider) loadUDPServers(client Client, namespace string, svc v1alpha1.ServiceUDP) ([]dynamic.UDPServer, error) { func (p *Provider) loadUDPServers(client Client, namespace string, svc traefikv1alpha1.ServiceUDP) ([]dynamic.UDPServer, error) {
service, exists, err := client.GetService(namespace, svc.Name) service, exists, err := client.GetService(namespace, svc.Name)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -3,7 +3,7 @@ package v1alpha1
import ( import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" kschema "k8s.io/apimachinery/pkg/runtime/schema"
) )
// GroupName is the group name for Traefik. // GroupName is the group name for Traefik.
@ -18,15 +18,15 @@ var (
) )
// SchemeGroupVersion is group version used to register these objects. // SchemeGroupVersion is group version used to register these objects.
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} var SchemeGroupVersion = kschema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Kind takes an unqualified kind and returns back a Group qualified GroupKind. // Kind takes an unqualified kind and returns back a Group qualified GroupKind.
func Kind(kind string) schema.GroupKind { func Kind(kind string) kschema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind() return SchemeGroupVersion.WithKind(kind).GroupKind()
} }
// Resource takes an unqualified resource and returns a Group qualified GroupResource. // Resource takes an unqualified resource and returns a Group qualified GroupResource.
func Resource(resource string) schema.GroupResource { func Resource(resource string) kschema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource() return SchemeGroupVersion.WithResource(resource).GroupResource()
} }

View file

@ -9,16 +9,16 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
kubeerror "k8s.io/apimachinery/pkg/api/errors" kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers" kinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes" kclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/gateway-api/apis/v1alpha2" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned" gateclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned"
"sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions" gateinformers "sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions"
) )
const resyncPeriod = 10 * time.Minute const resyncPeriod = 10 * time.Minute
@ -33,7 +33,7 @@ func (reh *resourceEventHandler) OnAdd(obj interface{}) {
func (reh *resourceEventHandler) OnUpdate(oldObj, newObj interface{}) { func (reh *resourceEventHandler) OnUpdate(oldObj, newObj interface{}) {
switch oldObj.(type) { switch oldObj.(type) {
case *v1alpha2.GatewayClass: case *gatev1alpha2.GatewayClass:
// Skip update for gateway classes. We only manage addition or deletion for this cluster-wide resource. // Skip update for gateway classes. We only manage addition or deletion for this cluster-wide resource.
return return
default: default:
@ -50,13 +50,13 @@ func (reh *resourceEventHandler) OnDelete(obj interface{}) {
// The stores can then be accessed via the Get* functions. // The stores can then be accessed via the Get* functions.
type Client interface { type Client interface {
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error)
UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error
UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error
GetGateways() []*v1alpha2.Gateway GetGateways() []*gatev1alpha2.Gateway
GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error)
GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error)
GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRoute, error)
GetService(namespace, name string) (*corev1.Service, bool, error) GetService(namespace, name string) (*corev1.Service, bool, error)
GetSecret(namespace, name string) (*corev1.Secret, bool, error) GetSecret(namespace, name string) (*corev1.Secret, bool, error)
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
@ -64,14 +64,14 @@ type Client interface {
} }
type clientWrapper struct { type clientWrapper struct {
csGateway versioned.Interface csGateway gateclientset.Interface
csKube kubernetes.Interface csKube kclientset.Interface
factoryNamespace informers.SharedInformerFactory factoryNamespace kinformers.SharedInformerFactory
factoryGatewayClass externalversions.SharedInformerFactory factoryGatewayClass gateinformers.SharedInformerFactory
factoriesGateway map[string]externalversions.SharedInformerFactory factoriesGateway map[string]gateinformers.SharedInformerFactory
factoriesKube map[string]informers.SharedInformerFactory factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]informers.SharedInformerFactory factoriesSecret map[string]kinformers.SharedInformerFactory
isNamespaceAll bool isNamespaceAll bool
watchedNamespaces []string watchedNamespaces []string
@ -80,12 +80,12 @@ type clientWrapper struct {
} }
func createClientFromConfig(c *rest.Config) (*clientWrapper, error) { func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
csGateway, err := versioned.NewForConfig(c) csGateway, err := gateclientset.NewForConfig(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
csKube, err := kubernetes.NewForConfig(c) csKube, err := kclientset.NewForConfig(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -93,13 +93,13 @@ func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
return newClientImpl(csKube, csGateway), nil return newClientImpl(csKube, csGateway), nil
} }
func newClientImpl(csKube kubernetes.Interface, csGateway versioned.Interface) *clientWrapper { func newClientImpl(csKube kclientset.Interface, csGateway gateclientset.Interface) *clientWrapper {
return &clientWrapper{ return &clientWrapper{
csGateway: csGateway, csGateway: csGateway,
csKube: csKube, csKube: csKube,
factoriesGateway: make(map[string]externalversions.SharedInformerFactory), factoriesGateway: make(map[string]gateinformers.SharedInformerFactory),
factoriesKube: make(map[string]informers.SharedInformerFactory), factoriesKube: make(map[string]kinformers.SharedInformerFactory),
factoriesSecret: make(map[string]informers.SharedInformerFactory), factoriesSecret: make(map[string]kinformers.SharedInformerFactory),
} }
} }
@ -126,8 +126,7 @@ func newExternalClusterClientFromFile(file string) (*clientWrapper, error) {
return createClientFromConfig(configFromFlags) return createClientFromConfig(configFromFlags)
} }
// newExternalClusterClient returns a new Provider client that may run outside // newExternalClusterClient returns a new Provider client that may run outside of the cluster.
// of the cluster.
// The endpoint parameter must not be empty. // The endpoint parameter must not be empty.
func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrapper, error) { func newExternalClusterClient(endpoint, token, caFilePath string) (*clientWrapper, error) {
if endpoint == "" { if endpoint == "" {
@ -171,28 +170,55 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
options.LabelSelector = c.labelSelector options.LabelSelector = c.labelSelector
} }
c.factoryNamespace = informers.NewSharedInformerFactory(c.csKube, resyncPeriod) c.factoryNamespace = kinformers.NewSharedInformerFactory(c.csKube, resyncPeriod)
c.factoryNamespace.Core().V1().Namespaces().Informer().AddEventHandler(eventHandler) _, err := c.factoryNamespace.Core().V1().Namespaces().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.factoryGatewayClass = externalversions.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, externalversions.WithTweakListOptions(labelSelectorOptions)) c.factoryGatewayClass = gateinformers.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, gateinformers.WithTweakListOptions(labelSelectorOptions))
c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Informer().AddEventHandler(eventHandler) _, err = c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
// TODO manage Reference Policy // TODO manage Reference Policy
// https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.ReferencePolicy // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.ReferencePolicy
for _, ns := range namespaces { for _, ns := range namespaces {
factoryGateway := externalversions.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, externalversions.WithNamespace(ns)) factoryGateway := gateinformers.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, gateinformers.WithNamespace(ns))
factoryGateway.Gateway().V1alpha2().Gateways().Informer().AddEventHandler(eventHandler) _, err = factoryGateway.Gateway().V1alpha2().Gateways().Informer().AddEventHandler(eventHandler)
factoryGateway.Gateway().V1alpha2().HTTPRoutes().Informer().AddEventHandler(eventHandler) if err != nil {
factoryGateway.Gateway().V1alpha2().TCPRoutes().Informer().AddEventHandler(eventHandler) return nil, err
factoryGateway.Gateway().V1alpha2().TLSRoutes().Informer().AddEventHandler(eventHandler) }
_, err = factoryGateway.Gateway().V1alpha2().HTTPRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1alpha2().TCPRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
_, err = factoryGateway.Gateway().V1alpha2().TLSRoutes().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
factoryKube := informers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, informers.WithNamespace(ns)) factoryKube := kinformers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, kinformers.WithNamespace(ns))
factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler) _, err = factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler) if err != nil {
return nil, err
}
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
factorySecret := informers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, informers.WithNamespace(ns), informers.WithTweakListOptions(notOwnedByHelm)) factorySecret := kinformers.NewSharedInformerFactoryWithOptions(c.csKube, resyncPeriod, kinformers.WithNamespace(ns), kinformers.WithTweakListOptions(notOwnedByHelm))
factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler) _, err = factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.factoriesGateway[ns] = factoryGateway c.factoriesGateway[ns] = factoryGateway
c.factoriesKube[ns] = factoryKube c.factoriesKube[ns] = factoryKube
@ -260,8 +286,8 @@ func (c *clientWrapper) GetNamespaces(selector labels.Selector) ([]string, error
return namespaces, nil return namespaces, nil
} }
func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) { func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error) {
var httpRoutes []*v1alpha2.HTTPRoute var httpRoutes []*gatev1alpha2.HTTPRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
if !c.isWatchedNamespace(namespace) { if !c.isWatchedNamespace(namespace) {
log.Warn().Msgf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace) log.Warn().Msgf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace)
@ -284,8 +310,8 @@ func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRout
return httpRoutes, nil return httpRoutes, nil
} }
func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) { func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error) {
var tcpRoutes []*v1alpha2.TCPRoute var tcpRoutes []*gatev1alpha2.TCPRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
if !c.isWatchedNamespace(namespace) { if !c.isWatchedNamespace(namespace) {
log.Warn().Msgf("Failed to get TCPRoutes: %q is not within watched namespaces", namespace) log.Warn().Msgf("Failed to get TCPRoutes: %q is not within watched namespaces", namespace)
@ -307,8 +333,8 @@ func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute,
return tcpRoutes, nil return tcpRoutes, nil
} }
func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) { func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRoute, error) {
var tlsRoutes []*v1alpha2.TLSRoute var tlsRoutes []*gatev1alpha2.TLSRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
if !c.isWatchedNamespace(namespace) { if !c.isWatchedNamespace(namespace) {
log.Warn().Msgf("Failed to get TLSRoutes: %q is not within watched namespaces", namespace) log.Warn().Msgf("Failed to get TLSRoutes: %q is not within watched namespaces", namespace)
@ -330,8 +356,8 @@ func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute,
return tlsRoutes, nil return tlsRoutes, nil
} }
func (c *clientWrapper) GetGateways() []*v1alpha2.Gateway { func (c *clientWrapper) GetGateways() []*gatev1alpha2.Gateway {
var result []*v1alpha2.Gateway var result []*gatev1alpha2.Gateway
for ns, factory := range c.factoriesGateway { for ns, factory := range c.factoriesGateway {
gateways, err := factory.Gateway().V1alpha2().Gateways().Lister().List(labels.Everything()) gateways, err := factory.Gateway().V1alpha2().Gateways().Lister().List(labels.Everything())
@ -345,11 +371,11 @@ func (c *clientWrapper) GetGateways() []*v1alpha2.Gateway {
return result return result
} }
func (c *clientWrapper) GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) { func (c *clientWrapper) GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error) {
return c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Lister().List(labels.Everything()) return c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Lister().List(labels.Everything())
} }
func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error { func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error {
gc := gatewayClass.DeepCopy() gc := gatewayClass.DeepCopy()
var newConditions []metav1.Condition var newConditions []metav1.Condition
@ -380,7 +406,7 @@ func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayC
return nil return nil
} }
func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error { func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error {
if !c.isWatchedNamespace(gateway.Namespace) { if !c.isWatchedNamespace(gateway.Namespace) {
return fmt.Errorf("cannot update Gateway status %s/%s: namespace is not within watched namespaces", gateway.Namespace, gateway.Name) return fmt.Errorf("cannot update Gateway status %s/%s: namespace is not within watched namespaces", gateway.Namespace, gateway.Name)
} }
@ -403,7 +429,7 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewaySt
return nil return nil
} }
func statusEquals(oldStatus, newStatus v1alpha2.GatewayStatus) bool { func statusEquals(oldStatus, newStatus gatev1alpha2.GatewayStatus) bool {
if len(oldStatus.Listeners) != len(newStatus.Listeners) { if len(oldStatus.Listeners) != len(newStatus.Listeners) {
return false return false
} }
@ -510,7 +536,7 @@ func eventHandlerFunc(events chan<- interface{}, obj interface{}) {
// translateNotFoundError will translate a "not found" error to a boolean return // translateNotFoundError will translate a "not found" error to a boolean return
// value which indicates if the resource exists and a nil error. // value which indicates if the resource exists and a nil error.
func translateNotFoundError(err error) (bool, error) { func translateNotFoundError(err error) (bool, error) {
if kubeerror.IsNotFound(err) { if kerror.IsNotFound(err) {
return false, nil return false, nil
} }
return err == nil, err return err == nil, err

View file

@ -9,15 +9,15 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes/scheme" kscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/gateway-api/apis/v1alpha2" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
) )
var _ Client = (*clientMock)(nil) var _ Client = (*clientMock)(nil)
func init() { func init() {
// required by k8s.MustParseYaml // required by k8s.MustParseYaml
err := v1alpha2.AddToScheme(scheme.Scheme) err := gatev1alpha2.AddToScheme(kscheme.Scheme)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -33,11 +33,11 @@ type clientMock struct {
apiSecretError error apiSecretError error
apiEndpointsError error apiEndpointsError error
gatewayClasses []*v1alpha2.GatewayClass gatewayClasses []*gatev1alpha2.GatewayClass
gateways []*v1alpha2.Gateway gateways []*gatev1alpha2.Gateway
httpRoutes []*v1alpha2.HTTPRoute httpRoutes []*gatev1alpha2.HTTPRoute
tcpRoutes []*v1alpha2.TCPRoute tcpRoutes []*gatev1alpha2.TCPRoute
tlsRoutes []*v1alpha2.TLSRoute tlsRoutes []*gatev1alpha2.TLSRoute
watchChan chan interface{} watchChan chan interface{}
} }
@ -62,15 +62,15 @@ func newClientMock(paths ...string) clientMock {
c.namespaces = append(c.namespaces, o) c.namespaces = append(c.namespaces, o)
case *corev1.Endpoints: case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o) c.endpoints = append(c.endpoints, o)
case *v1alpha2.GatewayClass: case *gatev1alpha2.GatewayClass:
c.gatewayClasses = append(c.gatewayClasses, o) c.gatewayClasses = append(c.gatewayClasses, o)
case *v1alpha2.Gateway: case *gatev1alpha2.Gateway:
c.gateways = append(c.gateways, o) c.gateways = append(c.gateways, o)
case *v1alpha2.HTTPRoute: case *gatev1alpha2.HTTPRoute:
c.httpRoutes = append(c.httpRoutes, o) c.httpRoutes = append(c.httpRoutes, o)
case *v1alpha2.TCPRoute: case *gatev1alpha2.TCPRoute:
c.tcpRoutes = append(c.tcpRoutes, o) c.tcpRoutes = append(c.tcpRoutes, o)
case *v1alpha2.TLSRoute: case *gatev1alpha2.TLSRoute:
c.tlsRoutes = append(c.tlsRoutes, o) c.tlsRoutes = append(c.tlsRoutes, o)
default: default:
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o)) panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
@ -81,7 +81,7 @@ func newClientMock(paths ...string) clientMock {
return c return c
} }
func (c clientMock) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus v1alpha2.GatewayStatus) error { func (c clientMock) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error {
for _, g := range c.gateways { for _, g := range c.gateways {
if g.Name == gateway.Name { if g.Name == gateway.Name {
if !statusEquals(g.Status, gatewayStatus) { if !statusEquals(g.Status, gatewayStatus) {
@ -94,7 +94,7 @@ func (c clientMock) UpdateGatewayStatus(gateway *v1alpha2.Gateway, gatewayStatus
return nil return nil
} }
func (c clientMock) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass, condition metav1.Condition) error { func (c clientMock) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error {
for _, gc := range c.gatewayClasses { for _, gc := range c.gatewayClasses {
if gc.Name == gatewayClass.Name { if gc.Name == gatewayClass.Name {
for _, c := range gc.Status.Conditions { for _, c := range gc.Status.Conditions {
@ -110,7 +110,7 @@ func (c clientMock) UpdateGatewayClassStatus(gatewayClass *v1alpha2.GatewayClass
return nil return nil
} }
func (c clientMock) UpdateGatewayStatusConditions(gateway *v1alpha2.Gateway, condition metav1.Condition) error { func (c clientMock) UpdateGatewayStatusConditions(gateway *gatev1alpha2.Gateway, condition metav1.Condition) error {
for _, g := range c.gatewayClasses { for _, g := range c.gatewayClasses {
if g.Name == gateway.Name { if g.Name == gateway.Name {
for _, c := range g.Status.Conditions { for _, c := range g.Status.Conditions {
@ -126,11 +126,11 @@ func (c clientMock) UpdateGatewayStatusConditions(gateway *v1alpha2.Gateway, con
return nil return nil
} }
func (c clientMock) GetGatewayClasses() ([]*v1alpha2.GatewayClass, error) { func (c clientMock) GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error) {
return c.gatewayClasses, nil return c.gatewayClasses, nil
} }
func (c clientMock) GetGateways() []*v1alpha2.Gateway { func (c clientMock) GetGateways() []*gatev1alpha2.Gateway {
return c.gateways return c.gateways
} }
@ -148,8 +148,8 @@ func (c clientMock) GetNamespaces(selector labels.Selector) ([]string, error) {
return ns, nil return ns, nil
} }
func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, error) { func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error) {
var httpRoutes []*v1alpha2.HTTPRoute var httpRoutes []*gatev1alpha2.HTTPRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
for _, httpRoute := range c.httpRoutes { for _, httpRoute := range c.httpRoutes {
if inNamespace(httpRoute.ObjectMeta, namespace) { if inNamespace(httpRoute.ObjectMeta, namespace) {
@ -160,8 +160,8 @@ func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRoute, e
return httpRoutes, nil return httpRoutes, nil
} }
func (c clientMock) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, error) { func (c clientMock) GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error) {
var tcpRoutes []*v1alpha2.TCPRoute var tcpRoutes []*gatev1alpha2.TCPRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
for _, tcpRoute := range c.tcpRoutes { for _, tcpRoute := range c.tcpRoutes {
if inNamespace(tcpRoute.ObjectMeta, namespace) { if inNamespace(tcpRoute.ObjectMeta, namespace) {
@ -172,8 +172,8 @@ func (c clientMock) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, err
return tcpRoutes, nil return tcpRoutes, nil
} }
func (c clientMock) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, error) { func (c clientMock) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRoute, error) {
var tlsRoutes []*v1alpha2.TLSRoute var tlsRoutes []*gatev1alpha2.TLSRoute
for _, namespace := range namespaces { for _, namespace := range namespaces {
for _, tlsRoute := range c.tlsRoutes { for _, tlsRoute := range c.tlsRoutes {
if inNamespace(tlsRoute.ObjectMeta, namespace) { if inNamespace(tlsRoute.ObjectMeta, namespace) {

View file

@ -5,32 +5,32 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/gateway-api/apis/v1alpha2" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
) )
func TestStatusEquals(t *testing.T) { func TestStatusEquals(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
statusA v1alpha2.GatewayStatus statusA gatev1alpha2.GatewayStatus
statusB v1alpha2.GatewayStatus statusB gatev1alpha2.GatewayStatus
expected bool expected bool
}{ }{
{ {
desc: "Empty", desc: "Empty",
statusA: v1alpha2.GatewayStatus{}, statusA: gatev1alpha2.GatewayStatus{},
statusB: v1alpha2.GatewayStatus{}, statusB: gatev1alpha2.GatewayStatus{},
expected: true, expected: true,
}, },
{ {
desc: "Same status", desc: "Same status",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobar", Type: "foobar",
Reason: "foobar", Reason: "foobar",
}, },
}, },
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "foo", Name: "foo",
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
@ -42,14 +42,14 @@ func TestStatusEquals(t *testing.T) {
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobar", Type: "foobar",
Reason: "foobar", Reason: "foobar",
}, },
}, },
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "foo", Name: "foo",
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
@ -65,11 +65,11 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Listeners length not equal", desc: "Listeners length not equal",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{}, Listeners: []gatev1alpha2.ListenerStatus{},
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{}, {},
}, },
}, },
@ -77,10 +77,10 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway conditions length not equal", desc: "Gateway conditions length not equal",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{}, Conditions: []metav1.Condition{},
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{}, {},
}, },
@ -89,14 +89,14 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway conditions different types", desc: "Gateway conditions different types",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobar", Type: "foobar",
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobir", Type: "foobir",
@ -107,14 +107,14 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway conditions same types but different reason", desc: "Gateway conditions same types but different reason",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobar", Type: "foobar",
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
Type: "foobar", Type: "foobar",
@ -126,16 +126,16 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway listeners conditions length", desc: "Gateway listeners conditions length",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "foo", Name: "foo",
Conditions: []metav1.Condition{}, Conditions: []metav1.Condition{},
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "foo", Name: "foo",
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
@ -148,8 +148,8 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway listeners conditions same types but different status", desc: "Gateway listeners conditions same types but different status",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
@ -159,8 +159,8 @@ func TestStatusEquals(t *testing.T) {
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
@ -175,8 +175,8 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway listeners conditions same types but different message", desc: "Gateway listeners conditions same types but different message",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
@ -186,8 +186,8 @@ func TestStatusEquals(t *testing.T) {
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
{ {
@ -202,8 +202,8 @@ func TestStatusEquals(t *testing.T) {
}, },
{ {
desc: "Gateway listeners conditions same types/reason but different names", desc: "Gateway listeners conditions same types/reason but different names",
statusA: v1alpha2.GatewayStatus{ statusA: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "foo", Name: "foo",
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{
@ -215,8 +215,8 @@ func TestStatusEquals(t *testing.T) {
}, },
}, },
}, },
statusB: v1alpha2.GatewayStatus{ statusB: gatev1alpha2.GatewayStatus{
Listeners: []v1alpha2.ListenerStatus{ Listeners: []gatev1alpha2.ListenerStatus{
{ {
Name: "bar", Name: "bar",
Conditions: []metav1.Condition{ Conditions: []metav1.Condition{

View file

@ -31,7 +31,7 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
"k8s.io/utils/strings/slices" "k8s.io/utils/strings/slices"
"sigs.k8s.io/gateway-api/apis/v1alpha2" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
) )
const ( const (
@ -209,14 +209,14 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie
gatewayClassNames[gatewayClass.Name] = struct{}{} gatewayClassNames[gatewayClass.Name] = struct{}{}
err := client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{ err := client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{
Type: string(v1alpha2.GatewayClassConditionStatusAccepted), Type: string(gatev1alpha2.GatewayClassConditionStatusAccepted),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
Reason: "Handled", Reason: "Handled",
Message: "Handled by Traefik controller", Message: "Handled by Traefik controller",
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
}) })
if err != nil { if err != nil {
logger.Error().Err(err).Msgf("Failed to update %s condition", v1alpha2.GatewayClassConditionStatusAccepted) logger.Error().Err(err).Msgf("Failed to update %s condition", gatev1alpha2.GatewayClassConditionStatusAccepted)
} }
} }
} }
@ -272,7 +272,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie
return conf return conf
} }
func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway) (*dynamic.Configuration, error) { func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *gatev1alpha2.Gateway) (*dynamic.Configuration, error) {
conf := &dynamic.Configuration{ conf := &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{}, Routers: map[string]*dynamic.Router{},
@ -318,15 +318,15 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway
return conf, nil return conf, nil
} }
func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []v1alpha2.ListenerStatus { func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *gatev1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []gatev1alpha2.ListenerStatus {
logger := log.Ctx(ctx) logger := log.Ctx(ctx)
listenerStatuses := make([]v1alpha2.ListenerStatus, len(gateway.Spec.Listeners)) listenerStatuses := make([]gatev1alpha2.ListenerStatus, len(gateway.Spec.Listeners))
allocatedListeners := make(map[string]struct{}) allocatedListeners := make(map[string]struct{})
for i, listener := range gateway.Spec.Listeners { for i, listener := range gateway.Spec.Listeners {
listenerStatuses[i] = v1alpha2.ListenerStatus{ listenerStatuses[i] = gatev1alpha2.ListenerStatus{
Name: listener.Name, Name: listener.Name,
SupportedKinds: []v1alpha2.RouteGroupKind{}, SupportedKinds: []gatev1alpha2.RouteGroupKind{},
Conditions: []metav1.Condition{}, Conditions: []metav1.Condition{},
} }
@ -348,7 +348,7 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
if _, ok := allocatedListeners[listenerKey]; ok { if _, ok := allocatedListeners[listenerKey]; ok {
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionConflicted), Type: string(gatev1alpha2.ListenerConditionConflicted),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "DuplicateListener", Reason: "DuplicateListener",
@ -364,19 +364,19 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
if err != nil { if err != nil {
// update "Detached" status with "PortUnavailable" reason // update "Detached" status with "PortUnavailable" reason
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonPortUnavailable), Reason: string(gatev1alpha2.ListenerReasonPortUnavailable),
Message: fmt.Sprintf("Cannot find entryPoint for Gateway: %v", err), Message: fmt.Sprintf("Cannot find entryPoint for Gateway: %v", err),
}) })
continue continue
} }
if (listener.Protocol == v1alpha2.HTTPProtocolType || listener.Protocol == v1alpha2.TCPProtocolType) && listener.TLS != nil { if (listener.Protocol == gatev1alpha2.HTTPProtocolType || listener.Protocol == gatev1alpha2.TCPProtocolType) && listener.TLS != nil {
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point
@ -387,11 +387,11 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
} }
// TLS // TLS
if listener.Protocol == v1alpha2.HTTPSProtocolType || listener.Protocol == v1alpha2.TLSProtocolType { if listener.Protocol == gatev1alpha2.HTTPSProtocolType || listener.Protocol == gatev1alpha2.TLSProtocolType {
if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != v1alpha2.TLSModePassthrough) { if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != gatev1alpha2.TLSModePassthrough) {
// update "Detached" status with "UnsupportedProtocol" reason // update "Detached" status with "UnsupportedProtocol" reason
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point
@ -402,12 +402,12 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
continue continue
} }
var tlsModeType v1alpha2.TLSModeType var tlsModeType gatev1alpha2.TLSModeType
if listener.TLS.Mode != nil { if listener.TLS.Mode != nil {
tlsModeType = *listener.TLS.Mode tlsModeType = *listener.TLS.Mode
} }
isTLSPassthrough := tlsModeType == v1alpha2.TLSModePassthrough isTLSPassthrough := tlsModeType == gatev1alpha2.TLSModePassthrough
if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 { if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 {
// https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig
@ -418,12 +418,12 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
// Protocol TLS -> Passthrough -> TLSRoute/TCPRoute // Protocol TLS -> Passthrough -> TLSRoute/TCPRoute
// Protocol TLS -> Terminate -> TLSRoute/TCPRoute // Protocol TLS -> Terminate -> TLSRoute/TCPRoute
// Protocol HTTPS -> Terminate -> HTTPRoute // Protocol HTTPS -> Terminate -> HTTPRoute
if listener.Protocol == v1alpha2.HTTPSProtocolType && isTLSPassthrough { if listener.Protocol == gatev1alpha2.HTTPSProtocolType && isTLSPassthrough {
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonUnsupportedProtocol), Reason: string(gatev1alpha2.ListenerReasonUnsupportedProtocol),
Message: "HTTPS protocol is not supported with TLS mode Passthrough", Message: "HTTPS protocol is not supported with TLS mode Passthrough",
}) })
@ -434,10 +434,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
if len(listener.TLS.CertificateRefs) == 0 { if len(listener.TLS.CertificateRefs) == 0 {
// update "ResolvedRefs" status true with "InvalidCertificateRef" reason // update "ResolvedRefs" status true with "InvalidCertificateRef" reason
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef),
Message: "One TLS CertificateRef is required in Terminate mode", Message: "One TLS CertificateRef is required in Terminate mode",
}) })
@ -451,10 +451,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != "core") { certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != "core") {
// update "ResolvedRefs" status true with "InvalidCertificateRef" reason // update "ResolvedRefs" status true with "InvalidCertificateRef" reason
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef),
Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %v/%v", certificateRef.Group, certificateRef.Kind), Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %v/%v", certificateRef.Group, certificateRef.Kind),
}) })
@ -464,10 +464,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
// TODO Support ReferencePolicy to support cross namespace references. // TODO Support ReferencePolicy to support cross namespace references.
if certificateRef.Namespace != nil && string(*certificateRef.Namespace) != gateway.Namespace { if certificateRef.Namespace != nil && string(*certificateRef.Namespace) != gateway.Namespace {
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef),
Message: "Cross namespace secrets are not supported", Message: "Cross namespace secrets are not supported",
}) })
@ -480,10 +480,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidCertificateRef" reason // update "ResolvedRefs" status true with "InvalidCertificateRef" reason
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonInvalidCertificateRef), Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef),
Message: fmt.Sprintf("Error while retrieving certificate: %v", err), Message: fmt.Sprintf("Error while retrieving certificate: %v", err),
}) })
@ -510,10 +510,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
return listenerStatuses return listenerStatuses
} }
func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus) (v1alpha2.GatewayStatus, error) { func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerStatus) (gatev1alpha2.GatewayStatus, error) {
// As Status.Addresses are not implemented yet, we initialize an empty array to follow the API expectations. // As Status.Addresses are not implemented yet, we initialize an empty array to follow the API expectations.
gatewayStatus := v1alpha2.GatewayStatus{ gatewayStatus := gatev1alpha2.GatewayStatus{
Addresses: []v1alpha2.GatewayAddress{}, Addresses: []gatev1alpha2.GatewayAddress{},
} }
var result error var result error
@ -521,7 +521,7 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus)
if len(listener.Conditions) == 0 { if len(listener.Conditions) == 0 {
// GatewayConditionReady "Ready", GatewayConditionReason "ListenerReady" // GatewayConditionReady "Ready", GatewayConditionReason "ListenerReady"
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionReady), Type: string(gatev1alpha2.ListenerConditionReady),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "ListenerReady", Reason: "ListenerReady",
@ -539,10 +539,10 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus)
if result != nil { if result != nil {
// GatewayConditionReady "Ready", GatewayConditionReason "ListenersNotValid" // GatewayConditionReady "Ready", GatewayConditionReason "ListenersNotValid"
gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{ gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{
Type: string(v1alpha2.GatewayConditionReady), Type: string(gatev1alpha2.GatewayConditionReady),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.GatewayReasonListenersNotValid), Reason: string(gatev1alpha2.GatewayReasonListenersNotValid),
Message: "All Listeners must be valid", Message: "All Listeners must be valid",
}) })
@ -554,7 +554,7 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus)
gatewayStatus.Conditions = append(gatewayStatus.Conditions, gatewayStatus.Conditions = append(gatewayStatus.Conditions,
// update "Scheduled" status with "ResourcesAvailable" reason // update "Scheduled" status with "ResourcesAvailable" reason
metav1.Condition{ metav1.Condition{
Type: string(v1alpha2.GatewayConditionScheduled), Type: string(gatev1alpha2.GatewayConditionScheduled),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
Reason: "ResourcesAvailable", Reason: "ResourcesAvailable",
Message: "Resources available", Message: "Resources available",
@ -562,7 +562,7 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus)
}, },
// update "Ready" status with "ListenersValid" reason // update "Ready" status with "ListenersValid" reason
metav1.Condition{ metav1.Condition{
Type: string(v1alpha2.GatewayConditionReady), Type: string(gatev1alpha2.GatewayConditionReady),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
Reason: "ListenersValid", Reason: "ListenersValid",
Message: "Listeners valid", Message: "Listeners valid",
@ -573,14 +573,14 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []v1alpha2.ListenerStatus)
return gatewayStatus, nil return gatewayStatus, nil
} }
func (p *Provider) entryPointName(port v1alpha2.PortNumber, protocol v1alpha2.ProtocolType) (string, error) { func (p *Provider) entryPointName(port gatev1alpha2.PortNumber, protocol gatev1alpha2.ProtocolType) (string, error) {
portStr := strconv.FormatInt(int64(port), 10) portStr := strconv.FormatInt(int64(port), 10)
for name, entryPoint := range p.EntryPoints { for name, entryPoint := range p.EntryPoints {
if strings.HasSuffix(entryPoint.Address, ":"+portStr) { if strings.HasSuffix(entryPoint.Address, ":"+portStr) {
// If the protocol is HTTP the entryPoint must have no TLS conf // If the protocol is HTTP the entryPoint must have no TLS conf
// Not relevant for v1alpha2.TLSProtocolType && v1alpha2.TCPProtocolType // Not relevant for gatev1alpha2.TLSProtocolType && gatev1alpha2.TCPProtocolType
if protocol == v1alpha2.HTTPProtocolType && entryPoint.HasHTTPTLSConf { if protocol == gatev1alpha2.HTTPProtocolType && entryPoint.HasHTTPTLSConf {
continue continue
} }
@ -591,43 +591,43 @@ func (p *Provider) entryPointName(port v1alpha2.PortNumber, protocol v1alpha2.Pr
return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol) return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol)
} }
func supportedRouteKinds(protocol v1alpha2.ProtocolType) ([]v1alpha2.RouteGroupKind, []metav1.Condition) { func supportedRouteKinds(protocol gatev1alpha2.ProtocolType) ([]gatev1alpha2.RouteGroupKind, []metav1.Condition) {
group := v1alpha2.Group(v1alpha2.GroupName) group := gatev1alpha2.Group(gatev1alpha2.GroupName)
switch protocol { switch protocol {
case v1alpha2.TCPProtocolType: case gatev1alpha2.TCPProtocolType:
return []v1alpha2.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil return []gatev1alpha2.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil
case v1alpha2.HTTPProtocolType, v1alpha2.HTTPSProtocolType: case gatev1alpha2.HTTPProtocolType, gatev1alpha2.HTTPSProtocolType:
return []v1alpha2.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil return []gatev1alpha2.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil
case v1alpha2.TLSProtocolType: case gatev1alpha2.TLSProtocolType:
return []v1alpha2.RouteGroupKind{ return []gatev1alpha2.RouteGroupKind{
{Kind: kindTCPRoute, Group: &group}, {Kind: kindTCPRoute, Group: &group},
{Kind: kindTLSRoute, Group: &group}, {Kind: kindTLSRoute, Group: &group},
}, nil }, nil
} }
return nil, []metav1.Condition{{ return nil, []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonUnsupportedProtocol), Reason: string(gatev1alpha2.ListenerReasonUnsupportedProtocol),
Message: fmt.Sprintf("Unsupported listener protocol %q", protocol), Message: fmt.Sprintf("Unsupported listener protocol %q", protocol),
}} }}
} }
func getAllowedRouteKinds(listener v1alpha2.Listener, supportedKinds []v1alpha2.RouteGroupKind) ([]v1alpha2.RouteGroupKind, []metav1.Condition) { func getAllowedRouteKinds(listener gatev1alpha2.Listener, supportedKinds []gatev1alpha2.RouteGroupKind) ([]gatev1alpha2.RouteGroupKind, []metav1.Condition) {
if listener.AllowedRoutes == nil || len(listener.AllowedRoutes.Kinds) == 0 { if listener.AllowedRoutes == nil || len(listener.AllowedRoutes.Kinds) == 0 {
return supportedKinds, nil return supportedKinds, nil
} }
var ( var (
routeKinds []v1alpha2.RouteGroupKind routeKinds []gatev1alpha2.RouteGroupKind
conditions []metav1.Condition conditions []metav1.Condition
) )
uniqRouteKinds := map[v1alpha2.Kind]struct{}{} uniqRouteKinds := map[gatev1alpha2.Kind]struct{}{}
for _, routeKind := range listener.AllowedRoutes.Kinds { for _, routeKind := range listener.AllowedRoutes.Kinds {
var isSupported bool var isSupported bool
for _, kind := range supportedKinds { for _, kind := range supportedKinds {
@ -639,10 +639,10 @@ func getAllowedRouteKinds(listener v1alpha2.Listener, supportedKinds []v1alpha2.
if !isSupported { if !isSupported {
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionDetached), Type: string(gatev1alpha2.ListenerConditionDetached),
Status: metav1.ConditionTrue, Status: metav1.ConditionTrue,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonInvalidRouteKinds), Reason: string(gatev1alpha2.ListenerReasonInvalidRouteKinds),
Message: fmt.Sprintf("Listener protocol %q does not support RouteGroupKind %v/%s", listener.Protocol, routeKind.Group, routeKind.Kind), Message: fmt.Sprintf("Listener protocol %q does not support RouteGroupKind %v/%s", listener.Protocol, routeKind.Group, routeKind.Kind),
}) })
continue continue
@ -657,7 +657,7 @@ func getAllowedRouteKinds(listener v1alpha2.Listener, supportedKinds []v1alpha2.
return routeKinds, conditions return routeKinds, conditions
} }
func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition {
if listener.AllowedRoutes == nil { if listener.AllowedRoutes == nil {
// Should not happen due to validation. // Should not happen due to validation.
return nil return nil
@ -667,7 +667,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouteNamespacesSelector", // Should never happen as the selector is validated by kubernetes Reason: "InvalidRouteNamespacesSelector", // Should never happen as the selector is validated by kubernetes
@ -679,10 +679,10 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonRefNotPermitted), Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted),
Message: fmt.Sprintf("Cannot fetch HTTPRoutes: %v", err), Message: fmt.Sprintf("Cannot fetch HTTPRoutes: %v", err),
}} }}
} }
@ -708,7 +708,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
hostRule, err := hostRule(hostnames) hostRule, err := hostRule(hostnames)
if err != nil { if err != nil {
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouteHostname", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidRouteHostname", // TODO check the spec if a proper reason is introduced at some point
@ -722,7 +722,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "UnsupportedPathOrHeaderType", // TODO check the spec if a proper reason is introduced at some point Reason: "UnsupportedPathOrHeaderType", // TODO check the spec if a proper reason is introduced at some point
@ -735,7 +735,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
EntryPoints: []string{ep}, EntryPoints: []string{ep},
} }
if listener.Protocol == v1alpha2.HTTPSProtocolType && listener.TLS != nil { if listener.Protocol == gatev1alpha2.HTTPSProtocolType && listener.TLS != nil {
// TODO support let's encrypt // TODO support let's encrypt
router.TLS = &dynamic.RouterTLSConfig{} router.TLS = &dynamic.RouterTLSConfig{}
} }
@ -746,7 +746,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouterKey", // Should never happen Reason: "InvalidRouterKey", // Should never happen
@ -761,7 +761,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidFilters" reason // update "ResolvedRefs" status true with "InvalidFilters" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidFilters", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidFilters", // TODO check the spec if a proper reason is introduced at some point
@ -789,7 +789,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point
@ -818,7 +818,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha
return conditions return conditions
} }
func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition {
if listener.AllowedRoutes == nil { if listener.AllowedRoutes == nil {
// Should not happen due to validation. // Should not happen due to validation.
return nil return nil
@ -828,7 +828,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes
@ -840,10 +840,10 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonRefNotPermitted), Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted),
Message: fmt.Sprintf("Cannot fetch TCPRoutes: %v", err), Message: fmt.Sprintf("Cannot fetch TCPRoutes: %v", err),
}} }}
} }
@ -864,10 +864,10 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
EntryPoints: []string{ep}, EntryPoints: []string{ep},
} }
if listener.Protocol == v1alpha2.TLSProtocolType && listener.TLS != nil { if listener.Protocol == gatev1alpha2.TLSProtocolType && listener.TLS != nil {
// TODO support let's encrypt // TODO support let's encrypt
router.TLS = &dynamic.RouterTCPTLSConfig{ router.TLS = &dynamic.RouterTCPTLSConfig{
Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == v1alpha2.TLSModePassthrough, Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1alpha2.TLSModePassthrough,
} }
} }
@ -877,7 +877,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouterKey", // Should never happen Reason: "InvalidRouterKey", // Should never happen
@ -902,7 +902,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point
@ -948,7 +948,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
return conditions return conditions
} }
func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.Listener, gateway *v1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition {
if listener.AllowedRoutes == nil { if listener.AllowedRoutes == nil {
// Should not happen due to validation. // Should not happen due to validation.
return nil return nil
@ -958,7 +958,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes
@ -970,10 +970,10 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "InvalidRoutesRef" reason // update "ResolvedRefs" status true with "InvalidRoutesRef" reason
return []metav1.Condition{{ return []metav1.Condition{{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: string(v1alpha2.ListenerReasonRefNotPermitted), Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted),
Message: fmt.Sprintf("Cannot fetch TLSRoutes: %v", err), Message: fmt.Sprintf("Cannot fetch TLSRoutes: %v", err),
}} }}
} }
@ -993,9 +993,9 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 {
for _, parent := range route.Status.Parents { for _, parent := range route.Status.Parents {
parent.Conditions = append(parent.Conditions, metav1.Condition{ parent.Conditions = append(parent.Conditions, metav1.Condition{
Type: string(v1alpha2.GatewayClassConditionStatusAccepted), Type: string(gatev1alpha2.GatewayClassConditionStatusAccepted),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
Reason: string(v1alpha2.ListenerReasonRouteConflict), Reason: string(gatev1alpha2.ListenerReasonRouteConflict),
Message: fmt.Sprintf("No hostname match between listener: %v and route: %v", listener.Hostname, route.Spec.Hostnames), Message: fmt.Sprintf("No hostname match between listener: %v and route: %v", listener.Hostname, route.Spec.Hostnames),
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
}) })
@ -1008,7 +1008,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidHostnames", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidHostnames", // TODO check the spec if a proper reason is introduced at some point
@ -1022,7 +1022,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
Rule: rule, Rule: rule,
EntryPoints: []string{ep}, EntryPoints: []string{ep},
TLS: &dynamic.RouterTCPTLSConfig{ TLS: &dynamic.RouterTCPTLSConfig{
Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == v1alpha2.TLSModePassthrough, Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1alpha2.TLSModePassthrough,
}, },
} }
@ -1032,7 +1032,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidRouterKey", // Should never happen Reason: "InvalidRouterKey", // Should never happen
@ -1057,7 +1057,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
if err != nil { if err != nil {
// update "ResolvedRefs" status true with "DroppedRoutes" reason // update "ResolvedRefs" status true with "DroppedRoutes" reason
conditions = append(conditions, metav1.Condition{ conditions = append(conditions, metav1.Condition{
Type: string(v1alpha2.ListenerConditionResolvedRefs), Type: string(gatev1alpha2.ListenerConditionResolvedRefs),
Status: metav1.ConditionFalse, Status: metav1.ConditionFalse,
LastTransitionTime: metav1.Now(), LastTransitionTime: metav1.Now(),
Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point
@ -1105,18 +1105,18 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
// Because of Kubernetes validation we admit that the given Hostnames are valid. // Because of Kubernetes validation we admit that the given Hostnames are valid.
// https://github.com/kubernetes-sigs/gateway-api/blob/ff9883da4cad8554cd300394f725ab3a27502785/apis/v1alpha2/shared_types.go#L252 // https://github.com/kubernetes-sigs/gateway-api/blob/ff9883da4cad8554cd300394f725ab3a27502785/apis/v1alpha2/shared_types.go#L252
func matchingHostnames(listener v1alpha2.Listener, hostnames []v1alpha2.Hostname) []v1alpha2.Hostname { func matchingHostnames(listener gatev1alpha2.Listener, hostnames []gatev1alpha2.Hostname) []gatev1alpha2.Hostname {
if listener.Hostname == nil || *listener.Hostname == "" { if listener.Hostname == nil || *listener.Hostname == "" {
return hostnames return hostnames
} }
if len(hostnames) == 0 { if len(hostnames) == 0 {
return []v1alpha2.Hostname{*listener.Hostname} return []gatev1alpha2.Hostname{*listener.Hostname}
} }
listenerLabels := strings.Split(string(*listener.Hostname), ".") listenerLabels := strings.Split(string(*listener.Hostname), ".")
var matches []v1alpha2.Hostname var matches []gatev1alpha2.Hostname
for _, hostname := range hostnames { for _, hostname := range hostnames {
if hostname == *listener.Hostname { if hostname == *listener.Hostname {
@ -1147,9 +1147,9 @@ func matchingHostnames(listener v1alpha2.Listener, hostnames []v1alpha2.Hostname
return matches return matches
} }
func shouldAttach(gateway *v1alpha2.Gateway, listener v1alpha2.Listener, routeNamespace string, routeSpec v1alpha2.CommonRouteSpec) bool { func shouldAttach(gateway *gatev1alpha2.Gateway, listener gatev1alpha2.Listener, routeNamespace string, routeSpec gatev1alpha2.CommonRouteSpec) bool {
for _, parentRef := range routeSpec.ParentRefs { for _, parentRef := range routeSpec.ParentRefs {
if parentRef.Group == nil || *parentRef.Group != v1alpha2.GroupName { if parentRef.Group == nil || *parentRef.Group != gatev1alpha2.GroupName {
continue continue
} }
@ -1174,19 +1174,19 @@ func shouldAttach(gateway *v1alpha2.Gateway, listener v1alpha2.Listener, routeNa
return false return false
} }
func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *v1alpha2.RouteNamespaces) ([]string, error) { func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *gatev1alpha2.RouteNamespaces) ([]string, error) {
if routeNamespaces == nil || routeNamespaces.From == nil { if routeNamespaces == nil || routeNamespaces.From == nil {
return []string{gatewayNamespace}, nil return []string{gatewayNamespace}, nil
} }
switch *routeNamespaces.From { switch *routeNamespaces.From {
case v1alpha2.NamespacesFromAll: case gatev1alpha2.NamespacesFromAll:
return []string{metav1.NamespaceAll}, nil return []string{metav1.NamespaceAll}, nil
case v1alpha2.NamespacesFromSame: case gatev1alpha2.NamespacesFromSame:
return []string{gatewayNamespace}, nil return []string{gatewayNamespace}, nil
case v1alpha2.NamespacesFromSelector: case gatev1alpha2.NamespacesFromSelector:
selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector) selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector)
if err != nil { if err != nil {
return nil, fmt.Errorf("malformed selector: %w", err) return nil, fmt.Errorf("malformed selector: %w", err)
@ -1198,7 +1198,7 @@ func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, ro
return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From) return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From)
} }
func hostRule(hostnames []v1alpha2.Hostname) (string, error) { func hostRule(hostnames []gatev1alpha2.Hostname) (string, error) {
var rules []string var rules []string
for _, hostname := range hostnames { for _, hostname := range hostnames {
@ -1235,9 +1235,9 @@ func hostRule(hostnames []v1alpha2.Hostname) (string, error) {
} }
} }
func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) { func hostSNIRule(hostnames []gatev1alpha2.Hostname) (string, error) {
rules := make([]string, 0, len(hostnames)) rules := make([]string, 0, len(hostnames))
uniqHostnames := map[v1alpha2.Hostname]struct{}{} uniqHostnames := map[gatev1alpha2.Hostname]struct{}{}
for _, hostname := range hostnames { for _, hostname := range hostnames {
if len(hostname) == 0 { if len(hostname) == 0 {
@ -1272,7 +1272,7 @@ func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) {
return strings.Join(rules, " || "), nil return strings.Join(rules, " || "), nil
} }
func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, error) { func extractRule(routeRule gatev1alpha2.HTTPRouteRule, hostRule string) (string, error) {
var rule string var rule string
var matchesRules []string var matchesRules []string
@ -1286,9 +1286,9 @@ func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, err
if match.Path != nil && match.Path.Type != nil && match.Path.Value != nil { if match.Path != nil && match.Path.Type != nil && match.Path.Value != nil {
// TODO handle other path types // TODO handle other path types
switch *match.Path.Type { switch *match.Path.Type {
case v1alpha2.PathMatchExact: case gatev1alpha2.PathMatchExact:
matchRules = append(matchRules, fmt.Sprintf("Path(`%s`)", *match.Path.Value)) matchRules = append(matchRules, fmt.Sprintf("Path(`%s`)", *match.Path.Value))
case v1alpha2.PathMatchPathPrefix: case gatev1alpha2.PathMatchPathPrefix:
matchRules = append(matchRules, fmt.Sprintf("PathPrefix(`%s`)", *match.Path.Value)) matchRules = append(matchRules, fmt.Sprintf("PathPrefix(`%s`)", *match.Path.Value))
default: default:
return "", fmt.Errorf("unsupported path match %s", *match.Path.Type) return "", fmt.Errorf("unsupported path match %s", *match.Path.Type)
@ -1329,7 +1329,7 @@ func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, err
return rule + "(" + strings.Join(matchesRules, " || ") + ")", nil return rule + "(" + strings.Join(matchesRules, " || ") + ")", nil
} }
func extractHeaderRules(headers []v1alpha2.HTTPHeaderMatch) ([]string, error) { func extractHeaderRules(headers []gatev1alpha2.HTTPHeaderMatch) ([]string, error) {
var headerRules []string var headerRules []string
// TODO handle other headers types // TODO handle other headers types
@ -1340,7 +1340,7 @@ func extractHeaderRules(headers []v1alpha2.HTTPHeaderMatch) ([]string, error) {
} }
switch *header.Type { switch *header.Type {
case v1alpha2.HeaderMatchExact: case gatev1alpha2.HeaderMatchExact:
headerRules = append(headerRules, fmt.Sprintf("Headers(`%s`,`%s`)", header.Name, header.Value)) headerRules = append(headerRules, fmt.Sprintf("Headers(`%s`,`%s`)", header.Name, header.Value))
default: default:
return nil, fmt.Errorf("unsupported header match type %s", *header.Type) return nil, fmt.Errorf("unsupported header match type %s", *header.Type)
@ -1369,7 +1369,7 @@ func makeID(namespace, name string) string {
return namespace + "-" + name return namespace + "-" + name
} }
func getTLS(k8sClient Client, secretName v1alpha2.ObjectName, namespace string) (*tls.CertAndStores, error) { func getTLS(k8sClient Client, secretName gatev1alpha2.ObjectName, namespace string) (*tls.CertAndStores, error) {
secret, exists, err := k8sClient.GetSecret(namespace, string(secretName)) secret, exists, err := k8sClient.GetSecret(namespace, string(secretName))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err) return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err)
@ -1443,7 +1443,7 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (
} }
// loadServices is generating a WRR service, even when there is only one target. // loadServices is generating a WRR service, even when there is only one target.
func loadServices(client Client, namespace string, backendRefs []v1alpha2.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) { func loadServices(client Client, namespace string, backendRefs []gatev1alpha2.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) {
services := map[string]*dynamic.Service{} services := map[string]*dynamic.Service{}
wrrSvc := &dynamic.Service{ wrrSvc := &dynamic.Service{
@ -1566,7 +1566,7 @@ func loadServices(client Client, namespace string, backendRefs []v1alpha2.HTTPBa
} }
// loadTCPServices is generating a WRR service, even when there is only one target. // loadTCPServices is generating a WRR service, even when there is only one target.
func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { func loadTCPServices(client Client, namespace string, backendRefs []gatev1alpha2.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) {
services := map[string]*dynamic.TCPService{} services := map[string]*dynamic.TCPService{}
wrrSvc := &dynamic.TCPService{ wrrSvc := &dynamic.TCPService{
@ -1684,16 +1684,16 @@ func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.Bac
return wrrSvc, services, nil return wrrSvc, services, nil
} }
func loadMiddlewares(listener v1alpha2.Listener, prefix string, filters []v1alpha2.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) { func loadMiddlewares(listener gatev1alpha2.Listener, prefix string, filters []gatev1alpha2.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) {
middlewares := make(map[string]*dynamic.Middleware) middlewares := make(map[string]*dynamic.Middleware)
// The spec allows for an empty string in which case we should use the // The spec allows for an empty string in which case we should use the
// scheme of the request which in this case is the listener scheme. // scheme of the request which in this case is the listener scheme.
var listenerScheme string var listenerScheme string
switch listener.Protocol { switch listener.Protocol {
case v1alpha2.HTTPProtocolType: case gatev1alpha2.HTTPProtocolType:
listenerScheme = "http" listenerScheme = "http"
case v1alpha2.HTTPSProtocolType: case gatev1alpha2.HTTPSProtocolType:
listenerScheme = "https" listenerScheme = "https"
default: default:
return nil, fmt.Errorf("invalid listener protocol %s", listener.Protocol) return nil, fmt.Errorf("invalid listener protocol %s", listener.Protocol)
@ -1702,7 +1702,7 @@ func loadMiddlewares(listener v1alpha2.Listener, prefix string, filters []v1alph
for i, filter := range filters { for i, filter := range filters {
var middleware *dynamic.Middleware var middleware *dynamic.Middleware
switch filter.Type { switch filter.Type {
case v1alpha2.HTTPRouteFilterRequestRedirect: case gatev1alpha2.HTTPRouteFilterRequestRedirect:
var err error var err error
middleware, err = createRedirectRegexMiddleware(listenerScheme, filter.RequestRedirect) middleware, err = createRedirectRegexMiddleware(listenerScheme, filter.RequestRedirect)
if err != nil { if err != nil {
@ -1724,7 +1724,7 @@ func loadMiddlewares(listener v1alpha2.Listener, prefix string, filters []v1alph
return middlewares, nil return middlewares, nil
} }
func createRedirectRegexMiddleware(scheme string, filter *v1alpha2.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) { func createRedirectRegexMiddleware(scheme string, filter *gatev1alpha2.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) {
// Use the HTTPRequestRedirectFilter scheme if defined. // Use the HTTPRequestRedirectFilter scheme if defined.
filterScheme := scheme filterScheme := scheme
if filter.Scheme != nil { if filter.Scheme != nil {
@ -1802,7 +1802,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s
return eventsChanBuffered return eventsChanBuffered
} }
func isTraefikService(ref v1alpha2.BackendRef) bool { func isTraefikService(ref gatev1alpha2.BackendRef) bool {
if ref.Kind == nil || ref.Group == nil { if ref.Kind == nil || ref.Group == nil {
return false return false
} }
@ -1810,13 +1810,13 @@ func isTraefikService(ref v1alpha2.BackendRef) bool {
return *ref.Group == traefikv1alpha1.GroupName && *ref.Kind == kindTraefikService return *ref.Group == traefikv1alpha1.GroupName && *ref.Kind == kindTraefikService
} }
func isInternalService(ref v1alpha2.BackendRef) bool { func isInternalService(ref gatev1alpha2.BackendRef) bool {
return isTraefikService(ref) && strings.HasSuffix(string(ref.Name), "@internal") return isTraefikService(ref) && strings.HasSuffix(string(ref.Name), "@internal")
} }
// makeListenerKey joins protocol, hostname, and port of a listener into a string key. // makeListenerKey joins protocol, hostname, and port of a listener into a string key.
func makeListenerKey(l v1alpha2.Listener) string { func makeListenerKey(l gatev1alpha2.Listener) string {
var hostname v1alpha2.Hostname var hostname gatev1alpha2.Hostname
if l.Hostname != nil { if l.Hostname != nil {
hostname = *l.Hostname hostname = *l.Hostname
} }

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
package ingress package ingress
import networkingv1 "k8s.io/api/networking/v1" import netv1 "k8s.io/api/networking/v1"
func buildIngress(opts ...func(*networkingv1.Ingress)) *networkingv1.Ingress { func buildIngress(opts ...func(*netv1.Ingress)) *netv1.Ingress {
i := &networkingv1.Ingress{} i := &netv1.Ingress{}
i.Kind = "Ingress" i.Kind = "Ingress"
for _, opt := range opts { for _, opt := range opts {
opt(i) opt(i)
@ -11,15 +11,15 @@ func buildIngress(opts ...func(*networkingv1.Ingress)) *networkingv1.Ingress {
return i return i
} }
func iNamespace(value string) func(*networkingv1.Ingress) { func iNamespace(value string) func(*netv1.Ingress) {
return func(i *networkingv1.Ingress) { return func(i *netv1.Ingress) {
i.Namespace = value i.Namespace = value
} }
} }
func iRules(opts ...func(*networkingv1.IngressSpec)) func(*networkingv1.Ingress) { func iRules(opts ...func(*netv1.IngressSpec)) func(*netv1.Ingress) {
return func(i *networkingv1.Ingress) { return func(i *netv1.Ingress) {
s := &networkingv1.IngressSpec{} s := &netv1.IngressSpec{}
for _, opt := range opts { for _, opt := range opts {
opt(s) opt(s)
} }
@ -27,9 +27,9 @@ func iRules(opts ...func(*networkingv1.IngressSpec)) func(*networkingv1.Ingress)
} }
} }
func iRule(opts ...func(*networkingv1.IngressRule)) func(*networkingv1.IngressSpec) { func iRule(opts ...func(*netv1.IngressRule)) func(*netv1.IngressSpec) {
return func(spec *networkingv1.IngressSpec) { return func(spec *netv1.IngressSpec) {
r := &networkingv1.IngressRule{} r := &netv1.IngressRule{}
for _, opt := range opts { for _, opt := range opts {
opt(r) opt(r)
} }
@ -37,24 +37,24 @@ func iRule(opts ...func(*networkingv1.IngressRule)) func(*networkingv1.IngressSp
} }
} }
func iHost(name string) func(*networkingv1.IngressRule) { func iHost(name string) func(*netv1.IngressRule) {
return func(rule *networkingv1.IngressRule) { return func(rule *netv1.IngressRule) {
rule.Host = name rule.Host = name
} }
} }
func iTLSes(opts ...func(*networkingv1.IngressTLS)) func(*networkingv1.Ingress) { func iTLSes(opts ...func(*netv1.IngressTLS)) func(*netv1.Ingress) {
return func(i *networkingv1.Ingress) { return func(i *netv1.Ingress) {
for _, opt := range opts { for _, opt := range opts {
iTLS := networkingv1.IngressTLS{} iTLS := netv1.IngressTLS{}
opt(&iTLS) opt(&iTLS)
i.Spec.TLS = append(i.Spec.TLS, iTLS) i.Spec.TLS = append(i.Spec.TLS, iTLS)
} }
} }
} }
func iTLS(secret string, hosts ...string) func(*networkingv1.IngressTLS) { func iTLS(secret string, hosts ...string) func(*netv1.IngressTLS) {
return func(i *networkingv1.IngressTLS) { return func(i *netv1.IngressTLS) {
i.SecretName = secret i.SecretName = secret
i.Hosts = hosts i.Hosts = hosts
} }

View file

@ -14,14 +14,14 @@ import (
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
traefikversion "github.com/traefik/traefik/v3/pkg/version" traefikversion "github.com/traefik/traefik/v3/pkg/version"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
networkingv1beta1 "k8s.io/api/networking/v1beta1" netv1beta1 "k8s.io/api/networking/v1beta1"
kubeerror "k8s.io/apimachinery/pkg/api/errors" kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/informers" kinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes" kclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )
@ -31,30 +31,26 @@ const (
defaultTimeout = 5 * time.Second defaultTimeout = 5 * time.Second
) )
type marshaler interface {
Marshal() ([]byte, error)
}
// Client is a client for the Provider master. // Client is a client for the Provider master.
// WatchAll starts the watch of the Provider resources and updates the stores. // WatchAll starts the watch of the Provider resources and updates the stores.
// The stores can then be accessed via the Get* functions. // The stores can then be accessed via the Get* functions.
type Client interface { type Client interface {
WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error)
GetIngresses() []*networkingv1.Ingress GetIngresses() []*netv1.Ingress
GetIngressClasses() ([]*networkingv1.IngressClass, error) GetIngressClasses() ([]*netv1.IngressClass, error)
GetService(namespace, name string) (*corev1.Service, bool, error) GetService(namespace, name string) (*corev1.Service, bool, error)
GetSecret(namespace, name string) (*corev1.Secret, bool, error) GetSecret(namespace, name string) (*corev1.Secret, bool, error)
GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error)
UpdateIngressStatus(ing *networkingv1.Ingress, ingStatus []corev1.LoadBalancerIngress) error UpdateIngressStatus(ing *netv1.Ingress, ingStatus []netv1.IngressLoadBalancerIngress) error
GetServerVersion() *version.Version GetServerVersion() *version.Version
} }
type clientWrapper struct { type clientWrapper struct {
clientset kubernetes.Interface clientset kclientset.Interface
factoriesKube map[string]informers.SharedInformerFactory factoriesKube map[string]kinformers.SharedInformerFactory
factoriesSecret map[string]informers.SharedInformerFactory factoriesSecret map[string]kinformers.SharedInformerFactory
factoriesIngress map[string]informers.SharedInformerFactory factoriesIngress map[string]kinformers.SharedInformerFactory
clusterFactory informers.SharedInformerFactory clusterFactory kinformers.SharedInformerFactory
ingressLabelSelector string ingressLabelSelector string
isNamespaceAll bool isNamespaceAll bool
disableIngressClassInformer bool disableIngressClassInformer bool
@ -118,7 +114,7 @@ func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
runtime.GOARCH, runtime.GOARCH,
) )
clientset, err := kubernetes.NewForConfig(c) clientset, err := kclientset.NewForConfig(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -126,12 +122,12 @@ func createClientFromConfig(c *rest.Config) (*clientWrapper, error) {
return newClientImpl(clientset), nil return newClientImpl(clientset), nil
} }
func newClientImpl(clientset kubernetes.Interface) *clientWrapper { func newClientImpl(clientset kclientset.Interface) *clientWrapper {
return &clientWrapper{ return &clientWrapper{
clientset: clientset, clientset: clientset,
factoriesSecret: make(map[string]informers.SharedInformerFactory), factoriesSecret: make(map[string]kinformers.SharedInformerFactory),
factoriesIngress: make(map[string]informers.SharedInformerFactory), factoriesIngress: make(map[string]kinformers.SharedInformerFactory),
factoriesKube: make(map[string]informers.SharedInformerFactory), factoriesKube: make(map[string]kinformers.SharedInformerFactory),
} }
} }
@ -169,23 +165,38 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
for _, ns := range namespaces { for _, ns := range namespaces {
factoryIngress := informers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, informers.WithNamespace(ns), informers.WithTweakListOptions(matchesLabelSelector)) factoryIngress := kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, kinformers.WithNamespace(ns), kinformers.WithTweakListOptions(matchesLabelSelector))
if supportsNetworkingV1Ingress(serverVersion) { if supportsNetworkingV1Ingress(serverVersion) {
factoryIngress.Networking().V1().Ingresses().Informer().AddEventHandler(eventHandler) _, err = factoryIngress.Networking().V1().Ingresses().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
} else { } else {
factoryIngress.Networking().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler) _, err = factoryIngress.Networking().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
} }
c.factoriesIngress[ns] = factoryIngress c.factoriesIngress[ns] = factoryIngress
factoryKube := informers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, informers.WithNamespace(ns)) factoryKube := kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, kinformers.WithNamespace(ns))
factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler) _, err = factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler) if err != nil {
return nil, err
}
_, err = factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.factoriesKube[ns] = factoryKube c.factoriesKube[ns] = factoryKube
factorySecret := informers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, informers.WithNamespace(ns), informers.WithTweakListOptions(notOwnedByHelm)) factorySecret := kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod, kinformers.WithNamespace(ns), kinformers.WithTweakListOptions(notOwnedByHelm))
factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler) _, err = factorySecret.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
c.factoriesSecret[ns] = factorySecret c.factoriesSecret[ns] = factorySecret
} }
@ -216,12 +227,18 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
if !c.disableIngressClassInformer && supportsIngressClass(serverVersion) { if !c.disableIngressClassInformer && supportsIngressClass(serverVersion) {
c.clusterFactory = informers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod) c.clusterFactory = kinformers.NewSharedInformerFactoryWithOptions(c.clientset, resyncPeriod)
if supportsNetworkingV1Ingress(serverVersion) { if supportsNetworkingV1Ingress(serverVersion) {
c.clusterFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler) _, err = c.clusterFactory.Networking().V1().IngressClasses().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
} else { } else {
c.clusterFactory.Networking().V1beta1().IngressClasses().Informer().AddEventHandler(eventHandler) _, err = c.clusterFactory.Networking().V1beta1().IngressClasses().Informer().AddEventHandler(eventHandler)
if err != nil {
return nil, err
}
} }
c.clusterFactory.Start(stopCh) c.clusterFactory.Start(stopCh)
@ -237,8 +254,8 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
} }
// GetIngresses returns all Ingresses for observed namespaces in the cluster. // GetIngresses returns all Ingresses for observed namespaces in the cluster.
func (c *clientWrapper) GetIngresses() []*networkingv1.Ingress { func (c *clientWrapper) GetIngresses() []*netv1.Ingress {
var results []*networkingv1.Ingress var results []*netv1.Ingress
isNetworkingV1Supported := supportsNetworkingV1Ingress(c.serverVersion) isNetworkingV1Supported := supportsNetworkingV1Ingress(c.serverVersion)
@ -263,7 +280,7 @@ func (c *clientWrapper) GetIngresses() []*networkingv1.Ingress {
} }
for _, ing := range list { for _, ing := range list {
n, err := toNetworkingV1(ing) n, err := convert[netv1.Ingress](ing)
if err != nil { if err != nil {
log.Error().Err(err).Msgf("Failed to convert ingress %s from networking/v1beta1 to networking/v1", ns) log.Error().Err(err).Msgf("Failed to convert ingress %s from networking/v1beta1 to networking/v1", ns)
continue continue
@ -277,39 +294,9 @@ func (c *clientWrapper) GetIngresses() []*networkingv1.Ingress {
return results return results
} }
func toNetworkingV1(ing marshaler) (*networkingv1.Ingress, error) { func addServiceFromV1Beta1(ing *netv1.Ingress, old netv1beta1.Ingress) {
data, err := ing.Marshal()
if err != nil {
return nil, err
}
ni := &networkingv1.Ingress{}
err = ni.Unmarshal(data)
if err != nil {
return nil, err
}
return ni, nil
}
func toNetworkingV1IngressClass(ing marshaler) (*networkingv1.IngressClass, error) {
data, err := ing.Marshal()
if err != nil {
return nil, err
}
ni := &networkingv1.IngressClass{}
err = ni.Unmarshal(data)
if err != nil {
return nil, err
}
return ni, nil
}
func addServiceFromV1Beta1(ing *networkingv1.Ingress, old networkingv1beta1.Ingress) {
if old.Spec.Backend != nil { if old.Spec.Backend != nil {
port := networkingv1.ServiceBackendPort{} port := netv1.ServiceBackendPort{}
if old.Spec.Backend.ServicePort.Type == intstr.Int { if old.Spec.Backend.ServicePort.Type == intstr.Int {
port.Number = old.Spec.Backend.ServicePort.IntVal port.Number = old.Spec.Backend.ServicePort.IntVal
} else { } else {
@ -317,8 +304,8 @@ func addServiceFromV1Beta1(ing *networkingv1.Ingress, old networkingv1beta1.Ingr
} }
if old.Spec.Backend.ServiceName != "" { if old.Spec.Backend.ServiceName != "" {
ing.Spec.DefaultBackend = &networkingv1.IngressBackend{ ing.Spec.DefaultBackend = &netv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &netv1.IngressServiceBackend{
Name: old.Spec.Backend.ServiceName, Name: old.Spec.Backend.ServiceName,
Port: port, Port: port,
}, },
@ -334,14 +321,14 @@ func addServiceFromV1Beta1(ing *networkingv1.Ingress, old networkingv1beta1.Ingr
if path.Backend.Service == nil { if path.Backend.Service == nil {
oldBackend := old.Spec.Rules[rc].HTTP.Paths[pc].Backend oldBackend := old.Spec.Rules[rc].HTTP.Paths[pc].Backend
port := networkingv1.ServiceBackendPort{} port := netv1.ServiceBackendPort{}
if oldBackend.ServicePort.Type == intstr.Int { if oldBackend.ServicePort.Type == intstr.Int {
port.Number = oldBackend.ServicePort.IntVal port.Number = oldBackend.ServicePort.IntVal
} else { } else {
port.Name = oldBackend.ServicePort.StrVal port.Name = oldBackend.ServicePort.StrVal
} }
svc := networkingv1.IngressServiceBackend{ svc := netv1.IngressServiceBackend{
Name: oldBackend.ServiceName, Name: oldBackend.ServiceName,
Port: port, Port: port,
} }
@ -353,7 +340,7 @@ func addServiceFromV1Beta1(ing *networkingv1.Ingress, old networkingv1beta1.Ingr
} }
// UpdateIngressStatus updates an Ingress with a provided status. // UpdateIngressStatus updates an Ingress with a provided status.
func (c *clientWrapper) UpdateIngressStatus(src *networkingv1.Ingress, ingStatus []corev1.LoadBalancerIngress) error { func (c *clientWrapper) UpdateIngressStatus(src *netv1.Ingress, ingStatus []netv1.IngressLoadBalancerIngress) error {
if !c.isWatchedNamespace(src.Namespace) { if !c.isWatchedNamespace(src.Namespace) {
return fmt.Errorf("failed to get ingress %s/%s: namespace is not within watched namespaces", src.Namespace, src.Name) return fmt.Errorf("failed to get ingress %s/%s: namespace is not within watched namespaces", src.Namespace, src.Name)
} }
@ -375,7 +362,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1.Ingress, ingStatus
} }
ingCopy := ing.DeepCopy() ingCopy := ing.DeepCopy()
ingCopy.Status = networkingv1.IngressStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: ingStatus}} ingCopy.Status = netv1.IngressStatus{LoadBalancer: netv1.IngressLoadBalancerStatus{Ingress: ingStatus}}
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel() defer cancel()
@ -389,7 +376,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1.Ingress, ingStatus
return nil return nil
} }
func (c *clientWrapper) updateIngressStatusOld(src *networkingv1.Ingress, ingStatus []corev1.LoadBalancerIngress) error { func (c *clientWrapper) updateIngressStatusOld(src *netv1.Ingress, ingStatus []netv1.IngressLoadBalancerIngress) error {
ing, err := c.factoriesIngress[c.lookupNamespace(src.Namespace)].Networking().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name) ing, err := c.factoriesIngress[c.lookupNamespace(src.Namespace)].Networking().V1beta1().Ingresses().Lister().Ingresses(src.Namespace).Get(src.Name)
if err != nil { if err != nil {
return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err) return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err)
@ -397,13 +384,23 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1.Ingress, ingSta
logger := log.With().Str("namespace", ing.Namespace).Str("ingress", ing.Name).Logger() logger := log.With().Str("namespace", ing.Namespace).Str("ingress", ing.Name).Logger()
if isLoadBalancerIngressEquals(ing.Status.LoadBalancer.Ingress, ingStatus) { ingresses, err := convertSlice[netv1.IngressLoadBalancerIngress](ing.Status.LoadBalancer.Ingress)
if err != nil {
return err
}
if isLoadBalancerIngressEquals(ingresses, ingStatus) {
logger.Debug().Msg("Skipping ingress status update") logger.Debug().Msg("Skipping ingress status update")
return nil return nil
} }
ingressesBeta1, err := convertSlice[netv1beta1.IngressLoadBalancerIngress](ingStatus)
if err != nil {
return err
}
ingCopy := ing.DeepCopy() ingCopy := ing.DeepCopy()
ingCopy.Status = networkingv1beta1.IngressStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: ingStatus}} ingCopy.Status = netv1beta1.IngressStatus{LoadBalancer: netv1beta1.IngressLoadBalancerStatus{Ingress: ingressesBeta1}}
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel() defer cancel()
@ -417,7 +414,7 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1.Ingress, ingSta
} }
// isLoadBalancerIngressEquals returns true if the given slices are equal, false otherwise. // isLoadBalancerIngressEquals returns true if the given slices are equal, false otherwise.
func isLoadBalancerIngressEquals(aSlice, bSlice []corev1.LoadBalancerIngress) bool { func isLoadBalancerIngressEquals(aSlice, bSlice []netv1.IngressLoadBalancerIngress) bool {
if len(aSlice) != len(bSlice) { if len(aSlice) != len(bSlice) {
return false return false
} }
@ -469,12 +466,12 @@ func (c *clientWrapper) GetSecret(namespace, name string) (*corev1.Secret, bool,
return secret, exist, err return secret, exist, err
} }
func (c *clientWrapper) GetIngressClasses() ([]*networkingv1.IngressClass, error) { func (c *clientWrapper) GetIngressClasses() ([]*netv1.IngressClass, error) {
if c.clusterFactory == nil { if c.clusterFactory == nil {
return nil, errors.New("cluster factory not loaded") return nil, errors.New("cluster factory not loaded")
} }
var ics []*networkingv1.IngressClass var ics []*netv1.IngressClass
if !supportsNetworkingV1Ingress(c.serverVersion) { if !supportsNetworkingV1Ingress(c.serverVersion) {
ingressClasses, err := c.clusterFactory.Networking().V1beta1().IngressClasses().Lister().List(labels.Everything()) ingressClasses, err := c.clusterFactory.Networking().V1beta1().IngressClasses().Lister().List(labels.Everything())
if err != nil { if err != nil {
@ -483,7 +480,7 @@ func (c *clientWrapper) GetIngressClasses() ([]*networkingv1.IngressClass, error
for _, ic := range ingressClasses { for _, ic := range ingressClasses {
if ic.Spec.Controller == traefikDefaultIngressClassController { if ic.Spec.Controller == traefikDefaultIngressClassController {
icN, err := toNetworkingV1IngressClass(ic) icN, err := convert[netv1.IngressClass](ic)
if err != nil { if err != nil {
log.Error().Err(err).Msgf("Failed to convert ingress class %s from networking/v1beta1 to networking/v1", ic.Name) log.Error().Err(err).Msgf("Failed to convert ingress class %s from networking/v1beta1 to networking/v1", ic.Name)
continue continue
@ -530,7 +527,7 @@ func (c *clientWrapper) GetServerVersion() *version.Version {
// translateNotFoundError will translate a "not found" error to a boolean return // translateNotFoundError will translate a "not found" error to a boolean return
// value which indicates if the resource exists and a nil error. // value which indicates if the resource exists and a nil error.
func translateNotFoundError(err error) (bool, error) { func translateNotFoundError(err error) (bool, error) {
if kubeerror.IsNotFound(err) { if kerror.IsNotFound(err) {
return false, nil return false, nil
} }
return err == nil, err return err == nil, err
@ -559,8 +556,8 @@ func supportsIngressClass(serverVersion *version.Version) bool {
} }
// filterIngressClassByName return a slice containing ingressclasses with the correct name. // filterIngressClassByName return a slice containing ingressclasses with the correct name.
func filterIngressClassByName(ingressClassName string, ics []*networkingv1.IngressClass) []*networkingv1.IngressClass { func filterIngressClassByName(ingressClassName string, ics []*netv1.IngressClass) []*netv1.IngressClass {
var ingressClasses []*networkingv1.IngressClass var ingressClasses []*netv1.IngressClass
for _, ic := range ics { for _, ic := range ics {
if ic.Name == ingressClassName { if ic.Name == ingressClassName {

View file

@ -7,18 +7,18 @@ import (
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
networkingv1beta1 "k8s.io/api/networking/v1beta1" netv1beta1 "k8s.io/api/networking/v1beta1"
) )
var _ Client = (*clientMock)(nil) var _ Client = (*clientMock)(nil)
type clientMock struct { type clientMock struct {
ingresses []*networkingv1.Ingress ingresses []*netv1.Ingress
services []*corev1.Service services []*corev1.Service
secrets []*corev1.Secret secrets []*corev1.Secret
endpoints []*corev1.Endpoints endpoints []*corev1.Endpoints
ingressClasses []*networkingv1.IngressClass ingressClasses []*netv1.IngressClass
serverVersion *version.Version serverVersion *version.Version
@ -50,22 +50,22 @@ func newClientMock(serverVersion string, paths ...string) clientMock {
c.secrets = append(c.secrets, o) c.secrets = append(c.secrets, o)
case *corev1.Endpoints: case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o) c.endpoints = append(c.endpoints, o)
case *networkingv1beta1.Ingress: case *netv1beta1.Ingress:
ing, err := toNetworkingV1(o) ing, err := convert[netv1.Ingress](o)
if err != nil { if err != nil {
panic(err) panic(err)
} }
addServiceFromV1Beta1(ing, *o) addServiceFromV1Beta1(ing, *o)
c.ingresses = append(c.ingresses, ing) c.ingresses = append(c.ingresses, ing)
case *networkingv1.Ingress: case *netv1.Ingress:
c.ingresses = append(c.ingresses, o) c.ingresses = append(c.ingresses, o)
case *networkingv1beta1.IngressClass: case *netv1beta1.IngressClass:
ic, err := toNetworkingV1IngressClass(o) ic, err := convert[netv1.IngressClass](o)
if err != nil { if err != nil {
panic(err) panic(err)
} }
c.ingressClasses = append(c.ingressClasses, ic) c.ingressClasses = append(c.ingressClasses, ic)
case *networkingv1.IngressClass: case *netv1.IngressClass:
c.ingressClasses = append(c.ingressClasses, o) c.ingressClasses = append(c.ingressClasses, o)
default: default:
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o)) panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
@ -76,7 +76,7 @@ func newClientMock(serverVersion string, paths ...string) clientMock {
return c return c
} }
func (c clientMock) GetIngresses() []*networkingv1.Ingress { func (c clientMock) GetIngresses() []*netv1.Ingress {
return c.ingresses return c.ingresses
} }
@ -124,7 +124,7 @@ func (c clientMock) GetSecret(namespace, name string) (*corev1.Secret, bool, err
return nil, false, nil return nil, false, nil
} }
func (c clientMock) GetIngressClasses() ([]*networkingv1.IngressClass, error) { func (c clientMock) GetIngressClasses() ([]*netv1.IngressClass, error) {
return c.ingressClasses, nil return c.ingressClasses, nil
} }
@ -132,6 +132,6 @@ func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-cha
return c.watchChan, nil return c.watchChan, nil
} }
func (c clientMock) UpdateIngressStatus(_ *networkingv1.Ingress, _ []corev1.LoadBalancerIngress) error { func (c clientMock) UpdateIngressStatus(_ *netv1.Ingress, _ []netv1.IngressLoadBalancerIngress) error {
return c.apiIngressStatusError return c.apiIngressStatusError
} }

View file

@ -9,13 +9,13 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
"k8s.io/api/networking/v1beta1" netv1beta1 "k8s.io/api/networking/v1beta1"
kubeerror "k8s.io/apimachinery/pkg/api/errors" kerror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" kschema "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/version" kversion "k8s.io/apimachinery/pkg/version"
fakediscovery "k8s.io/client-go/discovery/fake" discoveryfake "k8s.io/client-go/discovery/fake"
kubefake "k8s.io/client-go/kubernetes/fake" kubefake "k8s.io/client-go/kubernetes/fake"
) )
@ -28,7 +28,7 @@ func TestTranslateNotFoundError(t *testing.T) {
}{ }{
{ {
desc: "kubernetes not found error", desc: "kubernetes not found error",
err: kubeerror.NewNotFound(schema.GroupResource{}, "foo"), err: kerror.NewNotFound(kschema.GroupResource{}, "foo"),
expectedExists: false, expectedExists: false,
expectedError: nil, expectedError: nil,
}, },
@ -61,8 +61,8 @@ func TestTranslateNotFoundError(t *testing.T) {
func TestIsLoadBalancerIngressEquals(t *testing.T) { func TestIsLoadBalancerIngressEquals(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
aSlice []corev1.LoadBalancerIngress aSlice []netv1.IngressLoadBalancerIngress
bSlice []corev1.LoadBalancerIngress bSlice []netv1.IngressLoadBalancerIngress
expectedEqual bool expectedEqual bool
}{ }{
{ {
@ -71,28 +71,28 @@ func TestIsLoadBalancerIngressEquals(t *testing.T) {
}, },
{ {
desc: "not the same length", desc: "not the same length",
bSlice: []corev1.LoadBalancerIngress{ bSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
}, },
expectedEqual: false, expectedEqual: false,
}, },
{ {
desc: "same ordered content", desc: "same ordered content",
aSlice: []corev1.LoadBalancerIngress{ aSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
}, },
bSlice: []corev1.LoadBalancerIngress{ bSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
}, },
expectedEqual: true, expectedEqual: true,
}, },
{ {
desc: "same unordered content", desc: "same unordered content",
aSlice: []corev1.LoadBalancerIngress{ aSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
{IP: "192.168.1.2", Hostname: "traefik2"}, {IP: "192.168.1.2", Hostname: "traefik2"},
}, },
bSlice: []corev1.LoadBalancerIngress{ bSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.2", Hostname: "traefik2"}, {IP: "192.168.1.2", Hostname: "traefik2"},
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
}, },
@ -100,11 +100,11 @@ func TestIsLoadBalancerIngressEquals(t *testing.T) {
}, },
{ {
desc: "different ordered content", desc: "different ordered content",
aSlice: []corev1.LoadBalancerIngress{ aSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
{IP: "192.168.1.2", Hostname: "traefik2"}, {IP: "192.168.1.2", Hostname: "traefik2"},
}, },
bSlice: []corev1.LoadBalancerIngress{ bSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
{IP: "192.168.1.2", Hostname: "traefik"}, {IP: "192.168.1.2", Hostname: "traefik"},
}, },
@ -112,11 +112,11 @@ func TestIsLoadBalancerIngressEquals(t *testing.T) {
}, },
{ {
desc: "different unordered content", desc: "different unordered content",
aSlice: []corev1.LoadBalancerIngress{ aSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
{IP: "192.168.1.2", Hostname: "traefik2"}, {IP: "192.168.1.2", Hostname: "traefik2"},
}, },
bSlice: []corev1.LoadBalancerIngress{ bSlice: []netv1.IngressLoadBalancerIngress{
{IP: "192.168.1.2", Hostname: "traefik3"}, {IP: "192.168.1.2", Hostname: "traefik3"},
{IP: "192.168.1.1", Hostname: "traefik"}, {IP: "192.168.1.1", Hostname: "traefik"},
}, },
@ -154,8 +154,8 @@ func TestClientIgnoresHelmOwnedSecrets(t *testing.T) {
kubeClient := kubefake.NewSimpleClientset(helmSecret, secret) kubeClient := kubefake.NewSimpleClientset(helmSecret, secret)
discovery, _ := kubeClient.Discovery().(*fakediscovery.FakeDiscovery) discovery, _ := kubeClient.Discovery().(*discoveryfake.FakeDiscovery)
discovery.FakedServerVersion = &version.Info{ discovery.FakedServerVersion = &kversion.Info{
GitVersion: "v1.19", GitVersion: "v1.19",
} }
@ -223,8 +223,8 @@ func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
kubeClient := kubefake.NewSimpleClientset(emptyEndpoint, filledEndpoint) kubeClient := kubefake.NewSimpleClientset(emptyEndpoint, filledEndpoint)
discovery, _ := kubeClient.Discovery().(*fakediscovery.FakeDiscovery) discovery, _ := kubeClient.Discovery().(*discoveryfake.FakeDiscovery)
discovery.FakedServerVersion = &version.Info{ discovery.FakedServerVersion = &kversion.Info{
GitVersion: "v1.19", GitVersion: "v1.19",
} }
@ -291,14 +291,14 @@ func TestClientIgnoresEmptyEndpointUpdates(t *testing.T) {
} }
func TestClientUsesCorrectServerVersion(t *testing.T) { func TestClientUsesCorrectServerVersion(t *testing.T) {
ingressV1Beta := &v1beta1.Ingress{ ingressV1Beta := &netv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Namespace: "default", Namespace: "default",
Name: "ingress-v1beta", Name: "ingress-v1beta",
}, },
} }
ingressV1 := &networkingv1.Ingress{ ingressV1 := &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Namespace: "default", Namespace: "default",
Name: "ingress-v1", Name: "ingress-v1",
@ -307,8 +307,8 @@ func TestClientUsesCorrectServerVersion(t *testing.T) {
kubeClient := kubefake.NewSimpleClientset(ingressV1Beta, ingressV1) kubeClient := kubefake.NewSimpleClientset(ingressV1Beta, ingressV1)
discovery, _ := kubeClient.Discovery().(*fakediscovery.FakeDiscovery) discovery, _ := kubeClient.Discovery().(*discoveryfake.FakeDiscovery)
discovery.FakedServerVersion = &version.Info{ discovery.FakedServerVersion = &kversion.Info{
GitVersion: "v1.18.12+foobar", GitVersion: "v1.18.12+foobar",
} }
@ -321,7 +321,7 @@ func TestClientUsesCorrectServerVersion(t *testing.T) {
select { select {
case event := <-eventCh: case event := <-eventCh:
ingress, ok := event.(*v1beta1.Ingress) ingress, ok := event.(*netv1beta1.Ingress)
require.True(t, ok) require.True(t, ok)
assert.Equal(t, "ingress-v1beta", ingress.Name) assert.Equal(t, "ingress-v1beta", ingress.Name)
@ -335,7 +335,7 @@ func TestClientUsesCorrectServerVersion(t *testing.T) {
case <-time.After(50 * time.Millisecond): case <-time.After(50 * time.Millisecond):
} }
discovery.FakedServerVersion = &version.Info{ discovery.FakedServerVersion = &kversion.Info{
GitVersion: "v1.19", GitVersion: "v1.19",
} }
@ -344,7 +344,7 @@ func TestClientUsesCorrectServerVersion(t *testing.T) {
select { select {
case event := <-eventCh: case event := <-eventCh:
ingress, ok := event.(*networkingv1.Ingress) ingress, ok := event.(*netv1.Ingress)
require.True(t, ok) require.True(t, ok)
assert.Equal(t, "ingress-v1", ingress.Name) assert.Equal(t, "ingress-v1", ingress.Name)

View file

@ -0,0 +1,70 @@
package ingress
import (
"errors"
corev1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
netv1beta1 "k8s.io/api/networking/v1beta1"
)
type marshaler interface {
Marshal() ([]byte, error)
}
type unmarshaler interface {
Unmarshal([]byte) error
}
type LoadBalancerIngress interface {
corev1.LoadBalancerIngress | netv1beta1.IngressLoadBalancerIngress | netv1.IngressLoadBalancerIngress
}
// convertSlice converts slice of LoadBalancerIngress to slice of LoadBalancerIngress.
// O (Bar), I (Foo) => []Bar.
func convertSlice[O LoadBalancerIngress, I LoadBalancerIngress](loadBalancerIngresses []I) ([]O, error) {
var results []O
for _, loadBalancerIngress := range loadBalancerIngresses {
mar, ok := any(&loadBalancerIngress).(marshaler)
if !ok {
// All the pointer of types related to the interface LoadBalancerIngress are compatible with the interface marshaler.
continue
}
um, err := convert[O](mar)
if err != nil {
return nil, err
}
v, ok := any(*um).(O)
if !ok {
continue
}
results = append(results, v)
}
return results, nil
}
// convert must only be used with unmarshaler and marshaler compatible types.
func convert[T any](input marshaler) (*T, error) {
data, err := input.Marshal()
if err != nil {
return nil, err
}
var output T
um, ok := any(&output).(unmarshaler)
if !ok {
return nil, errors.New("the output type doesn't implement unmarshaler interface")
}
err = um.Unmarshal(data)
if err != nil {
return nil, err
}
return &output, nil
}

View file

@ -0,0 +1,151 @@
package ingress
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1"
netv1beta1 "k8s.io/api/networking/v1beta1"
)
func Test_convertSlice_corev1_to_networkingv1(t *testing.T) {
g := []corev1.LoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []corev1.PortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
actual, err := convertSlice[netv1.IngressLoadBalancerIngress](g)
require.NoError(t, err)
expected := []netv1.IngressLoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []netv1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
assert.Equal(t, expected, actual)
}
func Test_convertSlice_networkingv1beta1_to_networkingv1(t *testing.T) {
g := []netv1beta1.IngressLoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []netv1beta1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
actual, err := convertSlice[netv1.IngressLoadBalancerIngress](g)
require.NoError(t, err)
expected := []netv1.IngressLoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []netv1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
assert.Equal(t, expected, actual)
}
func Test_convertSlice_networkingv1_to_networkingv1beta1(t *testing.T) {
g := []netv1.IngressLoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []netv1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
actual, err := convertSlice[netv1beta1.IngressLoadBalancerIngress](g)
require.NoError(t, err)
expected := []netv1beta1.IngressLoadBalancerIngress{
{
IP: "132456",
Hostname: "foo",
Ports: []netv1beta1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
},
}
assert.Equal(t, expected, actual)
}
func Test_convert(t *testing.T) {
g := &corev1.LoadBalancerIngress{
IP: "132456",
Hostname: "foo",
Ports: []corev1.PortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
}
actual, err := convert[netv1.IngressLoadBalancerIngress](g)
require.NoError(t, err)
expected := &netv1.IngressLoadBalancerIngress{
IP: "132456",
Hostname: "foo",
Ports: []netv1.IngressPortStatus{
{
Port: 123,
Protocol: "https",
Error: ptr("test"),
},
},
}
assert.Equal(t, expected, actual)
}
func ptr[T any](v T) *T {
return &v
}

View file

@ -25,7 +25,7 @@ import (
"github.com/traefik/traefik/v3/pkg/safe" "github.com/traefik/traefik/v3/pkg/safe"
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
) )
@ -195,7 +195,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
serverVersion := client.GetServerVersion() serverVersion := client.GetServerVersion()
var ingressClasses []*networkingv1.IngressClass var ingressClasses []*netv1.IngressClass
if !p.DisableIngressClassLookup && supportsIngressClass(serverVersion) { if !p.DisableIngressClassLookup && supportsIngressClass(serverVersion) {
ics, err := client.GetIngressClasses() ics, err := client.GetIngressClasses()
@ -346,7 +346,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
return conf return conf
} }
func (p *Provider) updateIngressStatus(ing *networkingv1.Ingress, k8sClient Client) error { func (p *Provider) updateIngressStatus(ing *netv1.Ingress, k8sClient Client) error {
// Only process if an EndpointIngress has been configured. // Only process if an EndpointIngress has been configured.
if p.IngressEndpoint == nil { if p.IngressEndpoint == nil {
return nil return nil
@ -357,7 +357,7 @@ func (p *Provider) updateIngressStatus(ing *networkingv1.Ingress, k8sClient Clie
return errors.New("publishedService or ip or hostname must be defined") return errors.New("publishedService or ip or hostname must be defined")
} }
return k8sClient.UpdateIngressStatus(ing, []corev1.LoadBalancerIngress{{IP: p.IngressEndpoint.IP, Hostname: p.IngressEndpoint.Hostname}}) return k8sClient.UpdateIngressStatus(ing, []netv1.IngressLoadBalancerIngress{{IP: p.IngressEndpoint.IP, Hostname: p.IngressEndpoint.Hostname}})
} }
serviceInfo := strings.Split(p.IngressEndpoint.PublishedService, "/") serviceInfo := strings.Split(p.IngressEndpoint.PublishedService, "/")
@ -382,10 +382,15 @@ func (p *Provider) updateIngressStatus(ing *networkingv1.Ingress, k8sClient Clie
return fmt.Errorf("missing service: %s", p.IngressEndpoint.PublishedService) return fmt.Errorf("missing service: %s", p.IngressEndpoint.PublishedService)
} }
return k8sClient.UpdateIngressStatus(ing, service.Status.LoadBalancer.Ingress) ingresses, err := convertSlice[netv1.IngressLoadBalancerIngress](service.Status.LoadBalancer.Ingress)
if err != nil {
return err
} }
func (p *Provider) shouldProcessIngress(ingress *networkingv1.Ingress, ingressClasses []*networkingv1.IngressClass) bool { return k8sClient.UpdateIngressStatus(ing, ingresses)
}
func (p *Provider) shouldProcessIngress(ingress *netv1.Ingress, ingressClasses []*netv1.IngressClass) bool {
// configuration through the new kubernetes ingressClass // configuration through the new kubernetes ingressClass
if ingress.Spec.IngressClassName != nil { if ingress.Spec.IngressClassName != nil {
for _, ic := range ingressClasses { for _, ic := range ingressClasses {
@ -410,7 +415,7 @@ func buildHostRule(host string) string {
return fmt.Sprintf("Host(`%s`)", host) return fmt.Sprintf("Host(`%s`)", host)
} }
func getCertificates(ctx context.Context, ingress *networkingv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { func getCertificates(ctx context.Context, ingress *netv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
for _, t := range ingress.Spec.TLS { for _, t := range ingress.Spec.TLS {
if t.SecretName == "" { if t.SecretName == "" {
log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided") log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided")
@ -495,7 +500,7 @@ func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores
return configs return configs
} }
func (p *Provider) loadService(client Client, namespace string, backend networkingv1.IngressBackend) (*dynamic.Service, error) { func (p *Provider) loadService(client Client, namespace string, backend netv1.IngressBackend) (*dynamic.Service, error) {
service, exists, err := client.GetService(namespace, backend.Service.Name) service, exists, err := client.GetService(namespace, backend.Service.Name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -645,7 +650,7 @@ func makeRouterKeyWithHash(key, rule string) (string, error) {
return dupKey, nil return dupKey, nil
} }
func loadRouter(rule networkingv1.IngressRule, pa networkingv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router { func loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
var rules []string var rules []string
if len(rule.Host) > 0 { if len(rule.Host) > 0 {
rules = []string{buildHostRule(rule.Host)} rules = []string{buildHostRule(rule.Host)}
@ -654,11 +659,11 @@ func loadRouter(rule networkingv1.IngressRule, pa networkingv1.HTTPIngressPath,
if len(pa.Path) > 0 { if len(pa.Path) > 0 {
matcher := defaultPathMatcher matcher := defaultPathMatcher
if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == networkingv1.PathTypeImplementationSpecific { if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == netv1.PathTypeImplementationSpecific {
if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" { if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" {
matcher = rtConfig.Router.PathMatcher matcher = rtConfig.Router.PathMatcher
} }
} else if *pa.PathType == networkingv1.PathTypeExact { } else if *pa.PathType == netv1.PathTypeExact {
matcher = "Path" matcher = "Path"
} }

View file

@ -17,7 +17,7 @@ import (
"github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/types"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -2160,7 +2160,7 @@ func TestGetCertificates(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingress *networkingv1.Ingress ingress *netv1.Ingress
client Client client Client
result map[string]*tls.CertAndStores result map[string]*tls.CertAndStores
errResult string errResult string

View file

@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/networking/v1" netv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -63,12 +63,12 @@ func Test_detectChanges(t *testing.T) {
}, },
{ {
name: "Ingress With same version", name: "Ingress With same version",
oldObj: &v1.Ingress{ oldObj: &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "1", ResourceVersion: "1",
}, },
}, },
newObj: &v1.Ingress{ newObj: &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "1", ResourceVersion: "1",
}, },
@ -76,12 +76,12 @@ func Test_detectChanges(t *testing.T) {
}, },
{ {
name: "Ingress With different version", name: "Ingress With different version",
oldObj: &v1.Ingress{ oldObj: &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "1", ResourceVersion: "1",
}, },
}, },
newObj: &v1.Ingress{ newObj: &netv1.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
ResourceVersion: "2", ResourceVersion: "2",
}, },

View file

@ -7,7 +7,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme" kscheme "k8s.io/client-go/kubernetes/scheme"
) )
// MustParseYaml parses a YAML to objects. // MustParseYaml parses a YAML to objects.
@ -21,7 +21,7 @@ func MustParseYaml(content []byte) []runtime.Object {
continue continue
} }
decode := scheme.Codecs.UniversalDeserializer().Decode decode := kscheme.Codecs.UniversalDeserializer().Decode
obj, groupVersionKind, err := decode([]byte(file), nil, nil) obj, groupVersionKind, err := decode([]byte(file), nil, nil)
if err != nil { if err != nil {
panic(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err)) panic(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err))

View file

@ -467,9 +467,6 @@ func newFakeSpiffePKI(trustDomain spiffeid.TrustDomain) (fakeSpiffePKI, error) {
IsCA: true, IsCA: true,
PublicKey: caPrivateKey.Public(), PublicKey: caPrivateKey.Public(),
} }
if err != nil {
return fakeSpiffePKI{}, err
}
caCertDER, err := x509.CreateCertificate( caCertDER, err := x509.CreateCertificate(
rand.Reader, rand.Reader,

View file

@ -27,7 +27,7 @@ import (
// Config provides configuration settings for the open-telemetry tracer. // Config provides configuration settings for the open-telemetry tracer.
type Config struct { type Config struct {
// NOTE: as no gRPC option is implemented yet, the type is empty and is used as a boolean for upward compatibility purposes. // NOTE: as no gRPC option is implemented yet, the type is empty and is used as a boolean for upward compatibility purposes.
GRPC *struct{} `description:"gRPC specific configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` GRPC *struct{} `description:"gRPC specific configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Address string `description:"Sets the address (host:port) of the collector endpoint." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` Address string `description:"Sets the address (host:port) of the collector endpoint." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
Path string `description:"Sets the URL path of the collector endpoint." json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"` Path string `description:"Sets the URL path of the collector endpoint." json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"`

View file

@ -107,7 +107,7 @@ func (i *InfluxDB2) SetDefaults() {
// OpenTelemetry contains specific configuration used by the OpenTelemetry Metrics exporter. // OpenTelemetry contains specific configuration used by the OpenTelemetry Metrics exporter.
type OpenTelemetry struct { type OpenTelemetry struct {
// NOTE: as no gRPC option is implemented yet, the type is empty and is used as a boolean for upward compatibility purposes. // NOTE: as no gRPC option is implemented yet, the type is empty and is used as a boolean for upward compatibility purposes.
GRPC *struct{} `description:"gRPC specific configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` GRPC *struct{} `description:"gRPC specific configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Address string `description:"Address (host:port) of the collector endpoint." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` Address string `description:"Address (host:port) of the collector endpoint." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"` AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"`

View file

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example final release of v2.9.0 # example final release of v2.10.0
CurrentRef = "v2.9" CurrentRef = "v2.10"
PreviousRef = "v2.9.0-rc1" PreviousRef = "v2.10.0-rc1"
BaseBranch = "v2.9" BaseBranch = "v2.10"
FutureCurrentRefName = "v2.9.0" FutureCurrentRefName = "v2.10.0"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10

View file

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example final release of v2.9.0 # example final release of v2.10.0
CurrentRef = "v2.9.0-rc1" CurrentRef = "v2.10.0-rc1"
PreviousRef = "v2.8.0-rc1" PreviousRef = "v2.9.0-rc1"
BaseBranch = "master" BaseBranch = "master"
FutureCurrentRefName = "v2.9.0-rc1" FutureCurrentRefName = "v2.10.0-rc1"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10

1
webui/.nvmrc Normal file
View file

@ -0,0 +1 @@
12.11.1

View file

@ -30,7 +30,13 @@
</q-tabs> </q-tabs>
<div class="right-menu"> <div class="right-menu">
<q-tabs> <q-tabs>
<q-btn type="a" href="https://hub.traefik.io/" target="_blank" flat no-caps label="Go to Hub Dashboard →" class="btn-menu btn-hub" /> <div class="tooltip" :class="{ 'is-dark-mode': $q.dark.isActive }">
<q-btn type="a" href="https://traefik.io/try-hub-now" target="_blank" flat no-caps label="Try Traefik Hub →" class="btn-menu btn-hub" />
<div class="content">
<p>Extend your capabilities to API Management</p>
<img alt="" v-bind:src="getHubLogoSrc($q.dark.isActive)" width="100px" />
</div>
</div>
<q-btn @click="$q.dark.toggle()" stretch flat no-caps icon="invert_colors" :label="`${$q.dark.isActive ? 'Light' : 'Dark'} theme`" class="btn-menu" /> <q-btn @click="$q.dark.toggle()" stretch flat no-caps icon="invert_colors" :label="`${$q.dark.isActive ? 'Light' : 'Dark'} theme`" class="btn-menu" />
<q-btn stretch flat icon="eva-question-mark-circle-outline"> <q-btn stretch flat icon="eva-question-mark-circle-outline">
<q-menu anchor="bottom left" auto-close> <q-menu anchor="bottom left" auto-close>
@ -86,7 +92,12 @@ export default {
} }
}, },
methods: { methods: {
...mapActions('core', { getVersion: 'getVersion' }) ...mapActions('core', { getVersion: 'getVersion' }),
getHubLogoSrc (isDarkMode) {
return isDarkMode
? 'statics/hub-logo-horizontal-dark.png'
: 'statics/hub-logo-horizontal-clear.png'
}
}, },
created () { created () {
this.getVersion() this.getVersion()
@ -154,8 +165,8 @@ export default {
} }
.btn-hub { .btn-hub {
color: #0e204c; color: #dedede;
background: #deea48; background: #5f6572;
} }
.q-item { .q-item {
@ -166,4 +177,70 @@ export default {
font-weight: 700; font-weight: 700;
align-items: flex-start; align-items: flex-start;
} }
.tooltip {
display: inline-block;
.content {
display: flex;
align-items: center;
visibility: hidden;
font-size: 16px;
padding: 20px;
border-radius: 16px;
background-color: #fff;
box-shadow: 0 0 6px rgba(0,0,0,0.16), 0 0 6px rgba(0,0,0,0.23);
/* Position the tooltip text */
position: absolute;
z-index: 1;
top: 90%;
left: -5%;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
&::after {
content: "";
position: absolute;
top: -10px;
left: 22%;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 10px solid #fff;
}
p {
align-self: baseline;
color: var(--q-color-primary);
font-weight: bold;
margin: 0 20px 0 0;
max-width: 180px;
}
img {
margin: 0 20px;
}
}
&.is-dark-mode .content {
background-color: #262626;
box-shadow: 0 0 6px rgba(10,18,36,0.16), 0 0 6px rgba(10,18,36,0.23);
&::after {
border-bottom: 10px solid #262626;
}
p {
color: #fff;
}
}
&:hover .content {
visibility: visible;
opacity: 1;
}
}
</style> </style>

View file

@ -723,7 +723,7 @@
</div> </div>
</q-card-section> </q-card-section>
<!-- EXTRA FIELDS FROM MIDDLEWARES - [rateLimit] - average && burst--> <!-- EXTRA FIELDS FROM MIDDLEWARES - [rateLimit] - average & burst & period -->
<q-card-section v-if="middleware.rateLimit"> <q-card-section v-if="middleware.rateLimit">
<div class="row items-start no-wrap"> <div class="row items-start no-wrap">
<div class="col"> <div class="col">
@ -742,6 +742,14 @@
{{ exData(middleware).burst }} {{ exData(middleware).burst }}
</q-chip> </q-chip>
</div> </div>
<div class="col">
<div class="text-subtitle2">Period</div>
<q-chip
dense
class="app-chip app-chip-green">
{{ exData(middleware).period }}
</q-chip>
</div>
</div> </div>
</q-card-section> </q-card-section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB