diff --git a/CHANGELOG.md b/CHANGELOG.md index d077e6863..e87a30922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,82 @@ +## [v3.2.0](https://github.com/traefik/traefik/tree/v3.2.0) (2024-10-28) +[All Commits](https://github.com/traefik/traefik/compare/v3.2.0-rc1...v3.2.0) + +**Enhancements:** +- **[acme]** Remove same email requirement for certresolvers ([#11019](https://github.com/traefik/traefik/pull/11019) by [Emrio](https://github.com/Emrio)) +- **[acme]** Add support for custom CA certificates by certificate resolver ([#10816](https://github.com/traefik/traefik/pull/10816) by [ldez](https://github.com/ldez)) +- **[acme]** Add 30 day certificatesDuration step ([#10970](https://github.com/traefik/traefik/pull/10970) by [luker983](https://github.com/luker983)) +- **[docker]** Support HTTP BasicAuth for docker and swarm endpoint ([#10776](https://github.com/traefik/traefik/pull/10776) by [985492783](https://github.com/985492783)) +- **[k8s,k8s/gatewayapi]** Add supported features to the Gateway API GatewayClass status ([#11056](https://github.com/traefik/traefik/pull/11056) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Update sigs.k8s.io/gateway-api to v1.2.0-rc1 ([#11124](https://github.com/traefik/traefik/pull/11124) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Add support for backend protocol selection in HTTP and GRPC routes ([#11051](https://github.com/traefik/traefik/pull/11051) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Improve Kubernetes GatewayAPI TCPRoute and TLSRoute support ([#11042](https://github.com/traefik/traefik/pull/11042) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Support HTTPRoute destination port matching ([#11134](https://github.com/traefik/traefik/pull/11134) by [kevinpollet](https://github.com/kevinpollet)) +- **[k8s,k8s/gatewayapi]** Bump sigs.k8s.io/gateway-api to v1.2.0-rc2 ([#11131](https://github.com/traefik/traefik/pull/11131) by [kevinpollet](https://github.com/kevinpollet)) +- **[k8s,k8s/gatewayapi]** Add support for Gateway API BackendTLSPolicies ([#11009](https://github.com/traefik/traefik/pull/11009) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Support NativeLB option in GatewayAPI provider ([#11147](https://github.com/traefik/traefik/pull/11147) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Support ResponseHeaderModifier filter ([#10987](https://github.com/traefik/traefik/pull/10987) by [kevinpollet](https://github.com/kevinpollet)) +- **[k8s,k8s/gatewayapi]** Support GRPC routes ([#10975](https://github.com/traefik/traefik/pull/10975) by [kevinpollet](https://github.com/kevinpollet)) +- **[k8s,k8s/gatewayapi]** Bump sigs.k8s.io/gateway-api to v1.2.0 ([#11167](https://github.com/traefik/traefik/pull/11167) by [rtribotte](https://github.com/rtribotte)) +- **[metrics,otel]** Allow setting service.name for OTLP metrics ([#10917](https://github.com/traefik/traefik/pull/10917) by [cmartell-at-ocp](https://github.com/cmartell-at-ocp)) +- **[middleware,accesslogs]** Record trace id and EntryPoint span id into access log ([#10921](https://github.com/traefik/traefik/pull/10921) by [weijiany](https://github.com/weijiany)) +- **[middleware,authentication]** Support LogUserHeader with forwardAuth middleware ([#10833](https://github.com/traefik/traefik/pull/10833) by [GaleHuang](https://github.com/GaleHuang)) +- **[middleware]** Add encodings option to the compression middleware ([#10943](https://github.com/traefik/traefik/pull/10943) by [wollomatic](https://github.com/wollomatic)) +- **[middleware]** Add support for ipv6 subnet in ipStrategy ([#9747](https://github.com/traefik/traefik/pull/9747) by [michal-kralik](https://github.com/michal-kralik)) +- **[nomad]** Support for watching instead of polling Nomad ([#10997](https://github.com/traefik/traefik/pull/10997) by [deverton-godaddy](https://github.com/deverton-godaddy)) +- **[server,performance]** Introduce a fast proxy mode to improve HTTP/1.1 performances with backends ([#11122](https://github.com/traefik/traefik/pull/11122) by [kevinpollet](https://github.com/kevinpollet)) +- **[server]** Configurable max request header size ([#10995](https://github.com/traefik/traefik/pull/10995) by [lucasrod16](https://github.com/lucasrod16)) +- **[service]** Add mirrorBody option to HTTP mirroring ([#11032](https://github.com/traefik/traefik/pull/11032) by [MatteoPaier](https://github.com/MatteoPaier)) +- **[service]** Add an option to preserve server path ([#11193](https://github.com/traefik/traefik/pull/11193) by [mmatur](https://github.com/mmatur)) + +**Bug fixes:** +- **[k8s,k8s/gatewayapi]** Ensuring Gateway API reflected Traefik resource name unicity ([#11222](https://github.com/traefik/traefik/pull/11222) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Preserve GRPCRoute filters order ([#11199](https://github.com/traefik/traefik/pull/11199) by [kevinpollet](https://github.com/kevinpollet)) +- **[k8s,k8s/gatewayapi]** Support http and https appProtocol for Kubernetes Service ([#11176](https://github.com/traefik/traefik/pull/11176) by [WillDaSilva](https://github.com/WillDaSilva)) +- **[k8s,k8s/gatewayapi]** Avoid updating Accepted status for routes matching no Gateways ([#11170](https://github.com/traefik/traefik/pull/11170) by [rtribotte](https://github.com/rtribotte)) +- **[k8s,k8s/gatewayapi]** Do not update gateway status when not selected by a gateway class ([#11169](https://github.com/traefik/traefik/pull/11169) by [kevinpollet](https://github.com/kevinpollet)) +- **[service]** Detect and drop broken conns in the fastproxy pool ([#11212](https://github.com/traefik/traefik/pull/11212) by [kevinpollet](https://github.com/kevinpollet)) + +**Documentation:** +- **[k8s,k8s/gatewayapi]** Document nativeLBByDefault annotation on Kubernetes Gateway provider ([#11209](https://github.com/traefik/traefik/pull/11209) by [mloiseleur](https://github.com/mloiseleur)) +- **[k8s/crd,k8s]** Detail CRD update with v3.2 in the migration guide ([#11164](https://github.com/traefik/traefik/pull/11164) by [mloiseleur](https://github.com/mloiseleur)) +- **[k8s/gatewayapi]** Add missing RBAC in the migration guide ([#11189](https://github.com/traefik/traefik/pull/11189) by [mloiseleur](https://github.com/mloiseleur)) +- **[k8s]** Fix instructions for downloading CRDs of Gateway API v1.2 ([#11191](https://github.com/traefik/traefik/pull/11191) by [mloiseleur](https://github.com/mloiseleur)) +- Prepare release v3.2.0-rc2 ([#11182](https://github.com/traefik/traefik/pull/11182) by [kevinpollet](https://github.com/kevinpollet)) +- Prepare Release v3.2.0-rc1 ([#11154](https://github.com/traefik/traefik/pull/11154) by [rtribotte](https://github.com/rtribotte)) + +**Misc:** +- Merge branch v3.1 into v3.2 ([#11219](https://github.com/traefik/traefik/pull/11219) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v3.1 into v3.2 ([#11181](https://github.com/traefik/traefik/pull/11181) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v3.1 into master ([#11153](https://github.com/traefik/traefik/pull/11153) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v3.1 into master ([#11110](https://github.com/traefik/traefik/pull/11110) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v3.1 into master ([#11066](https://github.com/traefik/traefik/pull/11066) by [mmatur](https://github.com/mmatur)) +- Merge branch v3.1 into master ([#11047](https://github.com/traefik/traefik/pull/11047) by [mmatur](https://github.com/mmatur)) +- Merge branch v3.1 into master ([#10980](https://github.com/traefik/traefik/pull/10980) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v3.1 into master ([#10952](https://github.com/traefik/traefik/pull/10952) by [mmatur](https://github.com/mmatur)) +- Merge branch v3.1 into master ([#10906](https://github.com/traefik/traefik/pull/10906) by [rtribotte](https://github.com/rtribotte)) + +## [v3.1.7](https://github.com/traefik/traefik/tree/v3.1.7) (2024-10-28) +[All Commits](https://github.com/traefik/traefik/compare/v3.1.6...v3.1.7) + +**Bug fixes:** +- **[k8s,k8s/gatewayapi]** Preserve HTTPRoute filters order ([#11198](https://github.com/traefik/traefik/pull/11198) by [kevinpollet](https://github.com/kevinpollet)) + +**Documentation:** +- **[k8s,k8s/gatewayapi]** Fix broken links in Kubernetes Gateway provider page ([#11188](https://github.com/traefik/traefik/pull/11188) by [mloiseleur](https://github.com/mloiseleur)) + +**Misc:** +- Merge branch v2.11 into v3.1 ([#11232](https://github.com/traefik/traefik/pull/11232) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v2.11 into v3.1 ([#11218](https://github.com/traefik/traefik/pull/11218) by [kevinpollet](https://github.com/kevinpollet)) + +## [v2.11.13](https://github.com/traefik/traefik/tree/v2.11.13) (2024-10-28) +[All Commits](https://github.com/traefik/traefik/compare/v2.11.12...v2.11.13) + +**Bug fixes:** +- **[middleware,service]** Panic on aborted requests to properly close the connection ([#11129](https://github.com/traefik/traefik/pull/11129) by [tonybart1337](https://github.com/tonybart1337)) + +**Documentation:** +- Update business callouts ([#11217](https://github.com/traefik/traefik/pull/11217) by [tomatokoolaid](https://github.com/tomatokoolaid)) + ## [v3.2.0-rc2](https://github.com/traefik/traefik/tree/v3.2.0-rc2) (2024-10-09) [All Commits](https://github.com/traefik/traefik/compare/v3.2.0-rc1...v3.2.0-rc2) diff --git a/Makefile b/Makefile index e562eae6a..79126164c 100644 --- a/Makefile +++ b/Makefile @@ -126,20 +126,16 @@ lint: .PHONY: validate-files #? validate-files: Validate code and docs -validate-files: lint +validate-files: $(foreach exec,$(LINT_EXECUTABLES),\ $(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) + $(CURDIR)/script/validate-vendor.sh $(CURDIR)/script/validate-misspell.sh $(CURDIR)/script/validate-shell-script.sh .PHONY: validate #? validate: Validate code, docs, and vendor -validate: lint - $(foreach exec,$(EXECUTABLES),\ - $(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) - $(CURDIR)/script/validate-vendor.sh - $(CURDIR)/script/validate-misspell.sh - $(CURDIR)/script/validate-shell-script.sh +validate: lint validate-files # Target for building images for multiple architectures. .PHONY: multi-arch-image-% diff --git a/docs/content/getting-started/faq.md b/docs/content/getting-started/faq.md index facdd71bf..66f2d4d04 100644 --- a/docs/content/getting-started/faq.md +++ b/docs/content/getting-started/faq.md @@ -251,3 +251,5 @@ In which case, you should make sure your infrastructure is properly set up for a ```shell LEGO_DISABLE_CNAME_SUPPORT=true ``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/https/acme.md b/docs/content/https/acme.md index 955cc0271..82b87a210 100644 --- a/docs/content/https/acme.md +++ b/docs/content/https/acme.md @@ -370,6 +370,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) | | [Hosttech](https://www.hosttech.eu) | `hosttech` | `HOSTTECH_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech) | | [http.net](https://www.http.net/) | `httpnet` | `HTTPNET_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/httpnet) | +| [Huawei Cloud](https://huaweicloud.com) | `huaweicloud` | `HUAWEICLOUD_ACCESS_KEY_ID`, `HUAWEICLOUD_SECRET_ACCESS_KEY`, `HUAWEICLOUD_REGION` | [Additional configuration](https://go-acme.github.io/lego/dns/huaweicloud) | | [Hurricane Electric](https://dns.he.net) | `hurricane` | `HURRICANE_TOKENS` [^6] | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane) | | [HyperOne](https://www.hyperone.com) | `hyperone` | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone) | | [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/) | `ibmcloud` | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud) | @@ -424,6 +425,7 @@ For complete details, refer to your provider's _Additional configuration_ link. | [Scaleway](https://www.scaleway.com) | `scaleway` | `SCW_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) | | [Selectel v2](https://selectel.ru/en/) | `selectelv2` | `SELECTELV2_ACCOUNT_ID`, `SELECTELV2_PASSWORD`, `SELECTELV2_PROJECT_ID`, `SELECTELV2_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/selectelv2) | | [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) | +| [SelfHost.(de/eu)](https://www.selfhost.de) | `selfhostde` | `SELFHOSTDE_USERNAME`, `SELFHOSTDE_PASSWORD`, `SELFHOSTDE_RECORDS_MAPPING` | [Additional configuration](https://go-acme.github.io/lego/dns/selfhostde) | | [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) | | [Shellrent](https://www.shellrent.com) | `shellrent` | `SHELLRENT_USERNAME`, `SHELLRENT_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/shellrent) | | [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) | @@ -460,11 +462,6 @@ For complete details, refer to your provider's _Additional configuration_ link. [^5]: The `Global API Key` needs to be used, not the `Origin CA Key`. [^6]: As explained in the [LEGO hurricane configuration](https://go-acme.github.io/lego/dns/hurricane/#credentials), each domain or wildcard (record name) needs a token. So each update of record name must be followed by an update of the `HURRICANE_TOKENS` variable, and a restart of Traefik. -!!! info "`delayBeforeCheck`" - By default, the `provider` verifies the TXT record _before_ letting ACME verify. - You can delay this operation by specifying a delay (in seconds) with `delayBeforeCheck` (value must be greater than zero). - This option is useful when internal networks block external DNS queries. - #### `resolvers` Use custom DNS servers to resolve the FQDN authority. @@ -494,6 +491,66 @@ certificatesResolvers: --certificatesresolvers.myresolver.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53 ``` +#### `delayBeforeCheck` + +By default, the `provider` verifies the TXT record _before_ letting ACME verify. + +You can delay this operation by specifying a delay (in seconds) with `delayBeforeCheck` (value must be greater than zero). + +This option is useful when internal networks block external DNS queries. + +```yaml tab="File (YAML)" +certificatesResolvers: + myresolver: + acme: + # ... + dnsChallenge: + # ... + delayBeforeCheck: 2s +``` + +```toml tab="File (TOML)" +[certificatesResolvers.myresolver.acme] + # ... + [certificatesResolvers.myresolver.acme.dnsChallenge] + # ... + delayBeforeCheck = "2s" +``` + +```bash tab="CLI" +# ... +--certificatesresolvers.myresolver.acme.dnschallenge.delayBeforeCheck=2s +``` + +#### `disablePropagationCheck` + +**Not recommended** + +Disable the TXT records propagation checks before notifying ACME that the DNS challenge is ready. + +```yaml tab="File (YAML)" +certificatesResolvers: + myresolver: + acme: + # ... + dnsChallenge: + # ... + disablePropagationCheck: true +``` + +```toml tab="File (TOML)" +[certificatesResolvers.myresolver.acme] + # ... + [certificatesResolvers.myresolver.acme.dnsChallenge] + # ... + disablePropagationCheck = true +``` + +```bash tab="CLI" +# ... +--certificatesresolvers.myresolver.acme.dnschallenge.disablePropagationCheck=true +``` + #### Wildcard Domains [ACME V2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates. diff --git a/docs/content/includes/traefik-for-business-applications.md b/docs/content/includes/traefik-for-business-applications.md index 474c815d2..b0e360f95 100644 --- a/docs/content/includes/traefik-for-business-applications.md +++ b/docs/content/includes/traefik-for-business-applications.md @@ -1,10 +1,10 @@ --- -!!! question "Using Traefik OSS in Production? Consider Adding Advanced Capabilities." +!!! question "Using Traefik OSS in Production?" - Add API Gateway or API Management capabilities seamlessly to your existing Traefik deployments. - No rip and replace. No learning curve. + If you are using Traefik at work, consider adding enterprise-grade API gateway capabilities or commercial support for Traefik OSS. - - [Explore our API Gateway](https://traefik.io/traefik-hub-api-gateway/) ([Watch the Demo Video](https://info.traefik.io/watch-traefik-api-gw-demo?cta=doc)) - - [Explore our API Management](https://traefik.io/traefik-hub/) - - [Get 24/7/365 Commercial Support for Traefik OSS](https://info.traefik.io/request-commercial-support) + - [Watch our API Gateway Demo Video](https://info.traefik.io/watch-traefik-api-gw-demo?cta=doc) + - [Request 24/7/365 OSS Support](https://info.traefik.io/request-commercial-support?cta=doc) + + Adding API Gateway capabilities to Traefik OSS is fast and seamless. There's no rip and replace and all configurations remain intact. See it in action via [this short video](https://info.traefik.io/watch-traefik-api-gw-demo?cta=doc). diff --git a/docs/content/index.md b/docs/content/index.md index e419f3321..2708d08de 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -18,11 +18,7 @@ Traefik is natively compliant with every major cluster technology, such as Kuber With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. -And if your needs change, you can add API gateway and API management capabilities seamlessly to your existing Traefik deployments. It takes less than a minute, there’s no rip-and-replace, and all your configurations are preserved. See how it works in this video: - -
- -
+And if your needs change, you can add API gateway and API management capabilities seamlessly to your existing Traefik deployments. It takes less than a minute, there’s no rip-and-replace, and all your configurations are preserved. See this in action in [our API gateway demo video](https://info.traefik.io/watch-traefik-api-gw-demo?cta=docs). Developing Traefik, our main goal is to make it effortless to use, and we're sure you'll enjoy it. @@ -30,6 +26,8 @@ Developing Traefik, our main goal is to make it effortless to use, and we're sur !!! info - 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. + Have a question? Join our [Community Forum](https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the Traefik community. - Using Traefik OSS in Production? Consider our enterprise-grade [API Gateway](https://traefik.io/traefik-hub-api-gateway/), [API Management](https://traefik.io/traefik-hub/), and [Commercial Support](https://info.traefik.io/request-commercial-support) solutions. + Using Traefik OSS in Production? Consider our enterprise-grade [API Gateway](https://info.traefik.io/watch-traefik-api-gw-demo?cta=doc) or our [24/7/365 OSS Support](https://info.traefik.io/request-commercial-support?cta=doc). + + Explore our API Gateway upgrade via [this short demo video](https://info.traefik.io/watch-traefik-api-gw-demo?cta=doc). diff --git a/docs/content/middlewares/http/basicauth.md b/docs/content/middlewares/http/basicauth.md index de5655bf3..6e5105a5b 100644 --- a/docs/content/middlewares/http/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -341,3 +341,4 @@ http: [http.middlewares.test-auth.basicAuth] removeHeader = true ``` +{!traefik-for-business-applications.md!} diff --git a/docs/content/middlewares/http/forwardauth.md b/docs/content/middlewares/http/forwardauth.md index c8167b964..b9682b842 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -611,4 +611,6 @@ http: [http.middlewares.test-auth.forwardAuth] # ... headerField = "X-WebAuth-User" -``` \ No newline at end of file +``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/middlewares/http/redirectregex.md b/docs/content/middlewares/http/redirectregex.md index 2788a3c6f..5488117db 100644 --- a/docs/content/middlewares/http/redirectregex.md +++ b/docs/content/middlewares/http/redirectregex.md @@ -84,3 +84,5 @@ The `replacement` option defines how to modify the URL to have the new target UR !!! warning Care should be taken when defining replacement expand variables: `$1x` is equivalent to `${1x}`, not `${1}x` (see [Regexp.Expand](https://golang.org/pkg/regexp/#Regexp.Expand)), so use `${1}` syntax. + +{!traefik-for-business-applications.md!} diff --git a/docs/content/middlewares/http/stripprefix.md b/docs/content/middlewares/http/stripprefix.md index b84442321..5c985b243 100644 --- a/docs/content/middlewares/http/stripprefix.md +++ b/docs/content/middlewares/http/stripprefix.md @@ -145,3 +145,5 @@ http: prefixes = ["/foobar"] forceSlash = false ``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/migration/v3.md b/docs/content/migration/v3.md index 64ac460e5..d4cf9fc3e 100644 --- a/docs/content/migration/v3.md +++ b/docs/content/migration/v3.md @@ -125,10 +125,18 @@ the `grcroutes` and `grpcroutes/status` rights have to be added. Starting with v3.2, the Kubernetes Gateway Provider now supports [BackendTLSPolicy](https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/). Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) provider RBACs), -the `backendtlspolicies` and `backendtlspolicies/status` rights have to be added. +the `configmaps`, `backendtlspolicies` and `backendtlspolicies/status` rights have to be added. ```yaml ... + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch - apiGroups: - gateway.networking.k8s.io resources: diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 58cba2066..bb664dc51 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -291,3 +291,5 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock ``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/observability/logs.md b/docs/content/observability/logs.md index 2009aeee7..4ee168e66 100644 --- a/docs/content/observability/logs.md +++ b/docs/content/observability/logs.md @@ -180,3 +180,5 @@ log: ```bash tab="CLI" --log.compress=true ``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/operations/api.md b/docs/content/operations/api.md index a495ab4e5..7c8248c2e 100644 --- a/docs/content/operations/api.md +++ b/docs/content/operations/api.md @@ -174,3 +174,5 @@ All the following endpoints must be accessed with a `GET` HTTP request. | `/debug/pprof/profile` | See the [pprof Profile](https://golang.org/pkg/net/http/pprof/#Profile) Go documentation. | | `/debug/pprof/symbol` | See the [pprof Symbol](https://golang.org/pkg/net/http/pprof/#Symbol) Go documentation. | | `/debug/pprof/trace` | See the [pprof Trace](https://golang.org/pkg/net/http/pprof/#Trace) Go documentation. | + +{!traefik-for-business-applications.md!} diff --git a/docs/content/plugins/index.md b/docs/content/plugins/index.md index 7eb57106d..9cd3662f8 100644 --- a/docs/content/plugins/index.md +++ b/docs/content/plugins/index.md @@ -30,3 +30,5 @@ They need not be compiled, and no complex toolchain is necessary to build them. The experience of implementing a Traefik plugin is comparable to writing a web browser extension. To learn more about Traefik plugin creation, please refer to the [developer documentation](https://plugins.traefik.io/create). + +{!traefik-for-business-applications.md!} diff --git a/docs/content/providers/kubernetes-gateway.md b/docs/content/providers/kubernetes-gateway.md index 072a4c47f..e21309df8 100644 --- a/docs/content/providers/kubernetes-gateway.md +++ b/docs/content/providers/kubernetes-gateway.md @@ -27,10 +27,10 @@ For more details, check out the conformance [report](https://github.com/kubernet ```bash # Install Gateway API CRDs from the Standard channel. - kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml + kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml ``` -2. Install/update the Traefik [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac). +2. Install the additional Traefik RBAC required for Gateway API. ```bash # Install Traefik RBACs. @@ -275,7 +275,7 @@ providers: ```bash # Install Gateway API CRDs from the Experimental channel. - kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/experimental-install.yaml + kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml ``` ### `labelselector` @@ -304,6 +304,30 @@ providers: --providers.kubernetesgateway.labelselector="app=traefik" ``` +### `nativeLBByDefault` + +_Optional, Default: false_ + +Defines whether to use Native Kubernetes load-balancing mode by default. +For more information, please check out the `traefik.io/service.nativelb` [service annotation documentation](../routing/providers/kubernetes-gateway.md#native-load-balancing). + +```yaml tab="File (YAML)" +providers: + kubernetesGateway: + nativeLBByDefault: true + # ... +``` + +```toml tab="File (TOML)" +[providers.kubernetesGateway] + nativeLBByDefault = true + # ... +``` + +```bash tab="CLI" +--providers.kubernetesgateway.nativeLBByDefault=true +``` + ### `throttleDuration` _Optional, Default: 0_ diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 18fc9bc84..065d3ca16 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -59,10 +59,12 @@ [[http.services.Service02.loadBalancer.servers]] url = "foobar" weight = 42 + preservePath = true [[http.services.Service02.loadBalancer.servers]] url = "foobar" weight = 42 + preservePath = true [http.services.Service02.loadBalancer.healthCheck] scheme = "foobar" mode = "foobar" diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index d0b0fc0fb..08cb9c385 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -66,8 +66,10 @@ http: servers: - url: foobar weight: 42 + preservePath: true - url: foobar weight: 42 + preservePath: true healthCheck: scheme: foobar mode: foobar diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index 01de7ee69..a2f24a805 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -256,8 +256,10 @@ THIS FILE MUST NOT BE EDITED BY HAND | `traefik/http/services/Service02/loadBalancer/healthCheck/timeout` | `42s` | | `traefik/http/services/Service02/loadBalancer/passHostHeader` | `true` | | `traefik/http/services/Service02/loadBalancer/responseForwarding/flushInterval` | `42s` | +| `traefik/http/services/Service02/loadBalancer/servers/0/preservePath` | `true` | | `traefik/http/services/Service02/loadBalancer/servers/0/url` | `foobar` | | `traefik/http/services/Service02/loadBalancer/servers/0/weight` | `42` | +| `traefik/http/services/Service02/loadBalancer/servers/1/preservePath` | `true` | | `traefik/http/services/Service02/loadBalancer/servers/1/url` | `foobar` | | `traefik/http/services/Service02/loadBalancer/servers/1/weight` | `42` | | `traefik/http/services/Service02/loadBalancer/serversTransport` | `foobar` | diff --git a/docs/content/routing/providers/kubernetes-gateway.md b/docs/content/routing/providers/kubernetes-gateway.md index 8e97b5c75..c2da4447c 100644 --- a/docs/content/routing/providers/kubernetes-gateway.md +++ b/docs/content/routing/providers/kubernetes-gateway.md @@ -723,4 +723,31 @@ X-Forwarded-Server: traefik-6b66d45748-ns8mt X-Real-Ip: 10.42.2.1 ``` +## Native Load Balancing + +By default, Traefik sends the traffic directly to the pod IPs and reuses the established connections to the backends for performance purposes. + +It is possible to override this behavior and configure Traefik to send the traffic to the service IP. +The Kubernetes service itself does the load balancing to the pods. +It can be done with the annotation `traefik.io/service.nativelb` on the backend `Service`. + +By default, NativeLB is `false`. + +!!! info "Default value" + + Note that it is possible to override the default value by using the option [`nativeLBByDefault`](../../providers/kubernetes-gateway.md#nativelbbydefault) at the provider level. + +```yaml +--- +apiVersion: v1 +kind: Service +metadata: + name: myservice + namespace: default + annotations: + traefik.io/service.nativelb: "true" +spec: +[...] +``` + {!traefik-for-business-applications.md!} \ No newline at end of file diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index 8e4cc41f0..b58ac814a 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -116,12 +116,8 @@ Each service has a load-balancer, even if there is only one server to forward tr #### Servers Servers declare a single instance of your program. -The `url` option point to a specific instance. -!!! info "" - Paths in the servers' `url` have no effect. - If you want the requests to be sent to a specific path on your servers, - configure your [`routers`](../routers/index.md) to use a corresponding [middleware](../../middlewares/overview.md) (e.g. the [AddPrefix](../../middlewares/http/addprefix.md) or [ReplacePath](../../middlewares/http/replacepath.md)) middlewares. +The `url` option point to a specific instance. ??? example "A Service with One Server -- Using the [File Provider](../../providers/file.md)" @@ -173,6 +169,34 @@ The `weight` option allows for weighted load balancing on the servers. weight = 1 ``` +The `preservePath` option allows to preserve the URL path. + +!!! info "Health Check" + + When a [health check](#health-check) is configured for the server, the path is not preserved. + +??? example "A Service with One Server and PreservePath -- Using the [File Provider](../../providers/file.md)" + + ```yaml tab="YAML" + ## Dynamic configuration + http: + services: + my-service: + loadBalancer: + servers: + - url: "http://private-ip-server-1/base" + preservePath: true + ``` + + ```toml tab="TOML" + ## Dynamic configuration + [http.services] + [http.services.my-service.loadBalancer] + [[http.services.my-service.loadBalancer.servers]] + url = "http://private-ip-server-1/base" + preservePath = true + ``` + #### Load-balancing For now, only round robin load balancing is supported: diff --git a/docs/content/user-guides/docker-compose/acme-dns/index.md b/docs/content/user-guides/docker-compose/acme-dns/index.md index 5affbe009..57752f855 100644 --- a/docs/content/user-guides/docker-compose/acme-dns/index.md +++ b/docs/content/user-guides/docker-compose/acme-dns/index.md @@ -186,3 +186,5 @@ environment: - "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret" - "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key" ``` + +{!traefik-for-business-applications.md!} diff --git a/docs/content/user-guides/docker-compose/acme-tls/index.md b/docs/content/user-guides/docker-compose/acme-tls/index.md index a781a1cd3..cb1a40e49 100644 --- a/docs/content/user-guides/docker-compose/acme-tls/index.md +++ b/docs/content/user-guides/docker-compose/acme-tls/index.md @@ -82,3 +82,5 @@ labels: # Uses the Host rule to define which certificate to issue - "traefik.http.routers.whoami.tls.certresolver=myresolver" ``` + +{!traefik-for-business-applications.md!} diff --git a/go.mod b/go.mod index de36f184a..de3781781 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/fatih/structs v1.1.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-acme/lego/v4 v4.18.0 + github.com/go-acme/lego/v4 v4.19.2 github.com/go-kit/kit v0.13.0 github.com/go-kit/log v0.2.1 github.com/golang/protobuf v1.5.4 @@ -73,23 +73,23 @@ require ( github.com/vulcand/predicate v1.2.0 go.opentelemetry.io/collector/pdata v1.10.0 go.opentelemetry.io/contrib/propagators/autoprop v0.53.0 - go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel v1.29.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 - go.opentelemetry.io/otel/metric v1.28.0 + go.opentelemetry.io/otel/metric v1.29.0 go.opentelemetry.io/otel/sdk v1.28.0 go.opentelemetry.io/otel/sdk/metric v1.28.0 - go.opentelemetry.io/otel/trace v1.28.0 + go.opentelemetry.io/otel/trace v1.29.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // No tag on the repo. golang.org/x/mod v0.21.0 golang.org/x/net v0.29.0 golang.org/x/sync v0.8.0 golang.org/x/sys v0.25.0 golang.org/x/text v0.18.0 - golang.org/x/time v0.5.0 + golang.org/x/time v0.6.0 golang.org/x/tools v0.25.0 google.golang.org/grpc v1.66.2 gopkg.in/natefinch/lumberjack.v2 v2.2.1 @@ -106,13 +106,15 @@ require ( ) require ( - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/auth v0.9.3 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.1 // indirect dario.cat/mergo v1.0.0 // indirect github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect @@ -135,30 +137,30 @@ require ( github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go-v2 v1.27.2 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.18 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect - github.com/aws/aws-sdk-go-v2/service/lightsail v1.38.3 // indirect - github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect - github.com/aws/smithy-go v1.20.2 // indirect + github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.33 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect + github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6 // indirect + github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/bytedance/sonic v1.10.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/civo/civogo v0.3.11 // indirect - github.com/cloudflare/cloudflare-go v0.97.0 // indirect + github.com/cloudflare/cloudflare-go v0.104.0 // indirect github.com/containerd/containerd v1.7.20 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect @@ -175,14 +177,15 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/exoscale/egoscale v0.102.3 // indirect + github.com/exoscale/egoscale/v3 v3.1.5 // indirect github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/gin-gonic/gin v1.9.1 // indirect github.com/go-errors/errors v1.0.1 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -191,13 +194,15 @@ require ( github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-resty/resty/v2 v2.11.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/go-resty/resty/v2 v2.13.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-viper/mapstructure/v2 v2.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-zookeeper/zk v1.0.3 // indirect github.com/goccy/go-json v0.10.3 // indirect - github.com/gofrs/flock v0.12.0 // indirect - github.com/gofrs/uuid v4.4.0+incompatible // indirect + github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -207,11 +212,11 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect - github.com/google/s2a-go v0.1.7 // indirect + github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.3 // indirect - github.com/gophercloud/gophercloud v1.12.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/gophercloud/gophercloud v1.14.0 // indirect github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect @@ -222,8 +227,10 @@ require ( github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/hashicorp/hcl v1.0.1-vault-5 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/huandu/xstrings v1.5.0 // indirect + github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114 // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect @@ -238,7 +245,8 @@ require ( github.com/kylelemons/godebug v1.1.0 // indirect github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect github.com/labbsr0x/goh v1.0.1 // indirect - github.com/linode/linodego v1.28.0 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/linode/linodego v1.40.0 // indirect github.com/liquidweb/liquidweb-cli v0.6.9 // indirect github.com/liquidweb/liquidweb-go v1.6.4 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect @@ -274,16 +282,16 @@ require ( github.com/nrdcg/mailinabox v0.2.0 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect github.com/nrdcg/nodion v0.1.0 // indirect - github.com/nrdcg/porkbun v0.3.0 // indirect + github.com/nrdcg/porkbun v0.4.0 // indirect github.com/nzdjb/go-metaname v1.0.0 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo/v2 v2.20.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/oracle/oci-go-sdk/v65 v65.63.1 // indirect - github.com/ovh/go-ovh v1.5.1 // indirect - github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/oracle/oci-go-sdk/v65 v65.73.0 // indirect + github.com/ovh/go-ovh v1.6.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect @@ -297,7 +305,9 @@ require ( github.com/sacloud/go-http v0.1.8 // indirect github.com/sacloud/iaas-api-go v1.12.0 // indirect github.com/sacloud/packages-go v0.0.10 // indirect - github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 // indirect github.com/selectel/domains-go v1.1.0 // indirect github.com/selectel/go-selvpcclient/v3 v3.1.1 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect @@ -307,30 +317,35 @@ require ( github.com/softlayer/softlayer-go v1.1.5 // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect github.com/sony/gobreaker v0.5.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.2 // indirect - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 // indirect - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect - github.com/transip/gotransip/v6 v6.23.0 // indirect - github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect + github.com/transip/gotransip/v6 v6.26.0 // indirect + github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/vinyldns/go-vinyldns v0.9.16 // indirect - github.com/vultr/govultr/v3 v3.9.0 // indirect + github.com/vultr/govultr/v3 v3.9.1 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e // indirect - github.com/yandex-cloud/go-sdk v0.0.0-20240318084659-dfa50323a0b4 // indirect + github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2 // indirect + github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/zeebo/errs v1.2.2 // indirect go.etcd.io/etcd/api/v3 v3.5.14 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect go.etcd.io/etcd/client/v3 v3.5.14 // indirect + go.mongodb.org/mongo-driver v1.12.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/contrib/propagators/aws v1.28.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.28.0 // indirect go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 // indirect @@ -343,18 +358,18 @@ require ( go.uber.org/zap v1.26.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/term v0.24.0 // indirect - google.golang.org/api v0.172.0 // indirect - google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/api v0.197.0 // indirect + google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/h2non/gock.v1 v1.0.16 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/ns1/ns1-go.v2 v2.9.1 // indirect + gopkg.in/ns1/ns1-go.v2 v2.12.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index e9b441b35..e4d264275 100644 --- a/go.sum +++ b/go.sum @@ -5,9 +5,13 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= +cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs= +cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -21,12 +25,12 @@ github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYs github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= @@ -96,8 +100,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 h1:lM7JnA9dEdDFH9XOgRNQMDTQnOjlLkDTNA7c0aWTQ30= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.712/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 h1:r2uwBUQhLhcPzaWz9tRJqc8MjYwHb+oF2+Q6467BF14= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.15/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -111,36 +115,36 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.44.327 h1:ZS8oO4+7MOBLhkdwIhgtVeDzCeWOlTfKJS7EgggbIEY= github.com/aws/aws-sdk-go v1.44.327/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= -github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= -github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= -github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= -github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.38.3 h1:YdA5QgoYa2wNblkWyZfPlLLYsAEKCwLfdMxpWu16wpM= -github.com/aws/aws-sdk-go-v2/service/lightsail v1.38.3/go.mod h1:T0LiPG5vKHZ7DmOq4Cmw0Kku3tMkaR9AknskS2hUXvI= -github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10 h1:J9uHribwEgHmesH5r0enxsZYyiGBWd2AaExSW2SydqE= -github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10/go.mod h1:tdzmlLwRjsHJjd4XXoSSnubCkVdRa39y4jCp4RACMkY= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g= +github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU= +github.com/aws/aws-sdk-go-v2/config v1.27.33/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6 h1:ea6TO3HgVeVTB2Ie1djyBFWBOc9CohpKbo/QZbGTCJQ= +github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6/go.mod h1:D2TUTD3v6AWmE5LzdCXLWNFtoYbSf6IEjKh1ggbuVdw= +github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 h1:957e1/SwXIfPi/0OUJkH9YnPZRe9G6Kisd/xUhF7AUE= +github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2/go.mod h1:343vcjcyOTuHTBBgUrOxPM36/jE96qLZnGL447ldrB0= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -182,8 +186,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/civo/civogo v0.3.11 h1:mON/fyrV946Sbk6paRtOSGsN+asCgCmHCgArf5xmGxM= github.com/civo/civogo v0.3.11/go.mod h1:7+GeeFwc4AYTULaEshpT2vIcl3Qq8HPoxA17viX3l6g= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.97.0 h1:feZRGiRF1EbljnNIYdt8014FnOLtC3CCvgkLXu915ks= -github.com/cloudflare/cloudflare-go v0.97.0/go.mod h1:JXRwuTfHpe5xFg8xytc2w0XC6LcrFsBVMS4WlVaiGg8= +github.com/cloudflare/cloudflare-go v0.104.0 h1:R/lB0dZupaZbOgibAH/BRrkFbZ6Acn/WsKg2iX2xXuY= +github.com/cloudflare/cloudflare-go v0.104.0/go.mod h1:pfUQ4PIG4ISI0/Mmc21Bp86UnFU0ktmPf3iTgbSL+cM= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= @@ -271,8 +275,8 @@ github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/exoscale/egoscale v0.102.3 h1:DYqN2ipoLKpiFoprRGQkp2av/Ze7sUYYlGhi1N62tfY= -github.com/exoscale/egoscale v0.102.3/go.mod h1:RPf2Gah6up+6kAEayHTQwqapzXlm93f0VQas/UEGU5c= +github.com/exoscale/egoscale/v3 v3.1.5 h1:Nsfmqiq/CQJM3Ukqg9/u4rc9Q0QBeTQc3JFPMpFkhJg= +github.com/exoscale/egoscale/v3 v3.1.5/go.mod h1:GHKucK/J26v8PGWztGdhxWNMjrjG9PbelxKCJ4YI11Q= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -304,15 +308,15 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-acme/lego/v4 v4.18.0 h1:2hH8KcdRBSb+p5o9VZIm61GAOXYALgILUCSs1Q+OYsk= -github.com/go-acme/lego/v4 v4.18.0/go.mod h1:Blkg3izvXpl3zxk7WKngIuwR2I/hvYVP3vRnvgBp7m8= +github.com/go-acme/lego/v4 v4.19.2 h1:Y8hrmMvWETdqzzkRly7m98xtPJJivWFsgWi8fcvZo+Y= +github.com/go-acme/lego/v4 v4.19.2/go.mod h1:wtDe3dDkmV4/oI2nydpNXSJpvV10J9RCyZ6MbYxNtlQ= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= -github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= @@ -341,6 +345,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -354,14 +360,14 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= -github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g= +github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= -github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA= @@ -377,10 +383,8 @@ github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/flock v0.12.0 h1:xHW8t8GPAiGtqz7KxiSqfOEXwpOaqhpYZrTE2MQBgXY= -github.com/gofrs/flock v0.12.0/go.mod h1:FirDy1Ing0mI2+kB6wk+vyyAH+e6xiE+EYA0jnzV9jc= -github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= -github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -420,6 +424,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -457,22 +462,22 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 h1:c5FlPPgxOn7kJz3VoPLkQYQXGBS3EklQ4Zfi57uOuqQ= github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= -github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gophercloud/gophercloud v1.12.0 h1:Jrz16vPAL93l80q16fp8NplrTCp93y7rZh2P3Q4Yq7g= -github.com/gophercloud/gophercloud v1.12.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +github.com/gophercloud/gophercloud v1.14.0 h1:Bt9zQDhPrbd4qX7EILGmy+i7GP35cc+AAL2+wIJpUE8= +github.com/gophercloud/gophercloud v1.14.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE= github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -539,6 +544,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= @@ -556,6 +563,8 @@ github.com/http-wasm/http-wasm-host-go v0.7.0/go.mod h1:adXKcLmL7yuavH/e0kBAp7b3 github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114 h1:X3E16S6AUZsQKhJIQ5kNnylnp0GtSy2YhIbxfvDavtU= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114/go.mod h1:JWz2ujO9X3oU5wb6kXp+DpR2UuDj2SldDbX8T0FSuhI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= @@ -599,6 +608,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11-0.20241004063537-dbd6c381492a h1:cwHOqPB4H4iQq8177kf2SxpjNbcjJ2m3lNwKIe28Hqg= github.com/klauspost/compress v1.17.11-0.20241004063537-dbd6c381492a/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -650,8 +660,8 @@ github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++ github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= github.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/linode/linodego v1.28.0 h1:lzxxJebsYg5cCWRNDLyL2StW3sfMyAwf/FYfxFjFrlk= -github.com/linode/linodego v1.28.0/go.mod h1:5oAsx+uinHtVo6U77nXXXtox7MWzUW6aEkTOKXxA9uo= +github.com/linode/linodego v1.40.0 h1:7ESY0PwK94hoggoCtIroT1Xk6b1flrFBNZ6KwqbTqlI= +github.com/linode/linodego v1.40.0/go.mod h1:NsUw4l8QrLdIofRg1NYFBbW5ZERnmbZykVBszPZLORM= github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs= github.com/liquidweb/liquidweb-cli v0.6.9 h1:acbIvdRauiwbxIsOCEMXGwF75aSJDbDiyAWPjVnwoYM= github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ= @@ -753,6 +763,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -784,8 +795,8 @@ github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg= github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= github.com/nrdcg/nodion v0.1.0 h1:zLKaqTn2X0aDuBHHfyA1zFgeZfiCpmu/O9DM73okavw= github.com/nrdcg/nodion v0.1.0/go.mod h1:inbuh3neCtIWlMPZHtEpe43TmRXxHV6+hk97iCZicms= -github.com/nrdcg/porkbun v0.3.0 h1:jnRV7j2zd3hmh+tSDOGetJyy3+WklaMxbs7HtTTmWMs= -github.com/nrdcg/porkbun v0.3.0/go.mod h1:jh1DKz96jGHW+NCdG3AmTbbnQeBlNUz1KeSgeN/cBVw= +github.com/nrdcg/porkbun v0.4.0 h1:rWweKlwo1PToQ3H+tEO9gPRW0wzzgmI/Ob3n2Guticw= +github.com/nrdcg/porkbun v0.4.0/go.mod h1:/QMskrHEIM0IhC/wY7iTCUgINsxdT2WcOphktJ9+Q54= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -814,10 +825,10 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/oracle/oci-go-sdk/v65 v65.63.1 h1:dYL7sk9L1+C9LCmoq+zjPMNteuJJfk54YExq/4pV9xQ= -github.com/oracle/oci-go-sdk/v65 v65.63.1/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0= -github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI= -github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= +github.com/oracle/oci-go-sdk/v65 v65.73.0 h1:C7uel6CoKk4A1KPkdhFBAyvVyFRTHAmX8m0o64RmfPg= +github.com/oracle/oci-go-sdk/v65 v65.73.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0= +github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= +github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -825,8 +836,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -903,8 +914,12 @@ github.com/sacloud/iaas-api-go v1.12.0 h1:kqXFn3HzCiawlX6hVJb1GVqcSJqcmiGHB4Zp14 github.com/sacloud/iaas-api-go v1.12.0/go.mod h1:SZLXeWOdXk3WReIS557sbU1gkOgrE4rseIBQV1B3b7o= github.com/sacloud/packages-go v0.0.10 h1:UiQGjy8LretewkRhsuna1TBM9Vz/l9FoYpQx+D+AOck= github.com/sacloud/packages-go v0.0.10/go.mod h1:f8QITBh9z4IZc4yE9j21Q8b0sXEMwRlRmhhjWeDVTYs= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= @@ -944,9 +959,13 @@ github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e/go.mod h1:fKZCUVd github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= @@ -959,6 +978,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/spiffe/go-spiffe/v2 v2.1.1 h1:RT9kM8MZLZIsPTH+HKQEP5yaAk3yd/VBzlINaRjXs8k= github.com/spiffe/go-spiffe/v2 v2.1.1/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg= github.com/stealthrocket/wasi-go v0.8.0 h1:Hwnv3CUoMhhRyero9vt1vfwaYa9tu/Z5kmCW4WeAmVI= @@ -981,18 +1002,21 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 h1:XGopsea1Dw7ecQ8JscCNQXDGYAKDiWjDeXnpN/+BY9g= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tailscale/tscert v0.0.0-20230806124524-28a91b69a046 h1:8rUlviSVOEe7TMk7W0gIPrW8MqEzYfZHpsNWSf8s2vg= github.com/tailscale/tscert v0.0.0-20230806124524-28a91b69a046/go.mod h1:kNGUQ3VESx3VZwRwA9MSCUegIl6+saPL8Noq82ozCaU= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 h1:ERwcXqhc94L9cFxtiI0pvt7IJtlHl/p/Jayl3mLw+ms= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 h1:LoYv5u+gUoFpU/AmIuTRG/2KiEkdm9gCC0dTvk8WITQ= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898/go.mod h1:c1j6YQ+vCbeA8kJ59Im4UnMd1GxovlpPBDhGZoewfn8= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002 h1:RE84sHFFx6t24DJvSnF9fS1DzBNv9OpctzHK3t7AY+I= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002 h1:QwE0dRkAAbdf+eACnkNULgDn9ZKUJpPWRyXdqJolP5E= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002/go.mod h1:WdC0FYbqYhJwQ3kbqri6hVP5HAEp+rzX9FToItTAzUg= github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME= github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E= github.com/testcontainers/testcontainers-go/modules/k3s v0.32.0 h1:Z3DTMveNUqeGJZ+CXZhpvI7OF1BS71Ywi3SwoXLZ4Lc= @@ -1006,6 +1030,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= @@ -1017,8 +1043,8 @@ github.com/traefik/paerser v0.2.1 h1:LFgeak1NmjEHF53c9ENdXdL1UMkF/lD5t+7Evsz4hH4 github.com/traefik/paerser v0.2.1/go.mod h1:7BBDd4FANoVgaTZG+yh26jI6CA2nds7D/4VTEdIsh24= github.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E= github.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY= -github.com/transip/gotransip/v6 v6.23.0 h1:PsTdjortrEZ8IFFifEryzjVjOy9SgK4ahlnhKBBIQgA= -github.com/transip/gotransip/v6 v6.23.0/go.mod h1:nzv9eN2tdsUrm5nG5ZX6AugYIU4qgsMwIn2c0EZLk8c= +github.com/transip/gotransip/v6 v6.26.0 h1:Aejfvh8rSp8Mj2GX/RpdBjMCv+Iy/DmgfNgczPDP550= +github.com/transip/gotransip/v6 v6.26.0/go.mod h1:x0/RWGRK/zob817O3tfO2xhFoP1vu8YOHORx6Jpk80s= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1033,8 +1059,8 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a h1:w4PK5/N9kq8PfNxBv8a5t1bqlYRrVT7XzT7iTPTtiPk= -github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a/go.mod h1:Xwz7o+ExFtxR/i0aJDnTXuiccQJlOxDgNe6FsZC4TzQ= +github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a h1:R6IR+Vj/RnGZLnX8PpPQsbbQthctO7Ah2q4tj5eoe2o= +github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a/go.mod h1:BZr7Qs3ku1ckpqed8tCRSqTlp8NAeZfAVpfx4OzXMss= github.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/unrolled/secure v1.0.9 h1:BWRuEb1vDrBFFDdbCnKkof3gZ35I/bnHGyt0LB0TNyQ= @@ -1053,18 +1079,22 @@ github.com/vulcand/oxy/v2 v2.0.0 h1:V+scHhd2xBjO8ojBRgxCM+OdZxRA/YTs8M70w5tdNy8= github.com/vulcand/oxy/v2 v2.0.0/go.mod h1:uIAz3sYafO7i+V3SC8oDlMn/lt1i9aWcyXuXqVswKzE= 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/vultr/govultr/v3 v3.9.0 h1:63V/22mpfquRA5DenJ9EF0VozHg0k+X4dhUWcDXHPyc= -github.com/vultr/govultr/v3 v3.9.0/go.mod h1:Rd8ebpXm7jxH3MDmhnEs+zrlYW212ouhx+HeUMfHm2o= +github.com/vultr/govultr/v3 v3.9.1 h1:uxSIb8Miel7tqTs3ee+z3t+JelZikwqBBsZzCOPBy/8= +github.com/vultr/govultr/v3 v3.9.1/go.mod h1:Rd8ebpXm7jxH3MDmhnEs+zrlYW212ouhx+HeUMfHm2o= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e h1:jLIqA7M9qY31g/Nw/5htVD0DFbxmLnlFZcHKJiG3osI= -github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= -github.com/yandex-cloud/go-sdk v0.0.0-20240318084659-dfa50323a0b4 h1:wtzLQJmghkSUb1YkeFphIh7ST7NNVDaVOJZSAJcjMdw= -github.com/yandex-cloud/go-sdk v0.0.0-20240318084659-dfa50323a0b4/go.mod h1:9d1MV6u4lK715YXnZceKqhP4L0bKBKmv4mSLnVSjJaM= +github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2 h1:WgeEP+8WizCQyccJNHOMLONq23qVAzYHtyg5qTdUWmg= +github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= +github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5 h1:Q4LvUMF4kzaGtopoIdXReL9/qGtmzOewBhF3dQvuHMU= +github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5/go.mod h1:9dt2V80cfJGRZA+5SKP3Ky+R/DxH02XfKObi2Uy2uPc= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -1080,14 +1110,16 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxv go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= +go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= +go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.10.0 h1:oLyPLGvPTQrcRT64ZVruwvmH/u3SHTfNo01pteS4WOE= go.opentelemetry.io/collector/pdata v1.10.0/go.mod h1:IHxHsp+Jq/xfjORQMDJjSH6jvedOSTOyu3nbxqhWSYE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/contrib/propagators/autoprop v0.53.0 h1:4zaVLcJ5mvYw0vlk63TX62qS4qty/4jAY1BKZ1usu18= go.opentelemetry.io/contrib/propagators/autoprop v0.53.0/go.mod h1:RPlvYtxp5D8PKnRzyPM+rwMQrvzdlfA49Sgworkg7aQ= go.opentelemetry.io/contrib/propagators/aws v1.28.0 h1:acyTl4oyin/iLr5Nz3u7p/PKHUbLh42w/fqg9LblExk= @@ -1098,8 +1130,8 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.28.0 h1:xQ3ktSVS128JWIaN1DiPGI go.opentelemetry.io/contrib/propagators/jaeger v1.28.0/go.mod h1:O9HIyI2kVBrFoEwQZ0IN6PHXykGoit4mZV2aEjkTRH4= go.opentelemetry.io/contrib/propagators/ot v1.28.0 h1:rmlG+2pc5k5M7Y7izDrxAHZUIwDERdGMTD9oMV7llMk= go.opentelemetry.io/contrib/propagators/ot v1.28.0/go.mod h1:MNgXIn+UrMbNGpd7xyckyo2LCHIgCdmdjEE7YNZGG+w= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= @@ -1110,14 +1142,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6Z go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= @@ -1151,18 +1183,21 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1218,6 +1253,7 @@ golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -1235,15 +1271,16 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1322,8 +1359,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1333,8 +1371,9 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1345,11 +1384,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1358,8 +1398,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1407,8 +1448,8 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= -google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= +google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= +google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1426,12 +1467,12 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= +google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= +google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0= +google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1489,8 +1530,8 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/ns1/ns1-go.v2 v2.9.1 h1:3/QYzUazRCSE49d3sh1Q+X7IrDp/I7OqR/M7dKA0Oks= -gopkg.in/ns1/ns1-go.v2 v2.9.1/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc= +gopkg.in/ns1/ns1-go.v2 v2.12.0 h1:cqdqQoTx17JmTusfxh5m3e2b36jfUzFAZedv89pFX18= +gopkg.in/ns1/ns1-go.v2 v2.12.0/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= diff --git a/integration/grpc_test.go b/integration/grpc_test.go index 6dce232d7..856b1980d 100644 --- a/integration/grpc_test.go +++ b/integration/grpc_test.go @@ -93,7 +93,7 @@ func getHelloClientGRPC() (helloworld.GreeterClient, func() error, error) { roots := x509.NewCertPool() roots.AppendCertsFromPEM(LocalhostCert) credsClient := credentials.NewClientTLSFromCert(roots, "") - conn, err := grpc.Dial("127.0.0.1:4443", grpc.WithTransportCredentials(credsClient)) + conn, err := grpc.NewClient("127.0.0.1:4443", grpc.WithTransportCredentials(credsClient)) if err != nil { return nil, func() error { return nil }, err } @@ -101,7 +101,7 @@ func getHelloClientGRPC() (helloworld.GreeterClient, func() error, error) { } func getHelloClientGRPCh2c() (helloworld.GreeterClient, func() error, error) { - conn, err := grpc.Dial("127.0.0.1:8081", grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient("127.0.0.1:8081", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, func() error { return nil }, err } diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index 15ee8b6ce..6ed949440 100644 --- a/integration/testdata/rawdata-gateway.json +++ b/integration/testdata/rawdata-gateway.json @@ -30,11 +30,11 @@ "traefik" ] }, - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06@kubernetesgateway": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06@kubernetesgateway": { "entryPoints": [ "web" ], - "service": "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + "service": "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", "ruleSyntax": "v3", "priority": 100008, @@ -43,11 +43,11 @@ "web" ] }, - "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway": { + "httproute-default-http-app-1-gw-default-my-https-gateway-ep-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway": { "entryPoints": [ "websecure" ], - "service": "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr", + "service": "httproute-default-http-app-1-gw-default-my-https-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr", "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", "ruleSyntax": "v3", "priority": 100008, @@ -96,42 +96,14 @@ "dashboard@internal" ] }, - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr@kubernetesgateway": { - "weighted": { - "services": [ - { - "name": "default-whoami-80", - "weight": 1 - } - ] - }, - "status": "enabled", - "usedBy": [ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06@kubernetesgateway" - ] - }, - "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr@kubernetesgateway": { - "weighted": { - "services": [ - { - "name": "default-whoami-80", - "weight": 1 - } - ] - }, - "status": "enabled", - "usedBy": [ - "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway" - ] - }, - "default-whoami-80@kubernetesgateway": { + "default-whoami-http-80@kubernetesgateway": { "loadBalancer": { "servers": [ { - "url": "http://10.42.0.3:80" + "url": "http://10.42.0.4:80" }, { - "url": "http://10.42.0.5:80" + "url": "http://10.42.0.6:80" } ], "passHostHeader": true, @@ -141,20 +113,48 @@ }, "status": "enabled", "serverStatus": { - "http://10.42.0.3:80": "UP", - "http://10.42.0.5:80": "UP" + "http://10.42.0.4:80": "UP", + "http://10.42.0.6:80": "UP" } }, + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr@kubernetesgateway": { + "weighted": { + "services": [ + { + "name": "default-whoami-http-80", + "weight": 1 + } + ] + }, + "status": "enabled", + "usedBy": [ + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06@kubernetesgateway" + ] + }, + "httproute-default-http-app-1-gw-default-my-https-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr@kubernetesgateway": { + "weighted": { + "services": [ + { + "name": "default-whoami-http-80", + "weight": 1 + } + ] + }, + "status": "enabled", + "usedBy": [ + "httproute-default-http-app-1-gw-default-my-https-gateway-ep-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway" + ] + }, "noop@internal": { "status": "enabled" } }, "tcpRouters": { - "default-tcp-app-1-my-tcp-gateway-footcp-0-e3b0c44298fc1c149afb@kubernetesgateway": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-footcp-0-e3b0c44298fc1c149afb@kubernetesgateway": { "entryPoints": [ "footcp" ], - "service": "default-tcp-app-1-my-tcp-gateway-footcp-0-e3b0c44298fc1c149afb-wrr", + "service": "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-footcp-0-e3b0c44298fc1c149afb-wrr", "rule": "HostSNI(`*`)", "ruleSyntax": "v3", "priority": -1, @@ -163,11 +163,11 @@ "footcp" ] }, - "default-tcp-app-1-my-tls-gateway-footlsterminate-0-e3b0c44298fc1c149afb@kubernetesgateway": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-footlsterminate-0-e3b0c44298fc1c149afb@kubernetesgateway": { "entryPoints": [ "footlsterminate" ], - "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-0-e3b0c44298fc1c149afb-wrr", + "service": "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-footlsterminate-0-e3b0c44298fc1c149afb-wrr", "rule": "HostSNI(`*`)", "ruleSyntax": "v3", "priority": -1, @@ -179,11 +179,11 @@ "footlsterminate" ] }, - "default-tls-app-1-my-tls-gateway-footlspassthrough-0-e3b0c44298fc1c149afb@kubernetesgateway": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-footlspassthrough-0-e3b0c44298fc1c149afb@kubernetesgateway": { "entryPoints": [ "footlspassthrough" ], - "service": "default-tls-app-1-my-tls-gateway-footlspassthrough-0-e3b0c44298fc1c149afb-wrr", + "service": "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-footlspassthrough-0-e3b0c44298fc1c149afb-wrr", "rule": "HostSNI(`foo.bar`)", "ruleSyntax": "v3", "priority": 18, @@ -197,48 +197,6 @@ } }, "tcpServices": { - "default-tcp-app-1-my-tcp-gateway-footcp-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { - "weighted": { - "services": [ - { - "name": "default-whoamitcp-8080", - "weight": 1 - } - ] - }, - "status": "enabled", - "usedBy": [ - "default-tcp-app-1-my-tcp-gateway-footcp-0-e3b0c44298fc1c149afb@kubernetesgateway" - ] - }, - "default-tcp-app-1-my-tls-gateway-footlsterminate-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { - "weighted": { - "services": [ - { - "name": "default-whoamitcp-8080", - "weight": 1 - } - ] - }, - "status": "enabled", - "usedBy": [ - "default-tcp-app-1-my-tls-gateway-footlsterminate-0-e3b0c44298fc1c149afb@kubernetesgateway" - ] - }, - "default-tls-app-1-my-tls-gateway-footlspassthrough-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { - "weighted": { - "services": [ - { - "name": "default-whoamitcp-8080", - "weight": 1 - } - ] - }, - "status": "enabled", - "usedBy": [ - "default-tls-app-1-my-tls-gateway-footlspassthrough-0-e3b0c44298fc1c149afb@kubernetesgateway" - ] - }, "default-whoamitcp-8080@kubernetesgateway": { "loadBalancer": { "servers": [ @@ -246,11 +204,53 @@ "address": "10.42.0.2:8080" }, { - "address": "10.42.0.6:8080" + "address": "10.42.0.3:8080" } ] }, "status": "enabled" + }, + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-footcp-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { + "weighted": { + "services": [ + { + "name": "default-whoamitcp-8080", + "weight": 1 + } + ] + }, + "status": "enabled", + "usedBy": [ + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-footcp-0-e3b0c44298fc1c149afb@kubernetesgateway" + ] + }, + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-footlsterminate-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { + "weighted": { + "services": [ + { + "name": "default-whoamitcp-8080", + "weight": 1 + } + ] + }, + "status": "enabled", + "usedBy": [ + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-footlsterminate-0-e3b0c44298fc1c149afb@kubernetesgateway" + ] + }, + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-footlspassthrough-0-e3b0c44298fc1c149afb-wrr@kubernetesgateway": { + "weighted": { + "services": [ + { + "name": "default-whoamitcp-8080", + "weight": 1 + } + ] + }, + "status": "enabled", + "usedBy": [ + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-footlspassthrough-0-e3b0c44298fc1c149afb@kubernetesgateway" + ] } } } \ No newline at end of file diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index d347df81e..e29bdd30a 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -244,10 +244,11 @@ func (r *ResponseForwarding) SetDefaults() { // Server holds the server configuration. type Server struct { - URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"` - Weight *int `json:"weight,omitempty" toml:"weight,omitempty" yaml:"weight,omitempty" label:"weight"` - Scheme string `json:"-" toml:"-" yaml:"-" file:"-"` - Port string `json:"-" toml:"-" yaml:"-" file:"-"` + URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"` + Weight *int `json:"weight,omitempty" toml:"weight,omitempty" yaml:"weight,omitempty" label:"weight" export:"true"` + PreservePath bool `json:"preservePath,omitempty" toml:"preservePath,omitempty" yaml:"preservePath,omitempty" label:"-" export:"true"` + Scheme string `json:"-" toml:"-" yaml:"-" file:"-"` + Port string `json:"-" toml:"-" yaml:"-" file:"-"` } // SetDefaults Default values for a Server. diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index ba89e344c..d00f159f8 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -25,7 +25,6 @@ import ( "github.com/stretchr/testify/require" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v3/pkg/middlewares/capture" - "github.com/traefik/traefik/v3/pkg/middlewares/recovery" "github.com/traefik/traefik/v3/pkg/types" ) @@ -954,8 +953,14 @@ func doLoggingWithAbortedStream(t *testing.T, config *types.AccessLog) { req = req.WithContext(reqContext) chain := alice.New() + chain = chain.Append(func(next http.Handler) (http.Handler, error) { - return recovery.New(context.Background(), next) + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + defer func() { + _ = recover() // ignore the stream backend panic to avoid the test to fail. + }() + next.ServeHTTP(rw, req) + }), nil }) chain = chain.Append(capture.Wrap) chain = chain.Append(WrapHandler(logger)) diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index d3205e3a7..cdf4d972b 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -8,7 +8,9 @@ import ( "net/http" "slices" + "github.com/andybalholm/brotli" "github.com/klauspost/compress/gzhttp" + "github.com/klauspost/compress/zstd" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "go.opentelemetry.io/otel/trace" @@ -94,12 +96,12 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str var err error - c.zstdHandler, err = c.newCompressionHandler(zstdName, name) + c.zstdHandler, err = c.newZstdHandler(name) if err != nil { return nil, err } - c.brotliHandler, err = c.newCompressionHandler(brotliName, name) + c.brotliHandler, err = c.newBrotliHandler(name) if err != nil { return nil, err } @@ -190,13 +192,34 @@ func (c *compress) newGzipHandler() (http.Handler, error) { return wrapper(c.next), nil } -func (c *compress) newCompressionHandler(algo string, middlewareName string) (http.Handler, error) { - cfg := Config{MinSize: c.minSize, Algorithm: algo, MiddlewareName: middlewareName} +func (c *compress) newBrotliHandler(middlewareName string) (http.Handler, error) { + cfg := Config{MinSize: c.minSize, MiddlewareName: middlewareName} if len(c.includes) > 0 { cfg.IncludedContentTypes = c.includes } else { cfg.ExcludedContentTypes = c.excludes } - return NewCompressionHandler(cfg, c.next) + newBrotliWriter := func(rw http.ResponseWriter) (CompressionWriter, string, error) { + return brotli.NewWriter(rw), brotliName, nil + } + return NewCompressionHandler(cfg, newBrotliWriter, c.next) +} + +func (c *compress) newZstdHandler(middlewareName string) (http.Handler, error) { + cfg := Config{MinSize: c.minSize, MiddlewareName: middlewareName} + if len(c.includes) > 0 { + cfg.IncludedContentTypes = c.includes + } else { + cfg.ExcludedContentTypes = c.excludes + } + + newZstdWriter := func(rw http.ResponseWriter) (CompressionWriter, string, error) { + writer, err := zstd.NewWriter(rw) + if err != nil { + return nil, "", fmt.Errorf("creating zstd writer: %w", err) + } + return writer, zstdName, nil + } + return NewCompressionHandler(cfg, newZstdWriter, c.next) } diff --git a/pkg/middlewares/compress/compression_handler.go b/pkg/middlewares/compress/compression_handler.go index a8f08ec83..1c5065ca7 100644 --- a/pkg/middlewares/compress/compression_handler.go +++ b/pkg/middlewares/compress/compression_handler.go @@ -10,8 +10,6 @@ import ( "net/http" "sync" - "github.com/andybalholm/brotli" - "github.com/klauspost/compress/zstd" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/observability" ) @@ -24,6 +22,30 @@ const ( contentType = "Content-Type" ) +// CompressionWriter compresses the written bytes. +type CompressionWriter interface { + // Write data to the encoder. + // Input data will be buffered and as the buffer fills up + // content will be compressed and written to the output. + // When done writing, use Close to flush the remaining output + // and write CRC if requested. + Write(p []byte) (n int, err error) + // Flush will send the currently written data to output + // and block until everything has been written. + // This should only be used on rare occasions where pushing the currently queued data is critical. + Flush() error + // Close closes the underlying writers if/when appropriate. + // Note that the compressed writer should not be closed if we never used it, + // as it would otherwise send some extra "end of compression" bytes. + // Close also makes sure to flush whatever was left to write from the buffer. + Close() error + // Reset reinitializes the state of the encoder, allowing it to be reused. + Reset(w io.Writer) +} + +// NewCompressionWriter returns a new CompressionWriter with its corresponding algorithm. +type NewCompressionWriter func(rw http.ResponseWriter) (CompressionWriter, string, error) + // Config is the Brotli handler configuration. type Config struct { // ExcludedContentTypes is the list of content types for which we should not compress. @@ -34,8 +56,6 @@ type Config struct { IncludedContentTypes []string // MinSize is the minimum size (in bytes) required to enable compression. MinSize int - // Algorithm used for the compression (currently Brotli and Zstandard) - Algorithm string // MiddlewareName use for logging purposes MiddlewareName string } @@ -46,15 +66,13 @@ type CompressionHandler struct { excludedContentTypes []parsedContentType includedContentTypes []parsedContentType next http.Handler - writerPool sync.Pool + + writerPool sync.Pool + newWriter NewCompressionWriter } // NewCompressionHandler returns a new compressing handler. -func NewCompressionHandler(cfg Config, next http.Handler) (http.Handler, error) { - if cfg.Algorithm == "" { - return nil, errors.New("compression algorithm undefined") - } - +func NewCompressionHandler(cfg Config, newWriter NewCompressionWriter, next http.Handler) (http.Handler, error) { if cfg.MinSize < 0 { return nil, errors.New("minimum size must be greater than or equal to zero") } @@ -88,6 +106,7 @@ func NewCompressionHandler(cfg Config, next http.Handler) (http.Handler, error) excludedContentTypes: excludedContentTypes, includedContentTypes: includedContentTypes, next: next, + newWriter: newWriter, }, nil } @@ -117,70 +136,38 @@ func (c *CompressionHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) c.next.ServeHTTP(responseWriter, r) } -type compression interface { - // Write data to the encoder. - // Input data will be buffered and as the buffer fills up - // content will be compressed and written to the output. - // When done writing, use Close to flush the remaining output - // and write CRC if requested. - Write(p []byte) (n int, err error) - // Flush will send the currently written data to output - // and block until everything has been written. - // This should only be used on rare occasions where pushing the currently queued data is critical. - Flush() error - // Close closes the underlying writers if/when appropriate. - // Note that the compressed writer should not be closed if we never used it, - // as it would otherwise send some extra "end of compression" bytes. - // Close also makes sure to flush whatever was left to write from the buffer. - Close() error - // Reset reinitializes the state of the encoder, allowing it to be reused. - Reset(w io.Writer) -} - -type compressionWriter struct { - compression - alg string -} - -func (c *CompressionHandler) getCompressionWriter(rw io.Writer) (*compressionWriter, error) { - if writer, ok := c.writerPool.Get().(*compressionWriter); ok { - writer.compression.Reset(rw) +func (c *CompressionHandler) getCompressionWriter(rw http.ResponseWriter) (*compressionWriterWrapper, error) { + if writer, ok := c.writerPool.Get().(*compressionWriterWrapper); ok { + writer.Reset(rw) return writer, nil } - return newCompressionWriter(c.cfg.Algorithm, rw) + + writer, algo, err := c.newWriter(rw) + if err != nil { + return nil, fmt.Errorf("creating compression writer: %w", err) + } + return &compressionWriterWrapper{CompressionWriter: writer, algo: algo}, nil } -func (c *CompressionHandler) putCompressionWriter(writer *compressionWriter) { +func (c *CompressionHandler) putCompressionWriter(writer *compressionWriterWrapper) { writer.Reset(nil) c.writerPool.Put(writer) } -func newCompressionWriter(algo string, in io.Writer) (*compressionWriter, error) { - switch algo { - case brotliName: - return &compressionWriter{compression: brotli.NewWriter(in), alg: algo}, nil - - case zstdName: - writer, err := zstd.NewWriter(in) - if err != nil { - return nil, fmt.Errorf("creating zstd writer: %w", err) - } - return &compressionWriter{compression: writer, alg: algo}, nil - - default: - return nil, fmt.Errorf("unknown compression algo: %s", algo) - } +type compressionWriterWrapper struct { + CompressionWriter + algo string } -func (c *compressionWriter) ContentEncoding() string { - return c.alg +func (c *compressionWriterWrapper) ContentEncoding() string { + return c.algo } // TODO: check whether we want to implement content-type sniffing (as gzip does) // TODO: check whether we should support Accept-Ranges (as gzip does, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges) type responseWriter struct { rw http.ResponseWriter - compressionWriter *compressionWriter + compressionWriter *compressionWriterWrapper minSize int excludedContentTypes []parsedContentType diff --git a/pkg/middlewares/compress/compression_handler_test.go b/pkg/middlewares/compress/compression_handler_test.go index 1df9e9588..c702500d7 100644 --- a/pkg/middlewares/compress/compression_handler_test.go +++ b/pkg/middlewares/compress/compression_handler_test.go @@ -162,7 +162,7 @@ func Test_NoBody(t *testing.T) { require.NoError(t, err) }) - h := mustNewCompressionHandler(t, Config{MinSize: 1024, Algorithm: zstdName}, next) + h := mustNewCompressionHandler(t, Config{MinSize: 1024}, zstdName, next) req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Set(acceptEncoding, "zstd") @@ -181,8 +181,7 @@ func Test_NoBody(t *testing.T) { func Test_MinSize(t *testing.T) { cfg := Config{ - MinSize: 128, - Algorithm: zstdName, + MinSize: 128, } var bodySize int @@ -197,7 +196,7 @@ func Test_MinSize(t *testing.T) { } }) - h := mustNewCompressionHandler(t, cfg, next) + h := mustNewCompressionHandler(t, cfg, zstdName, next) req, _ := http.NewRequest(http.MethodGet, "/whatever", &bytes.Buffer{}) req.Header.Add(acceptEncoding, "zstd") @@ -224,7 +223,7 @@ func Test_MultipleWriteHeader(t *testing.T) { rw.WriteHeader(http.StatusNotFound) }) - h := mustNewCompressionHandler(t, Config{MinSize: 1024, Algorithm: zstdName}, next) + h := mustNewCompressionHandler(t, Config{MinSize: 1024}, zstdName, next) req := httptest.NewRequest(http.MethodGet, "/", nil) req.Header.Set(acceptEncoding, "zstd") @@ -239,12 +238,14 @@ func Test_FlushBeforeWrite(t *testing.T) { testCases := []struct { desc string cfg Config + algo string readerBuilder func(io.Reader) (io.Reader, error) acceptEncoding string }{ { desc: "brotli", - cfg: Config{MinSize: 1024, Algorithm: brotliName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: brotliName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return brotli.NewReader(reader), nil }, @@ -252,7 +253,8 @@ func Test_FlushBeforeWrite(t *testing.T) { }, { desc: "zstd", - cfg: Config{MinSize: 1024, Algorithm: zstdName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: zstdName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return zstd.NewReader(reader) }, @@ -272,7 +274,7 @@ func Test_FlushBeforeWrite(t *testing.T) { require.NoError(t, err) }) - srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, next)) + srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, test.algo, next)) defer srv.Close() req, err := http.NewRequest(http.MethodGet, srv.URL, http.NoBody) @@ -302,12 +304,14 @@ func Test_FlushAfterWrite(t *testing.T) { testCases := []struct { desc string cfg Config + algo string readerBuilder func(io.Reader) (io.Reader, error) acceptEncoding string }{ { desc: "brotli", - cfg: Config{MinSize: 1024, Algorithm: brotliName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: brotliName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return brotli.NewReader(reader), nil }, @@ -315,7 +319,8 @@ func Test_FlushAfterWrite(t *testing.T) { }, { desc: "zstd", - cfg: Config{MinSize: 1024, Algorithm: zstdName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: zstdName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return zstd.NewReader(reader) }, @@ -338,7 +343,7 @@ func Test_FlushAfterWrite(t *testing.T) { } }) - srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, next)) + srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, test.algo, next)) defer srv.Close() req, err := http.NewRequest(http.MethodGet, srv.URL, http.NoBody) @@ -368,12 +373,14 @@ func Test_FlushAfterWriteNil(t *testing.T) { testCases := []struct { desc string cfg Config + algo string readerBuilder func(io.Reader) (io.Reader, error) acceptEncoding string }{ { desc: "brotli", - cfg: Config{MinSize: 1024, Algorithm: brotliName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: brotliName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return brotli.NewReader(reader), nil }, @@ -381,7 +388,8 @@ func Test_FlushAfterWriteNil(t *testing.T) { }, { desc: "zstd", - cfg: Config{MinSize: 1024, Algorithm: zstdName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: zstdName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return zstd.NewReader(reader) }, @@ -400,7 +408,7 @@ func Test_FlushAfterWriteNil(t *testing.T) { rw.(http.Flusher).Flush() }) - srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, next)) + srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, test.algo, next)) defer srv.Close() req, err := http.NewRequest(http.MethodGet, srv.URL, http.NoBody) @@ -430,12 +438,14 @@ func Test_FlushAfterAllWrites(t *testing.T) { testCases := []struct { desc string cfg Config + algo string readerBuilder func(io.Reader) (io.Reader, error) acceptEncoding string }{ { desc: "brotli", - cfg: Config{MinSize: 1024, Algorithm: brotliName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: brotliName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return brotli.NewReader(reader), nil }, @@ -443,7 +453,8 @@ func Test_FlushAfterAllWrites(t *testing.T) { }, { desc: "zstd", - cfg: Config{MinSize: 1024, Algorithm: zstdName, MiddlewareName: "Test"}, + cfg: Config{MinSize: 1024, MiddlewareName: "Test"}, + algo: zstdName, readerBuilder: func(reader io.Reader) (io.Reader, error) { return zstd.NewReader(reader) }, @@ -461,7 +472,7 @@ func Test_FlushAfterAllWrites(t *testing.T) { rw.(http.Flusher).Flush() }) - srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, next)) + srv := httptest.NewServer(mustNewCompressionHandler(t, test.cfg, test.algo, next)) defer srv.Close() req, err := http.NewRequest(http.MethodGet, srv.URL, http.NoBody) @@ -556,7 +567,6 @@ func Test_ExcludedContentTypes(t *testing.T) { cfg := Config{ MinSize: 1024, ExcludedContentTypes: test.excludedContentTypes, - Algorithm: zstdName, } next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -568,7 +578,7 @@ func Test_ExcludedContentTypes(t *testing.T) { require.NoError(t, err) }) - h := mustNewCompressionHandler(t, cfg, next) + h := mustNewCompressionHandler(t, cfg, zstdName, next) req, _ := http.NewRequest(http.MethodGet, "/whatever", nil) req.Header.Set(acceptEncoding, zstdName) @@ -667,7 +677,6 @@ func Test_IncludedContentTypes(t *testing.T) { cfg := Config{ MinSize: 1024, IncludedContentTypes: test.includedContentTypes, - Algorithm: zstdName, } next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -679,7 +688,7 @@ func Test_IncludedContentTypes(t *testing.T) { require.NoError(t, err) }) - h := mustNewCompressionHandler(t, cfg, next) + h := mustNewCompressionHandler(t, cfg, zstdName, next) req, _ := http.NewRequest(http.MethodGet, "/whatever", nil) req.Header.Set(acceptEncoding, zstdName) @@ -778,7 +787,6 @@ func Test_FlushExcludedContentTypes(t *testing.T) { cfg := Config{ MinSize: 1024, ExcludedContentTypes: test.excludedContentTypes, - Algorithm: zstdName, } next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -803,7 +811,7 @@ func Test_FlushExcludedContentTypes(t *testing.T) { } }) - h := mustNewCompressionHandler(t, cfg, next) + h := mustNewCompressionHandler(t, cfg, zstdName, next) req, _ := http.NewRequest(http.MethodGet, "/whatever", nil) req.Header.Set(acceptEncoding, zstdName) @@ -903,7 +911,6 @@ func Test_FlushIncludedContentTypes(t *testing.T) { cfg := Config{ MinSize: 1024, IncludedContentTypes: test.includedContentTypes, - Algorithm: zstdName, } next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -928,7 +935,7 @@ func Test_FlushIncludedContentTypes(t *testing.T) { } }) - h := mustNewCompressionHandler(t, cfg, next) + h := mustNewCompressionHandler(t, cfg, zstdName, next) req, _ := http.NewRequest(http.MethodGet, "/whatever", nil) req.Header.Set(acceptEncoding, zstdName) @@ -959,10 +966,26 @@ func Test_FlushIncludedContentTypes(t *testing.T) { } } -func mustNewCompressionHandler(t *testing.T, cfg Config, next http.Handler) http.Handler { +func mustNewCompressionHandler(t *testing.T, cfg Config, algo string, next http.Handler) http.Handler { t.Helper() - w, err := NewCompressionHandler(cfg, next) + var writer NewCompressionWriter + switch algo { + case zstdName: + writer = func(rw http.ResponseWriter) (CompressionWriter, string, error) { + writer, err := zstd.NewWriter(rw) + require.NoError(t, err) + return writer, zstdName, nil + } + case brotliName: + writer = func(rw http.ResponseWriter) (CompressionWriter, string, error) { + return brotli.NewWriter(rw), brotliName, nil + } + default: + assert.Failf(t, "unknown compression algorithm: %s", algo) + } + + w, err := NewCompressionHandler(cfg, writer, next) require.NoError(t, err) return w @@ -981,7 +1004,7 @@ func newTestBrotliHandler(t *testing.T, body []byte) http.Handler { require.NoError(t, err) }) - return mustNewCompressionHandler(t, Config{MinSize: 1024, Algorithm: brotliName, MiddlewareName: "Compress"}, next) + return mustNewCompressionHandler(t, Config{MinSize: 1024, MiddlewareName: "Compress"}, brotliName, next) } func newTestZstandardHandler(t *testing.T, body []byte) http.Handler { @@ -997,7 +1020,7 @@ func newTestZstandardHandler(t *testing.T, body []byte) http.Handler { require.NoError(t, err) }) - return mustNewCompressionHandler(t, Config{MinSize: 1024, Algorithm: zstdName, MiddlewareName: "Compress"}, next) + return mustNewCompressionHandler(t, Config{MinSize: 1024, MiddlewareName: "Compress"}, zstdName, next) } func Test_ParseContentType_equals(t *testing.T) { diff --git a/pkg/middlewares/recovery/recovery.go b/pkg/middlewares/recovery/recovery.go index ebd3edcb5..1d825a7ad 100644 --- a/pkg/middlewares/recovery/recovery.go +++ b/pkg/middlewares/recovery/recovery.go @@ -1,7 +1,10 @@ package recovery import ( + "bufio" "context" + "fmt" + "net" "net/http" "runtime" @@ -27,12 +30,16 @@ func New(ctx context.Context, next http.Handler) (http.Handler, error) { } func (re *recovery) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - defer recoverFunc(rw, req) - re.next.ServeHTTP(rw, req) + recoveryRW := newRecoveryResponseWriter(rw) + defer recoverFunc(recoveryRW, req) + + re.next.ServeHTTP(recoveryRW, req) } -func recoverFunc(rw http.ResponseWriter, req *http.Request) { +func recoverFunc(rw recoveryResponseWriter, req *http.Request) { if err := recover(); err != nil { + defer rw.finalizeResponse() + logger := middlewares.GetLogger(req.Context(), middlewareName, typeName) if !shouldLogPanic(err) { logger.Debug().Msgf("Request has been aborted [%s - %s]: %v", req.RemoteAddr, req.URL, err) @@ -44,8 +51,6 @@ func recoverFunc(rw http.ResponseWriter, req *http.Request) { buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] logger.Error().Msgf("Stack: %s", buf) - - http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } } @@ -55,3 +60,81 @@ func shouldLogPanic(panicValue interface{}) bool { //nolint:errorlint // false-positive because panicValue is an interface. return panicValue != nil && panicValue != http.ErrAbortHandler } + +type recoveryResponseWriter interface { + http.ResponseWriter + + finalizeResponse() +} + +func newRecoveryResponseWriter(rw http.ResponseWriter) recoveryResponseWriter { + wrapper := &responseWriterWrapper{rw: rw} + if _, ok := rw.(http.CloseNotifier); !ok { + return wrapper + } + + return &responseWriterWrapperWithCloseNotify{wrapper} +} + +type responseWriterWrapper struct { + rw http.ResponseWriter + headersSent bool +} + +func (r *responseWriterWrapper) Header() http.Header { + return r.rw.Header() +} + +func (r *responseWriterWrapper) Write(bytes []byte) (int, error) { + r.headersSent = true + return r.rw.Write(bytes) +} + +func (r *responseWriterWrapper) WriteHeader(code int) { + if r.headersSent { + return + } + + // Handling informational headers. + if code >= 100 && code <= 199 { + r.rw.WriteHeader(code) + return + } + + r.headersSent = true + r.rw.WriteHeader(code) +} + +func (r *responseWriterWrapper) Flush() { + if f, ok := r.rw.(http.Flusher); ok { + f.Flush() + } +} + +func (r *responseWriterWrapper) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if h, ok := r.rw.(http.Hijacker); ok { + return h.Hijack() + } + + return nil, nil, fmt.Errorf("not a hijacker: %T", r.rw) +} + +func (r *responseWriterWrapper) finalizeResponse() { + // If headers have been sent this is not possible to respond with an HTTP error, + // and we let the server abort the response silently thanks to the http.ErrAbortHandler sentinel panic value. + if r.headersSent { + panic(http.ErrAbortHandler) + } + + // The response has not yet started to be written, + // we can safely return a fresh new error response. + http.Error(r.rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) +} + +type responseWriterWrapperWithCloseNotify struct { + *responseWriterWrapper +} + +func (r *responseWriterWrapperWithCloseNotify) CloseNotify() <-chan bool { + return r.rw.(http.CloseNotifier).CloseNotify() +} diff --git a/pkg/middlewares/recovery/recovery_test.go b/pkg/middlewares/recovery/recovery_test.go index 570717ebc..1929f0b54 100644 --- a/pkg/middlewares/recovery/recovery_test.go +++ b/pkg/middlewares/recovery/recovery_test.go @@ -2,6 +2,8 @@ package recovery import ( "context" + "errors" + "io" "net/http" "net/http/httptest" "testing" @@ -11,17 +13,54 @@ import ( ) func TestRecoverHandler(t *testing.T) { - fn := func(w http.ResponseWriter, r *http.Request) { - panic("I love panicking!") + tests := []struct { + desc string + panicErr error + headersSent bool + }{ + { + desc: "headers sent and custom panic error", + panicErr: errors.New("foo"), + headersSent: true, + }, + { + desc: "headers sent and error abort handler", + panicErr: http.ErrAbortHandler, + headersSent: true, + }, + { + desc: "custom panic error", + panicErr: errors.New("foo"), + }, + { + desc: "error abort handler", + panicErr: http.ErrAbortHandler, + }, } - recovery, err := New(context.Background(), http.HandlerFunc(fn)) - require.NoError(t, err) + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() - server := httptest.NewServer(recovery) - defer server.Close() + fn := func(rw http.ResponseWriter, req *http.Request) { + if test.headersSent { + rw.WriteHeader(http.StatusTeapot) + } + panic(test.panicErr) + } + recovery, err := New(context.Background(), http.HandlerFunc(fn)) + require.NoError(t, err) - resp, err := http.Get(server.URL) - require.NoError(t, err) + server := httptest.NewServer(recovery) + t.Cleanup(server.Close) - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) + res, err := http.Get(server.URL) + if test.headersSent { + require.Nil(t, res) + assert.ErrorIs(t, err, io.EOF) + } else { + require.NoError(t, err) + assert.Equal(t, http.StatusInternalServerError, res.StatusCode) + } + }) + } } diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index 79da46edb..126ddc33f 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -312,19 +312,9 @@ func (p *Provider) getClient() (*lego.Client, error) { } err = client.Challenge.SetDNS01Provider(provider, - dns01.CondOption(len(p.DNSChallenge.Resolvers) > 0, dns01.AddRecursiveNameservers(p.DNSChallenge.Resolvers)), - dns01.WrapPreCheck(func(domain, fqdn, value string, check dns01.PreCheckFunc) (bool, error) { - if p.DNSChallenge.DelayBeforeCheck > 0 { - logger.Debug().Msgf("Delaying %d rather than validating DNS propagation now.", p.DNSChallenge.DelayBeforeCheck) - time.Sleep(time.Duration(p.DNSChallenge.DelayBeforeCheck)) - } - - if p.DNSChallenge.DisablePropagationCheck { - return true, nil - } - - return check(fqdn, value) - }), + dns01.CondOption(len(p.DNSChallenge.Resolvers) > 0, + dns01.AddRecursiveNameservers(p.DNSChallenge.Resolvers)), + dns01.PropagationWait(time.Duration(p.DNSChallenge.DelayBeforeCheck), p.DNSChallenge.DisablePropagationCheck), ) if err != nil { return nil, err diff --git a/pkg/provider/http/http.go b/pkg/provider/http/http.go index 4da8a2973..1068429b2 100644 --- a/pkg/provider/http/http.go +++ b/pkg/provider/http/http.go @@ -7,6 +7,7 @@ import ( "hash/fnv" "io" "net/http" + "strings" "time" "github.com/cenkalti/backoff/v4" @@ -149,7 +150,11 @@ func (p *Provider) fetchConfigurationData() ([]byte, error) { } for k, v := range p.Headers { - req.Header.Set(k, v) + if strings.EqualFold(k, "Host") { + req.Host = v + } else { + req.Header.Set(k, v) + } } res, err := p.httpClient.Do(req) diff --git a/pkg/provider/http/http_test.go b/pkg/provider/http/http_test.go index f99706ba9..c9f932536 100644 --- a/pkg/provider/http/http_test.go +++ b/pkg/provider/http/http_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "strings" "testing" "time" @@ -85,8 +86,9 @@ func TestProvider_fetchConfigurationData(t *testing.T) { desc: "should send configured headers", statusCode: http.StatusOK, headers: map[string]string{ - "Foo": "bar", - "Bar": "baz", + "Foo": "bar", + "Bar": "baz", + "Host": "localhost", }, expData: []byte("{}"), expErr: require.NoError, @@ -105,7 +107,11 @@ func TestProvider_fetchConfigurationData(t *testing.T) { handlerCalled = true for k, v := range test.headers { - assert.Equal(t, v, req.Header.Get(k)) + if strings.EqualFold(k, "Host") { + assert.Equal(t, v, req.Host) + } else { + assert.Equal(t, v, req.Header.Get(k)) + } } rw.WriteHeader(test.statusCode) diff --git a/pkg/provider/kubernetes/gateway/fixtures/grpcroute/filter_extension_ref.yml b/pkg/provider/kubernetes/gateway/fixtures/grpcroute/filter_extension_ref.yml new file mode 100644 index 000000000..675374765 --- /dev/null +++ b/pkg/provider/kubernetes/gateway/fixtures/grpcroute/filter_extension_ref.yml @@ -0,0 +1,56 @@ +--- +kind: GatewayClass +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway-class +spec: + controllerName: traefik.io/gateway-controller + +--- +kind: Gateway +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: my-gateway + namespace: default +spec: + gatewayClassName: my-gateway-class + listeners: # Use GatewayClass defaults for listener definition. + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + kinds: + - kind: GRPCRoute + group: gateway.networking.k8s.io + namespaces: + from: Same + +--- +kind: GRPCRoute +apiVersion: gateway.networking.k8s.io/v1 +metadata: + name: grpc-app-1 + namespace: default +spec: + parentRefs: + - name: my-gateway + kind: Gateway + group: gateway.networking.k8s.io + hostnames: + - foo.com + rules: + - backendRefs: + - name: whoami + port: 80 + weight: 1 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: my-first-middleware + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: my-second-middleware \ No newline at end of file diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_extension_ref.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_extension_ref.yml index c377fd139..0d2ffc918 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_extension_ref.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_extension_ref.yml @@ -54,4 +54,9 @@ spec: extensionRef: group: traefik.io kind: Middleware - name: my-middleware + name: my-first-middleware + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: my-second-middleware diff --git a/pkg/provider/kubernetes/gateway/grpcroute.go b/pkg/provider/kubernetes/gateway/grpcroute.go index 021a3909c..5529b9c07 100644 --- a/pkg/provider/kubernetes/gateway/grpcroute.go +++ b/pkg/provider/kubernetes/gateway/grpcroute.go @@ -120,7 +120,7 @@ func (p *Provider) loadGRPCRoute(ctx context.Context, listener gatewayListener, for ri, routeRule := range route.Spec.Rules { // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-%s-%d", route.Namespace, route.Name, listener.GWName, listener.EPName, ri)) + routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-gw-%s-%s-ep-%s-%d", strings.ToLower(kindGRPCRoute), route.Namespace, route.Name, listener.GWNamespace, listener.GWName, listener.EPName, ri)) matches := routeRule.Matches if len(matches) == 0 { @@ -166,7 +166,7 @@ func (p *Provider) loadGRPCRoute(ctx context.Context, listener gatewayListener, default: var serviceCondition *metav1.Condition - router.Service, serviceCondition = p.loadGRPCService(conf, routeKey, routeRule, route) + router.Service, serviceCondition = p.loadGRPCService(conf, routerName, routeRule, route) if serviceCondition != nil { condition = *serviceCondition } @@ -267,7 +267,7 @@ func (p *Provider) loadGRPCBackendRef(route *gatev1.GRPCRoute, backendRef gatev1 } portStr := strconv.FormatInt(int64(port), 10) - serviceName = provider.Normalize(serviceName + "-" + portStr) + serviceName = provider.Normalize(serviceName + "-" + portStr + "-grpc") lb, errCondition := p.loadGRPCServers(namespace, route, backendRef) if errCondition != nil { @@ -278,20 +278,30 @@ func (p *Provider) loadGRPCBackendRef(route *gatev1.GRPCRoute, backendRef gatev1 } func (p *Provider) loadGRPCMiddlewares(conf *dynamic.Configuration, namespace, routerName string, filters []gatev1.GRPCRouteFilter) ([]string, error) { - middlewares := make(map[string]*dynamic.Middleware) + type namedMiddleware struct { + Name string + Config *dynamic.Middleware + } + + var middlewares []namedMiddleware for i, filter := range filters { name := fmt.Sprintf("%s-%s-%d", routerName, strings.ToLower(string(filter.Type)), i) switch filter.Type { case gatev1.GRPCRouteFilterRequestHeaderModifier: - middlewares[name] = createRequestHeaderModifier(filter.RequestHeaderModifier) + middlewares = append(middlewares, namedMiddleware{ + name, + createRequestHeaderModifier(filter.RequestHeaderModifier), + }) case gatev1.GRPCRouteFilterExtensionRef: name, middleware, err := p.loadHTTPRouteFilterExtensionRef(namespace, filter.ExtensionRef) if err != nil { return nil, fmt.Errorf("loading ExtensionRef filter %s: %w", filter.Type, err) } - - middlewares[name] = middleware + middlewares = append(middlewares, namedMiddleware{ + name, + middleware, + }) default: // As per the spec: https://gateway-api.sigs.k8s.io/api-types/httproute/#filters-optional @@ -303,12 +313,11 @@ func (p *Provider) loadGRPCMiddlewares(conf *dynamic.Configuration, namespace, r } var middlewareNames []string - for name, middleware := range middlewares { - if middleware != nil { - conf.HTTP.Middlewares[name] = middleware + for _, m := range middlewares { + if m.Config != nil { + conf.HTTP.Middlewares[m.Name] = m.Config } - - middlewareNames = append(middlewareNames, name) + middlewareNames = append(middlewareNames, m.Name) } return middlewareNames, nil diff --git a/pkg/provider/kubernetes/gateway/httproute.go b/pkg/provider/kubernetes/gateway/httproute.go index a45d007e9..a58d53560 100644 --- a/pkg/provider/kubernetes/gateway/httproute.go +++ b/pkg/provider/kubernetes/gateway/httproute.go @@ -123,7 +123,7 @@ func (p *Provider) loadHTTPRoute(ctx context.Context, listener gatewayListener, for ri, routeRule := range route.Spec.Rules { // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-%s-%d", route.Namespace, route.Name, listener.GWName, listener.EPName, ri)) + routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-gw-%s-%s-ep-%s-%d", strings.ToLower(kindHTTPRoute), route.Namespace, route.Name, listener.GWNamespace, listener.GWName, listener.EPName, ri)) for _, match := range routeRule.Matches { rule, priority := buildMatchRule(hostnames, match) @@ -224,7 +224,7 @@ func (p *Provider) loadService(ctx context.Context, listener gatewayListener, co namespace = string(*backendRef.Namespace) } - serviceName := provider.Normalize(namespace + "-" + string(backendRef.Name)) + serviceName := provider.Normalize(namespace + "-" + string(backendRef.Name) + "-http") if err := p.isReferenceGranted(kindHTTPRoute, route.Namespace, group, string(kind), string(backendRef.Name), namespace); err != nil { return serviceName, &metav1.Condition{ @@ -384,39 +384,58 @@ func (p *Provider) loadHTTPBackendRef(namespace string, backendRef gatev1.HTTPBa } func (p *Provider) loadMiddlewares(conf *dynamic.Configuration, namespace, routerName string, filters []gatev1.HTTPRouteFilter, pathMatch *gatev1.HTTPPathMatch) ([]string, error) { + type namedMiddleware struct { + Name string + Config *dynamic.Middleware + } + pm := ptr.Deref(pathMatch, gatev1.HTTPPathMatch{ Type: ptr.To(gatev1.PathMatchPathPrefix), Value: ptr.To("/"), }) - middlewares := make(map[string]*dynamic.Middleware) + var middlewares []namedMiddleware for i, filter := range filters { name := fmt.Sprintf("%s-%s-%d", routerName, strings.ToLower(string(filter.Type)), i) + switch filter.Type { case gatev1.HTTPRouteFilterRequestRedirect: - middlewares[name] = createRequestRedirect(filter.RequestRedirect, pm) + middlewares = append(middlewares, namedMiddleware{ + name, + createRequestRedirect(filter.RequestRedirect, pm), + }) case gatev1.HTTPRouteFilterRequestHeaderModifier: - middlewares[name] = createRequestHeaderModifier(filter.RequestHeaderModifier) + middlewares = append(middlewares, namedMiddleware{ + name, + createRequestHeaderModifier(filter.RequestHeaderModifier), + }) case gatev1.HTTPRouteFilterResponseHeaderModifier: - middlewares[name] = createResponseHeaderModifier(filter.ResponseHeaderModifier) + middlewares = append(middlewares, namedMiddleware{ + name, + createResponseHeaderModifier(filter.ResponseHeaderModifier), + }) case gatev1.HTTPRouteFilterExtensionRef: name, middleware, err := p.loadHTTPRouteFilterExtensionRef(namespace, filter.ExtensionRef) if err != nil { return nil, fmt.Errorf("loading ExtensionRef filter %s: %w", filter.Type, err) } - - middlewares[name] = middleware + middlewares = append(middlewares, namedMiddleware{ + name, + middleware, + }) case gatev1.HTTPRouteFilterURLRewrite: - var err error middleware, err := createURLRewrite(filter.URLRewrite, pm) if err != nil { return nil, fmt.Errorf("invalid filter %s: %w", filter.Type, err) } - middlewares[name] = middleware + middlewares = append(middlewares, namedMiddleware{ + name, + middleware, + }) default: // As per the spec: https://gateway-api.sigs.k8s.io/api-types/httproute/#filters-optional @@ -428,12 +447,11 @@ func (p *Provider) loadMiddlewares(conf *dynamic.Configuration, namespace, route } var middlewareNames []string - for name, middleware := range middlewares { - if middleware != nil { - conf.HTTP.Middlewares[name] = middleware + for _, m := range middlewares { + if m.Config != nil { + conf.HTTP.Middlewares[m.Name] = m.Config } - - middlewareNames = append(middlewareNames, name) + middlewareNames = append(middlewareNames, m.Name) } return middlewareNames, nil diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 985096362..9e884f30d 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -18,6 +18,7 @@ import ( "github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s" "github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/types" + "google.golang.org/grpc/codes" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -245,9 +246,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -255,11 +256,11 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-9000", + Name: "default-whoami-http-9000", Weight: ptr.To(1), Status: ptr.To(500), }, @@ -614,9 +615,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -624,17 +625,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -675,7 +676,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, Service: "api@internal", Rule: "Host(`foo.com`) && Path(`/bar`)", @@ -709,9 +710,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -720,17 +721,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -780,9 +781,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-66e726cd8903b49727ae": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-66e726cd8903b49727ae": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-66e726cd8903b49727ae-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-66e726cd8903b49727ae-wrr", Rule: "(Host(`foo.com`) || Host(`bar.com`)) && PathPrefix(`/`)", Priority: 9, RuleSyntax: "v3", @@ -790,17 +791,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-66e726cd8903b49727ae-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-66e726cd8903b49727ae-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -841,9 +842,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-baa117c0219e3878749f": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-baa117c0219e3878749f": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-baa117c0219e3878749f-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-baa117c0219e3878749f-wrr", Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.bar\\.com$`)) && PathPrefix(`/`)", Priority: 11, RuleSyntax: "v3", @@ -851,17 +852,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-baa117c0219e3878749f-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-baa117c0219e3878749f-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -902,9 +903,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-45eba2eaf40ac792e036": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-45eba2eaf40ac792e036": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-45eba2eaf40ac792e036-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-45eba2eaf40ac792e036-wrr", Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.foo\\.com$`)) && PathPrefix(`/`)", Priority: 11, RuleSyntax: "v3", @@ -912,17 +913,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-45eba2eaf40ac792e036-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-45eba2eaf40ac792e036-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -963,44 +964,44 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100009, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", }, - "default-http-app-1-my-gateway-web-1-d737b4933fa88e68ab8a": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-d737b4933fa88e68ab8a": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && Path(`/bir`)", Priority: 100008, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-1-d737b4933fa88e68ab8a-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-d737b4933fa88e68ab8a-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-web-1-d737b4933fa88e68ab8a-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-d737b4933fa88e68ab8a-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami2-8080", + Name: "default-whoami2-http-8080", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1016,7 +1017,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-whoami2-8080": { + "default-whoami2-http-8080": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1057,31 +1058,31 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, { - Name: "default-whoami2-8080", + Name: "default-whoami2-http-8080", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1097,7 +1098,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-whoami2-8080": { + "default-whoami2-http-8080": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1143,16 +1144,16 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-http-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-http-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-http-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-http-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-https-websecure-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-https-ep-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-https-websecure-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-https-ep-websecure-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -1161,27 +1162,27 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-http-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-http-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-https-websecure-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-https-ep-websecure-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1236,16 +1237,16 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -1254,27 +1255,27 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1324,61 +1325,61 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-6cf37fa71907768d925c": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-6cf37fa71907768d925c": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && (Path(`/bar`) || PathPrefix(`/bar/`)) && Header(`my-header`,`foo`) && Header(`my-header2`,`bar`)", Priority: 10610, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-0-6cf37fa71907768d925c-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-6cf37fa71907768d925c-wrr", }, - "default-http-app-1-my-gateway-web-2-d23f7039bc8036fb918c": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-2-d23f7039bc8036fb918c": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && PathRegexp(`^/buzz/[0-9]+$`)", Priority: 11408, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-2-d23f7039bc8036fb918c-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-2-d23f7039bc8036fb918c-wrr", }, - "default-http-app-1-my-gateway-web-1-aaba0f24fd26e1ca2276": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-aaba0f24fd26e1ca2276": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && Path(`/bar`) && Header(`my-header`,`bar`)", Priority: 100109, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-1-aaba0f24fd26e1ca2276-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-aaba0f24fd26e1ca2276-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-6cf37fa71907768d925c-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-6cf37fa71907768d925c-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-web-2-d23f7039bc8036fb918c-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-2-d23f7039bc8036fb918c-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-web-1-aaba0f24fd26e1ca2276-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-1-aaba0f24fd26e1ca2276-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: func(i int) *int { return &i }(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1419,27 +1420,27 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-74ad70a7cf090becdd3c": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-74ad70a7cf090becdd3c": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && (Path(`/foo`) || PathPrefix(`/foo/`)) && Method(`GET`)", Priority: 11408, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-0-74ad70a7cf090becdd3c-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-74ad70a7cf090becdd3c-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-74ad70a7cf090becdd3c-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-74ad70a7cf090becdd3c-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1480,27 +1481,27 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-bb7b03c9610e982fd627": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-bb7b03c9610e982fd627": { EntryPoints: []string{"web"}, Rule: "Host(`foo.com`) && (Path(`/foo`) || PathPrefix(`/foo/`)) && Query(`foo`,`bar`) && QueryRegexp(`baz`,`buz`)", Priority: 10428, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-0-bb7b03c9610e982fd627-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-bb7b03c9610e982fd627-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-bb7b03c9610e982fd627-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-bb7b03c9610e982fd627-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1541,9 +1542,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb-wrr", Rule: "Host(`foo.com`) && Path(`/foo`)", Priority: 100008, RuleSyntax: "v3", @@ -1551,17 +1552,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1602,16 +1603,16 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb-wrr", Rule: "Host(`foo.com`) && Path(`/foo`)", Priority: 100008, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597-wrr", Rule: "Host(`bar.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -1619,27 +1620,27 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-efde1997778109a1f6eb-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1655,7 +1656,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "bar-whoami-bar-80": { + "bar-whoami-bar-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1696,9 +1697,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597-wrr", Rule: "Host(`bar.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -1706,17 +1707,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-66f5c78d03d948e36597-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, }, }, - "bar-whoami-bar-80": { + "bar-whoami-bar-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1757,17 +1758,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr", Rule: "Host(`example.org`) && PathPrefix(`/`)", Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0": { RequestHeaderModifier: &dynamic.HeaderModifier{ Set: map[string]string{"X-Foo": "Bar"}, Add: map[string]string{"X-Bar": "Foo"}, @@ -1776,17 +1777,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1827,17 +1828,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr", Rule: "Host(`example.org`) && PathPrefix(`/`)", Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-responseheadermodifier-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-responseheadermodifier-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-responseheadermodifier-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-responseheadermodifier-0": { ResponseHeaderModifier: &dynamic.HeaderModifier{ Set: map[string]string{"X-Foo": "Bar"}, Add: map[string]string{"X-Bar": "Foo"}, @@ -1846,17 +1847,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -1897,17 +1898,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr", Rule: "Host(`example.org`) && PathPrefix(`/`)", Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { RequestRedirect: &dynamic.RequestRedirect{ Scheme: ptr.To("https"), Port: ptr.To(""), @@ -1916,7 +1917,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr": { Weighted: &dynamic.WeightedRoundRobin{}, }, }, @@ -1944,17 +1945,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr", Rule: "Host(`example.org`) && PathPrefix(`/`)", Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { RequestRedirect: &dynamic.RequestRedirect{ Hostname: ptr.To("example.com"), Port: ptr.To("443"), @@ -1963,7 +1964,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-364ce6ec04c3d49b19c4-wrr": { Weighted: &dynamic.WeightedRoundRobin{}, }, }, @@ -1991,34 +1992,34 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr", Rule: "Host(`example.com`) && (Path(`/foo`) || PathPrefix(`/foo/`))", RuleSyntax: "v3", Priority: 10412, - Middlewares: []string{"default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { URLRewrite: &dynamic.URLRewrite{ Path: ptr.To("/bar"), }, }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: func(i int) *int { return &i }(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2059,34 +2060,34 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr", Rule: "Host(`example.com`) && (Path(`/foo`) || PathPrefix(`/foo/`))", RuleSyntax: "v3", Priority: 10412, - Middlewares: []string{"default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { URLRewrite: &dynamic.URLRewrite{ Hostname: ptr.To("www.foo.bar"), }, }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: func(i int) *int { return &i }(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2127,17 +2128,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr", Rule: "Host(`example.com`) && (Path(`/foo`) || PathPrefix(`/foo/`))", RuleSyntax: "v3", Priority: 10412, - Middlewares: []string{"default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, + Middlewares: []string{"httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-urlrewrite-0": { URLRewrite: &dynamic.URLRewrite{ Hostname: ptr.To("www.foo.bar"), Path: ptr.To("/xyz"), @@ -2146,17 +2147,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-7f90cf546b15efadf2f8-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-7f90cf546b15efadf2f8-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: func(i int) *int { return &i }(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2197,9 +2198,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2207,17 +2208,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2259,9 +2260,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2269,17 +2270,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2293,12 +2294,12 @@ func TestLoadHTTPRoutes(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, - ServersTransport: "default-whoami-80", + ServersTransport: "default-whoami-http-80", }, }, }, ServersTransports: map[string]*dynamic.ServersTransport{ - "default-whoami-80": { + "default-whoami-http-80": { ServerName: "whoami", RootCAs: []types.FileOrContent{ "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=", @@ -2329,9 +2330,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2339,17 +2340,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2363,12 +2364,12 @@ func TestLoadHTTPRoutes(t *testing.T) { ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, - ServersTransport: "default-whoami-80", + ServersTransport: "default-whoami-http-80", }, }, }, ServersTransports: map[string]*dynamic.ServersTransport{ - "default-whoami-80": { + "default-whoami-http-80": { ServerName: "whoami", }, }, @@ -2396,9 +2397,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2406,17 +2407,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2454,9 +2455,9 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2464,17 +2465,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-native-80", + Name: "default-whoami-native-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-native-80": { + "default-whoami-native-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2564,9 +2565,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2574,7 +2575,7 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2614,9 +2615,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2624,7 +2625,7 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2666,9 +2667,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2676,11 +2677,11 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami", + Name: "default-whoami-http", Weight: ptr.To(1), Status: ptr.To(500), }, @@ -2717,9 +2718,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2727,11 +2728,11 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami", + Name: "default-whoami-http", Weight: ptr.To(1), Status: ptr.To(500), }, @@ -2769,9 +2770,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2779,7 +2780,7 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2787,13 +2788,13 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { Weight: ptr.To(1), }, { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2840,9 +2841,9 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-multi-protocols-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-multi-protocols-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-multi-protocols-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-multi-protocols-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -2850,25 +2851,25 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-multi-protocols-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-multi-protocols-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-h2c-80", + Name: "default-whoami-h2c-http-80", Weight: ptr.To(1), }, { - Name: "default-whoami-ws-80", + Name: "default-whoami-ws-http-80", Weight: ptr.To(1), }, { - Name: "default-whoami-wss-80", + Name: "default-whoami-wss-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-h2c-80": { + "default-whoami-h2c-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2881,7 +2882,7 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, }, }, - "default-whoami-ws-80": { + "default-whoami-ws-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2894,7 +2895,7 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, }, }, - "default-whoami-wss-80": { + "default-whoami-wss-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -2962,7 +2963,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { entryPoints map[string]Entrypoint }{ { - desc: "HTTPRoute with ExtensionRef filter", + desc: "ExtensionRef filter", groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{ traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) { return namespace + "-" + name, nil, nil @@ -2984,28 +2985,31 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", - Middlewares: []string{"default-my-middleware"}, + Middlewares: []string{ + "default-my-first-middleware", + "default-my-second-middleware", + }, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -3028,7 +3032,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, }, { - desc: "HTTPRoute with ExtensionRef filter and create middleware", + desc: "ExtensionRef filter with middleware creation", groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{ traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) { return namespace + "-" + name, &dynamic.Middleware{Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, nil @@ -3050,30 +3054,34 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", - Middlewares: []string{"default-my-middleware"}, + Middlewares: []string{ + "default-my-first-middleware", + "default-my-second-middleware", + }, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-my-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, + "default-my-first-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, + "default-my-second-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -3096,7 +3104,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, }, { - desc: "ExtensionRef filter: Unknown", + desc: "Unknown ExtensionRef filter", entryPoints: map[string]Entrypoint{"web": { Address: ":80", }}, @@ -3113,9 +3121,9 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-err-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -3123,7 +3131,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-err-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -3163,9 +3171,9 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-err-wrr", Rule: "Host(`foo.com`) && Path(`/bar`)", Priority: 100008, RuleSyntax: "v3", @@ -3173,7 +3181,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-1c0cf64bde37d9d0df06-err-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -3231,6 +3239,296 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { } } +func TestLoadGRPCRoutes_filterExtensionRef(t *testing.T) { + testCases := []struct { + desc string + groupKindFilterFuncs map[string]map[string]BuildFilterFunc + expected *dynamic.Configuration + entryPoints map[string]Entrypoint + }{ + { + desc: "ExtensionRef filter", + groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{ + traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) { + return namespace + "-" + name, nil, nil + }}, + }, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00": { + EntryPoints: []string{"web"}, + Service: "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-wrr", + Rule: "Host(`foo.com`) && PathPrefix(`/`)", + Priority: 22, + RuleSyntax: "v3", + Middlewares: []string{ + "default-my-first-middleware", + "default-my-second-middleware", + }, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80-grpc", + Weight: ptr.To(1), + }, + }, + }, + }, + "default-whoami-80-grpc": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "h2c://10.10.0.1:80", + }, + { + URL: "h2c://10.10.0.2:80", + }, + }, + PassHostHeader: ptr.To(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "ExtensionRef filter with middleware creation", + groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{ + traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) { + return namespace + "-" + name, &dynamic.Middleware{Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, nil + }}, + }, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00": { + EntryPoints: []string{"web"}, + Service: "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-wrr", + Rule: "Host(`foo.com`) && PathPrefix(`/`)", + Priority: 22, + RuleSyntax: "v3", + Middlewares: []string{ + "default-my-first-middleware", + "default-my-second-middleware", + }, + }, + }, + Middlewares: map[string]*dynamic.Middleware{ + "default-my-first-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, + "default-my-second-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, + }, + Services: map[string]*dynamic.Service{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "default-whoami-80-grpc", + Weight: ptr.To(1), + }, + }, + }, + }, + "default-whoami-80-grpc": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "h2c://10.10.0.1:80", + }, + { + URL: "h2c://10.10.0.2:80", + }, + }, + PassHostHeader: ptr.To(true), + ResponseForwarding: &dynamic.ResponseForwarding{ + FlushInterval: ptypes.Duration(100 * time.Millisecond), + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Unknown ExtensionRef filter", + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00": { + EntryPoints: []string{"web"}, + Service: "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-err-wrr", + Rule: "Host(`foo.com`) && PathPrefix(`/`)", + Priority: 22, + RuleSyntax: "v3", + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-err-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "invalid-grpcroute-filter", + Weight: ptr.To(1), + GRPCStatus: &dynamic.GRPCStatus{ + Code: codes.Unavailable, + Msg: "Service Unavailable", + }, + }, + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "ExtensionRef filter with filterFunc error", + groupKindFilterFuncs: map[string]map[string]BuildFilterFunc{ + traefikv1alpha1.GroupName: {"Middleware": func(name, namespace string) (string, *dynamic.Middleware, error) { + return "", nil, errors.New("BOOM") + }}, + }, + entryPoints: map[string]Entrypoint{"web": { + Address: ":80", + }}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + ServersTransports: map[string]*dynamic.TCPServersTransport{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00": { + EntryPoints: []string{"web"}, + Service: "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-err-wrr", + Rule: "Host(`foo.com`) && PathPrefix(`/`)", + Priority: 22, + RuleSyntax: "v3", + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "grpcroute-default-grpc-app-1-gw-default-my-gateway-ep-web-0-74471866db6e94e08d00-err-wrr": { + Weighted: &dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { + Name: "invalid-grpcroute-filter", + Weight: ptr.To(1), + GRPCStatus: &dynamic.GRPCStatus{ + Code: codes.Unavailable, + Msg: "Service Unavailable", + }, + }, + }, + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + if test.expected == nil { + return + } + + k8sObjects, gwObjects := readResources(t, []string{"services.yml", "grpcroute/filter_extension_ref.yml"}) + + kubeClient := kubefake.NewSimpleClientset(k8sObjects...) + gwClient := newGatewaySimpleClientSet(t, gwObjects...) + + client := newClientImpl(kubeClient, gwClient) + + eventCh, err := client.WatchAll(nil, make(chan struct{})) + require.NoError(t, err) + + if len(k8sObjects) > 0 || len(gwObjects) > 0 { + // just wait for the first event + <-eventCh + } + + p := Provider{ + EntryPoints: test.entryPoints, + client: client, + } + + for group, kindFuncs := range test.groupKindFilterFuncs { + for kind, filterFunc := range kindFuncs { + p.RegisterFilterFuncs(group, kind, filterFunc) + } + } + conf := p.loadConfigurationFromGateways(context.Background()) + assert.Equal(t, test.expected, conf) + }) + } +} + func TestLoadTCPRoutes(t *testing.T) { testCases := []struct { desc string @@ -3405,24 +3703,24 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-TCP-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb": { + "tcproute-default-TCP-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"TCP"}, Rule: "HostSNI(`*`)", RuleSyntax: "v3", - Service: "default-TCP-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-TCP-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-wrr", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-TCP-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-TCP-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ - Name: "default-TCP-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-err-lb", + Name: "tcproute-default-TCP-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-err-lb", Weight: ptr.To(1), }}, }, }, - "default-TCP-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-err-lb": { + "tcproute-default-TCP-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-err-lb": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ Servers: []dynamic.TCPServer{}, }, @@ -3452,16 +3750,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3510,22 +3808,22 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-2-my-tcp-gateway-tcp-2-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-2-gw-default-my-tcp-gateway-ep-tcp-2-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-2"}, - Service: "default-tcp-app-2-my-tcp-gateway-tcp-2-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-2-gw-default-my-tcp-gateway-ep-tcp-2-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3535,7 +3833,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "default-tcp-app-2-my-tcp-gateway-tcp-2-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-2-gw-default-my-tcp-gateway-ep-tcp-2-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3596,22 +3894,22 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-my-tcp-gateway-tcp-1-1-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-my-tcp-gateway-tcp-1-1-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-my-tcp-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3621,7 +3919,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "default-tcp-app-my-tcp-gateway-tcp-1-1-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-gw-default-my-tcp-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3680,16 +3978,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3740,9 +4038,9 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -3750,7 +4048,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ Name: "default-whoamitcp-9000", @@ -3804,16 +4102,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3860,22 +4158,22 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3885,7 +4183,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3944,16 +4242,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "bar-tcp-app-bar-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4001,16 +4299,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4054,16 +4352,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tcp-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4281,25 +4579,25 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"TCP"}, Rule: "HostSNI(`*`)", RuleSyntax: "v3", - Service: "default-tls-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-wrr", TLS: &dynamic.RouterTCPTLSConfig{}, }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ - Name: "default-tls-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-err-lb", + Name: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-err-lb", Weight: ptr.To(1), }}, }, }, - "default-tls-app-1-my-gateway-TCP-0-e3b0c44298fc1c149afb-err-lb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-TCP-0-e3b0c44298fc1c149afb-err-lb": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ Servers: []dynamic.TCPServer{}, }, @@ -4372,9 +4670,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4382,7 +4680,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4438,9 +4736,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4450,7 +4748,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4497,9 +4795,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4509,7 +4807,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4557,16 +4855,16 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tls-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-tls-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4576,7 +4874,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-tls-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4586,7 +4884,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4654,9 +4952,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4664,7 +4962,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4724,9 +5022,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4736,7 +5034,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4783,9 +5081,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4795,7 +5093,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4842,9 +5140,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4854,7 +5152,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4901,9 +5199,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`) || HostSNI(`bar.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4913,7 +5211,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4960,9 +5258,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.default`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -4972,7 +5270,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5019,18 +5317,18 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.default`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, }, - "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.bar`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5040,7 +5338,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5050,7 +5348,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, - "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5109,9 +5407,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.bar`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5121,7 +5419,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "bar-tls-app-bar-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5168,18 +5466,18 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-my-gateway-tcp-1-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tls-app-my-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, }, - "default-tls-app-my-gateway-tcp-1-1-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp-1"}, - Service: "default-tls-app-my-gateway-tcp-1-1-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5189,7 +5487,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-my-gateway-tcp-1-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5199,7 +5497,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, - "default-tls-app-my-gateway-tcp-1-1-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-gw-default-my-gateway-ep-tcp-1-1-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5259,9 +5557,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5271,7 +5569,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5315,9 +5613,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5327,7 +5625,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tls-app-1-my-tls-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-tls-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5524,22 +5822,22 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-1-my-gateway-tls-1-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-1-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-1-my-gateway-tls-2-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-1-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`pass.tls.foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5549,7 +5847,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5559,7 +5857,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-1-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5569,7 +5867,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-1-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-1-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5596,16 +5894,16 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", @@ -5614,27 +5912,27 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-1-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -5711,22 +6009,22 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`pass.tls.foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -5736,7 +6034,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5746,7 +6044,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5756,7 +6054,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5783,16 +6081,16 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", @@ -5801,27 +6099,27 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -5870,37 +6168,37 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-2"}, - Service: "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`pass.tls.foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ Passthrough: true, }, }, - "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -5908,7 +6206,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5918,7 +6216,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5928,7 +6226,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tls-app-default-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-default-tls-app-default-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5962,7 +6260,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5972,7 +6270,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5987,31 +6285,31 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, - "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", @@ -6020,27 +6318,27 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -6056,7 +6354,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-whoami-bar-80": { + "bar-whoami-bar-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -6072,21 +6370,21 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, }, }, - "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, @@ -6125,22 +6423,22 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, }, - "bar-tls-app-bar-my-gateway-tls-2-0-e3b0c44298fc1c149afb": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls-2"}, - Service: "bar-tls-app-bar-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr", + Service: "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`pass.tls.foo.example.com`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -6162,7 +6460,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -6172,7 +6470,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-bar-tcp-app-bar-gw-default-my-gateway-ep-tls-1-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -6182,7 +6480,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tls-app-bar-my-gateway-tls-2-0-e3b0c44298fc1c149afb-wrr": { + "tlsroute-bar-tls-app-bar-gw-default-my-gateway-ep-tls-2-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -6197,16 +6495,16 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", @@ -6215,7 +6513,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "bar-whoami-bar-80": { + "bar-whoami-bar-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -6231,21 +6529,21 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, }, }, - "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-bar-http-app-bar-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "bar-whoami-bar-80", + Name: "bar-whoami-bar-http-80", Weight: ptr.To(1), }, }, @@ -6283,15 +6581,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -6299,7 +6597,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tcp-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -6309,7 +6607,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-default-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -6336,16 +6634,16 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr", + Service: "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr", Rule: "PathPrefix(`/`)", Priority: 2, RuleSyntax: "v3", @@ -6354,27 +6652,27 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-web-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd-wrr": { + "httproute-default-http-app-default-gw-default-my-gateway-ep-websecure-0-a431b128267aabc954fd-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-80", + Name: "default-whoami-http-80", Weight: ptr.To(1), }, }, }, }, - "default-whoami-80": { + "default-whoami-http-80": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ { @@ -6566,9 +6864,9 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr", + Service: "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -6576,7 +6874,7 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-0-e3b0c44298fc1c149afb-wrr": { + "tcproute-default-tcp-app-1-gw-default-my-gateway-ep-tls-0-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ Name: "default-whoamitcp-9000", @@ -6714,21 +7012,21 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-http-0-d40286ed9f4652ca2108": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-http-0-d40286ed9f4652ca2108": { EntryPoints: []string{"http"}, Rule: "Host(`foo.example.com`) && PathPrefix(`/`)", - Service: "default-http-app-1-my-gateway-http-0-d40286ed9f4652ca2108-wrr", + Service: "httproute-default-http-app-1-gw-default-my-gateway-ep-http-0-d40286ed9f4652ca2108-wrr", RuleSyntax: "v3", Priority: 17, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-http-0-d40286ed9f4652ca2108-wrr": { + "httproute-default-http-app-1-gw-default-my-gateway-ep-http-0-d40286ed9f4652ca2108-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { - Name: "default-whoami-bar-80", + Name: "default-whoami-bar-http-80", Weight: ptr.To(1), Status: ptr.To(500), }, diff --git a/pkg/provider/kubernetes/gateway/tcproute.go b/pkg/provider/kubernetes/gateway/tcproute.go index 0f859b5ae..9e302d001 100644 --- a/pkg/provider/kubernetes/gateway/tcproute.go +++ b/pkg/provider/kubernetes/gateway/tcproute.go @@ -130,7 +130,7 @@ func (p *Provider) loadTCPRoute(listener gatewayListener, route *gatev1alpha2.TC } // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-%s-%d", route.Namespace, route.Name, listener.GWName, listener.EPName, ri)) + routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-gw-%s-%s-ep-%s-%d", strings.ToLower(kindTCPRoute), route.Namespace, route.Name, listener.GWNamespace, listener.GWName, listener.EPName, ri)) // Routing criteria should be introduced at some point. routerName := makeRouterName("", routeKey) diff --git a/pkg/provider/kubernetes/gateway/tlsroute.go b/pkg/provider/kubernetes/gateway/tlsroute.go index 42b715de1..8c8e1cb76 100644 --- a/pkg/provider/kubernetes/gateway/tlsroute.go +++ b/pkg/provider/kubernetes/gateway/tlsroute.go @@ -132,7 +132,7 @@ func (p *Provider) loadTLSRoute(listener gatewayListener, route *gatev1alpha2.TL } // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-%s-%d", route.Namespace, route.Name, listener.GWName, listener.EPName, ri)) + routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-gw-%s-%s-ep-%s-%d", strings.ToLower(kindTLSRoute), route.Namespace, route.Name, listener.GWNamespace, listener.GWName, listener.EPName, ri)) // Routing criteria should be introduced at some point. routerName := makeRouterName("", routeKey) diff --git a/pkg/provider/kubernetes/k8s/parser.go b/pkg/provider/kubernetes/k8s/parser.go index 422513ade..053a912a1 100644 --- a/pkg/provider/kubernetes/k8s/parser.go +++ b/pkg/provider/kubernetes/k8s/parser.go @@ -12,7 +12,7 @@ import ( // MustParseYaml parses a YAML to objects. func MustParseYaml(content []byte) []runtime.Object { - acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|EndpointSlice|Node|Service|ConfigMap|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|ServersTransportTCP|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute|ReferenceGrant|BackendTLSPolicy)$`) + acceptedK8sTypes := regexp.MustCompile(`^(Namespace|Deployment|EndpointSlice|Node|Service|ConfigMap|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|ServersTransportTCP|GatewayClass|Gateway|GRPCRoute|HTTPRoute|TCPRoute|TLSRoute|ReferenceGrant|BackendTLSPolicy)$`) files := strings.Split(string(content), "---\n") retVal := make([]runtime.Object, 0, len(files)) diff --git a/pkg/proxy/fast/builder.go b/pkg/proxy/fast/builder.go index f330d6756..b41323dda 100644 --- a/pkg/proxy/fast/builder.go +++ b/pkg/proxy/fast/builder.go @@ -68,7 +68,7 @@ func (r *ProxyBuilder) Update(newConfigs map[string]*dynamic.ServersTransport) { } // Build builds a new ReverseProxy with the given configuration. -func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, passHostHeader bool) (http.Handler, error) { +func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, passHostHeader, preservePath bool) (http.Handler, error) { proxyURL, err := r.proxy(&http.Request{URL: targetURL}) if err != nil { return nil, fmt.Errorf("getting proxy: %w", err) @@ -79,18 +79,13 @@ func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, passHostHeader return nil, fmt.Errorf("getting ServersTransport: %w", err) } - var responseHeaderTimeout time.Duration - if cfg.ForwardingTimeouts != nil { - responseHeaderTimeout = time.Duration(cfg.ForwardingTimeouts.ResponseHeaderTimeout) - } - tlsConfig, err := r.transportManager.GetTLSConfig(cfgName) if err != nil { return nil, fmt.Errorf("getting TLS config: %w", err) } pool := r.getPool(cfgName, cfg, tlsConfig, targetURL, proxyURL) - return NewReverseProxy(targetURL, proxyURL, r.debug, passHostHeader, responseHeaderTimeout, pool) + return NewReverseProxy(targetURL, proxyURL, r.debug, passHostHeader, preservePath, pool) } func (r *ProxyBuilder) getPool(cfgName string, config *dynamic.ServersTransport, tlsConfig *tls.Config, targetURL *url.URL, proxyURL *url.URL) *connPool { @@ -106,9 +101,11 @@ func (r *ProxyBuilder) getPool(cfgName string, config *dynamic.ServersTransport, idleConnTimeout := 90 * time.Second dialTimeout := 30 * time.Second + var responseHeaderTimeout time.Duration if config.ForwardingTimeouts != nil { idleConnTimeout = time.Duration(config.ForwardingTimeouts.IdleConnTimeout) dialTimeout = time.Duration(config.ForwardingTimeouts.DialTimeout) + responseHeaderTimeout = time.Duration(config.ForwardingTimeouts.ResponseHeaderTimeout) } proxyDialer := newDialer(dialerConfig{ @@ -119,7 +116,7 @@ func (r *ProxyBuilder) getPool(cfgName string, config *dynamic.ServersTransport, ProxyURL: proxyURL, }, tlsConfig) - connPool := newConnPool(config.MaxIdleConnsPerHost, idleConnTimeout, func() (net.Conn, error) { + connPool := newConnPool(config.MaxIdleConnsPerHost, idleConnTimeout, responseHeaderTimeout, func() (net.Conn, error) { return proxyDialer.Dial("tcp", addrFromURL(targetURL)) }) diff --git a/pkg/proxy/fast/connpool.go b/pkg/proxy/fast/connpool.go index e0d2c4e7f..375fac2fb 100644 --- a/pkg/proxy/fast/connpool.go +++ b/pkg/proxy/fast/connpool.go @@ -1,42 +1,309 @@ package fast import ( + "bufio" + "errors" "fmt" + "io" "net" + "net/http" + "net/http/httputil" + "strings" + "sync" + "sync/atomic" "time" "github.com/rs/zerolog/log" + "github.com/valyala/fasthttp" ) +// rwWithUpgrade contains a ResponseWriter and an upgradeHandler, +// used to upgrade the connection (e.g. Websockets). +type rwWithUpgrade struct { + RW http.ResponseWriter + Upgrade upgradeHandler +} + // conn is an enriched net.Conn. type conn struct { net.Conn + RWCh chan rwWithUpgrade + ErrCh chan error + + br *bufio.Reader + idleAt time.Time // the last time it was marked as idle. idleTimeout time.Duration + + responseHeaderTimeout time.Duration + + expectedResponse atomic.Bool + broken atomic.Bool + upgraded atomic.Bool + + closeMu sync.Mutex + closed bool + closeErr error + + bufferPool *pool[[]byte] + limitedReaderPool *pool[*io.LimitedReader] } -func (c *conn) isExpired() bool { +// Read reads data from the connection. +// Overrides conn Read to use the buffered reader. +func (c *conn) Read(b []byte) (n int, err error) { + return c.br.Read(b) +} + +// Close closes the connection. +// Ensures that connection is closed only once, +// to avoid duplicate close error. +func (c *conn) Close() error { + c.closeMu.Lock() + defer c.closeMu.Unlock() + + if c.closed { + return c.closeErr + } + + c.closed = true + c.closeErr = c.Conn.Close() + + return c.closeErr +} + +// isStale returns whether the connection is in an invalid state (i.e. expired/broken). +func (c *conn) isStale() bool { expTime := c.idleAt.Add(c.idleTimeout) - return c.idleTimeout > 0 && time.Now().After(expTime) + return c.idleTimeout > 0 && time.Now().After(expTime) || c.broken.Load() +} + +// isUpgraded returns whether this connection has been upgraded (e.g. Websocket). +// An upgraded connection should not be reused and putted back in the connection pool. +func (c *conn) isUpgraded() bool { + return c.upgraded.Load() +} + +// readLoop handles the successive HTTP response read operations on the connection, +// and watches for unsolicited bytes or connection errors when idle. +func (c *conn) readLoop() { + defer c.Close() + + for { + _, err := c.br.Peek(1) + if err != nil { + select { + // An error occurred while a response was expected to be handled. + case <-c.RWCh: + c.ErrCh <- err + // An error occurred on an idle connection. + default: + c.broken.Store(true) + } + return + } + + // Unsolicited response received on an idle connection. + if !c.expectedResponse.Load() { + c.broken.Store(true) + return + } + + r := <-c.RWCh + if err = c.handleResponse(r); err != nil { + c.ErrCh <- err + return + } + + c.expectedResponse.Store(false) + c.ErrCh <- nil + } +} + +func (c *conn) handleResponse(r rwWithUpgrade) error { + res := fasthttp.AcquireResponse() + defer fasthttp.ReleaseResponse(res) + + res.Header.SetNoDefaultContentType(true) + + for { + var ( + timer *time.Timer + errTimeout atomic.Pointer[timeoutError] + ) + if c.responseHeaderTimeout > 0 { + timer = time.AfterFunc(c.responseHeaderTimeout, func() { + errTimeout.Store(&timeoutError{errors.New("timeout awaiting response headers")}) + c.Close() // This close call is needed to interrupt the read operation below when the timeout is over. + }) + } + + res.Header.SetNoDefaultContentType(true) + if err := res.Header.Read(c.br); err != nil { + if c.responseHeaderTimeout > 0 { + if errT := errTimeout.Load(); errT != nil { + return errT + } + } + return err + } + + if timer != nil { + timer.Stop() + } + + fixPragmaCacheControl(&res.Header) + + resCode := res.StatusCode() + is1xx := 100 <= resCode && resCode <= 199 + // treat 101 as a terminal status, see issue 26161 + is1xxNonTerminal := is1xx && resCode != http.StatusSwitchingProtocols + if is1xxNonTerminal { + removeConnectionHeaders(&res.Header) + h := r.RW.Header() + + for _, header := range hopHeaders { + res.Header.Del(header) + } + + res.Header.VisitAll(func(key, value []byte) { + r.RW.Header().Add(string(key), string(value)) + }) + + r.RW.WriteHeader(res.StatusCode()) + // Clear headers, it's not automatically done by ResponseWriter.WriteHeader() for 1xx responses + for k := range h { + delete(h, k) + } + + res.Reset() + res.Header.Reset() + res.Header.SetNoDefaultContentType(true) + + continue + } + break + } + + announcedTrailers := res.Header.Peek("Trailer") + + // Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc) + if res.StatusCode() == http.StatusSwitchingProtocols { + r.Upgrade(r.RW, res, c) + c.upgraded.Store(true) // As the connection has been upgraded, it cannot be added back to the pool. + return nil + } + + removeConnectionHeaders(&res.Header) + + for _, header := range hopHeaders { + res.Header.Del(header) + } + + if len(announcedTrailers) > 0 { + res.Header.Add("Trailer", string(announcedTrailers)) + } + + res.Header.VisitAll(func(key, value []byte) { + r.RW.Header().Add(string(key), string(value)) + }) + + r.RW.WriteHeader(res.StatusCode()) + + if res.Header.ContentLength() == 0 { + return nil + } + + // When a body is not allowed for a given status code the body is ignored. + // The connection will be marked as broken by the next Peek in the readloop. + if !isBodyAllowedForStatus(res.StatusCode()) { + return nil + } + + // Chunked response, Content-Length is set to -1 by FastProxy when "Transfer-Encoding: chunked" header is received. + if res.Header.ContentLength() == -1 { + cbr := httputil.NewChunkedReader(c.br) + + b := c.bufferPool.Get() + if b == nil { + b = make([]byte, bufferSize) + } + defer c.bufferPool.Put(b) + + if _, err := io.CopyBuffer(&writeFlusher{r.RW}, cbr, b); err != nil { + return err + } + + res.Header.Reset() + res.Header.SetNoDefaultContentType(true) + if err := res.Header.ReadTrailer(c.br); err != nil { + return err + } + + if res.Header.Len() > 0 { + var announcedTrailersKey []string + if len(announcedTrailers) > 0 { + announcedTrailersKey = strings.Split(string(announcedTrailers), ",") + } + + res.Header.VisitAll(func(key, value []byte) { + for _, s := range announcedTrailersKey { + if strings.EqualFold(s, strings.TrimSpace(string(key))) { + r.RW.Header().Add(string(key), string(value)) + return + } + } + + r.RW.Header().Add(http.TrailerPrefix+string(key), string(value)) + }) + } + + return nil + } + + brl := c.limitedReaderPool.Get() + if brl == nil { + brl = &io.LimitedReader{} + } + defer c.limitedReaderPool.Put(brl) + + brl.R = c.br + brl.N = int64(res.Header.ContentLength()) + + b := c.bufferPool.Get() + if b == nil { + b = make([]byte, bufferSize) + } + defer c.bufferPool.Put(b) + + if _, err := io.CopyBuffer(r.RW, brl, b); err != nil { + return err + } + + return nil } // connPool is a net.Conn pool implementation using channels. type connPool struct { - dialer func() (net.Conn, error) - idleConns chan *conn - idleConnTimeout time.Duration - ticker *time.Ticker - doneCh chan struct{} + dialer func() (net.Conn, error) + idleConns chan *conn + idleConnTimeout time.Duration + responseHeaderTimeout time.Duration + ticker *time.Ticker + bufferPool pool[[]byte] + limitedReaderPool pool[*io.LimitedReader] + doneCh chan struct{} } // newConnPool creates a new connPool. -func newConnPool(maxIdleConn int, idleConnTimeout time.Duration, dialer func() (net.Conn, error)) *connPool { +func newConnPool(maxIdleConn int, idleConnTimeout, responseHeaderTimeout time.Duration, dialer func() (net.Conn, error)) *connPool { c := &connPool{ - dialer: dialer, - idleConns: make(chan *conn, maxIdleConn), - idleConnTimeout: idleConnTimeout, - doneCh: make(chan struct{}), + dialer: dialer, + idleConns: make(chan *conn, maxIdleConn), + idleConnTimeout: idleConnTimeout, + responseHeaderTimeout: responseHeaderTimeout, + doneCh: make(chan struct{}), } if idleConnTimeout > 0 { @@ -72,22 +339,28 @@ func (c *connPool) AcquireConn() (*conn, error) { return nil, err } - if !co.isExpired() { + if !co.isStale() { return co, nil } - // As the acquired conn is expired we can close it + // As the acquired conn is stale we can close it // without putting it again into the pool. if err := co.Close(); err != nil { log.Debug(). Err(err). - Msg("Unexpected error while releasing the connection") + Msg("Unexpected error while closing the connection") } } } // ReleaseConn releases the given net.Conn to the pool. func (c *connPool) ReleaseConn(co *conn) { + // An upgraded connection cannot be safely reused for another roundTrip, + // thus we are not putting it back to the pool. + if co.isUpgraded() { + return + } + co.idleAt = time.Now() c.releaseConn(co) } @@ -97,7 +370,7 @@ func (c *connPool) cleanIdleConns() { for { select { case co := <-c.idleConns: - if !co.isExpired() { + if !co.isStale() { c.releaseConn(co) return } @@ -105,7 +378,7 @@ func (c *connPool) cleanIdleConns() { if err := co.Close(); err != nil { log.Debug(). Err(err). - Msg("Unexpected error while releasing the connection") + Msg("Unexpected error while closing the connection") } default: @@ -155,9 +428,33 @@ func (c *connPool) askForNewConn(errCh chan<- error) { return } - c.releaseConn(&conn{ - Conn: co, - idleAt: time.Now(), - idleTimeout: c.idleConnTimeout, - }) + newConn := &conn{ + Conn: co, + br: bufio.NewReaderSize(co, bufioSize), + idleAt: time.Now(), + idleTimeout: c.idleConnTimeout, + responseHeaderTimeout: c.responseHeaderTimeout, + RWCh: make(chan rwWithUpgrade), + ErrCh: make(chan error), + bufferPool: &c.bufferPool, + limitedReaderPool: &c.limitedReaderPool, + } + go newConn.readLoop() + + c.releaseConn(newConn) +} + +// isBodyAllowedForStatus reports whether a given response status code +// permits a body. See RFC 7230, section 3.3. +// From https://github.com/golang/go/blame/master/src/net/http/transfer.go#L459 +func isBodyAllowedForStatus(status int) bool { + switch { + case status >= 100 && status <= 199: + return false + case status == 204: + return false + case status == 304: + return false + } + return true } diff --git a/pkg/proxy/fast/connpool_test.go b/pkg/proxy/fast/connpool_test.go index 696e62a36..7532a3e3b 100644 --- a/pkg/proxy/fast/connpool_test.go +++ b/pkg/proxy/fast/connpool_test.go @@ -58,7 +58,7 @@ func TestConnPool_ConnReuse(t *testing.T) { return &net.TCPConn{}, nil } - pool := newConnPool(2, 0, dialer) + pool := newConnPool(2, 0, 0, dialer) test.poolFn(pool) assert.Equal(t, test.expected, connAlloc) @@ -102,13 +102,16 @@ func TestConnPool_MaxIdleConn(t *testing.T) { var keepOpenedConn int dialer := func() (net.Conn, error) { keepOpenedConn++ - return &mockConn{closeFn: func() error { - keepOpenedConn-- - return nil - }}, nil + return &mockConn{ + doneCh: make(chan struct{}), + closeFn: func() error { + keepOpenedConn-- + return nil + }, + }, nil } - pool := newConnPool(test.maxIdleConn, 0, dialer) + pool := newConnPool(test.maxIdleConn, 0, 0, dialer) test.poolFn(pool) assert.Equal(t, test.expected, keepOpenedConn) @@ -129,7 +132,7 @@ func TestGC(t *testing.T) { return c, nil } - pools["test"] = newConnPool(10, 1*time.Second, dialer) + pools["test"] = newConnPool(10, 1*time.Second, 0, dialer) runtime.SetFinalizer(pools["test"], func(p *connPool) { isDestroyed = true }) @@ -149,10 +152,12 @@ func TestGC(t *testing.T) { type mockConn struct { closeFn func() error + doneCh chan struct{} // makes sure that the readLoop is blocking avoiding close. } func (m *mockConn) Read(_ []byte) (n int, err error) { - panic("implement me") + <-m.doneCh + return 0, nil } func (m *mockConn) Write(_ []byte) (n int, err error) { @@ -160,6 +165,7 @@ func (m *mockConn) Write(_ []byte) (n int, err error) { } func (m *mockConn) Close() error { + defer close(m.doneCh) if m.closeFn != nil { return m.closeFn() } diff --git a/pkg/proxy/fast/proxy.go b/pkg/proxy/fast/proxy.go index e61a32ad8..a400ce646 100644 --- a/pkg/proxy/fast/proxy.go +++ b/pkg/proxy/fast/proxy.go @@ -4,18 +4,14 @@ import ( "bufio" "bytes" "encoding/base64" - "errors" "fmt" "io" "net" "net/http" "net/http/httptrace" - "net/http/httputil" "net/url" "strings" "sync" - "sync/atomic" - "time" "github.com/rs/zerolog/log" proxyhttputil "github.com/traefik/traefik/v3/pkg/proxy/httputil" @@ -57,15 +53,6 @@ func (p *pool[T]) Put(x T) { p.pool.Put(x) } -type buffConn struct { - *bufio.Reader - net.Conn -} - -func (b buffConn) Read(p []byte) (int, error) { - return b.Reader.Read(p) -} - type writeDetector struct { net.Conn @@ -112,20 +99,17 @@ type ReverseProxy struct { connPool *connPool - bufferPool pool[[]byte] - readerPool pool[*bufio.Reader] - writerPool pool[*bufio.Writer] - limitReaderPool pool[*io.LimitedReader] + writerPool pool[*bufio.Writer] proxyAuth string - targetURL *url.URL - passHostHeader bool - responseHeaderTimeout time.Duration + targetURL *url.URL + passHostHeader bool + preservePath bool } // NewReverseProxy creates a new ReverseProxy. -func NewReverseProxy(targetURL *url.URL, proxyURL *url.URL, debug, passHostHeader bool, responseHeaderTimeout time.Duration, connPool *connPool) (*ReverseProxy, error) { +func NewReverseProxy(targetURL, proxyURL *url.URL, debug, passHostHeader, preservePath bool, connPool *connPool) (*ReverseProxy, error) { var proxyAuth string if proxyURL != nil && proxyURL.User != nil && targetURL.Scheme == "http" { username := proxyURL.User.Username() @@ -134,12 +118,12 @@ func NewReverseProxy(targetURL *url.URL, proxyURL *url.URL, debug, passHostHeade } return &ReverseProxy{ - debug: debug, - passHostHeader: passHostHeader, - targetURL: targetURL, - proxyAuth: proxyAuth, - connPool: connPool, - responseHeaderTimeout: responseHeaderTimeout, + debug: debug, + passHostHeader: passHostHeader, + preservePath: preservePath, + targetURL: targetURL, + proxyAuth: proxyAuth, + connPool: connPool, }, nil } @@ -207,6 +191,11 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { u2.Path = u.Path u2.RawPath = u.RawPath + + if p.preservePath { + u2.Path, u2.RawPath = proxyhttputil.JoinURLPath(p.targetURL, u) + } + u2.RawQuery = strings.ReplaceAll(u.RawQuery, ";", "&") outReq.SetHost(u2.Host) @@ -266,8 +255,15 @@ func (p *ReverseProxy) roundTrip(rw http.ResponseWriter, req *http.Request, outR return fmt.Errorf("acquire connection: %w", err) } + // Before writing the request, + // we mark the conn as expecting to handle a response. + co.expectedResponse.Store(true) + wd := &writeDetector{Conn: co} + // TODO: do not wait to write the full request before reading the response (to handle "100 Continue"). + // TODO: this is currently impossible with fasthttp to write the request partially (headers only). + // Currently, writing the request fully is a mandatory step before handling the response. err = p.writeRequest(wd, outReq) if wd.written && trace != nil && trace.WroteRequest != nil { // WroteRequest hook is used by the tracing middleware to detect if the request has been written. @@ -286,169 +282,17 @@ func (p *ReverseProxy) roundTrip(rw http.ResponseWriter, req *http.Request, outR } } - br := p.readerPool.Get() - if br == nil { - br = bufio.NewReaderSize(co, bufioSize) - } - defer p.readerPool.Put(br) - - br.Reset(co) - - res := fasthttp.AcquireResponse() - defer fasthttp.ReleaseResponse(res) - - res.Header.SetNoDefaultContentType(true) - - for { - var timer *time.Timer - errTimeout := atomic.Pointer[timeoutError]{} - if p.responseHeaderTimeout > 0 { - timer = time.AfterFunc(p.responseHeaderTimeout, func() { - errTimeout.Store(&timeoutError{errors.New("timeout awaiting response headers")}) - co.Close() - }) - } - - res.Header.SetNoDefaultContentType(true) - if err := res.Header.Read(br); err != nil { - if p.responseHeaderTimeout > 0 { - if errT := errTimeout.Load(); errT != nil { - return errT - } - } - co.Close() - return err - } - - if timer != nil { - timer.Stop() - } - - fixPragmaCacheControl(&res.Header) - - resCode := res.StatusCode() - is1xx := 100 <= resCode && resCode <= 199 - // treat 101 as a terminal status, see issue 26161 - is1xxNonTerminal := is1xx && resCode != http.StatusSwitchingProtocols - if is1xxNonTerminal { - removeConnectionHeaders(&res.Header) - h := rw.Header() - - for _, header := range hopHeaders { - res.Header.Del(header) - } - - res.Header.VisitAll(func(key, value []byte) { - rw.Header().Add(string(key), string(value)) - }) - - rw.WriteHeader(res.StatusCode()) - // Clear headers, it's not automatically done by ResponseWriter.WriteHeader() for 1xx responses - for k := range h { - delete(h, k) - } - - res.Reset() - res.Header.Reset() - res.Header.SetNoDefaultContentType(true) - - continue - } - break + // Sending the responseWriter unlocks the connection readLoop, to handle the response. + co.RWCh <- rwWithUpgrade{ + RW: rw, + Upgrade: upgradeResponseHandler(req.Context(), reqUpType), } - announcedTrailers := res.Header.Peek("Trailer") - - // Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc) - if res.StatusCode() == http.StatusSwitchingProtocols { - // As the connection has been hijacked, it cannot be added back to the pool. - handleUpgradeResponse(rw, req, reqUpType, res, buffConn{Conn: co, Reader: br}) - return nil - } - - removeConnectionHeaders(&res.Header) - - for _, header := range hopHeaders { - res.Header.Del(header) - } - - if len(announcedTrailers) > 0 { - res.Header.Add("Trailer", string(announcedTrailers)) - } - - res.Header.VisitAll(func(key, value []byte) { - rw.Header().Add(string(key), string(value)) - }) - - rw.WriteHeader(res.StatusCode()) - - // Chunked response, Content-Length is set to -1 by FastProxy when "Transfer-Encoding: chunked" header is received. - if res.Header.ContentLength() == -1 { - cbr := httputil.NewChunkedReader(br) - - b := p.bufferPool.Get() - if b == nil { - b = make([]byte, bufferSize) - } - defer p.bufferPool.Put(b) - - if _, err := io.CopyBuffer(&writeFlusher{rw}, cbr, b); err != nil { - co.Close() - return err - } - - res.Header.Reset() - res.Header.SetNoDefaultContentType(true) - if err := res.Header.ReadTrailer(br); err != nil { - co.Close() - return err - } - - if res.Header.Len() > 0 { - var announcedTrailersKey []string - if len(announcedTrailers) > 0 { - announcedTrailersKey = strings.Split(string(announcedTrailers), ",") - } - - res.Header.VisitAll(func(key, value []byte) { - for _, s := range announcedTrailersKey { - if strings.EqualFold(s, strings.TrimSpace(string(key))) { - rw.Header().Add(string(key), string(value)) - return - } - } - - rw.Header().Add(http.TrailerPrefix+string(key), string(value)) - }) - } - - p.connPool.ReleaseConn(co) - - return nil - } - - brl := p.limitReaderPool.Get() - if brl == nil { - brl = &io.LimitedReader{} - } - defer p.limitReaderPool.Put(brl) - - brl.R = br - brl.N = int64(res.Header.ContentLength()) - - b := p.bufferPool.Get() - if b == nil { - b = make([]byte, bufferSize) - } - defer p.bufferPool.Put(b) - - if _, err := io.CopyBuffer(rw, brl, b); err != nil { - co.Close() + if err := <-co.ErrCh; err != nil { return err } p.connPool.ReleaseConn(co) - return nil } diff --git a/pkg/proxy/fast/proxy_test.go b/pkg/proxy/fast/proxy_test.go index ee75ae0db..f4593d9ce 100644 --- a/pkg/proxy/fast/proxy_test.go +++ b/pkg/proxy/fast/proxy_test.go @@ -230,7 +230,7 @@ func TestProxyFromEnvironment(t *testing.T) { return u, nil } - reverseProxy, err := builder.Build("foo", testhelpers.MustParseURL(backendURL), false) + reverseProxy, err := builder.Build("foo", testhelpers.MustParseURL(backendURL), false, false) require.NoError(t, err) reverseProxyServer := httptest.NewServer(reverseProxy) @@ -252,6 +252,32 @@ func TestProxyFromEnvironment(t *testing.T) { } } +func TestPreservePath(t *testing.T) { + var callCount int + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + callCount++ + assert.Equal(t, "/base/foo/bar", req.URL.Path) + assert.Equal(t, "/base/foo%2Fbar", req.URL.RawPath) + })) + t.Cleanup(server.Close) + + builder := NewProxyBuilder(&transportManagerMock{}, static.FastProxyConfig{}) + + serverURL, err := url.JoinPath(server.URL, "base") + require.NoError(t, err) + + proxyHandler, err := builder.Build("", testhelpers.MustParseURL(serverURL), true, true) + require.NoError(t, err) + + req := httptest.NewRequest(http.MethodGet, "/foo%2Fbar", http.NoBody) + res := httptest.NewRecorder() + + proxyHandler.ServeHTTP(res, req) + + assert.Equal(t, 1, callCount) + assert.Equal(t, http.StatusOK, res.Code) +} + func newCertificate(t *testing.T, domain string) *tls.Certificate { t.Helper() diff --git a/pkg/proxy/fast/proxy_websocket_test.go b/pkg/proxy/fast/proxy_websocket_test.go index ff2e273e9..b057f8b58 100644 --- a/pkg/proxy/fast/proxy_websocket_test.go +++ b/pkg/proxy/fast/proxy_websocket_test.go @@ -362,7 +362,7 @@ func TestWebSocketRequestWithHeadersInResponseWriter(t *testing.T) { u := parseURI(t, srv.URL) - f, err := NewReverseProxy(u, nil, true, false, 0, newConnPool(1, 0, func() (net.Conn, error) { + f, err := NewReverseProxy(u, nil, true, false, false, newConnPool(1, 0, 0, func() (net.Conn, error) { return net.Dial("tcp", u.Host) })) require.NoError(t, err) @@ -434,7 +434,7 @@ func TestWebSocketUpgradeFailed(t *testing.T) { defer srv.Close() u := parseURI(t, srv.URL) - f, err := NewReverseProxy(u, nil, true, false, 0, newConnPool(1, 0, func() (net.Conn, error) { + f, err := NewReverseProxy(u, nil, true, false, false, newConnPool(1, 0, 0, func() (net.Conn, error) { return net.Dial("tcp", u.Host) })) require.NoError(t, err) @@ -663,7 +663,7 @@ func parseURI(t *testing.T, uri string) *url.URL { func createConnectionPool(target string, tlsConfig *tls.Config) *connPool { u := testhelpers.MustParseURL(target) - return newConnPool(200, 0, func() (net.Conn, error) { + return newConnPool(200, 0, 0, func() (net.Conn, error) { if tlsConfig != nil { return tls.Dial("tcp", u.Host, tlsConfig) } @@ -676,7 +676,7 @@ func createProxyWithForwarder(t *testing.T, uri string, pool *connPool) *httptes t.Helper() u := parseURI(t, uri) - proxy, err := NewReverseProxy(u, nil, false, true, 0, pool) + proxy, err := NewReverseProxy(u, nil, false, true, false, pool) require.NoError(t, err) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { diff --git a/pkg/proxy/fast/upgrade.go b/pkg/proxy/fast/upgrade.go index a42fc97d8..7bec09e49 100644 --- a/pkg/proxy/fast/upgrade.go +++ b/pkg/proxy/fast/upgrade.go @@ -2,6 +2,7 @@ package fast import ( "bytes" + "context" "fmt" "io" "net" @@ -19,72 +20,75 @@ type switchProtocolCopier struct { user, backend io.ReadWriter } -func (c switchProtocolCopier) copyFromBackend(errc chan<- error) { +func (c switchProtocolCopier) copyFromBackend(errCh chan<- error) { _, err := io.Copy(c.user, c.backend) - errc <- err + errCh <- err } -func (c switchProtocolCopier) copyToBackend(errc chan<- error) { +func (c switchProtocolCopier) copyToBackend(errCh chan<- error) { _, err := io.Copy(c.backend, c.user) - errc <- err + errCh <- err } -func handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, reqUpType string, res *fasthttp.Response, backConn net.Conn) { - defer backConn.Close() +type upgradeHandler func(rw http.ResponseWriter, res *fasthttp.Response, backConn net.Conn) - resUpType := upgradeTypeFastHTTP(&res.Header) +func upgradeResponseHandler(ctx context.Context, reqUpType string) upgradeHandler { + return func(rw http.ResponseWriter, res *fasthttp.Response, backConn net.Conn) { + resUpType := upgradeTypeFastHTTP(&res.Header) - if !strings.EqualFold(reqUpType, resUpType) { - httputil.ErrorHandler(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType)) - return - } - - hj, ok := rw.(http.Hijacker) - if !ok { - httputil.ErrorHandler(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw)) - return - } - backConnCloseCh := make(chan bool) - go func() { - // Ensure that the cancellation of a request closes the backend. - // See issue https://golang.org/issue/35559. - select { - case <-req.Context().Done(): - case <-backConnCloseCh: + if !strings.EqualFold(reqUpType, resUpType) { + httputil.ErrorHandlerWithContext(ctx, rw, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType)) + backConn.Close() + return } - _ = backConn.Close() - }() - defer close(backConnCloseCh) - - conn, brw, err := hj.Hijack() - if err != nil { - httputil.ErrorHandler(rw, req, fmt.Errorf("hijack failed on protocol switch: %w", err)) - return - } - defer conn.Close() - - for k, values := range rw.Header() { - for _, v := range values { - res.Header.Add(k, v) + hj, ok := rw.(http.Hijacker) + if !ok { + httputil.ErrorHandlerWithContext(ctx, rw, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw)) + backConn.Close() + return } - } + backConnCloseCh := make(chan bool) + go func() { + // Ensure that the cancellation of a request closes the backend. + // See issue https://golang.org/issue/35559. + select { + case <-ctx.Done(): + case <-backConnCloseCh: + } + _ = backConn.Close() + }() + defer close(backConnCloseCh) - if err := res.Header.Write(brw.Writer); err != nil { - httputil.ErrorHandler(rw, req, fmt.Errorf("response write: %w", err)) - return - } + conn, brw, err := hj.Hijack() + if err != nil { + httputil.ErrorHandlerWithContext(ctx, rw, fmt.Errorf("hijack failed on protocol switch: %w", err)) + return + } + defer conn.Close() - if err := brw.Flush(); err != nil { - httputil.ErrorHandler(rw, req, fmt.Errorf("response flush: %w", err)) - return - } + for k, values := range rw.Header() { + for _, v := range values { + res.Header.Add(k, v) + } + } - errc := make(chan error, 1) - spc := switchProtocolCopier{user: conn, backend: backConn} - go spc.copyToBackend(errc) - go spc.copyFromBackend(errc) - <-errc + if err := res.Header.Write(brw.Writer); err != nil { + httputil.ErrorHandlerWithContext(ctx, rw, fmt.Errorf("response write: %w", err)) + return + } + + if err := brw.Flush(); err != nil { + httputil.ErrorHandlerWithContext(ctx, rw, fmt.Errorf("response flush: %w", err)) + return + } + + errCh := make(chan error, 1) + spc := switchProtocolCopier{user: conn, backend: backConn} + go spc.copyToBackend(errCh) + go spc.copyFromBackend(errCh) + <-errCh + } } func upgradeType(h http.Header) string { diff --git a/pkg/proxy/httputil/builder.go b/pkg/proxy/httputil/builder.go index ee88bd0c3..64360517a 100644 --- a/pkg/proxy/httputil/builder.go +++ b/pkg/proxy/httputil/builder.go @@ -38,7 +38,7 @@ func NewProxyBuilder(transportManager TransportManager, semConvMetricsRegistry * func (r *ProxyBuilder) Update(_ map[string]*dynamic.ServersTransport) {} // Build builds a new httputil.ReverseProxy with the given configuration. -func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, shouldObserve, passHostHeader bool, flushInterval time.Duration) (http.Handler, error) { +func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, shouldObserve, passHostHeader, preservePath bool, flushInterval time.Duration) (http.Handler, error) { roundTripper, err := r.transportManager.GetRoundTripper(cfgName) if err != nil { return nil, fmt.Errorf("getting RoundTripper: %w", err) @@ -50,5 +50,5 @@ func (r *ProxyBuilder) Build(cfgName string, targetURL *url.URL, shouldObserve, roundTripper = newObservabilityRoundTripper(r.semConvMetricsRegistry, roundTripper) } - return buildSingleHostProxy(targetURL, passHostHeader, flushInterval, roundTripper, r.bufferPool), nil + return buildSingleHostProxy(targetURL, passHostHeader, preservePath, flushInterval, roundTripper, r.bufferPool), nil } diff --git a/pkg/proxy/httputil/builder_test.go b/pkg/proxy/httputil/builder_test.go index 8033635d2..f7ff93902 100644 --- a/pkg/proxy/httputil/builder_test.go +++ b/pkg/proxy/httputil/builder_test.go @@ -23,7 +23,7 @@ func TestEscapedPath(t *testing.T) { roundTrippers: map[string]http.RoundTripper{"default": &http.Transport{}}, } - p, err := NewProxyBuilder(transportManager, nil).Build("default", testhelpers.MustParseURL(srv.URL), false, true, 0) + p, err := NewProxyBuilder(transportManager, nil).Build("default", testhelpers.MustParseURL(srv.URL), false, true, false, 0) require.NoError(t, err) proxy := httptest.NewServer(http.HandlerFunc(p.ServeHTTP)) diff --git a/pkg/proxy/httputil/proxy.go b/pkg/proxy/httputil/proxy.go index e0401ea1f..78c09f9a4 100644 --- a/pkg/proxy/httputil/proxy.go +++ b/pkg/proxy/httputil/proxy.go @@ -15,15 +15,17 @@ import ( "golang.org/x/net/http/httpguts" ) -// StatusClientClosedRequest non-standard HTTP status code for client disconnection. -const StatusClientClosedRequest = 499 +const ( + // StatusClientClosedRequest non-standard HTTP status code for client disconnection. + StatusClientClosedRequest = 499 -// StatusClientClosedRequestText non-standard HTTP status for client disconnection. -const StatusClientClosedRequestText = "Client Closed Request" + // StatusClientClosedRequestText non-standard HTTP status for client disconnection. + StatusClientClosedRequestText = "Client Closed Request" +) -func buildSingleHostProxy(target *url.URL, passHostHeader bool, flushInterval time.Duration, roundTripper http.RoundTripper, bufferPool httputil.BufferPool) http.Handler { +func buildSingleHostProxy(target *url.URL, passHostHeader bool, preservePath bool, flushInterval time.Duration, roundTripper http.RoundTripper, bufferPool httputil.BufferPool) http.Handler { return &httputil.ReverseProxy{ - Director: directorBuilder(target, passHostHeader), + Director: directorBuilder(target, passHostHeader, preservePath), Transport: roundTripper, FlushInterval: flushInterval, BufferPool: bufferPool, @@ -31,7 +33,7 @@ func buildSingleHostProxy(target *url.URL, passHostHeader bool, flushInterval ti } } -func directorBuilder(target *url.URL, passHostHeader bool) func(req *http.Request) { +func directorBuilder(target *url.URL, passHostHeader bool, preservePath bool) func(req *http.Request) { return func(outReq *http.Request) { outReq.URL.Scheme = target.Scheme outReq.URL.Host = target.Host @@ -46,6 +48,11 @@ func directorBuilder(target *url.URL, passHostHeader bool) func(req *http.Reques outReq.URL.Path = u.Path outReq.URL.RawPath = u.RawPath + + if preservePath { + outReq.URL.Path, outReq.URL.RawPath = JoinURLPath(target, u) + } + // If a plugin/middleware adds semicolons in query params, they should be urlEncoded. outReq.URL.RawQuery = strings.ReplaceAll(u.RawQuery, ";", "&") outReq.RequestURI = "" // Outgoing request should not have RequestURI @@ -54,7 +61,7 @@ func directorBuilder(target *url.URL, passHostHeader bool) func(req *http.Reques outReq.ProtoMajor = 1 outReq.ProtoMinor = 1 - // Do not pass client Host header unless optsetter PassHostHeader is set. + // Do not pass client Host header unless option PassHostHeader is set. if !passHostHeader { outReq.Host = outReq.URL.Host } @@ -95,9 +102,14 @@ func isWebSocketUpgrade(req *http.Request) bool { // ErrorHandler is the http.Handler called when something goes wrong when forwarding the request. func ErrorHandler(w http.ResponseWriter, req *http.Request, err error) { + ErrorHandlerWithContext(req.Context(), w, err) +} + +// ErrorHandlerWithContext is the http.Handler called when something goes wrong when forwarding the request. +func ErrorHandlerWithContext(ctx context.Context, w http.ResponseWriter, err error) { statusCode := ComputeStatusCode(err) - logger := log.Ctx(req.Context()) + logger := log.Ctx(ctx) logger.Debug().Err(err).Msgf("%d %s", statusCode, statusText(statusCode)) w.WriteHeader(statusCode) @@ -106,6 +118,13 @@ func ErrorHandler(w http.ResponseWriter, req *http.Request, err error) { } } +func statusText(statusCode int) string { + if statusCode == StatusClientClosedRequest { + return StatusClientClosedRequestText + } + return http.StatusText(statusCode) +} + // ComputeStatusCode computes the HTTP status code according to the given error. func ComputeStatusCode(err error) int { switch { @@ -127,9 +146,38 @@ func ComputeStatusCode(err error) int { return http.StatusInternalServerError } -func statusText(statusCode int) string { - if statusCode == StatusClientClosedRequest { - return StatusClientClosedRequestText +// JoinURLPath computes the joined path and raw path of the given URLs. +// From https://github.com/golang/go/blob/b521ebb55a9b26c8824b219376c7f91f7cda6ec2/src/net/http/httputil/reverseproxy.go#L221 +func JoinURLPath(a, b *url.URL) (path, rawpath string) { + if a.RawPath == "" && b.RawPath == "" { + return singleJoiningSlash(a.Path, b.Path), "" } - return http.StatusText(statusCode) + + // Same as singleJoiningSlash, but uses EscapedPath to determine + // whether a slash should be added + apath := a.EscapedPath() + bpath := b.EscapedPath() + + aslash := strings.HasSuffix(apath, "/") + bslash := strings.HasPrefix(bpath, "/") + + switch { + case aslash && bslash: + return a.Path + b.Path[1:], apath + bpath[1:] + case !aslash && !bslash: + return a.Path + "/" + b.Path, apath + "/" + bpath + } + return a.Path + b.Path, apath + bpath +} + +func singleJoiningSlash(a, b string) string { + aslash := strings.HasSuffix(a, "/") + bslash := strings.HasPrefix(b, "/") + switch { + case aslash && bslash: + return a + b[1:] + case !aslash && !bslash: + return a + "/" + b + } + return a + b } diff --git a/pkg/proxy/httputil/proxy_test.go b/pkg/proxy/httputil/proxy_test.go new file mode 100644 index 000000000..3d970fc53 --- /dev/null +++ b/pkg/proxy/httputil/proxy_test.go @@ -0,0 +1,102 @@ +package httputil + +import ( + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/traefik/traefik/v3/pkg/testhelpers" +) + +func Test_directorBuilder(t *testing.T) { + tests := []struct { + name string + target *url.URL + passHostHeader bool + preservePath bool + incomingURL string + expectedScheme string + expectedHost string + expectedPath string + expectedRawPath string + expectedQuery string + }{ + { + name: "Basic proxy", + target: testhelpers.MustParseURL("http://example.com"), + passHostHeader: false, + preservePath: false, + incomingURL: "http://localhost/test?param=value", + expectedScheme: "http", + expectedHost: "example.com", + expectedPath: "/test", + expectedQuery: "param=value", + }, + { + name: "HTTPS target", + target: testhelpers.MustParseURL("https://secure.example.com"), + passHostHeader: false, + preservePath: false, + incomingURL: "http://localhost/secure", + expectedScheme: "https", + expectedHost: "secure.example.com", + expectedPath: "/secure", + }, + { + name: "PassHostHeader", + target: testhelpers.MustParseURL("http://example.com"), + passHostHeader: true, + preservePath: false, + incomingURL: "http://original.host/test", + expectedScheme: "http", + expectedHost: "original.host", + expectedPath: "/test", + }, + { + name: "Preserve path", + target: testhelpers.MustParseURL("http://example.com/base"), + passHostHeader: false, + preservePath: true, + incomingURL: "http://localhost/foo%2Fbar", + expectedScheme: "http", + expectedHost: "example.com", + expectedPath: "/base/foo/bar", + expectedRawPath: "/base/foo%2Fbar", + }, + { + name: "Handle semicolons in query", + target: testhelpers.MustParseURL("http://example.com"), + passHostHeader: false, + preservePath: false, + incomingURL: "http://localhost/test?param1=value1;param2=value2", + expectedScheme: "http", + expectedHost: "example.com", + expectedPath: "/test", + expectedQuery: "param1=value1¶m2=value2", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + director := directorBuilder(test.target, test.passHostHeader, test.preservePath) + + req := httptest.NewRequest(http.MethodGet, test.incomingURL, http.NoBody) + director(req) + + assert.Equal(t, test.expectedScheme, req.URL.Scheme) + assert.Equal(t, test.expectedHost, req.Host) + assert.Equal(t, test.expectedPath, req.URL.Path) + assert.Equal(t, test.expectedRawPath, req.URL.RawPath) + assert.Equal(t, test.expectedQuery, req.URL.RawQuery) + assert.Empty(t, req.RequestURI) + assert.Equal(t, "HTTP/1.1", req.Proto) + assert.Equal(t, 1, req.ProtoMajor) + assert.Equal(t, 1, req.ProtoMinor) + assert.False(t, !test.passHostHeader && req.Host != req.URL.Host) + }) + } +} diff --git a/pkg/proxy/httputil/proxy_websocket_test.go b/pkg/proxy/httputil/proxy_websocket_test.go index dc6fa8c82..5472bcce0 100644 --- a/pkg/proxy/httputil/proxy_websocket_test.go +++ b/pkg/proxy/httputil/proxy_websocket_test.go @@ -298,9 +298,8 @@ func TestWebSocketRequestWithHeadersInResponseWriter(t *testing.T) { }, } - p, err := NewProxyBuilder(transportManager, nil).Build("default@internal", testhelpers.MustParseURL(srv.URL), false, true, 0) + p, err := NewProxyBuilder(transportManager, nil).Build("default@internal", testhelpers.MustParseURL(srv.URL), false, true, false, 0) require.NoError(t, err) - proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testhelpers.MustParseURL(srv.URL) w.Header().Set("HEADER-KEY", "HEADER-VALUE") @@ -355,9 +354,8 @@ func TestWebSocketUpgradeFailed(t *testing.T) { }, } - p, err := NewProxyBuilder(transportManager, nil).Build("default@internal", testhelpers.MustParseURL(srv.URL), false, true, 0) + p, err := NewProxyBuilder(transportManager, nil).Build("default@internal", testhelpers.MustParseURL(srv.URL), false, true, false, 0) require.NoError(t, err) - proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { path := req.URL.Path // keep the original path @@ -588,7 +586,7 @@ func createProxyWithForwarder(t *testing.T, uri string, transport http.RoundTrip roundTrippers: map[string]http.RoundTripper{"fwd": transport}, } - p, err := NewProxyBuilder(transportManager, nil).Build("fwd", u, false, true, 0) + p, err := NewProxyBuilder(transportManager, nil).Build("fwd", u, false, true, false, 0) require.NoError(t, err) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { diff --git a/pkg/proxy/smart_builder.go b/pkg/proxy/smart_builder.go index 1abadcca7..08b247c53 100644 --- a/pkg/proxy/smart_builder.go +++ b/pkg/proxy/smart_builder.go @@ -45,7 +45,7 @@ func (b *SmartBuilder) Update(newConfigs map[string]*dynamic.ServersTransport) { } // Build builds an HTTP proxy for the given URL using the ServersTransport with the given name. -func (b *SmartBuilder) Build(configName string, targetURL *url.URL, shouldObserve, passHostHeader bool, flushInterval time.Duration) (http.Handler, error) { +func (b *SmartBuilder) Build(configName string, targetURL *url.URL, shouldObserve, passHostHeader, preservePath bool, flushInterval time.Duration) (http.Handler, error) { serversTransport, err := b.transportManager.Get(configName) if err != nil { return nil, fmt.Errorf("getting ServersTransport: %w", err) @@ -55,7 +55,7 @@ func (b *SmartBuilder) Build(configName string, targetURL *url.URL, shouldObserv // For the https scheme we cannot guess if the backend communication will use HTTP2, // thus we check if HTTP/2 is disabled to use the fast proxy implementation when this is possible. if targetURL.Scheme == "h2c" || (targetURL.Scheme == "https" && !serversTransport.DisableHTTP2) { - return b.proxyBuilder.Build(configName, targetURL, shouldObserve, passHostHeader, flushInterval) + return b.proxyBuilder.Build(configName, targetURL, shouldObserve, passHostHeader, preservePath, flushInterval) } - return b.fastProxyBuilder.Build(configName, targetURL, passHostHeader) + return b.fastProxyBuilder.Build(configName, targetURL, passHostHeader, preservePath) } diff --git a/pkg/proxy/smart_builder_test.go b/pkg/proxy/smart_builder_test.go index d1c29ddd8..c03bd19f3 100644 --- a/pkg/proxy/smart_builder_test.go +++ b/pkg/proxy/smart_builder_test.go @@ -101,7 +101,7 @@ func TestSmartBuilder_Build(t *testing.T) { httpProxyBuilder := httputil.NewProxyBuilder(transportManager, nil) proxyBuilder := NewSmartBuilder(transportManager, httpProxyBuilder, test.fastProxyConfig) - proxyHandler, err := proxyBuilder.Build("test", targetURL, false, false, time.Second) + proxyHandler, err := proxyBuilder.Build("test", targetURL, false, false, false, time.Second) require.NoError(t, err) rw := httptest.NewRecorder() diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index b545bd2da..70808e9c6 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -897,7 +897,7 @@ func BenchmarkService(b *testing.B) { type proxyBuilderMock struct{} -func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _ bool, _ time.Duration) (http.Handler, error) { +func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _, _ bool, _ time.Duration) (http.Handler, error) { return http.HandlerFunc(func(responseWriter http.ResponseWriter, req *http.Request) {}), nil } diff --git a/pkg/server/routerfactory_test.go b/pkg/server/routerfactory_test.go index 6c0861d38..2b3d6fe1f 100644 --- a/pkg/server/routerfactory_test.go +++ b/pkg/server/routerfactory_test.go @@ -254,7 +254,7 @@ func TestInternalServices(t *testing.T) { type proxyBuilderMock struct{} -func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _ bool, _ time.Duration) (http.Handler, error) { +func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _, _ bool, _ time.Duration) (http.Handler, error) { return http.HandlerFunc(func(responseWriter http.ResponseWriter, req *http.Request) {}), nil } diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index e37ecdf09..349c03179 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -42,7 +42,7 @@ const ( // ProxyBuilder builds reverse proxy handlers. type ProxyBuilder interface { - Build(cfgName string, targetURL *url.URL, shouldObserve, passHostHeader bool, flushInterval time.Duration) (http.Handler, error) + Build(cfgName string, targetURL *url.URL, shouldObserve, passHostHeader, preservePath bool, flushInterval time.Duration) (http.Handler, error) Update(configs map[string]*dynamic.ServersTransport) } @@ -338,7 +338,7 @@ func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName qualifiedSvcName := provider.GetQualifiedName(ctx, serviceName) shouldObserve := m.observabilityMgr.ShouldAddTracing(qualifiedSvcName) || m.observabilityMgr.ShouldAddMetrics(qualifiedSvcName) - proxy, err := m.proxyBuilder.Build(service.ServersTransport, target, shouldObserve, passHostHeader, flushInterval) + proxy, err := m.proxyBuilder.Build(service.ServersTransport, target, shouldObserve, passHostHeader, server.PreservePath, flushInterval) if err != nil { return nil, fmt.Errorf("error building proxy for server URL %s: %w", server.URL, err) } diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 8e06b98e3..90dee22cf 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v3.1.6 +# example new bugfix v3.1.7 CurrentRef = "v3.1" -PreviousRef = "v3.1.5" +PreviousRef = "v3.1.6" BaseBranch = "v3.1" -FutureCurrentRefName = "v3.1.6" +FutureCurrentRefName = "v3.1.7" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part1.toml b/script/gcg/traefik-final-release-part1.toml index 69d309e74..8b2375d76 100644 --- a/script/gcg/traefik-final-release-part1.toml +++ b/script/gcg/traefik-final-release-part1.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v3.1.0 -CurrentRef = "v3.1" -PreviousRef = "v3.1.0-rc1" -BaseBranch = "v3.1" -FutureCurrentRefName = "v3.1.0" +# example final release of v3.2.0 +CurrentRef = "v3.2" +PreviousRef = "v3.2.0-rc1" +BaseBranch = "v3.2" +FutureCurrentRefName = "v3.2.0" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part2.toml b/script/gcg/traefik-final-release-part2.toml index f005fc043..81f571eef 100644 --- a/script/gcg/traefik-final-release-part2.toml +++ b/script/gcg/traefik-final-release-part2.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v3.1.0 -CurrentRef = "v3.1.0-rc1" -PreviousRef = "v3.0.0-beta2" # divergence with master and branch v3 has been initiated with v3.0.0-beta2 +# example final release of v3.2.0 +CurrentRef = "v3.2.0-rc1" +PreviousRef = "v3.1.0-rc1" BaseBranch = "master" -FutureCurrentRefName = "v3.1.0-rc1" +FutureCurrentRefName = "v3.2.0-rc1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10