Merge branch v3.0 into master
This commit is contained in:
commit
619045eb4b
67 changed files with 1862 additions and 1203 deletions
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -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
|
||||||
|
|
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
|
@ -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:
|
||||||
|
|
2
.github/workflows/validate.yaml
vendored
2
.github/workflows/validate.yaml
vendored
|
@ -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: ""
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
57
CHANGELOG.md
57
CHANGELOG.md
|
@ -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)
|
||||||
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -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 can’t be replicated due to a lack of reproducible case (a simple docker compose should be enough) -
|
If the issue can’t 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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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!}
|
||||||
|
|
|
@ -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) |
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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).
|
|
||||||
|
|
|
@ -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).
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
46
go.mod
|
@ -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
91
go.sum
|
@ -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=
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
75
pkg/config/dynamic/plugins_test.go
Normal file
75
pkg/config/dynamic/plugins_test.go
Normal 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()
|
||||||
|
})
|
||||||
|
}
|
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
70
pkg/provider/kubernetes/ingress/convert.go
Normal file
70
pkg/provider/kubernetes/ingress/convert.go
Normal 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
|
||||||
|
}
|
151
pkg/provider/kubernetes/ingress/convert_test.go
Normal file
151
pkg/provider/kubernetes/ingress/convert_test.go
Normal 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
|
||||||
|
}
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
1
webui/.nvmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
12.11.1
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
BIN
webui/src/statics/hub-logo-horizontal-clear.png
Normal file
BIN
webui/src/statics/hub-logo-horizontal-clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
webui/src/statics/hub-logo-horizontal-dark.png
Normal file
BIN
webui/src/statics/hub-logo-horizontal-dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Loading…
Reference in a new issue