From b6d2f2c09e067fb480c06dc4c01a2081e546f4cc Mon Sep 17 00:00:00 2001 From: Rob Scott Date: Fri, 18 Apr 2025 09:53:07 -0700 Subject: [PATCH 001/224] Simplify hack/build-install-yaml.sh (#3754) * Changelog for v1.3.0-rc.2 * Simplify hack/build-install-yaml.sh --- hack/build-install-yaml.sh | 73 ++++++++++++++------------------------ 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/hack/build-install-yaml.sh b/hack/build-install-yaml.sh index d3f5268216..e1bf0f2512 100755 --- a/hack/build-install-yaml.sh +++ b/hack/build-install-yaml.sh @@ -18,61 +18,40 @@ set -o errexit set -o nounset set -o pipefail -thisyear=$(date +"%Y") +readonly CHANNELS=(standard experimental) +readonly YEAR=$(date +"%Y") mkdir -p release/ -# Make clean files with boilerplate -cat hack/boilerplate/boilerplate.sh.txt > release/experimental-install.yaml - -if [[ "$OSTYPE" == "linux-gnu"* ]]; then - sed -i "s/YEAR/$thisyear/g" release/experimental-install.yaml -elif [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s/YEAR/$thisyear/g" release/experimental-install.yaml -else - echo "Unsupported OS" - exit 1 -fi - -cat << EOF >> release/experimental-install.yaml +for CHANNEL in "${CHANNELS[@]}"; do + echo $CHANNEL + # Make clean files with boilerplate + cat hack/boilerplate/boilerplate.sh.txt > release/${CHANNEL}-install.yaml + + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + sed -i "s/YEAR/${YEAR}/g" release/${CHANNEL}-install.yaml + elif [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "s/YEAR/${YEAR}/g" release/${CHANNEL}-install.yaml + else + echo "Unsupported OS" + exit 1 + fi + + cat << EOF >> release/${CHANNEL}-install.yaml # -# Gateway API Experimental channel install +# Gateway API ${CHANNEL^} channel install # EOF -cat hack/boilerplate/boilerplate.sh.txt > release/standard-install.yaml - -if [[ "$OSTYPE" == "linux-gnu"* ]]; then - sed -i "s/YEAR/$thisyear/g" release/experimental-install.yaml -elif [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s/YEAR/$thisyear/g" release/experimental-install.yaml -else - echo "Unsupported OS" - exit 1 -fi - -cat << EOF >> release/standard-install.yaml -# -# Gateway API Standard channel install -# -EOF - -for file in config/crd/experimental/gateway*.yaml -do - echo "---" >> release/experimental-install.yaml - echo "#" >> release/experimental-install.yaml - echo "# $file" >> release/experimental-install.yaml - echo "#" >> release/experimental-install.yaml - cat "$file" >> release/experimental-install.yaml -done + for file in config/crd/${CHANNEL}/gateway*.yaml + do + echo "---" >> release/${CHANNEL}-install.yaml + echo "#" >> release/${CHANNEL}-install.yaml + echo "# $file" >> release/${CHANNEL}-install.yaml + echo "#" >> release/${CHANNEL}-install.yaml + cat "$file" >> release/${CHANNEL}-install.yaml + done -for file in config/crd/standard/*.yaml -do - echo "---" >> release/standard-install.yaml - echo "#" >> release/standard-install.yaml - echo "# $file" >> release/standard-install.yaml - echo "#" >> release/standard-install.yaml - cat "$file" >> release/standard-install.yaml done echo "Generated:" release/*-install.yaml From efec20dbaa16f49f7227c576eb332c539715c6d3 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Mon, 21 Apr 2025 21:01:40 -0400 Subject: [PATCH 002/224] docs: add release managment to RELEASE.md (#3726) Signed-off-by: Shane Utt --- RELEASE.md | 3 ++ RELEASE_MANAGEMENT.md | 111 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 RELEASE_MANAGEMENT.md diff --git a/RELEASE.md b/RELEASE.md index d72758367e..fc8053cd87 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,8 @@ # Release Process +This details how releases of Gateway API are delivered. This process is +exercised by a [Release Manager](/RELEASE_MANAGEMENT.md). + ## Overview The Gateway API project is an API project that has the following two components: diff --git a/RELEASE_MANAGEMENT.md b/RELEASE_MANAGEMENT.md new file mode 100644 index 0000000000..cd8f0f1851 --- /dev/null +++ b/RELEASE_MANAGEMENT.md @@ -0,0 +1,111 @@ +# Release Management + +Major and minor releases for Gateway API are managed by a "Release Manager". +The responsibilities of the release manager include: + +* Creating and managing a GitHub Milestone for the release. +* Creating and managing a GitHub Project board for the release. +* Creating and managing a GitHub Discussion Boards announcement for the release. + * This includes discussions to handle scoping for each release _channel_ as well. +* Working through the [Release Cycle](#release-phases) for the release. + +This management process ultimately results in the manager of the release +shipping the release as per the [Release Process]. We will go into more detail +about this in the sections that follow. + +> **Note**: Patch releases need someone assigned to them as well, however they +> just happen organically, and as soon as possible. We currently we don't bother +> sending patch releases through this entire process. + +[Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ +[Release Process]:/RELEASE.md + +## Assigning a Release Manager + +The [maintainers] will find and assign a release managers for upcoming +releases. A release manager can be a community member on the contributor ladder +who volunteers (at the discretion of the maintainers), or otherwise the +responsibility falls back to the maintainers. + +[maintainers]:/OWNERS_ALIASES + +## GitHub Milestone + +Once a manager is assigned for the release, they must create a [GitHub +Milestone] for the release, where the name of the milestone is the eventual tag +that will be cut (e.g., `v1.0.0`). + +The release manager must mark themselves as the manager for the release at the +top of the milestone's description, and add any description to the milestone +that communicates to the community any major themes in the release, and +important notes: + +```console +release-manager: @ + +This milestone introduces the following new experimental features: + +* +* +* + +This milestone graduates the following features: + +* +* + +feature-freeze: +``` + +> **Note**: The GitHub Milestone may change over time, as things are added or +> removed. + +The release manager must assign a due date for the milestone, to communicate to +the community the intended date to ship the release. + +> **Note**: The due date may change as well, but it's valuable to try and +> communicate dates in this way as many implementations and community members +> plan their releases on ours. We will make every effort to avoid changes to the +> release date. + +[GitHub Milestone]:https://github.com/kubernetes-sigs/gateway-api/milestones + +## GitHub Project Board + +The release manager must create a [project board] for the release, which will +be used to help track the work in the [milestone](#github-milestone) over time +to refine and analyze progress as the release is ongoing. The columns for this +board should generally align with the [Release Cycle]. + +> **Note**: Changes to this board should be shared via updates on the community +> syncs as well. + +[project board]:https://github.com/kubernetes-sigs/gateway-api/projects +[Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ + +## Release Cycle + +The release manager is responsible for tracking and managing the release +through several phases, ultimately resulting in shipping the release. That +cycle is outlined in the [Release Cycle] documentation and should be followed +according to that. + +The release manager is responsible for communicating with the community and +seeking volunteers for features to be included in the release, and thus the +release will be considered a **feature release**. If there are few or no +volunteers the release may simply end being a smaller **maintenance release**. + +> **Note**: Updates on the community sync and discussion boards about the +> release process should be communicated regularly. We recommend bi-weekly +> unless there's a clear reason to do more, or less. + +> **Note**: Communicating whether a release is expected to be a **feature +> release** or a **maintenance release** is largely done via the [Milestone]. +> However, the final GitHub release should also make note of this in the +> release description. + +Release candidates--and the eventual final release--must utilize the [Release +Process](/RELEASE.md) for delivery. + +[Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ +[Milestone]:#github-milestone From 4d8c92c914b8cdd05908c2e3b139153af2c174e5 Mon Sep 17 00:00:00 2001 From: zirain Date: Thu, 24 Apr 2025 07:38:31 +0800 Subject: [PATCH 003/224] fix typo in BudgetDetails (#3762) * fix typo * fix test Signed-off-by: zirain --------- Signed-off-by: zirain --- apisx/v1alpha1/xbackendtrafficpolicy_types.go | 6 +++--- ...teway.networking.x-k8s.io_xbackendtrafficpolicies.yaml | 8 ++++---- pkg/generated/openapi/zz_generated.openapi.go | 4 ++-- pkg/test/cel/backendtrafficpolicy_test.go | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apisx/v1alpha1/xbackendtrafficpolicy_types.go b/apisx/v1alpha1/xbackendtrafficpolicy_types.go index 6d7af56dee..b2dcba6985 100644 --- a/apisx/v1alpha1/xbackendtrafficpolicy_types.go +++ b/apisx/v1alpha1/xbackendtrafficpolicy_types.go @@ -147,7 +147,7 @@ type RetryConstraint struct { // the percentage of requests in the budget, and the interval between // checks. type BudgetDetails struct { - // BudgetPercent defines the maximum percentage of active requests that may + // Percent defines the maximum percentage of active requests that may // be made up of retries. // // Support: Extended @@ -158,13 +158,13 @@ type BudgetDetails struct { // +kubebuilder:validation:Maximum=100 Percent *int `json:"percent,omitempty"` - // BudgetInterval defines the duration in which requests will be considered + // Interval defines the duration in which requests will be considered // for calculating the budget for retries. // // Support: Extended // // +optional // +kubebuilder:default="10s" - // +kubebuilder:validation:XValidation:message="budgetInterval can not be greater than one hour or less than one second",rule="!(duration(self) < duration('1s') || duration(self) > duration('1h'))" + // +kubebuilder:validation:XValidation:message="interval can not be greater than one hour or less than one second",rule="!(duration(self) < duration('1s') || duration(self) > duration('1h'))" Interval *Duration `json:"interval,omitempty"` } diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 27678db713..2fddbe9bb5 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -94,21 +94,21 @@ spec: interval: default: 10s description: |- - BudgetInterval defines the duration in which requests will be considered + Interval defines the duration in which requests will be considered for calculating the budget for retries. Support: Extended pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string x-kubernetes-validations: - - message: budgetInterval can not be greater than one hour - or less than one second + - message: interval can not be greater than one hour or less + than one second rule: '!(duration(self) < duration(''1s'') || duration(self) > duration(''1h''))' percent: default: 20 description: |- - BudgetPercent defines the maximum percentage of active requests that may + Percent defines the maximum percentage of active requests that may be made up of retries. Support: Extended diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 1516450f27..60e2caa920 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7706,14 +7706,14 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_BudgetDetails(ref common.Refere Properties: map[string]spec.Schema{ "percent": { SchemaProps: spec.SchemaProps{ - Description: "BudgetPercent defines the maximum percentage of active requests that may be made up of retries.\n\nSupport: Extended", + Description: "Percent defines the maximum percentage of active requests that may be made up of retries.\n\nSupport: Extended", Type: []string{"integer"}, Format: "int32", }, }, "interval": { SchemaProps: spec.SchemaProps{ - Description: "BudgetInterval defines the duration in which requests will be considered for calculating the budget for retries.\n\nSupport: Extended", + Description: "Interval defines the duration in which requests will be considered for calculating the budget for retries.\n\nSupport: Extended", Type: []string{"string"}, Format: "", }, diff --git a/pkg/test/cel/backendtrafficpolicy_test.go b/pkg/test/cel/backendtrafficpolicy_test.go index 443b82bf26..0ea42097fe 100644 --- a/pkg/test/cel/backendtrafficpolicy_test.go +++ b/pkg/test/cel/backendtrafficpolicy_test.go @@ -105,7 +105,7 @@ func TestBackendTrafficPolicyConfig(t *testing.T) { Interval: toDuration("10s"), }), }, - wantErrors: []string{"budgetInterval can not be greater than one hour or less than one second"}, + wantErrors: []string{"interval can not be greater than one hour or less than one second"}, }, { name: "invalid BackendTrafficPolicyConfig budgetInterval too short", @@ -124,7 +124,7 @@ func TestBackendTrafficPolicyConfig(t *testing.T) { Interval: toDuration("10s"), }), }, - wantErrors: []string{"budgetInterval can not be greater than one hour or less than one second"}, + wantErrors: []string{"interval can not be greater than one hour or less than one second"}, }, { name: "invalid BackendTrafficPolicyConfig minRetryRate interval", From cd09161d81ecb25a08bff334c254db1467a6e78b Mon Sep 17 00:00:00 2001 From: Nick Young Date: Thu, 24 Apr 2025 11:44:29 +1000 Subject: [PATCH 004/224] Add 1.3 release team and update relevant GEPs (#3764) Signed-off-by: Nick Young --- CHANGELOG/1.3-TEAM.md | 9 +++++++++ geps/gep-1713/metadata.yaml | 12 +++++++++++- geps/gep-1767/metadata.yaml | 8 ++++++++ geps/gep-3171/metadata.yaml | 5 ++++- geps/gep-3388/metadata.yaml | 7 ++++++- geps/gep-696/metadata.yaml | 1 + 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG/1.3-TEAM.md diff --git a/CHANGELOG/1.3-TEAM.md b/CHANGELOG/1.3-TEAM.md new file mode 100644 index 0000000000..8306cdd22e --- /dev/null +++ b/CHANGELOG/1.3-TEAM.md @@ -0,0 +1,9 @@ +# v1.3 Release Team + +| Enhancement | Leads | +| - | - | +| Percentage-Based Request Mirroring | @LiorLieberman, @jakebennert | +| CORS (Cross Origin Resource Sharing) Filter | @liangli, @EyalPazz, @robscott | +| XListenerSets (Standard Mechanism to Merge Gateways)| @dprotaso | +| XBackendTrafficPolicy (Retry Budgets) | @ericdbishop | + diff --git a/geps/gep-1713/metadata.yaml b/geps/gep-1713/metadata.yaml index 3f8a460621..9d0aac9942 100644 --- a/geps/gep-1713/metadata.yaml +++ b/geps/gep-1713/metadata.yaml @@ -1,7 +1,17 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 1713 -name: Gateway Merging - ListenerSet +name: XListenerSets (Standard Mechanism to Merge Gateways) status: Experimental authors: - dprotaso + - youngnick + - mlavacca +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3477 + - https://github.com/kubernetes-sigs/gateway-api/pull/3213 + - https://github.com/kubernetes-sigs/gateway-api/pull/3632 + - https://github.com/kubernetes-sigs/gateway-api/pull/3664 + - https://github.com/kubernetes-sigs/gateway-api/pull/3587 + - https://github.com/kubernetes-sigs/gateway-api/pull/3588 + - https://github.com/kubernetes-sigs/gateway-api/pull/3682 diff --git a/geps/gep-1767/metadata.yaml b/geps/gep-1767/metadata.yaml index 4e08d22ac5..c7fe532b81 100644 --- a/geps/gep-1767/metadata.yaml +++ b/geps/gep-1767/metadata.yaml @@ -5,3 +5,11 @@ name: CORS Filter status: Experimental authors: - lianglli + - robscott + - EyalPazz +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3435 + - https://github.com/kubernetes-sigs/gateway-api/pull/3637 + - https://github.com/kubernetes-sigs/gateway-api/pull/3656 + - https://github.com/kubernetes-sigs/gateway-api/pull/3668 + diff --git a/geps/gep-3171/metadata.yaml b/geps/gep-3171/metadata.yaml index 1c3b055003..3b4d54fc26 100644 --- a/geps/gep-3171/metadata.yaml +++ b/geps/gep-3171/metadata.yaml @@ -5,9 +5,12 @@ name: Percentage-based Request Mirroring status: Standard authors: - jakebennert + - LiorLieberman references: - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRequestMirrorFilter - https://github.com/kubernetes-sigs/gateway-api/pull/3199 - https://github.com/kubernetes-sigs/gateway-api/pull/3301 + - https://github.com/kubernetes-sigs/gateway-api/pull/3638 + - https://github.com/kubernetes-sigs/gateway-api/pull/3508 featureNames: - - Percentage-based Request Mirroring + - HTTPRouteRequestPercentageMirror diff --git a/geps/gep-3388/metadata.yaml b/geps/gep-3388/metadata.yaml index 5f33570fa2..53b9ef127a 100644 --- a/geps/gep-3388/metadata.yaml +++ b/geps/gep-3388/metadata.yaml @@ -26,7 +26,12 @@ relationships: seeAlso: {} # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3607 + - https://github.com/kubernetes-sigs/gateway-api/pull/3488 + - https://github.com/kubernetes-sigs/gateway-api/pull/3682 + - https://github.com/kubernetes-sigs/gateway-api/pull/3692 + - https://github.com/kubernetes-sigs/gateway-api/pull/3695 # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. featureNames: {} diff --git a/geps/gep-696/metadata.yaml b/geps/gep-696/metadata.yaml index cd15a89cd4..0eedd6cabe 100644 --- a/geps/gep-696/metadata.yaml +++ b/geps/gep-696/metadata.yaml @@ -29,6 +29,7 @@ relationships: references: {} # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. featureNames: {} # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. From 40be951cebe5cb3f0365fe6951403de4ff8b9f33 Mon Sep 17 00:00:00 2001 From: Rob Scott Date: Wed, 23 Apr 2025 19:02:30 -0700 Subject: [PATCH 005/224] Adding changelog for v1.3 (#3765) --- CHANGELOG/1.3-CHANGELOG.md | 331 +++++++++++++++++- README.md | 2 +- ....networking.k8s.io_backendtlspolicies.yaml | 2 +- ...eway.networking.k8s.io_gatewayclasses.yaml | 2 +- .../gateway.networking.k8s.io_gateways.yaml | 2 +- .../gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../gateway.networking.k8s.io_httproutes.yaml | 2 +- ...way.networking.k8s.io_referencegrants.yaml | 2 +- .../gateway.networking.k8s.io_tcproutes.yaml | 2 +- .../gateway.networking.k8s.io_tlsroutes.yaml | 2 +- .../gateway.networking.k8s.io_udproutes.yaml | 2 +- ...king.x-k8s.io_xbackendtrafficpolicies.yaml | 2 +- ...way.networking.x-k8s.io_xlistenersets.yaml | 2 +- ...eway.networking.k8s.io_gatewayclasses.yaml | 2 +- .../gateway.networking.k8s.io_gateways.yaml | 2 +- .../gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../gateway.networking.k8s.io_httproutes.yaml | 2 +- ...way.networking.k8s.io_referencegrants.yaml | 2 +- pkg/consts/consts.go | 2 +- site-src/guides/index.md | 4 +- 20 files changed, 350 insertions(+), 21 deletions(-) diff --git a/CHANGELOG/1.3-CHANGELOG.md b/CHANGELOG/1.3-CHANGELOG.md index bedc1061b3..2d1005f575 100644 --- a/CHANGELOG/1.3-CHANGELOG.md +++ b/CHANGELOG/1.3-CHANGELOG.md @@ -2,11 +2,339 @@ ## Table of Contents - [v1.3.0](#v130) +- [v1.3.0-rc.2](#v130-rc2) - [v1.3.0-rc.1](#v130-rc1) # v1.3.0 -TBD +## Changes since v1.3.0-rc.2 + +- Fixed typo in Retry Budget configuration ([#3762](https://github.com/kubernetes-sigs/gateway-api/pull/3762),[@zirain](https://github.com/zirain)) + +## Changes since v1.2.1 + +### Noteworthy Changes for Implementors +This section is intended to be a guide for API changes that might inspire or require implementation changes. +None of these API changes represent breaking changes. + +#### OverlappingTLSConfig for Connection Coalescing +A new `OverlappingTLSConfig` condition has been added to Gateway Listeners to indicate situations where +Connection Coalescing could be problematic. The Gateway specification for handling Hostname and SNI matching for HTTPS +requests has been clarified and now recommends that implementations return 421 HTTP code responses in certain cases. + +- Implementation of GEP-3567 - TLS Updates for Connection Coalescing. ([#3630](https://github.com/kubernetes-sigs/gateway-api/pull/3630),[@robscott](https://github.com/robscott)) +- Add GEP-3567: Gateway TLS Updates for HTTP/2 Connection Coalescing. ([#3572](https://github.com/kubernetes-sigs/gateway-api/pull/3630),[@robscott](https://github.com/robscott)) + +#### Move `BackendTLSPolicy` `SubjectAltNames` from Core to Extended +- The `SubjectAltNames` field of `BackendTLSPolicy` changed from Core to Extended feature. ([#3591](https://github.com/kubernetes-sigs/gateway-api/pull/3591),[@mlavacca](https://github.com/mlavacca)) + +#### The `backendRef` filter must send traffic to the correct backends when weighted routing is configured +- A new conformance test was added to ensure `backendRef` filters don't affect weighted routing. ([#3604](https://github.com/kubernetes-sigs/gateway-api/pull/3604),[@dprotaso](https://github.com/dprotaso)) + +#### Clarify reasons for certain object status conditions +- Set proper reason for Gateway `parametersRef` `Accepted` condition when `parametersRef` is invalid. ([#3579](https://github.com/kubernetes-sigs/gateway-api/pull/3579),[@mlavacca](https://github.com/mlavacca)) +- Improve GatewayClass `GatewayClassReasonInvalidParameters` reason description. ([#3553](https://github.com/kubernetes-sigs/gateway-api/pull/3553),[@mlavacca](https://github.com/mlavacca)) + +#### BackendTLSPolicy +- CEL validation for target references in `BackendTLSPolicy`. ([#3496](https://github.com/kubernetes-sigs/gateway-api/pull/3496),[@snorwin](https://github.com/snorwin)) + +#### GRPCRoute +- Increase the `GRPCRoute` match limit from 8 -> 64 ([#3601](https://github.com/kubernetes-sigs/gateway-api/pull/3601),[@EyalPazz](https://github.com/EyalPazz)) + +#### Gateway.Spec.Addresses changes +A new type `GatewaySpecAddress` replaces `GatewayAddress`. In `GatewayAddress` the `Value` field was required. In +`GatewaySpecAddress` the `Value` field is **optional**. When the `Value` is unspecified, if an implementation supports that, +it SHOULD automatically assign an address. If an implementation does not support an empty `Value`, it MUST set the +`Programmed` condition in status to false with a reason of "AddressNotAssigned". The `Addresses` field in +`Gateway.Spec` has changed from type `[]GatewayAddress` to `[]GatewaySpecAddress`. + +- Make the `value` field in `Gateway.Spec.Addresses` array optional ([#3616](https://github.com/kubernetes-sigs/gateway-api/pull/3616),[@EyalPazz](https://github.com/EyalPazz)) + +### Standard Channel Additions and Changes +The Standard channel is Gateway API's set of maximally-stable install files. +Only features with the best testing and support are added to the standard +channel. This channel should be considered GA or stable, and future changes will +be fully backwards compatible. + +#### Percentage-Based Request Mirroring 🎉 +This feature enhances the existing [request mirroring feature](https://gateway-api.sigs.k8s.io/guides/http-request-mirroring/) +by allowing users to specify a percentage of requests to be mirrored in both `HTTPRoute` +and `GRPCRoute` objects. + +This feature has graduated to Standard and is now considered GA or Stable. + +This feature's name for conformance tests (and GatewayClass status reporting) is +`HTTPRouteRequestPercentageMirror`. + +This feature's status is **Extended**, meaning that it is _optional_ for +implementations to support. If you're using Experimental Channel, you can refer +to the `supportedFeatures` field in the `status` of any GatewayClass. + +Relevant PRs: +- Promote percentage-based-request-mirroring GEP-3171 to standard ([#3638](https://github.com/kubernetes-sigs/gateway-api/pull/3638),[@LiorLieberman](https://github.com/LiorLieberman)) +- Add conformance tests for percentage-based request mirroring ([#3508](https://github.com/kubernetes-sigs/gateway-api/pull/3508),[@LiorLieberman](https://github.com/LiorLieberman)) + +### Experimental Channel Additions and Changes + +The Experimental Channel is Gateway API's channel for testing out changes and +gaining confidence with them before allowing them to go to Standard. + +**This channel may include features that are changed or removed later!** + +#### New experimental resources now start with "X" +This release introduces 2 new experimental resources: + +* XBackendTrafficPolicy +* XListenerSet + +Both of these resources are described in more detail below. As you may notice, +these resource names start with `X` and are part of an effort to distinguish +experimental channel resources from standard channel resources. + +In addition to the separate names, these resources are also part of the +`x-k8s.io` API group instead of `k8s.io`, as a further effort to signal the +experimental nature of these resources. + +In practice this means two things: + +1) These resources can coexist with standard channel resources +2) Migrating to standard channel will require recreating these resources with + the standard channel names and API Group (both lacking the "x" prefix) + +For more context on this change, refer to the [related discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/3497). + +#### CORS (Cross Origin Resource Sharing) Filter +[GEP-1767](https://gateway-api.sigs.k8s.io/geps/gep-1767/) describes how to add +configuration of CORS filters on HTTPRoute objects, and in this release, this change +has moved to Experimental. + +Please see the GEP reference document or the API reference for the details. + +This feature has graduated to Experimental and should now be used for testing +and verification purposes only. Experimental features may be changed or removed +in a future version. + +This feature does not currently have a feature name defined. + +This feature's status is **Extended**, meaning that it is _optional_ for +implementations to support. + +As there is no feature name or conformance testing available for this feature +yet, please check your implementation's documentation to see if it is supported. + +Relevant PRs: +- Implementing CORS Filter for `HTTPRoute` ([#3637](https://github.com/kubernetes-sigs/gateway-api/pull/3637),[@robscott](https://github.com/robscott)) +- Change `HTTPRouteFilter.CORS.AllowCredentials` to expect a boolean and not a string ([#3656](https://github.com/kubernetes-sigs/gateway-api/pull/3656),[@EyalPazz](https://github.com/EyalPazz)) +- Add CORS to `HTTPRouteFilterType` ([#3668](https://github.com/kubernetes-sigs/gateway-api/pull/3668),[@EyalPazz](https://github.com/EyalPazz)) + +#### XListenerSets (Standard Mechanism to Merge Gateways) +[GEP-1713](https://gateway-api.sigs.k8s.io/geps/gep-1713/) defines a new mechanism to merge listeners into a single +Gateway, and in this release, this change has moved to Experimental. Following a new naming convention, an +experimental object name is prefaced with an **X**, thus `ListenerSet` has changed to `XListenerSet`. +The object group name has changed from `gateway.networking.k8s.io` to `gateway.networking.x-k8s.io`. + +Please see the GEP reference document or the API reference for the details. + +This feature has graduated to Experimental and should now be used for testing +and verification purposes only. Experimental features may be changed or removed +in a future version. + +This feature does not currently have a feature name defined. + +This feature's status is **Extended**, meaning that it is _optional_ for +implementations to support. + +As there is no feature name or conformance testing available for this feature +yet, please check your implementation's documentation to see if it is supported. + +Relevant PRs: +- Clarified what it means for Gateway Listeners to be distinct ([#3477](https://github.com/kubernetes-sigs/gateway-api/pull/3477),[@youngnick](https://github.com/youngnick)) +- GEP-1713: Standard Mechanism to Merge Multiple Gateways ([#3213](https://github.com/kubernetes-sigs/gateway-api/pull/3213)),[@dprotaso](https://github.com/dprotaso)) +- Update GEP-1713 - Support attaching `ListenerSet`s across namespaces ([#3632](https://github.com/kubernetes-sigs/gateway-api/pull/3632),[@dprotaso](https://github.com/dprotaso)) +- GEP-1713: Standard Mechanism to Merge Multiple Gateways - move GEP Link to Experimental ([#3664](https://github.com/kubernetes-sigs/gateway-api/pull/3664)),[@gcs278](https://github.com/gcs278)) +- Refactor codegen scripts to make it easier to generate two clients ([#3589](https://github.com/kubernetes-sigs/gateway-api/pull/3589),[@dprotaso](https://github.com/dprotaso)) +- Add ListenerSet GEP-1713 to the website ([#3587](https://github.com/kubernetes-sigs/gateway-api/pull/3587),[@dprotaso](https://github.com/dprotaso)) +- Introduces `ListenerSet` API & Generate Clients (in the group gateway.networking.k8s-x.io) ([#3588](https://github.com/kubernetes-sigs/gateway-api/pull/3588),[@dprotaso](https://github.com/dprotaso)) +- The resource `ListenerSet` has been renamed to `XListenerSet`. The Resource `BackendTrafficPolicy` has been renamed to + `XBackendTrafficPolicy`. ([#3682](https://github.com/kubernetes-sigs/gateway-api/pull/3682),[@mlavacca](https://github.com/mlavacca)) + +#### XBackendTrafficPolicy (Retry Budgets) +[GEP-3388](https://gateway-api.sigs.k8s.io/geps/gep-3388/) +specifies the configuration of a "retry budget" across all endpoints of a destination service in order to prevent +additional client-side retries after reaching a configured threshold. The budget can be configured using a maximum +percentage of active requests, or an interval during which requests will be considered. In this release, this change has +moved to Experimental. Following a new naming convention, an experimental object name is prefaced with an **X**, thus +`BackendTrafficPolicy` has changed to `XBackendTrafficPolicy`. The object group name has changed from +`gateway.networking.k8s.io` to `gateway.networking.x-k8s.io`. + +Please see the GEP reference document or the API reference for the details. + +This feature has graduated to Experimental and should now be used for testing +and verification purposes only. Experimental features may be changed or removed +in a future version. + +This feature does not currently have a feature name defined. + +This feature's status is **Extended**, meaning that it is _optional_ for +implementations to support. + +As there is no feature name or conformance testing available for this feature +yet, please check your implementation's documentation to see if it is supported. + +Relevant PRs: +- Adds a new `BackendTrafficPolicy` with ability to configure budgeted retries ([#3607](https://github.com/kubernetes-sigs/gateway-api/pull/3607),[@ericdbishop](https://github.com/ericdbishop)) +- Add GEP-3388 HTTP Retry Budget ([#3488](https://github.com/kubernetes-sigs/gateway-api/pull/3488),[@ericdbishop](https://github.com/ericdbishop)) +- The resource `ListenerSet` has been renamed to `XListenerSet`. The Resource `BackendTrafficPolicy` has been renamed to + `XBackendTrafficPolicy`. ([#3682](https://github.com/kubernetes-sigs/gateway-api/pull/3682),[@mlavacca](https://github.com/mlavacca)) +- Retry budget fields are now in their own struct, moving from `budgetPercent` and `budgetInterval` to `budget.percent` + and `budget.interval` respectively. ([#3695](https://github.com/kubernetes-sigs/gateway-api/pull/3695),[@youngnick](https://github.com/youngnick)) + +#### BackendLBPolicy has been replaced by XBackendTrafficPolicy + +In the interest of combining similar concepts in a single policy, we've decided +to merge the contents of BackendLBPolicy (session persistence) into +XBackendTrafficPolicy (retry budgets). + +- BackendLBPolicy has been renamed to XBackendTrafficPolicy ([#3692](https://github.com/kubernetes-sigs/gateway-api/pull/3692),[@robscott](https://github.com/robscott)) + + +## GEPs +- Initial draft of Auth GEP-1494 ([#3500](https://github.com/kubernetes-sigs/gateway-api/pull/3500),[@youngnick](https://github.com/youngnick)) + +## Documentation +- For the Gateway infrastructure stanza, the `InvalidParameters` reason SHOULD be used with the `Accepted` condition in case the object referenced does not exist, is of an unsupported kind, or is malformed. ([#3579](https://github.com/kubernetes-sigs/gateway-api/pull/3579),[@mlavacca](https://github.com/mlavacca)) +- Specify default type for `sessionPersistence.cookieConfig.lifetimeType` ([#3540](https://github.com/kubernetes-sigs/gateway-api/pull/3540),[@arkodg](https://github.com/arkodg)) +- Updates docs for the Kuadrant implementation ([#3598](https://github.com/kubernetes-sigs/gateway-api/pull/3598),[@jasonmadigan](https://github.com/jasonmadigan)) +- Updates comparison of Gateway API and API Gateway to use the CNCF's definition of the latter ([#3653](https://github.com/kubernetes-sigs/gateway-api/pull/3653),[@craigbox](https://github.com/craigbox)) +- Fix 'mkdocs serve' endless build loop ([#3662](https://github.com/kubernetes-sigs/gateway-api/pull/3662),[@blake](https://github.com/blake)) +- Fix several MkDocs info and warning messages ([#3663](https://github.com/kubernetes-sigs/gateway-api/pull/3663),[@blake](https://github.com/blake)) +- Fix broken links and spelling ([#3655](https://github.com/kubernetes-sigs/gateway-api/pull/3655),[@blake](https://github.com/blake)), ([#3615](https://github.com/kubernetes-sigs/gateway-api/pull/3615),[@jsoref](https://github.com/jsoref)), +([#3657](https://github.com/kubernetes-sigs/gateway-api/pull/3657),[@blake](https://github.com/blake)), + ([#3400](https://github.com/kubernetes-sigs/gateway-api/pull/3400),[@jsoref](https://github.com/jsoref)), + ([#3626](https://github.com/kubernetes-sigs/gateway-api/pull/3626),[@zirain](https://github.com/zirain)), + ([#3565](https://github.com/kubernetes-sigs/gateway-api/pull/3565/files),[@Vaniog](https://github.com/Vaniog)), + ([#3485](https://github.com/kubernetes-sigs/gateway-api/pull/3485),[@fatsheep9146](https://github.com/fatsheep9146)) +- GRPCRoute name is not set ([#3639](https://github.com/kubernetes-sigs/gateway-api/pull/3639),[@Xunhuo](https://github.com/Xunzhuo)) +- Update GEPs in navbar ([#3634](https://github.com/kubernetes-sigs/gateway-api/pull/3634),[@blake](https://github.com/blake)) +- Remove experimental callout on GRPCRoute guide ([#3595](https://github.com/kubernetes-sigs/gateway-api/pull/3595),[@blake](https://github.com/blake)) +- Fix GRPCRoute structure definition error in the document ([#3344](https://github.com/kubernetes-sigs/gateway-api/pull/3344),[@0xff-dev](https://github.com/0xff-dev)) +- Add Gateway For Mesh section to the GEP template ([#3577](https://github.com/kubernetes-sigs/gateway-api/pull/3577),[@LiorLieberman](https://github.com/LiorLieberman)) +- Fix group description in `LocalObjectReference` (empty string infers core API group) ([#3597](https://github.com/kubernetes-sigs/gateway-api/pull/3597),[@EyalPazz](https://github.com/EyalPazz)) +- Remove "experimental" language from gamma implementations ([#3580](https://github.com/kubernetes-sigs/gateway-api/pull/3580),[@LiorLieberman](https://github.com/LiorLieberman)) +- Clarify frontend/backend relationship in GEP-91 ([#3571](https://github.com/kubernetes-sigs/gateway-api/pull/3571),[@htuch](https://github.com/htuch)) + +## Cleanup +- Remove mkdocs-material-extensions from requirements.txt ([#3666](https://github.com/kubernetes-sigs/gateway-api/pull/3666), [@gcs278](https://github.com/gcs278)) +- Remove extra newlines and format descriptions of items for code generation ([#3574](https://github.com/kubernetes-sigs/gateway-api/pull/3574),[@snorwin](https://github.com/snorwin)) +- Fix mkdocs so at least 3 conformance reports are uploaded before update ([#3549](https://github.com/kubernetes-sigs/gateway-api/pull/3549),[@xtineskim](https://github.com/xtineskim)) +- Dependencies have been upgraded to Kubernetes v1.32 and Go v1.24 ([#3697](https://github.com/kubernetes-sigs/gateway-api/pull/3697),[@robscott](https://github.com/robscott)) + +## Bug or Regression +- Sort api versions when updating clientset during code generation ([#3652](https://github.com/kubernetes-sigs/gateway-api/pull/3652),[@bentheelder](https://github.com/BenTheElder)) +- Retry failed calls when waiting for namespace ready in tests ([#3627](https://github.com/kubernetes-sigs/gateway-api/pull/3627),[@aojea](https://github.com/aojea)) +- Some tests are not formatted properly ([#3610](https://github.com/kubernetes-sigs/gateway-api/pull/3610),[@EyalPazz](https://github.com/EyalPazz)) +- Doesn't allow a user to provide both an asterisk and another method/s along with it in `HTTPCORSFilter.AllowMethods` + ([#3667](https://github.com/kubernetes-sigs/gateway-api/pull/3667),[@EyalPazz](https://github.com/EyalPazz)) + +## Dependencies + +### Added +- github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp: [v1.25.0](https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/tree/detectors/gcp/v1.25.0) +- github.com/Masterminds/goutils: [v1.1.1](https://github.com/Masterminds/goutils/tree/v1.1.1) +- github.com/Masterminds/semver: [v1.5.0](https://github.com/Masterminds/semver/tree/v1.5.0) +- github.com/Masterminds/sprig: [v2.22.0+incompatible](https://github.com/Masterminds/sprig/tree/v2.22.0) +- github.com/elastic/crd-ref-docs: [v0.1.0](https://github.com/elastic/crd-ref-docs/tree/v0.1.0) +- github.com/envoyproxy/go-control-plane/envoy: [v1.32.4](https://github.com/envoyproxy/go-control-plane/tree/envoy/v1.32.4) +- github.com/envoyproxy/go-control-plane/ratelimit: [v0.1.0](https://github.com/envoyproxy/go-control-plane/tree/ratelimit/v0.1.0) +- github.com/go-playground/locales: [v0.13.0](https://github.com/go-playground/locales/tree/v0.13.0) +- github.com/go-playground/universal-translator: [v0.17.0](https://github.com/go-playground/universal-translator/tree/v0.17.0) +- github.com/go-playground/validator/v10: [v10.4.1](https://github.com/go-playground/validator/tree/v10.4.1) +- github.com/goccy/go-yaml: [v1.11.3](https://github.com/goccy/go-yaml/tree/v1.11.3) +- github.com/huandu/xstrings: [v1.3.3](https://github.com/huandu/xstrings/tree/v1.3.3) +- github.com/leodido/go-urn: [v1.2.0](https://github.com/leodido/go-urn/tree/v1.2.0) +- github.com/mitchellh/copystructure: [v1.2.0](https://github.com/mitchellh/copystructure/tree/v1.2.0) +- github.com/mitchellh/reflectwalk: [v1.0.2](https://github.com/mitchellh/reflectwalk/tree/v1.0.2) +- go.opentelemetry.io/auto/sdk: v1.1.0 +- go.opentelemetry.io/contrib/detectors/gcp: v1.34.0 +- go.opentelemetry.io/otel/sdk/metric: v1.34.0 + +### Changed +- cel.dev/expr: v0.16.0 → v0.19.1 +- cloud.google.com/go/compute/metadata: v0.5.0 → v0.6.0 +- github.com/cncf/xds/go: [024c85f → cff3c89](https://github.com/cncf/xds/compare/024c85f...cff3c89) +- github.com/envoyproxy/go-control-plane: [v0.13.0 → v0.13.4](https://github.com/envoyproxy/go-control-plane/compare/v0.13.0...v0.13.4) +- github.com/envoyproxy/protoc-gen-validate: [v1.1.0 → v1.2.1](https://github.com/envoyproxy/protoc-gen-validate/compare/v1.1.0...v1.2.1) +- github.com/evanphx/json-patch/v5: [v5.9.0 → v5.9.11](https://github.com/evanphx/json-patch/compare/v5.9.0...v5.9.11) +- github.com/golang/glog: [v1.2.2 → v1.2.4](https://github.com/golang/glog/compare/v1.2.2...v1.2.4) +- github.com/google/btree: [v1.0.1 → v1.1.3](https://github.com/google/btree/compare/v1.0.1...v1.1.3) +- github.com/google/cel-go: [v0.20.1 → v0.22.0](https://github.com/google/cel-go/compare/v0.20.1...v0.22.0) +- github.com/google/pprof: [4bfdf5a → d1b30fe](https://github.com/google/pprof/compare/4bfdf5a...d1b30fe) +- github.com/gregjones/httpcache: [9cad4c3 → 901d907](https://github.com/gregjones/httpcache/compare/9cad4c3...901d907) +- github.com/imdario/mergo: [v0.3.16 → v0.3.11](https://github.com/imdario/mergo/compare/v0.3.16...v0.3.11) +- github.com/jessevdk/go-flags: [v1.4.0 → v1.6.1](https://github.com/jessevdk/go-flags/compare/v1.4.0...v1.6.1) +- github.com/jonboulle/clockwork: [v0.2.2 → v0.4.0](https://github.com/jonboulle/clockwork/compare/v0.2.2...v0.4.0) +- github.com/miekg/dns: [v1.1.62 → v1.1.64](https://github.com/miekg/dns/compare/v1.1.62...v1.1.64) +- github.com/moby/spdystream: [v0.4.0 → v0.5.0](https://github.com/moby/spdystream/compare/v0.4.0...v0.5.0) +- github.com/onsi/ginkgo/v2: [v2.19.0 → v2.22.0](https://github.com/onsi/ginkgo/compare/v2.19.0...v2.22.0) +- github.com/onsi/gomega: [v1.34.2 → v1.36.2](https://github.com/onsi/gomega/compare/v1.34.2...v1.36.2) +- github.com/spf13/pflag: [v1.0.5 → v1.0.6](https://github.com/spf13/pflag/compare/v1.0.5...v1.0.6) +- github.com/stoewer/go-strcase: [v1.2.0 → v1.3.0](https://github.com/stoewer/go-strcase/compare/v1.2.0...v1.3.0) +- github.com/xiang90/probing: [43a291a → a49e3df](https://github.com/xiang90/probing/compare/43a291a...a49e3df) +- go.etcd.io/bbolt: v1.3.9 → v1.3.11 +- go.etcd.io/etcd/api/v3: v3.5.14 → v3.5.16 +- go.etcd.io/etcd/client/pkg/v3: v3.5.14 → v3.5.16 +- go.etcd.io/etcd/client/v2: v2.305.13 → v2.305.16 +- go.etcd.io/etcd/client/v3: v3.5.14 → v3.5.16 +- go.etcd.io/etcd/pkg/v3: v3.5.13 → v3.5.16 +- go.etcd.io/etcd/raft/v3: v3.5.13 → v3.5.16 +- go.etcd.io/etcd/server/v3: v3.5.13 → v3.5.16 +- go.opentelemetry.io/otel/metric: v1.28.0 → v1.34.0 +- go.opentelemetry.io/otel/sdk: v1.28.0 → v1.34.0 +- go.opentelemetry.io/otel/trace: v1.28.0 → v1.34.0 +- go.opentelemetry.io/otel: v1.28.0 → v1.34.0 +- go.uber.org/zap: v1.26.0 → v1.27.0 +- golang.org/x/crypto: v0.29.0 → v0.33.0 +- golang.org/x/exp: fe59bbe → 8a7402a +- golang.org/x/mod: v0.21.0 → v0.23.0 +- golang.org/x/net: v0.31.0 → v0.35.0 +- golang.org/x/oauth2: v0.22.0 → v0.25.0 +- golang.org/x/sync: v0.9.0 → v0.11.0 +- golang.org/x/sys: v0.27.0 → v0.30.0 +- golang.org/x/term: v0.26.0 → v0.29.0 +- golang.org/x/text: v0.20.0 → v0.22.0 +- golang.org/x/time: v0.5.0 → v0.7.0 +- golang.org/x/tools: v0.26.0 → v0.30.0 +- golang.org/x/xerrors: 04be3eb → 104605a +- google.golang.org/genproto: b8732ec → ef43131 +- google.golang.org/genproto/googleapis/api: ddb44da → 5f5ef82 +- google.golang.org/genproto/googleapis/rpc: ddb44da → 1a7da9e +- google.golang.org/grpc: v1.67.1 → v1.71.0 +- google.golang.org/protobuf: v1.35.2 → v1.36.5 +- k8s.io/api: v0.31.3 → v0.32.2 +- k8s.io/apiextensions-apiserver: v0.31.3 → v0.32.2 +- k8s.io/apimachinery: v0.31.3 → v0.32.2 +- k8s.io/apiserver: v0.31.3 → v0.32.2 +- k8s.io/client-go: v0.31.3 → v0.32.2 +- k8s.io/code-generator: v0.31.3 → v0.32.2 +- k8s.io/component-base: v0.31.3 → v0.32.2 +- k8s.io/gengo/v2: 51d4e06 → 2b36238 +- k8s.io/kms: v0.31.3 → v0.32.2 + k8s.io/kube-openapi: 8948a66 → 32ad38e +- k8s.io/utils: 18e509b → 3ea5e8c +- sigs.k8s.io/apiserver-network-proxy/konnectivity-client: v0.30.3 → v0.31.0 +- sigs.k8s.io/controller-runtime: v0.19.1 → v0.20.3 +- sigs.k8s.io/controller-tools: v0.16.5 → v0.17.2 +- sigs.k8s.io/json: bc3834c → 9aa6b5e +- sigs.k8s.io/structured-merge-diff/v4: v4.4.3 → v4.5.0 + +### Removed +- github.com/ahmetb/gen-crd-api-reference-docs: [v0.3.0](https://github.com/ahmetb/gen-crd-api-reference-docs/tree/v0.3.0) +- github.com/census-instrumentation/opencensus-proto: [v0.4.1](https://github.com/census-instrumentation/opencensus-proto/tree/v0.4.1) +- github.com/golang/groupcache: [41bb18b](https://github.com/golang/groupcache/tree/41bb18b) +- github.com/kr/pty: [v1.1.1](https://github.com/kr/pty/tree/v1.1.1) +- github.com/shurcooL/sanitized_anchor_name: [v1.0.0](https://github.com/shurcooL/sanitized_anchor_name/tree/v1.0.0) +- k8s.io/gengo: 9cce18d +- k8s.io/klog: v0.2.0 # v1.3.0-rc.2 - _start-sha: b316db57e63e9a58058880982750dc035a347d6_ @@ -42,6 +370,7 @@ changes since v1.3.0-rc.1: * Small clarification to HTTPRouteMatch rules ([#3741](https://github.com/kubernetes-sigs/gateway-api/pull/3741),[@vehagn](https://github.com/vehagn)) + # v1.3.0-rc.1 - _start-sha: 066411e5d45ea58c954bc144b88f82f534355a63_ - _end-sha: b316db57e63e9a58058880982750dc035a347d6_ diff --git a/README.md b/README.md index 7f4151a352..3dbd66b39e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ the specification and Custom Resource Definitions (CRDs). ## Status The latest supported version is `v1` as released by -the [v1.2.1 release][gh_release] of this project. +the [v1.3.0 release][gh_release] of this project. This version of the API is has GA level support for the following resources: diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index 8aab2a18d3..6a9e653a31 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index 1da5bbcb5f..831fbf4a8f 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 957e9c74d0..328999eee9 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index c33c73688d..9e8dd64201 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 91ddaae7fa..9f5f93d222 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: httproutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index 7d9c6ad526..a4952e39a6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: referencegrants.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index f7bede5cc6..7365304e2a 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 9d9ad41da4..eaac6b6692 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 69858dff0f..5ef205c1d2 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: udproutes.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 2fddbe9bb5..a4674dec56 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null labels: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 0e5b501e8c..5176322413 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: xlistenersets.gateway.networking.x-k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 98d1e56ca2..9268f6f173 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index a4227cfd87..2952481bdb 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: gateways.gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 3bd6a4a2d6..3bbc0af4ca 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 936f55bbbd..7f3b970a7a 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: httproutes.gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index 61892b85b8..da71ceaac4 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard creationTimestamp: null name: referencegrants.gateway.networking.k8s.io diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 8e9de4d163..3ef3980581 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -27,7 +27,7 @@ const ( // BundleVersion is the value used for the "gateway.networking.k8s.io/bundle-version" annotation. // These value must be updated during the release process. - BundleVersion = "v1.3.0-rc.2" + BundleVersion = "v1.3.0" // ApprovalLink is the value used for the "api-approved.kubernetes.io" annotation. // These value must be updated during the release process. diff --git a/site-src/guides/index.md b/site-src/guides/index.md index ac1a14a7b8..21fbe942b1 100644 --- a/site-src/guides/index.md +++ b/site-src/guides/index.md @@ -45,7 +45,7 @@ beta, including GatewayClass, Gateway, HTTPRoute, and ReferenceGrant. To install this channel, run the following kubectl command: ```bash -kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml ``` ### Install Experimental Channel @@ -63,7 +63,7 @@ documentation](../concepts/versioning.md). To install the experimental channel, run the following kubectl command: ```bash -kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/experimental-install.yaml ``` ### v1.2 Upgrade Notes From 1e14dd602df6c0bad62c0e7f83dd2c7d1d2d6886 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Thu, 24 Apr 2025 14:42:35 -0700 Subject: [PATCH 006/224] add mesh conformance tests structure and a first test (#3729) * add mesh confomance tests structure and first test * move mesh tests to mesh folder --- conformance/tests/main.go | 8 +- .../tests/mesh/httproute-rewrite-path.go | 155 ++++++++++++++++++ .../tests/mesh/httproute-rewrite-path.yaml | 101 ++++++++++++ conformance/tests/mesh/main.go | 21 +++ conformance/tests/{ => mesh}/mesh-basic.go | 4 +- .../tests/{ => mesh}/mesh-consumer-route.go | 6 +- .../tests/{ => mesh}/mesh-consumer-route.yaml | 0 .../{ => mesh}/mesh-frontend-hostname.go | 6 +- conformance/tests/{ => mesh}/mesh-frontend.go | 6 +- .../tests/{ => mesh}/mesh-frontend.yaml | 0 conformance/tests/{ => mesh}/mesh-ports.go | 6 +- conformance/tests/{ => mesh}/mesh-ports.yaml | 0 conformance/tests/{ => mesh}/mesh-split.go | 6 +- conformance/tests/{ => mesh}/mesh-split.yaml | 0 conformance/utils/echo/pod.go | 8 + pkg/features/mesh.go | 9 + 16 files changed, 317 insertions(+), 19 deletions(-) create mode 100644 conformance/tests/mesh/httproute-rewrite-path.go create mode 100644 conformance/tests/mesh/httproute-rewrite-path.yaml create mode 100644 conformance/tests/mesh/main.go rename conformance/tests/{ => mesh}/mesh-basic.go (95%) rename conformance/tests/{ => mesh}/mesh-consumer-route.go (94%) rename conformance/tests/{ => mesh}/mesh-consumer-route.yaml (100%) rename conformance/tests/{ => mesh}/mesh-frontend-hostname.go (94%) rename conformance/tests/{ => mesh}/mesh-frontend.go (94%) rename conformance/tests/{ => mesh}/mesh-frontend.yaml (100%) rename conformance/tests/{ => mesh}/mesh-ports.go (95%) rename conformance/tests/{ => mesh}/mesh-ports.yaml (100%) rename conformance/tests/{ => mesh}/mesh-split.go (93%) rename conformance/tests/{ => mesh}/mesh-split.yaml (100%) diff --git a/conformance/tests/main.go b/conformance/tests/main.go index 7cbcebc27f..4dc3775b27 100644 --- a/conformance/tests/main.go +++ b/conformance/tests/main.go @@ -16,6 +16,10 @@ limitations under the License. package tests -import "sigs.k8s.io/gateway-api/conformance/utils/suite" +import ( + "slices" -var ConformanceTests []suite.ConformanceTest + meshtests "sigs.k8s.io/gateway-api/conformance/tests/mesh" +) + +var ConformanceTests = slices.Clone(meshtests.MeshConformanceTests) diff --git a/conformance/tests/mesh/httproute-rewrite-path.go b/conformance/tests/mesh/httproute-rewrite-path.go new file mode 100644 index 0000000000..79416a96c8 --- /dev/null +++ b/conformance/tests/mesh/httproute-rewrite-path.go @@ -0,0 +1,155 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteRewritePath) +} + +var MeshHTTPRouteRewritePath = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteRewritePath", + Description: "An HTTPRoute with path rewrite filter", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportMeshHTTPRouteRewritePath, + features.SupportHTTPRoute, + }, + Manifests: []string{"tests/mesh/httproute-rewrite-path.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + cases := []http.ExpectedResponse{ + { + Request: http.Request{ + Path: "/prefix/one/two", + Host: "echo", + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/one/two", + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{ + Path: "/strip-prefix/three", + Host: "echo", + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/three", + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{ + Path: "/strip-prefix", + Host: "echo", + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/", + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{ + Path: "/full/one/two", + Host: "echo", + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/one", + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{ + Host: "echo", + Path: "/full/rewrite-path-and-modify-headers/test", + Headers: map[string]string{ + "X-Header-Remove": "remove-val", + "X-Header-Add-Append": "append-val-1", + "X-Header-Set": "set-val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/test", + Headers: map[string]string{ + "X-Header-Add": "header-val-1", + "X-Header-Add-Append": "append-val-1,header-val-2", + "X-Header-Set": "set-overwrites-values", + }, + }, + AbsentHeaders: []string{"X-Header-Remove"}, + }, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{ + Host: "echo", + Path: "/prefix/rewrite-path-and-modify-headers/one", + Headers: map[string]string{ + "X-Header-Remove": "remove-val", + "X-Header-Add-Append": "append-val-1", + "X-Header-Set": "set-val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/prefix/one", + Headers: map[string]string{ + "X-Header-Add": "header-val-1", + "X-Header-Add-Append": "append-val-1,header-val-2", + "X-Header-Set": "set-overwrites-values", + }, + }, + AbsentHeaders: []string{"X-Header-Remove"}, + }, + Backend: "echo-v1", + Namespace: ns, + }, + } + for i := range cases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := cases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-rewrite-path.yaml b/conformance/tests/mesh/httproute-rewrite-path.yaml new file mode 100644 index 0000000000..8186746f39 --- /dev/null +++ b/conformance/tests/mesh/httproute-rewrite-path.yaml @@ -0,0 +1,101 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-rewrite-path + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /prefix/one + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /one + backendRefs: + - name: echo-v1 + port: 80 + - matches: + - path: + type: PathPrefix + value: /strip-prefix + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + backendRefs: + - name: echo-v1 + port: 80 + - matches: + - path: + type: PathPrefix + value: /full/one + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplaceFullPath + replaceFullPath: /one + backendRefs: + - name: echo-v1 + port: 80 + - matches: + - path: + type: PathPrefix + value: /full/rewrite-path-and-modify-headers + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplaceFullPath + replaceFullPath: /test + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: set-overwrites-values + add: + - name: X-Header-Add + value: header-val-1 + - name: X-Header-Add-Append + value: header-val-2 + remove: + - X-Header-Remove + backendRefs: + - name: echo-v1 + port: 80 + - matches: + - path: + type: PathPrefix + value: /prefix/rewrite-path-and-modify-headers + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /prefix + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: set-overwrites-values + add: + - name: X-Header-Add + value: header-val-1 + - name: X-Header-Add-Append + value: header-val-2 + remove: + - X-Header-Remove + backendRefs: + - name: echo-v1 + port: 80 diff --git a/conformance/tests/mesh/main.go b/conformance/tests/mesh/main.go new file mode 100644 index 0000000000..9e9c87bd58 --- /dev/null +++ b/conformance/tests/mesh/main.go @@ -0,0 +1,21 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import "sigs.k8s.io/gateway-api/conformance/utils/suite" + +var MeshConformanceTests []suite.ConformanceTest diff --git a/conformance/tests/mesh-basic.go b/conformance/tests/mesh/mesh-basic.go similarity index 95% rename from conformance/tests/mesh-basic.go rename to conformance/tests/mesh/mesh-basic.go index ad878f3a48..377adce34e 100644 --- a/conformance/tests/mesh-basic.go +++ b/conformance/tests/mesh/mesh-basic.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshBasic) + MeshConformanceTests = append(MeshConformanceTests, MeshBasic) } var MeshBasic = suite.ConformanceTest{ diff --git a/conformance/tests/mesh-consumer-route.go b/conformance/tests/mesh/mesh-consumer-route.go similarity index 94% rename from conformance/tests/mesh-consumer-route.go rename to conformance/tests/mesh/mesh-consumer-route.go index 0bc4cfe522..e072ec1d27 100644 --- a/conformance/tests/mesh-consumer-route.go +++ b/conformance/tests/mesh/mesh-consumer-route.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshConsumerRoute) + MeshConformanceTests = append(MeshConformanceTests, MeshConsumerRoute) } var MeshConsumerRoute = suite.ConformanceTest{ @@ -38,7 +38,7 @@ var MeshConsumerRoute = suite.ConformanceTest{ features.SupportHTTPRoute, features.SupportHTTPRouteResponseHeaderModification, }, - Manifests: []string{"tests/mesh-consumer-route.yaml"}, + Manifests: []string{"tests/mesh/mesh-consumer-route.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { consumerClient := echo.ConnectToAppInNamespace(t, s, echo.MeshAppEchoV1, "gateway-conformance-mesh-consumer") consumerCases := []http.ExpectedResponse{ diff --git a/conformance/tests/mesh-consumer-route.yaml b/conformance/tests/mesh/mesh-consumer-route.yaml similarity index 100% rename from conformance/tests/mesh-consumer-route.yaml rename to conformance/tests/mesh/mesh-consumer-route.yaml diff --git a/conformance/tests/mesh-frontend-hostname.go b/conformance/tests/mesh/mesh-frontend-hostname.go similarity index 94% rename from conformance/tests/mesh-frontend-hostname.go rename to conformance/tests/mesh/mesh-frontend-hostname.go index 5d5e825e8a..097d3556dc 100644 --- a/conformance/tests/mesh-frontend-hostname.go +++ b/conformance/tests/mesh/mesh-frontend-hostname.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshFrontendHostname) + MeshConformanceTests = append(MeshConformanceTests, MeshFrontendHostname) } var MeshFrontendHostname = suite.ConformanceTest{ @@ -38,7 +38,7 @@ var MeshFrontendHostname = suite.ConformanceTest{ features.SupportHTTPRoute, features.SupportHTTPRouteResponseHeaderModification, }, - Manifests: []string{"tests/mesh-frontend.yaml"}, + Manifests: []string{"tests/mesh/mesh-frontend.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ diff --git a/conformance/tests/mesh-frontend.go b/conformance/tests/mesh/mesh-frontend.go similarity index 94% rename from conformance/tests/mesh-frontend.go rename to conformance/tests/mesh/mesh-frontend.go index 87b3c3437b..eb6c715243 100644 --- a/conformance/tests/mesh-frontend.go +++ b/conformance/tests/mesh/mesh-frontend.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshFrontend) + MeshConformanceTests = append(MeshConformanceTests, MeshFrontend) } var MeshFrontend = suite.ConformanceTest{ @@ -37,7 +37,7 @@ var MeshFrontend = suite.ConformanceTest{ features.SupportHTTPRoute, features.SupportHTTPRouteResponseHeaderModification, }, - Manifests: []string{"tests/mesh-frontend.yaml"}, + Manifests: []string{"tests/mesh/mesh-frontend.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) v2 := echo.ConnectToApp(t, s, echo.MeshAppEchoV2) diff --git a/conformance/tests/mesh-frontend.yaml b/conformance/tests/mesh/mesh-frontend.yaml similarity index 100% rename from conformance/tests/mesh-frontend.yaml rename to conformance/tests/mesh/mesh-frontend.yaml diff --git a/conformance/tests/mesh-ports.go b/conformance/tests/mesh/mesh-ports.go similarity index 95% rename from conformance/tests/mesh-ports.go rename to conformance/tests/mesh/mesh-ports.go index 67ebc21cef..2dfde3285e 100644 --- a/conformance/tests/mesh-ports.go +++ b/conformance/tests/mesh/mesh-ports.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshPorts) + MeshConformanceTests = append(MeshConformanceTests, MeshPorts) } var MeshPorts = suite.ConformanceTest{ @@ -38,7 +38,7 @@ var MeshPorts = suite.ConformanceTest{ features.SupportHTTPRouteParentRefPort, features.SupportHTTPRouteResponseHeaderModification, }, - Manifests: []string{"tests/mesh-ports.yaml"}, + Manifests: []string{"tests/mesh/mesh-ports.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ diff --git a/conformance/tests/mesh-ports.yaml b/conformance/tests/mesh/mesh-ports.yaml similarity index 100% rename from conformance/tests/mesh-ports.yaml rename to conformance/tests/mesh/mesh-ports.yaml diff --git a/conformance/tests/mesh-split.go b/conformance/tests/mesh/mesh-split.go similarity index 93% rename from conformance/tests/mesh-split.go rename to conformance/tests/mesh/mesh-split.go index 0864bbe378..dcb80ef90f 100644 --- a/conformance/tests/mesh-split.go +++ b/conformance/tests/mesh/mesh-split.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package tests +package meshtests import ( "testing" @@ -26,7 +26,7 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, MeshTrafficSplit) + MeshConformanceTests = append(MeshConformanceTests, MeshTrafficSplit) } var MeshTrafficSplit = suite.ConformanceTest{ @@ -36,7 +36,7 @@ var MeshTrafficSplit = suite.ConformanceTest{ features.SupportMesh, features.SupportHTTPRoute, }, - Manifests: []string{"tests/mesh-split.yaml"}, + Manifests: []string{"tests/mesh/mesh-split.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) cases := []http.ExpectedResponse{ diff --git a/conformance/tests/mesh-split.yaml b/conformance/tests/mesh/mesh-split.yaml similarity index 100% rename from conformance/tests/mesh-split.yaml rename to conformance/tests/mesh/mesh-split.yaml diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index f61d843744..24d0442945 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -57,6 +57,14 @@ const ( func (m *MeshPod) MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, exp http.ExpectedResponse, timeoutConfig config.TimeoutConfig) { t.Helper() + if exp.Request.Method == "" { + exp.Request.Method = "GET" + } + + if exp.Response.StatusCode == 0 { + exp.Response.StatusCode = 200 + } + http.AwaitConvergence(t, timeoutConfig.RequiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency, func(elapsed time.Duration) bool { req := makeRequest(t, exp.Request) diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index b52a7dff93..711681c58c 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -48,6 +48,8 @@ const ( SupportMeshClusterIPMatching FeatureName = "MeshClusterIPMatching" // This option indicates support for "consumer" routes, where a namespace creates a route for a service in another namespace. SupportMeshConsumerRoute FeatureName = "MeshConsumerRoute" + // This option indicates mesh support for HTTPRoute path rewrite (extended conformance) + SupportMeshHTTPRouteRewritePath FeatureName = "MeshHTTPRouteRewritePath" ) var ( @@ -61,6 +63,12 @@ var ( Name: SupportMeshConsumerRoute, Channel: FeatureChannelStandard, } + + // MeshHTTPRouteRewritePath contains metadata for the MeshHTTPRouteRewritePath feature. + MeshHTTPRouteRewritePath = Feature{ + Name: SupportMeshHTTPRouteRewritePath, + Channel: FeatureChannelStandard, + } ) // MeshExtendedFeatures includes all the supported features for the service mesh at @@ -68,4 +76,5 @@ var ( var MeshExtendedFeatures = sets.New( MeshClusterIPMatchingFeature, MeshConsumerRouteFeature, + MeshHTTPRouteRewritePath, ) From 983ce8afa758bf3007490e2dc55a61de2f0fc8dc Mon Sep 17 00:00:00 2001 From: Sergei Zviagintsev <10072335+szviagintsev@users.noreply.github.com> Date: Fri, 9 May 2025 03:15:14 +0200 Subject: [PATCH 007/224] Fix v1.3.0 release URL in README.md (#3782) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3dbd66b39e..e8ebd1ad5b 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Participation in the Kubernetes community is governed by the [spec]: https://gateway-api.sigs.k8s.io/reference/spec/ [concepts]: https://gateway-api.sigs.k8s.io/concepts/api-overview [security-model]: https://gateway-api.sigs.k8s.io/concepts/security-model -[gh_release]: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.2.1 +[gh_release]: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.3.0 [godoc]: https://pkg.go.dev/sigs.k8s.io/gateway-api [conformance-docs]: https://gateway-api.sigs.k8s.io/concepts/conformance/ [reports-readme]: ./conformance/reports/README.md From 2cb99f3a25421756f852aae6464e84a2e93e6274 Mon Sep 17 00:00:00 2001 From: Jonathan Stacks Date: Thu, 8 May 2025 20:39:14 -0500 Subject: [PATCH 008/224] docs: Update HTTPRoute status example (#3784) --- site-src/api-types/httproute.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-src/api-types/httproute.md b/site-src/api-types/httproute.md index a1e051ab8a..c9d96deef1 100644 --- a/site-src/api-types/httproute.md +++ b/site-src/api-types/httproute.md @@ -322,7 +322,7 @@ metadata: ... status: parents: - - parentRefs: + - parentRef: name: gw-example namespace: gw-example-ns conditions: From 344f8de09c63f03077743df802888d22e78712fe Mon Sep 17 00:00:00 2001 From: "naruse (poko)" <62323683+naruse666@users.noreply.github.com> Date: Mon, 12 May 2025 13:09:15 +0900 Subject: [PATCH 009/224] rm duplicate explanation (#3780) --- site-src/guides/http-header-modifier.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/site-src/guides/http-header-modifier.md b/site-src/guides/http-header-modifier.md index a55e2b86d4..1118124e00 100644 --- a/site-src/guides/http-header-modifier.md +++ b/site-src/guides/http-header-modifier.md @@ -1,7 +1,5 @@ # HTTP Header Modifiers -[HTTPRoute resources](../api-types/httproute.md) can modify the headers of HTTP requests and the HTTP responses from clients. -There are two types of [filters](../api-types/httproute.md#filters-optional) available to meet these requirements: `RequestHeaderModifier` and `ResponseHeaderModifier`. [HTTPRoute resources](../api-types/httproute.md) can modify the headers of HTTP requests and the HTTP responses from clients. There are two types of [filters](../api-types/httproute.md#filters-optional) available to meet these requirements: `RequestHeaderModifier` and `ResponseHeaderModifier`. From c698f24b49f80a50d371e61b47971ed3ecf01619 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Tue, 13 May 2025 18:43:16 -0700 Subject: [PATCH 010/224] Add mesh conformance tests for httproute path host and status redirect (#3777) * add redirect-port and redirect scheme mesh tests * mesh tests for path host and status redirect --- .../httproute-redirect-host-and-status.go | 84 +++++++++++ .../httproute-redirect-host-and-status.yaml | 30 ++++ .../tests/mesh/httproute-redirect-path.go | 139 ++++++++++++++++++ .../tests/mesh/httproute-redirect-path.yaml | 76 ++++++++++ .../tests/mesh/httproute-redirect-port.go | 113 ++++++++++++++ .../tests/mesh/httproute-redirect-port.yaml | 48 ++++++ .../tests/mesh/httproute-redirect-scheme.go | 116 +++++++++++++++ .../tests/mesh/httproute-redirect-scheme.yaml | 49 ++++++ .../tests/mesh/httproute-rewrite-path.go | 2 +- pkg/features/mesh.go | 26 ++++ 10 files changed, 682 insertions(+), 1 deletion(-) create mode 100644 conformance/tests/mesh/httproute-redirect-host-and-status.go create mode 100644 conformance/tests/mesh/httproute-redirect-host-and-status.yaml create mode 100644 conformance/tests/mesh/httproute-redirect-path.go create mode 100644 conformance/tests/mesh/httproute-redirect-path.yaml create mode 100644 conformance/tests/mesh/httproute-redirect-port.go create mode 100644 conformance/tests/mesh/httproute-redirect-port.yaml create mode 100644 conformance/tests/mesh/httproute-redirect-scheme.go create mode 100644 conformance/tests/mesh/httproute-redirect-scheme.yaml diff --git a/conformance/tests/mesh/httproute-redirect-host-and-status.go b/conformance/tests/mesh/httproute-redirect-host-and-status.go new file mode 100644 index 0000000000..055b70a256 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-host-and-status.go @@ -0,0 +1,84 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteRedirectHostAndStatus) +} + +var MeshHTTPRouteRedirectHostAndStatus = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteRedirectHostAndStatus", + Description: "An HTTPRoute with hostname and statusCode redirect filters", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + }, + Manifests: []string{"tests/mesh/httproute-redirect-host-and-status.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Host: "echo", + Path: "/hostname-redirect", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/host-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 301, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + }, + Namespace: ns, + }, + } + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-redirect-host-and-status.yaml b/conformance/tests/mesh/httproute-redirect-host-and-status.yaml new file mode 100644 index 0000000000..8bb2779800 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-host-and-status.yaml @@ -0,0 +1,30 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-redirect-host-and-status + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /hostname-redirect + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.org + - matches: + - path: + type: PathPrefix + value: /host-and-status + filters: + - type: RequestRedirect + requestRedirect: + statusCode: 301 + hostname: example.org + diff --git a/conformance/tests/mesh/httproute-redirect-path.go b/conformance/tests/mesh/httproute-redirect-path.go new file mode 100644 index 0000000000..bc4731e7a0 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-path.go @@ -0,0 +1,139 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteRedirectPath) +} + +var MeshHTTPRouteRedirectPath = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteRedirectPath", + Description: "An HTTPRoute with scheme redirect filter", + Manifests: []string{"tests/mesh/httproute-redirect-path.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteRedirectPath, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Host: "echo", + Path: "/original-prefix/lemon", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Path: "/replacement-prefix/lemon", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/full/path/original", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Path: "/full-path-replacement", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/path-and-host", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + Path: "/replacement-prefix", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/path-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 301, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Path: "/replacement-prefix", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/full-path-and-host", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + Path: "/replacement-full", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/full-path-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 301, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Path: "/replacement-full", + }, + Namespace: ns, + }, + } + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-redirect-path.yaml b/conformance/tests/mesh/httproute-redirect-path.yaml new file mode 100644 index 0000000000..05975f32a3 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-path.yaml @@ -0,0 +1,76 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-redirect-path + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /original-prefix + filters: + - type: RequestRedirect + requestRedirect: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /replacement-prefix + - matches: + - path: + type: PathPrefix + value: /full + filters: + - type: RequestRedirect + requestRedirect: + path: + type: ReplaceFullPath + replaceFullPath: /full-path-replacement + - matches: + - path: + type: PathPrefix + value: /path-and-host + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.org + path: + type: ReplacePrefixMatch + replacePrefixMatch: /replacement-prefix + - matches: + - path: + type: PathPrefix + value: /path-and-status + filters: + - type: RequestRedirect + requestRedirect: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /replacement-prefix + statusCode: 301 + - matches: + - path: + type: PathPrefix + value: /full-path-and-host + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.org + path: + type: ReplaceFullPath + replaceFullPath: /replacement-full + - matches: + - path: + type: PathPrefix + value: /full-path-and-status + filters: + - type: RequestRedirect + requestRedirect: + path: + type: ReplaceFullPath + replaceFullPath: /replacement-full + statusCode: 301 diff --git a/conformance/tests/mesh/httproute-redirect-port.go b/conformance/tests/mesh/httproute-redirect-port.go new file mode 100644 index 0000000000..cae14c230e --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-port.go @@ -0,0 +1,113 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteRedirectPort) +} + +var MeshHTTPRouteRedirectPort = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteRedirectPort", + Description: "An HTTPRoute with a port redirect filter", + Manifests: []string{"tests/mesh/httproute-redirect-port.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteRedirectPort, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Host: "echo", + Path: "/port", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Port: "8083", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/port-and-host", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + Port: "8083", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/port-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 301, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Port: "8083", + }, + Namespace: ns, + }, { + Request: http.Request{ + Host: "echo", + Path: "/port-and-host-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Port: "8083", + Host: "example.org", + }, + Namespace: ns, + }, + } + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-redirect-port.yaml b/conformance/tests/mesh/httproute-redirect-port.yaml new file mode 100644 index 0000000000..522d67327e --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-port.yaml @@ -0,0 +1,48 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-redirect-port + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /port + filters: + - type: RequestRedirect + requestRedirect: + port: 8083 + - matches: + - path: + type: PathPrefix + value: /port-and-host + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.org + port: 8083 + - matches: + - path: + type: PathPrefix + value: /port-and-status + filters: + - type: RequestRedirect + requestRedirect: + port: 8083 + statusCode: 301 + - matches: + - path: + type: PathPrefix + value: /port-and-host-and-status + filters: + - type: RequestRedirect + requestRedirect: + port: 8083 + hostname: example.org + statusCode: 302 diff --git a/conformance/tests/mesh/httproute-redirect-scheme.go b/conformance/tests/mesh/httproute-redirect-scheme.go new file mode 100644 index 0000000000..e241730914 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-scheme.go @@ -0,0 +1,116 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteSchemeRedirect) +} + +var MeshHTTPRouteSchemeRedirect = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteSchemeRedirect", + Description: "An HTTPRoute with a scheme redirect filter", + Manifests: []string{"tests/mesh/httproute-redirect-scheme.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteSchemeRedirect, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Host: "echo", + Path: "/scheme", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Scheme: "https", + }, + Namespace: ns, + }, + { + Request: http.Request{ + Host: "echo", + Path: "/scheme-and-host", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Host: "example.org", + Scheme: "https", + }, + Namespace: ns, + }, + { + Request: http.Request{ + Host: "echo", + Path: "/scheme-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 301, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Scheme: "https", + }, + Namespace: ns, + }, + { + Request: http.Request{ + Host: "echo", + Path: "/scheme-and-host-and-status", + UnfollowRedirect: true, + }, + Response: http.Response{ + StatusCode: 302, + }, + RedirectRequest: &roundtripper.RedirectRequest{ + Scheme: "https", + Host: "example.org", + }, + Namespace: ns, + }, + } + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-redirect-scheme.yaml b/conformance/tests/mesh/httproute-redirect-scheme.yaml new file mode 100644 index 0000000000..b5f4628cd9 --- /dev/null +++ b/conformance/tests/mesh/httproute-redirect-scheme.yaml @@ -0,0 +1,49 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-redirect-scheme + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /scheme + filters: + - type: RequestRedirect + requestRedirect: + scheme: "https" + - matches: + - path: + type: PathPrefix + value: /scheme-and-host + filters: + - type: RequestRedirect + requestRedirect: + hostname: example.org + scheme: "https" + - matches: + - path: + type: PathPrefix + value: /scheme-and-status + filters: + - type: RequestRedirect + requestRedirect: + scheme: "https" + statusCode: 301 + - matches: + - path: + type: PathPrefix + value: /scheme-and-host-and-status + filters: + - type: RequestRedirect + requestRedirect: + scheme: "https" + statusCode: 302 + hostname: example.org + diff --git a/conformance/tests/mesh/httproute-rewrite-path.go b/conformance/tests/mesh/httproute-rewrite-path.go index 79416a96c8..22f8ae66a3 100644 --- a/conformance/tests/mesh/httproute-rewrite-path.go +++ b/conformance/tests/mesh/httproute-rewrite-path.go @@ -34,8 +34,8 @@ var MeshHTTPRouteRewritePath = suite.ConformanceTest{ Description: "An HTTPRoute with path rewrite filter", Features: []features.FeatureName{ features.SupportMesh, - features.SupportMeshHTTPRouteRewritePath, features.SupportHTTPRoute, + features.SupportMeshHTTPRouteRewritePath, }, Manifests: []string{"tests/mesh/httproute-rewrite-path.yaml"}, Test: func(t *testing.T, s *suite.ConformanceTestSuite) { diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index 711681c58c..e2af0a6089 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -50,6 +50,12 @@ const ( SupportMeshConsumerRoute FeatureName = "MeshConsumerRoute" // This option indicates mesh support for HTTPRoute path rewrite (extended conformance) SupportMeshHTTPRouteRewritePath FeatureName = "MeshHTTPRouteRewritePath" + // This option indicates mesh support for HTTPRoute scheme redirect (extended conformance) + SupportMeshHTTPRouteSchemeRedirect FeatureName = "MeshHTTPRouteSchemeRedirect" + // This option indicates mesh support for HTTPRoute port redirect (extended conformance) + SupportMeshHTTPRouteRedirectPort FeatureName = "MeshHTTPRouteRedirectPort" + // This option indicates mesh support for HTTPRoute path redirect (extended conformance) + SupportMeshHTTPRouteRedirectPath FeatureName = "MeshHTTPRouteRedirectPath" ) var ( @@ -69,6 +75,24 @@ var ( Name: SupportMeshHTTPRouteRewritePath, Channel: FeatureChannelStandard, } + + // MeshHTTPRouteSchemeRedirect contains metadata for the MeshHTTPRouteSchemeRedirect feature. + MeshHTTPRouteSchemeRedirect = Feature{ + Name: SupportMeshHTTPRouteRewritePath, + Channel: FeatureChannelStandard, + } + + // MeshHTTPRouteRedirectPort contains metadata for the MeshHTTPRouteRedirectPort feature. + MeshHTTPRouteRedirectPort = Feature{ + Name: SupportMeshHTTPRouteRedirectPort, + Channel: FeatureChannelStandard, + } + + // MeshHTTPRouteRedirectPath contains metadata for the MeshHTTPRouteRedirectPath feature. + MeshHTTPRouteRedirectPath = Feature{ + Name: SupportMeshHTTPRouteRedirectPath, + Channel: FeatureChannelStandard, + } ) // MeshExtendedFeatures includes all the supported features for the service mesh at @@ -77,4 +101,6 @@ var MeshExtendedFeatures = sets.New( MeshClusterIPMatchingFeature, MeshConsumerRouteFeature, MeshHTTPRouteRewritePath, + MeshHTTPRouteSchemeRedirect, + MeshHTTPRouteRedirectPath, ) From 0912739c889731f9e2e1ffe94f0f4c21987da17c Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Wed, 14 May 2025 07:05:16 +0200 Subject: [PATCH 011/224] fix: remove misleading description (#3778) Signed-off-by: Norwin Schnyder --- apis/v1/httproute_types.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 6131d70b7b..6fec27d6e0 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -988,11 +988,11 @@ type HTTPHeader struct { } // HTTPHeaderFilter defines a filter that modifies the headers of an HTTP -// request or response. Only one action for a given header name is permitted. -// Filters specifying multiple actions of the same or different type for any one -// header name are invalid and will be rejected by CRD validation. -// Configuration to set or add multiple values for a header must use RFC 7230 -// header value formatting, separating each value with a comma. +// request or response. Only one action for a given header name is +// permitted. Filters specifying multiple actions of the same or different +// type for any one header name are invalid. Configuration to set or add +// multiple values for a header must use RFC 7230 header value formatting, +// separating each value with a comma. type HTTPHeaderFilter struct { // Set overwrites the request with the given header (name, value) // before the action. From 793e5626914ac3cd9015b4dc0c94f23f2c41bfbf Mon Sep 17 00:00:00 2001 From: Sunjay Bhatia <5337253+sunjayBhatia@users.noreply.github.com> Date: Wed, 14 May 2025 01:05:23 -0400 Subject: [PATCH 012/224] Add conformance report for Contour 1.31.0 (#3783) * Add conformance report for Contour 1.31.0 Supports gateway API 1.2.1 Signed-off-by: Sunjay Bhatia * update implementations.md Signed-off-by: Sunjay Bhatia --------- Signed-off-by: Sunjay Bhatia --- .../v1.2.1/projectcontour-contour/README.md | 48 +++++++++ .../experimental-v1.31.0-default-report.yaml | 101 ++++++++++++++++++ site-src/implementations.md | 6 +- 3 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 conformance/reports/v1.2.1/projectcontour-contour/README.md create mode 100644 conformance/reports/v1.2.1/projectcontour-contour/experimental-v1.31.0-default-report.yaml diff --git a/conformance/reports/v1.2.1/projectcontour-contour/README.md b/conformance/reports/v1.2.1/projectcontour-contour/README.md new file mode 100644 index 0000000000..2023c68db3 --- /dev/null +++ b/conformance/reports/v1.2.1/projectcontour-contour/README.md @@ -0,0 +1,48 @@ +# Projectcontour Contour + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|experimental|[v1.31.0](https://github.com/projectcontour/contour/releases/tag/v1.31.0)|x|[v1.31.0 report](./experimental-v1.31.0-default-report.yaml)| + +## Reproduce + +### Prerequisites + +Follow the Contour [contribution guide][0] documentation for setting up your local development environment, which includes ensuring `kubectl`, `docker`, `kinD`, and other tools are installed. + +### Steps + +1. Clone the Contour GitHub repository + + ```bash + git clone https://github.com/projectcontour/contour && cd contour + ``` + +2. Check out the desired version + + ```bash + export VERSION=v + git checkout $VERSION + ``` + +3. Run the conformance tests + + ```bash + export CONTOUR_E2E_IMAGE="ghcr.io/projectcontour/contour:$VERSION" + export GENERATE_GATEWAY_CONFORMANCE_REPORT="true" + make setup-kind-cluster run-gateway-conformance cleanup-kind + ``` + + Note: you can omit the `cleanup-kind` target if you would prefer to keep the `kinD` cluster. + +4. Check the produced report + + ```bash + cat gateway-conformance-report/projectcontour-contour-*.yaml + ``` + + Note: you can set `GATEWAY_CONFORMANCE_REPORT_OUTDIR` before running the tests to customize the output location. + +[0]: https://github.com/projectcontour/contour/blob/main/CONTRIBUTING.md#building-from-source diff --git a/conformance/reports/v1.2.1/projectcontour-contour/experimental-v1.31.0-default-report.yaml b/conformance/reports/v1.2.1/projectcontour-contour/experimental-v1.31.0-default-report.yaml new file mode 100644 index 0000000000..b3c0be99d4 --- /dev/null +++ b/conformance/reports/v1.2.1/projectcontour-contour/experimental-v1.31.0-default-report.yaml @@ -0,0 +1,101 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-06T14:44:31-04:00" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.2.1 +implementation: + contact: + - '@projectcontour/maintainers' + organization: projectcontour + project: contour + url: https://projectcontour.io/ + version: v1.31.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: partial + skippedTests: + - HTTPRouteHTTPSListener + statistics: + Failed: 0 + Passed: 32 + Skipped: 1 + extended: + result: partial + skippedTests: + - GatewayStaticAddresses + - HTTPRouteInvalidParentRefSectionNameNotMatchingPort + - HTTPRouteRedirectPortAndScheme + statistics: + Failed: 0 + Passed: 20 + Skipped: 3 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + name: GATEWAY-HTTP + summary: Core tests partially succeeded with 1 test skips. Extended tests partially + succeeded with 3 test skips. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: partial + skippedTests: + - GatewayStaticAddresses + statistics: + Failed: 0 + Passed: 1 + Skipped: 1 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests partially succeeded with 1 test skips. +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: partial + skippedTests: + - GatewayStaticAddresses + statistics: + Failed: 0 + Passed: 1 + Skipped: 1 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests partially succeeded with 1 test skips. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/site-src/implementations.md b/site-src/implementations.md index 77fa74a7d2..f571d5c865 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -209,13 +209,13 @@ effort, check out the #development channel or join our [weekly developer meeting ### Contour -[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.1.0-Contour-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/projectcontour-contour) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Contour-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/projectcontour-contour) [Contour][contour] is a CNCF open source Envoy-based ingress controller for Kubernetes. -Contour [v1.30.0][contour-release] implements Gateway API v1.1.0. +Contour [v1.31.0][contour-release] implements Gateway API v1.2.1. All [Standard channel][contour-standard] v1 API group resources (GatewayClass, Gateway, HTTPRoute, ReferenceGrant), plus most v1alpha2 API group resources (TLSRoute, TCPRoute, GRPCRoute, ReferenceGrant, and BackendTLSPolicy) are supported. -Contour's implementation passes all core and most extended Gateway API conformance tests included in the v1.1.0 release. +Contour's implementation passes most core extended Gateway API conformance tests included in the v1.2.1 release. See the [Contour Gateway API Guide][contour-guide] for information on how to deploy and use Contour's Gateway API implementation. From dce6bc41d2ddc352f512424f1c2f3b9a21a79a22 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Wed, 14 May 2025 19:27:24 -0700 Subject: [PATCH 013/224] Add Google Cloud Service Mesh to implementations.md (#3781) * add csm mesh to implementations.md * fix * fix1 * Update implementations.md Co-authored-by: Rob Scott --------- Co-authored-by: Rob Scott --- site-src/implementations.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site-src/implementations.md b/site-src/implementations.md index f571d5c865..4bc723430f 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -47,6 +47,7 @@ cover, and documentation to help users get started. ## Service Mesh Implementation Status +- [Google Cloud Service Mesh][38] (GA) - [Istio][9] (GA) - [Kuma][11] (GA) - [Linkerd][28] (experimental) @@ -95,6 +96,7 @@ cover, and documentation to help users get started. [35]:#kong-gateway-operator [36]:#loxilb [37]:#kgateway +[38]:#google-cloud-service-mesh [gamma]:/concepts/gamma/ @@ -290,6 +292,23 @@ profile except `HTTPRouteServiceTypes`. [gloogateway]:https://docs.solo.io/gateway/latest/ [solo]:https://www.solo.io +### Google Cloud Service Mesh + + +[Google Kubernetes Engine (GKE)][gke] is a managed Kubernetes platform offered +by Google Cloud. + +GKE's implementation of Gateway For Mesh (GAMMA) is through the [Cloud Service Mesh][cloud-service-mesh]. + + +Google Cloud Service Mesh supports [Envoy-based sidecar mesh][envoy-sidecar-mesh] and [Proxyless-GRPC][proxyless-grpc-mesh] (using GRPCRoute). + + +[gke]:https://cloud.google.com/kubernetes-engine +[cloud-service-mesh]:https://cloud.google.com/products/service-mesh +[envoy-sidecar-mesh]:https://cloud.google.com/service-mesh/docs/gateway/set-up-envoy-mesh +[proxyless-grpc-mesh]:https://cloud.google.com/service-mesh/docs/gateway/proxyless-grpc-mesh + ### Google Kubernetes Engine [![Conformance](https://img.shields.io/badge/Gateway_API_Partial_Conformance_v1.1.0-Google_Kubernetes_Engine-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/gke-gateway) From 6fbbd90954c2a30a6502cbb22ec6e7f3359ed3a0 Mon Sep 17 00:00:00 2001 From: Enrico Date: Thu, 15 May 2025 05:57:19 +0200 Subject: [PATCH 014/224] Improve feature name readability in conformance reports (#3564) Add feature name processing to remove redundant prefixes and improve readability in conformance comparison tables. Changes include: - Remove "HTTPRoute" and "Gateway" prefixes from feature names - Split camelCase words into space-separated words - Add process_feature_name() function for consistent text processing - Update generate_profiles_report() to use processed feature names This makes the conformance reports easier to read --- hack/mkdocs-generate-conformance.py | 15 ++++++++++++++- site-src/implementations/v1.0.md | 8 ++++---- site-src/implementations/v1.1.md | 8 ++++---- site-src/implementations/v1.2.md | 2 +- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/hack/mkdocs-generate-conformance.py b/hack/mkdocs-generate-conformance.py index f24832af57..0486c530da 100644 --- a/hack/mkdocs-generate-conformance.py +++ b/hack/mkdocs-generate-conformance.py @@ -21,10 +21,21 @@ from fnmatch import fnmatch import glob import os +import re log = logging.getLogger(f'mkdocs.plugins.{__name__}') +def process_feature_name(feature): + """ + Process feature names by splitting camelCase into space-separated words + """ + # Split camelCase + words = re.findall(r'HTTPRoute|[A-Z]+(?=[A-Z][a-z])|[A-Z][a-z]+|[A-Z\d]+', feature) + # Join words with spaces + return ' '.join(words) + + @plugins.event_priority(100) def on_files(files, config, **kwargs): log.info("generating conformance") @@ -151,7 +162,9 @@ def generate_profiles_report(reports, route,version): for row in http_table.itertuples(): if type(row._4) is list: for feat in row._4: - http_table.loc[row.Index, feat] = ':white_check_mark:' + # Process feature name before using it as a column + processed_feat = process_feature_name(feat) + http_table.loc[row.Index, processed_feat] = ':white_check_mark:' http_table = http_table.fillna(':x:') http_table = http_table.drop(['extended.supportedFeatures'], axis=1) diff --git a/site-src/implementations/v1.0.md b/site-src/implementations/v1.0.md index 901a48a138..ec3e6db233 100644 --- a/site-src/implementations/v1.0.md +++ b/site-src/implementations/v1.0.md @@ -42,7 +42,7 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | HTTPRouteRequestTimeout | HTTPRoutePathRedirect | HTTPRouteRequestMirror | HTTPRoutePathRewrite | HTTPRouteMethodMatching | HTTPRouteRequestMultipleMirrors | HTTPRouteBackendTimeout | HTTPRouteResponseHeaderModification | HTTPRoutePortRedirect | HTTPRouteSchemeRedirect | HTTPRouteHostRewrite | HTTPRouteQueryParamMatching | -|:---------------|:----------|:----------|:--------------------------|:------------------------|:-------------------------|:-----------------------|:--------------------------|:----------------------------------|:--------------------------|:--------------------------------------|:------------------------|:--------------------------|:-----------------------|:------------------------------| -| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kumahq | kuma | 2.6.0 | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | \ No newline at end of file +| Organization | Project | Version | HTTPRoute Request Timeout | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Path Rewrite | HTTPRoute Method Matching | HTTPRoute Request Multiple Mirrors | HTTPRoute Backend Timeout | HTTPRoute Response Header Modification | HTTPRoute Port Redirect | HTTPRoute Scheme Redirect | HTTPRoute Host Rewrite | HTTPRoute Query Param Matching | +|:---------------|:----------|:----------|:----------------------------|:--------------------------|:---------------------------|:-------------------------|:----------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:--------------------------|:----------------------------|:-------------------------|:---------------------------------| +| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kumahq | kuma | 2.6.0 | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/implementations/v1.1.md b/site-src/implementations/v1.1.md index 577c5642a6..443ea07fbc 100644 --- a/site-src/implementations/v1.1.md +++ b/site-src/implementations/v1.1.md @@ -59,7 +59,7 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRouteBackendProtocolH2C | HTTPRouteBackendProtocolWebSocket | HTTPRouteBackendRequestHeaderModification | HTTPRouteBackendTimeout | HTTPRouteHostRewrite | HTTPRouteMethodMatching | HTTPRoutePathRedirect | HTTPRoutePathRewrite | HTTPRoutePortRedirect | HTTPRouteQueryParamMatching | HTTPRouteRequestMirror | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | HTTPRouteResponseHeaderModification | HTTPRouteSchemeRedirect | MeshClusterIPMatching | MeshConsumerRoute | HTTPRouteParentRefPort | -|:---------------|:----------|:----------|:--------|:------------------------------|:------------------------------------|:--------------------------------------------|:--------------------------|:-----------------------|:--------------------------|:------------------------|:-----------------------|:------------------------|:------------------------------|:-------------------------|:----------------------------------|:--------------------------|:--------------------------------------|:--------------------------|:------------------------|:--------------------|:-------------------------| -| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | -| istio | istio | 1.22 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | Mesh Consumer Route | HTTPRoute Parent Ref Port | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------|:----------------------------| +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| istio | istio | 1.22 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/implementations/v1.2.md b/site-src/implementations/v1.2.md index 5f7b35a34b..21bb980689 100644 --- a/site-src/implementations/v1.2.md +++ b/site-src/implementations/v1.2.md @@ -55,4 +55,4 @@ Implementations only appear in this page if they pass Core conformance for the r | Organization | Project | Version | Mode | HTTPRouteBackendProtocolH2C | HTTPRouteBackendProtocolWebSocket | HTTPRouteBackendRequestHeaderModification | HTTPRouteBackendTimeout | HTTPRouteDestinationPortMatching | HTTPRouteHostRewrite | HTTPRouteMethodMatching | HTTPRoutePathRedirect | HTTPRoutePathRewrite | HTTPRoutePortRedirect | HTTPRouteQueryParamMatching | HTTPRouteRequestMirror | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | HTTPRouteResponseHeaderModification | HTTPRouteSchemeRedirect | MeshClusterIPMatching | HTTPRouteParentRefPort | MeshConsumerRoute | |:---------------|:----------|:--------------|:--------|:------------------------------|:------------------------------------|:--------------------------------------------|:--------------------------|:-----------------------------------|:-----------------------|:--------------------------|:------------------------|:-----------------------|:------------------------|:------------------------------|:-------------------------|:----------------------------------|:--------------------------|:--------------------------------------|:--------------------------|:------------------------|:-------------------------|:--------------------| | cilium | cilium | v1.17.0-pre.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | From b7d2c5788bf38fc2c18085de524e204034c69a14 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Sat, 17 May 2025 06:18:30 -0400 Subject: [PATCH 015/224] Update RELEASE_MANAGEMENT.md --- RELEASE_MANAGEMENT.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_MANAGEMENT.md b/RELEASE_MANAGEMENT.md index cd8f0f1851..94e2c724de 100644 --- a/RELEASE_MANAGEMENT.md +++ b/RELEASE_MANAGEMENT.md @@ -107,5 +107,9 @@ volunteers the release may simply end being a smaller **maintenance release**. Release candidates--and the eventual final release--must utilize the [Release Process](/RELEASE.md) for delivery. +As the release nears completion, the release-manager should proactively reach +out to implementations to get them ready to send conformance reports for the +final release when it is cut. + [Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ [Milestone]:#github-milestone From b9062b78fa40afb27d0701ef61b4db7756241c81 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Tue, 20 May 2025 10:45:15 -0700 Subject: [PATCH 016/224] Fix typo for the file name case type. (#3807) --- geps/gep-2162/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-2162/index.md b/geps/gep-2162/index.md index 38b2dbf60e..a8959acc8e 100644 --- a/geps/gep-2162/index.md +++ b/geps/gep-2162/index.md @@ -123,7 +123,7 @@ Every feature should: #### Conformance test names -Conformance tests file names should try to follow the `pascal-case-name.go` format. +Conformance tests file names should try to follow the `kebab-case-name.go` format. For example for `HTTPRoutePortRedirect` - the test file would be `httproute-port-redirect.go`. We should treat this guidance as "best effort" because we might have test files that check the combination of several features and can't follow the same format. From 7bfd028678c4bf831528184199e71c923b8f3ac5 Mon Sep 17 00:00:00 2001 From: Xunzhuo Date: Thu, 22 May 2025 00:58:35 +0800 Subject: [PATCH 017/224] feat: add eg v1.3 gwapi conformance report (#3795) Signed-off-by: bitliu --- .../reports/v1.3.0/envoy-gateway/README.md | 34 +++++++++ .../experimental-v1.4.0-default-report.yaml | 71 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 conformance/reports/v1.3.0/envoy-gateway/README.md create mode 100644 conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml diff --git a/conformance/reports/v1.3.0/envoy-gateway/README.md b/conformance/reports/v1.3.0/envoy-gateway/README.md new file mode 100644 index 0000000000..d48c5c9ac0 --- /dev/null +++ b/conformance/reports/v1.3.0/envoy-gateway/README.md @@ -0,0 +1,34 @@ +# Envoy Gateway + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +| experimental |[v1.4.0](https://github.com/envoyproxy/gateway/releases/tag/v1.4.0)| default |[link](./experimental-v1.4.0-default-report.yaml)| + +## Reproduce + +1. Clone the Envoy Gateway GitHub repository + + ```bash + git clone https://github.com/envoyproxy/gateway.git && cd gateway + ``` + +2. Check out the desired version + + ```bash + export VERSION=v + git checkout $VERSION + ``` + +3. Run the conformance tests + + ```bash + CONFORMANCE_REPORT_PATH=conformance-report-k8s.yaml make experimental-conformance + ``` + +4. Check the produced report + + ```bash + cat ./conformance-report-k8s.yaml + ``` diff --git a/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml new file mode 100644 index 0000000000..4504a506da --- /dev/null +++ b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml @@ -0,0 +1,71 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-14T03:12:24Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/envoyproxy/gateway/blob/main/GOVERNANCE.md + organization: envoyproxy + project: envoy-gateway + url: https://github.com/envoyproxy/gateway + version: latest +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + name: GATEWAY-GRPC + summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 23 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayInfrastructurePropagation + - GatewayStaticAddresses + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + name: GATEWAY-TLS + summary: Core tests succeeded. +succeededProvisionalTests: +- HTTPRouteRequestPercentageMirror From 5e934892dc226d88f7813cc1141f95ecbfc66336 Mon Sep 17 00:00:00 2001 From: Tam Mach Date: Thu, 22 May 2025 02:58:42 +1000 Subject: [PATCH 018/224] conformance: Add Cilium report for v1.3.0 (#3799) The report is generated by Cilium GHA CI https://github.com/cilium/cilium/actions/runs/15111523465 Signed-off-by: Tam Mach --- .../reports/v1.3.0/cilium-cilium/README.md | 12 ++ .../experimental-main-default-report.yaml | 140 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 conformance/reports/v1.3.0/cilium-cilium/README.md create mode 100644 conformance/reports/v1.3.0/cilium-cilium/experimental-main-default-report.yaml diff --git a/conformance/reports/v1.3.0/cilium-cilium/README.md b/conformance/reports/v1.3.0/cilium-cilium/README.md new file mode 100644 index 0000000000..81b4fe1760 --- /dev/null +++ b/conformance/reports/v1.3.0/cilium-cilium/README.md @@ -0,0 +1,12 @@ +# Cilium + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|--------------|-------------------------------------------|---------|--------------------------------------------------------| +| experimental | [main](https://github.com/cilium/cilium/) | default | [main report](./experimental-main-default-report.yaml) | + +## Reproduce + +Cilium conformance tests can be reproduced by follow the steps in CI `.github/workflows/conformance-gateway-api.yaml` +from within the [Cilium repo](https://github.com/cilium/cilium). diff --git a/conformance/reports/v1.3.0/cilium-cilium/experimental-main-default-report.yaml b/conformance/reports/v1.3.0/cilium-cilium/experimental-main-default-report.yaml new file mode 100644 index 0000000000..7784449030 --- /dev/null +++ b/conformance/reports/v1.3.0/cilium-cilium/experimental-main-default-report.yaml @@ -0,0 +1,140 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-19T11:21:16Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/cilium/community/blob/main/roles/Maintainers.md + organization: cilium + project: cilium + url: github.com/cilium/cilium + version: main +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 23 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - HTTPRouteParentRefPort + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + name: MESH-GRPC + summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + supportedFeatures: + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - MeshClusterIPMatching + unsupportedFeatures: + - HTTPRouteParentRefPort + - MeshConsumerRoute + name: MESH-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure +- HTTPRouteRequestPercentageMirror From 270a3892488c3b4ce8e8f66cec11ef61116aee1e Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Thu, 22 May 2025 23:06:35 +0200 Subject: [PATCH 019/224] conformance: Add Airlock Microgateway report for v1.3.0 (#3809) * conformance: Add Airlock Microgateway report for v1.3.0 Signed-off-by: Norwin Schnyder * add trailing new lines Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- .../v1.1.0/airlock-microgateway/README.md | 2 +- .../standard-4.6.0-default-report.yaml | 47 ++++++++++++++++ .../v1.1.1/airlock-microgateway/README.md | 1 + .../standard-4.6.0-default-report.yaml | 47 ++++++++++++++++ .../v1.2.0/airlock-microgateway/README.md | 1 + .../standard-4.6.0-default-report.yaml | 53 ++++++++++++++++++ .../v1.2.1/airlock-microgateway/README.md | 1 + .../standard-4.6.0-default-report.yaml | 53 ++++++++++++++++++ .../v1.3.0/airlock-microgateway/README.md | 20 +++++++ .../experimental-4.6.0-default-report.yaml | 55 +++++++++++++++++++ site-src/implementations.md | 15 ++--- 11 files changed, 284 insertions(+), 11 deletions(-) create mode 100644 conformance/reports/v1.1.0/airlock-microgateway/standard-4.6.0-default-report.yaml create mode 100644 conformance/reports/v1.1.1/airlock-microgateway/standard-4.6.0-default-report.yaml create mode 100644 conformance/reports/v1.2.0/airlock-microgateway/standard-4.6.0-default-report.yaml create mode 100644 conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml create mode 100644 conformance/reports/v1.3.0/airlock-microgateway/README.md create mode 100644 conformance/reports/v1.3.0/airlock-microgateway/experimental-4.6.0-default-report.yaml diff --git a/conformance/reports/v1.1.0/airlock-microgateway/README.md b/conformance/reports/v1.1.0/airlock-microgateway/README.md index c746409217..a23522a4ad 100644 --- a/conformance/reports/v1.1.0/airlock-microgateway/README.md +++ b/conformance/reports/v1.1.0/airlock-microgateway/README.md @@ -6,7 +6,7 @@ |--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v4.4.0](https://github.com/airlock/microgateway/releases/tag/4.4.0) | default | [v4.4.0 report](./experimental-4.4.0-default-report.yaml) | | standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [v4.5.0 report](./standard-4.5.0-default-report.yaml) | - +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [v4.6.0 report](./standard-4.6.0-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.1.0/airlock-microgateway/standard-4.6.0-default-report.yaml b/conformance/reports/v1.1.0/airlock-microgateway/standard-4.6.0-default-report.yaml new file mode 100644 index 0000000000..5152c07e47 --- /dev/null +++ b/conformance/reports/v1.1.0/airlock-microgateway/standard-4.6.0-default-report.yaml @@ -0,0 +1,47 @@ +apiVersion: gateway.networking.k8s.io/v1alpha1 +date: "2025-05-19T14:32:51Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.1.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.6.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/conformance/reports/v1.1.1/airlock-microgateway/README.md b/conformance/reports/v1.1.1/airlock-microgateway/README.md index 27868c3f1f..a61abd8398 100644 --- a/conformance/reports/v1.1.1/airlock-microgateway/README.md +++ b/conformance/reports/v1.1.1/airlock-microgateway/README.md @@ -5,6 +5,7 @@ | API channel | Implementation version | Mode | Report | |-------------|----------------------------------------------------------------------|---------|----------------------------------------------| | standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./standard-4.5.0-default-report.yaml) | +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.1.1/airlock-microgateway/standard-4.6.0-default-report.yaml b/conformance/reports/v1.1.1/airlock-microgateway/standard-4.6.0-default-report.yaml new file mode 100644 index 0000000000..93c2a25197 --- /dev/null +++ b/conformance/reports/v1.1.1/airlock-microgateway/standard-4.6.0-default-report.yaml @@ -0,0 +1,47 @@ +apiVersion: gateway.networking.k8s.io/v1alpha1 +date: "2025-05-19T14:32:48Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.1.1 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.6.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/conformance/reports/v1.2.0/airlock-microgateway/README.md b/conformance/reports/v1.2.0/airlock-microgateway/README.md index 27868c3f1f..a61abd8398 100644 --- a/conformance/reports/v1.2.0/airlock-microgateway/README.md +++ b/conformance/reports/v1.2.0/airlock-microgateway/README.md @@ -5,6 +5,7 @@ | API channel | Implementation version | Mode | Report | |-------------|----------------------------------------------------------------------|---------|----------------------------------------------| | standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./standard-4.5.0-default-report.yaml) | +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.2.0/airlock-microgateway/standard-4.6.0-default-report.yaml b/conformance/reports/v1.2.0/airlock-microgateway/standard-4.6.0-default-report.yaml new file mode 100644 index 0000000000..cce72e9086 --- /dev/null +++ b/conformance/reports/v1.2.0/airlock-microgateway/standard-4.6.0-default-report.yaml @@ -0,0 +1,53 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-19T14:33:20Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.6.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/conformance/reports/v1.2.1/airlock-microgateway/README.md b/conformance/reports/v1.2.1/airlock-microgateway/README.md index 6e691ffb1e..97c52418f9 100644 --- a/conformance/reports/v1.2.1/airlock-microgateway/README.md +++ b/conformance/reports/v1.2.1/airlock-microgateway/README.md @@ -5,6 +5,7 @@ | API channel | Implementation version | Mode | Report | |--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./experimental-4.5.0-default-report.yaml) | +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml new file mode 100644 index 0000000000..38f5f352f3 --- /dev/null +++ b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml @@ -0,0 +1,53 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-19T14:33:38Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.1 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.6.0-ci-4 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/conformance/reports/v1.3.0/airlock-microgateway/README.md b/conformance/reports/v1.3.0/airlock-microgateway/README.md new file mode 100644 index 0000000000..bae978e399 --- /dev/null +++ b/conformance/reports/v1.3.0/airlock-microgateway/README.md @@ -0,0 +1,20 @@ +# Airlock Microgateway + +## Table of contents + +| API channel | Implementation version | Mode | Report | +|--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| +| experimental | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./experimental-4.6.0-default-report.yaml) | + +## Reproduce + +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. + +> [!NOTE] +> The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. +> +> The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file diff --git a/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.6.0-default-report.yaml b/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.6.0-default-report.yaml new file mode 100644 index 0000000000..e0548256ea --- /dev/null +++ b/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.6.0-default-report.yaml @@ -0,0 +1,55 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-19T14:29:59Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.6.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/site-src/implementations.md b/site-src/implementations.md index 4bc723430f..3067f7d739 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -117,21 +117,17 @@ In this section you will find specific links to blog posts, documentation and ot [epicsource]:https://github.com/epic-gateway ### Airlock Microgateway -[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Airlock%20Microgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/airlock-microgateway) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Airlock%20Microgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/airlock-microgateway) -[Airlock Microgateway][airlock-microgateway] is a Kubernetes native WAAP (Web Application and API Protection) solution to protect microservices. +[Airlock Microgateway][airlock-microgateway] is a Kubernetes native WAAP (Web Application and API Protection, formerly known as WAF) solution optimized for Kubernetes environments and certified for RedHat OpenShift. Modern application security is embedded in the development workflow and follows DevSecOps paradigms. Airlock Microgateway protects your applications and microservices with the tried-and-tested Airlock security features against attacks, while also providing a high degree of scalability. -With [Airlock Microgateway 4.4][airlock-microgateway-gwapi-arch], Airlock Microgateway introduces a sidecarless data plane mode -based on Gateway API to avoid the operational complexity of sidecars. - #### Features -- Kubernetes native integration with sidecar injection and Gateway API support +- Comprehensive WAAP (formerly known as WAF) with security features like Deny Rules to protect against known attacks (OWASP Top 10), header filtering, JSON parsing, OpenAPI specification enforcement, and GraphQL schema validation +- Identity aware proxy which makes it possible to enforce authentication using JWT authentication or OIDC - Reverse proxy functionality with request routing rules, TLS termination and remote IP extraction -- Using native Envoy HTTP filters like Lua scripting, RBAC, ext_authz, JWT authentication -- Content security filters for protecting against known attacks (OWASP Top 10) -- API security features like JSON parsing, OpenAPI specification enforcement or GraphQL schema validation +- Easy-to-use Grafana dashboards which provide valuable insights in allowed and blocked traffic and other metrics #### Documentation and links - [Product documentation][airlock-microgateway-documentation] @@ -139,7 +135,6 @@ based on Gateway API to avoid the operational complexity of sidecars. - Check our [Airlock community forum][airlock-microgateway-community-support] and [support process][airlock-microgateway-premium-support] for support. [airlock-microgateway]:https://www.airlock.com/en/secure-access-hub/components/microgateway -[airlock-microgateway-gwapi-arch]:https://docs.airlock.com/microgateway/latest/?topic=MGW-00000141 [airlock-microgateway-documentation]:https://docs.airlock.com/microgateway/latest [airlock-microgateway-guide]:https://docs.airlock.com/microgateway/latest/?topic=MGW-00000142 [airlock-microgateway-community-support]:https://forum.airlock.com/ From fe41f50e3406682f68e462e185041585481b880e Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Sun, 25 May 2025 01:28:35 +0200 Subject: [PATCH 020/224] conformance: fix typo in Airlock Microgateway report (#3811) Signed-off-by: Norwin Schnyder --- .../airlock-microgateway/standard-4.6.0-default-report.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml index 38f5f352f3..0589d7e379 100644 --- a/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml +++ b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.6.0-default-report.yaml @@ -1,5 +1,5 @@ apiVersion: gateway.networking.k8s.io/v1 -date: "2025-05-19T14:33:38Z" +date: "2025-05-19T14:36:18Z" gatewayAPIChannel: standard gatewayAPIVersion: v1.2.1 implementation: @@ -8,7 +8,7 @@ implementation: organization: airlock project: microgateway url: https://github.com/airlock/microgateway - version: 4.6.0-ci-4 + version: 4.6.0 kind: ConformanceReport mode: default profiles: From ce0cfebeb52c10af6833beadbc2a1a70aea4c0df Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 27 May 2025 18:14:16 +0800 Subject: [PATCH 021/224] conformance: add Hook in ConformanceTestSuite (#3786) * conformance: add Hook in ConformanceTestSuite * update comment Signed-off-by: zirain * add Hook in ConformanceOptions Signed-off-by: zirain --------- Signed-off-by: zirain --- conformance/utils/suite/suite.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 53700d6c53..e6a5cb1264 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -74,6 +74,7 @@ type ConformanceTestSuite struct { SkipTests sets.Set[string] SkipProvisionalTests bool RunTest string + Hook func(t *testing.T, test ConformanceTest, suite *ConformanceTestSuite) ManifestFS []fs.FS UsableNetworkAddresses []v1beta1.GatewaySpecAddress UnusableNetworkAddresses []v1beta1.GatewaySpecAddress @@ -121,7 +122,7 @@ type ConformanceTestSuite struct { lock sync.RWMutex } -// Options can be used to initialize a ConformanceTestSuite. +// ConformanceOptions can be used to initialize a ConformanceTestSuite. type ConformanceOptions struct { Client client.Client ClientOptions client.Options @@ -152,7 +153,8 @@ type ConformanceOptions struct { SkipProvisionalTests bool // RunTest is a single test to run, mostly for development/debugging convenience. RunTest string - + // Hook is an optional function that can be used to run custom logic after each test at suite level. + Hook func(t *testing.T, test ConformanceTest, suite *ConformanceTestSuite) ManifestFS []fs.FS // UsableNetworkAddresses is an optional pool of usable addresses for @@ -268,6 +270,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, mode: mode, apiVersion: apiVersion, apiChannel: apiChannel, + Hook: options.Hook, } for _, conformanceProfileName := range options.ConformanceProfiles.UnsortedList() { @@ -470,6 +473,13 @@ func (suite *ConformanceTestSuite) Run(t *testing.T, tests []ConformanceTest) er if res == testSucceeded || res == testFailed { sleepForTestIsolation = true } + + // call the hook function if it was provided, + // this's useful for running custom logic after each test at suite level, + // such as collecting current state of the cluster for debugging. + if suite.Hook != nil { + suite.Hook(t, test, suite) + } } // now that the tests have completed, mark the test suite as not running From f311bd751e6ec6280af513210a1644ff66b250de Mon Sep 17 00:00:00 2001 From: Davin Kevin Date: Tue, 27 May 2025 21:40:16 +0200 Subject: [PATCH 022/224] fix(gep-1911): remove duplicated header in table (#3818) --- geps/gep-1911/index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/geps/gep-1911/index.md b/geps/gep-1911/index.md index c26565ce07..fb6df21430 100644 --- a/geps/gep-1911/index.md +++ b/geps/gep-1911/index.md @@ -85,7 +85,6 @@ Implementations MAY support the following combinations below: ServicePort Protocol | ServicePort AppProtocol | Route Type | Supported -|-|-|- -ServicePort Protocol | ServicePort AppProtocol | Route Type | Supported `TCP` | `kubernetes.io/wss` | `HTTPRoute` | Conditional [1] 1. Only if there is a corresponding `BackendTLSPolicy` - see [GEP-1897](../gep-1897/index.md) From 54df0a899c1c5c845dd3a80f05dcfdf65576f03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Y=C3=A9pez?= <58478476+FelipeYepez@users.noreply.github.com> Date: Wed, 28 May 2025 00:36:22 +0200 Subject: [PATCH 023/224] Remove unused dependabot config for Github actions (#3816) This PR removes the Dependabot configuration for the `github-actions` package ecosystem since Github Actions are not used in this repository. There is no PR ever created with a `dependencies` tag which is not for `go`, `docker`, or `python`. --- .github/dependabot.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bc2eca7f66..2746f0b99c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -30,17 +30,6 @@ updates: - ok-to-test - release-note-none - # Dependencies listed in .github/workflows/*.yml - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - labels: - - github_actions - - dependencies - - ok-to-test - - release-note-none - # Dependencies listed in Dockerfile - package-ecosystem: "docker" directory: "/" From e7c711b0a91273727288942faa10573164e6981b Mon Sep 17 00:00:00 2001 From: samcrichard <119348077+samcrichard@users.noreply.github.com> Date: Wed, 28 May 2025 20:36:16 -0400 Subject: [PATCH 024/224] Updating ngrok Gateway API Implementation on Implementations page (#3775) --- site-src/implementations.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index 3067f7d739..6f42e00e65 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -487,7 +487,12 @@ If you have any suggestions or experience issues with NGINX Gateway Fabric, plea ### ngrok Kubernetes Operator -[ngrok Kubernetes Operator][ngrok-k8s-operator] provides an implementation of the Gateway API that uses [ngrok's ingress-as-a-service][ngrok]. This project uses the Gateway API to support routing traffic from ngrok's global network to applications running on Kubernetes clusters. This easily adds the benefits of ngrok, like security, network policy, and a global presence with the simplicity of cloud service. The operator contains both a Gateway API implementation as well as a controller using Kubernetes Ingress. The Gateway API implementation is currently under development and supports only the Gateway, GatewayClass and HTTPRoute. As the TLSRoute and TCPRoute move from experimental to stable, they will also be implemented. +[ngrok Kubernetes Operator][ngrok-k8s-operator] After adding preliminary support last year, the [ngrok Kubernetes Operator][ngrok-k8s-operator] supports the entire core Gateway API. This includes: +-Routes (HTTPRoute, TCPRoute, TLSRoute) + RouteMatches (Header, Path, +more) +-Filters: Header, Redirect, Rewrite + more +-Backends: Backend Filters + Weighted balancing +-ReferenceGrant: RBAC for multi-tenant clusters handling +-Traffic Policy as an extensionRef or annotation when the Gateway API isn’t flexible enough You can read our [docs][ngrok-k8s-gwapi-docs] for more information. If you have any feature requests or bug reports, please [create an issue][ngrok-issue-new]. You can also reach out for help on [Slack][ngrok-slack] @@ -495,7 +500,7 @@ You can read our [docs][ngrok-k8s-gwapi-docs] for more information. If you have [ngrok]:https://ngrok.com [ngrok-k8s-gwapi-docs]:https://ngrok.com/docs/k8s/ [ngrok-issue-new]: https://github.com/ngrok/ngrok-operator/issues/new/choose -[ngrok-slack]:https://ngrokcommunity.slack.com/channels/general + ### STUNner From dbd2ff92a93e7c8a29bce07cc331e40e6d470efe Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Fri, 30 May 2025 17:00:18 -0700 Subject: [PATCH 025/224] add mesh conformance for request header modifier (#3812) * add mesh conformance for request header modifier * address feedback --- ...route-request-header-modifier-backend.yaml | 93 ++++++++ .../mesh/httproute-request-header-modifier.go | 213 ++++++++++++++++++ .../httproute-request-header-modifier.yaml | 93 ++++++++ conformance/utils/echo/parse.go | 3 +- conformance/utils/echo/pod.go | 67 ++++-- pkg/features/mesh.go | 9 + 6 files changed, 460 insertions(+), 18 deletions(-) create mode 100644 conformance/tests/mesh/httproute-request-header-modifier-backend.yaml create mode 100644 conformance/tests/mesh/httproute-request-header-modifier.go create mode 100644 conformance/tests/mesh/httproute-request-header-modifier.yaml diff --git a/conformance/tests/mesh/httproute-request-header-modifier-backend.yaml b/conformance/tests/mesh/httproute-request-header-modifier-backend.yaml new file mode 100644 index 0000000000..4ce7dfbbd0 --- /dev/null +++ b/conformance/tests/mesh/httproute-request-header-modifier-backend.yaml @@ -0,0 +1,93 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-request-header-modifier + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /set + backendRefs: + - name: echo-v1 + port: 8080 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: set-overwrites-values + - matches: + - path: + type: PathPrefix + value: /add + backendRefs: + - name: echo-v1 + port: 8080 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + add: + - name: X-Header-Add + value: add-appends-values + - matches: + - path: + type: PathPrefix + value: /remove + backendRefs: + - name: echo-v1 + port: 8080 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + remove: + - X-Header-Remove + - matches: + - path: + type: PathPrefix + value: /multiple + backendRefs: + - name: echo-v1 + port: 8080 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set-1 + value: header-set-1 + - name: X-Header-Set-2 + value: header-set-2 + add: + - name: X-Header-Add-1 + value: header-add-1 + - name: X-Header-Add-2 + value: header-add-2 + - name: X-Header-Add-3 + value: header-add-3 + remove: + - X-Header-Remove-1 + - X-Header-Remove-2 + - matches: + - path: + type: PathPrefix + value: /case-insensitivity + backendRefs: + - name: echo-v1 + port: 8080 + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: header-set + add: + - name: X-Header-Add + value: header-add + remove: + - X-Header-Remove diff --git a/conformance/tests/mesh/httproute-request-header-modifier.go b/conformance/tests/mesh/httproute-request-header-modifier.go new file mode 100644 index 0000000000..8c7abb83fb --- /dev/null +++ b/conformance/tests/mesh/httproute-request-header-modifier.go @@ -0,0 +1,213 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, + MeshHTTPRouteRequestHeaderModifier, + MeshHTTPRouteBackendRequestHeaderModifier, + ) +} + +var MeshHTTPRouteBackendRequestHeaderModifier = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteBackendRequestHeaderModifier", + Description: "An HTTPRoute backend has request header modifier filters applied correctly", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteBackendRequestHeaderModification, + }, + Manifests: []string{"tests/mesh/httproute-request-header-modifier-backend.yaml"}, + Test: MeshHTTPRouteRequestHeaderModifier.Test, +} + +var MeshHTTPRouteRequestHeaderModifier = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteRequestHeaderModifier", + Description: "An HTTPRoute has request header modifier filters applied correctly", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + }, + Manifests: []string{"tests/mesh/httproute-request-header-modifier.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Path: "/set", + Headers: map[string]string{ + "Some-Other-Header": "val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/set", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Set": "set-overwrites-values", + }, + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/set", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Set": "some-other-value", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/set", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Set": "set-overwrites-values", + }, + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/add", + Headers: map[string]string{ + "Some-Other-Header": "val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/add", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Add": "add-appends-values", + }, + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/add", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Add": "some-other-value", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/add", + Headers: map[string]string{ + "Some-Other-Header": "val", + "X-Header-Add": "some-other-value,add-appends-values", + }, + }, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/remove", + Headers: map[string]string{ + "X-Header-Remove": "val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/remove", + }, + AbsentHeaders: []string{"X-Header-Remove"}, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/multiple", + Headers: map[string]string{ + "X-Header-Set-2": "set-val-2", + "X-Header-Add-2": "add-val-2", + "X-Header-Remove-2": "remove-val-2", + "Another-Header": "another-header-val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/multiple", + Headers: map[string]string{ + "X-Header-Set-1": "header-set-1", + "X-Header-Set-2": "header-set-2", + "X-Header-Add-1": "header-add-1", + "X-Header-Add-2": "add-val-2,header-add-2", + "X-Header-Add-3": "header-add-3", + "Another-Header": "another-header-val", + }, + }, + AbsentHeaders: []string{"X-Header-Remove-1", "X-Header-Remove-2"}, + }, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{ + Path: "/case-insensitivity", + // The filter uses canonicalized header names, + // the request uses lowercase names. + Headers: map[string]string{ + "x-header-set": "original-val-set", + "x-header-add": "original-val-add", + "x-header-remove": "original-val-remove", + "Another-Header": "another-header-val", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/case-insensitivity", + Headers: map[string]string{ + "X-Header-Set": "header-set", + "X-Header-Add": "original-val-add,header-add", + "Another-Header": "another-header-val", + }, + }, + AbsentHeaders: []string{"x-header-remove", "X-Header-Remove"}, + }, + Backend: "echo-v1", + Namespace: ns, + }, + } + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-request-header-modifier.yaml b/conformance/tests/mesh/httproute-request-header-modifier.yaml new file mode 100644 index 0000000000..377ab22422 --- /dev/null +++ b/conformance/tests/mesh/httproute-request-header-modifier.yaml @@ -0,0 +1,93 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-request-header-modifier + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: /set + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: set-overwrites-values + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /add + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + add: + - name: X-Header-Add + value: add-appends-values + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /remove + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + remove: + - X-Header-Remove + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /multiple + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set-1 + value: header-set-1 + - name: X-Header-Set-2 + value: header-set-2 + add: + - name: X-Header-Add-1 + value: header-add-1 + - name: X-Header-Add-2 + value: header-add-2 + - name: X-Header-Add-3 + value: header-add-3 + remove: + - X-Header-Remove-1 + - X-Header-Remove-2 + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /case-insensitivity + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Header-Set + value: header-set + add: + - name: X-Header-Add + value: header-add + remove: + - X-Header-Remove + backendRefs: + - name: echo-v1 + port: 8080 diff --git a/conformance/utils/echo/parse.go b/conformance/utils/echo/parse.go index a175df926c..edabded67b 100644 --- a/conformance/utils/echo/parse.go +++ b/conformance/utils/echo/parse.go @@ -184,9 +184,8 @@ func ParseResponse(output string) Response { if len(sl) != 2 { continue } - out.RequestHeaders.Set(sl[0], sl[1]) + out.RequestHeaders.Add(sl[0], sl[1]) } - matches = responseHeaderFieldRegex.FindAllStringSubmatch(output, -1) for _, kv := range matches { sl := strings.SplitN(kv[1], ":", 2) diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index 24d0442945..3861f53c73 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -57,16 +57,8 @@ const ( func (m *MeshPod) MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, exp http.ExpectedResponse, timeoutConfig config.TimeoutConfig) { t.Helper() - if exp.Request.Method == "" { - exp.Request.Method = "GET" - } - - if exp.Response.StatusCode == 0 { - exp.Response.StatusCode = 200 - } - http.AwaitConvergence(t, timeoutConfig.RequiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency, func(elapsed time.Duration) bool { - req := makeRequest(t, exp.Request) + req := makeRequest(t, &exp) resp, err := m.request(req) if err != nil { @@ -84,7 +76,19 @@ func (m *MeshPod) MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, tlog.Logf(t, "Request passed") } -func makeRequest(t *testing.T, r http.Request) []string { +func makeRequest(t *testing.T, exp *http.ExpectedResponse) []string { + if exp.Request.Host == "" { + exp.Request.Host = "echo" + } + if exp.Request.Method == "" { + exp.Request.Method = "GET" + } + + if exp.Response.StatusCode == 0 { + exp.Response.StatusCode = 200 + } + + r := exp.Request protocol := strings.ToLower(r.Protocol) if protocol == "" { protocol = "http" @@ -95,22 +99,53 @@ func makeRequest(t *testing.T, r http.Request) []string { args = append(args, "--method="+r.Method) } for k, v := range r.Headers { - args = append(args, "-H", fmt.Sprintf("%v: %v", k, v)) + args = append(args, "-H", fmt.Sprintf("%v:%v", k, v)) } return args } func compareRequest(exp http.ExpectedResponse, resp Response) error { - want := exp.Response - if fmt.Sprint(want.StatusCode) != resp.Code { - return fmt.Errorf("wanted status code %v, got %v", want.StatusCode, resp.Code) + wantReq := exp.ExpectedRequest + wantResp := exp.Response + if fmt.Sprint(wantResp.StatusCode) != resp.Code { + return fmt.Errorf("wanted status code %v, got %v", wantResp.StatusCode, resp.Code) } - for _, name := range want.AbsentHeaders { + if wantReq.Headers != nil { + if resp.RequestHeaders == nil { + return fmt.Errorf("no headers captured, expected %v", len(wantReq.Headers)) + } + for name, val := range resp.RequestHeaders { + resp.RequestHeaders[strings.ToLower(name)] = val + } + for name, expectedVal := range wantReq.Headers { + actualVal, ok := resp.RequestHeaders[strings.ToLower(name)] + if !ok { + return fmt.Errorf("expected %s header to be set, actual headers: %v", name, resp.RequestHeaders) + } + if strings.Join(actualVal, ",") != expectedVal { + return fmt.Errorf("expected %s header to be set to %s, got %s", name, expectedVal, strings.Join(actualVal, ",")) + } + } + } + if len(wantReq.AbsentHeaders) > 0 { + for name, val := range resp.RequestHeaders { + resp.RequestHeaders[strings.ToLower(name)] = val + } + + for _, name := range wantReq.AbsentHeaders { + val, ok := resp.RequestHeaders[strings.ToLower(name)] + if ok { + return fmt.Errorf("expected %s header to not be set, got %s", name, val) + } + } + } + + for _, name := range wantResp.AbsentHeaders { if v := resp.ResponseHeaders.Values(name); len(v) != 0 { return fmt.Errorf("expected no header %q, got %v", name, v) } } - for k, v := range want.Headers { + for k, v := range wantResp.Headers { if got := resp.ResponseHeaders.Get(k); got != v { return fmt.Errorf("expected header %v=%v, got %v", k, v, got) } diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index e2af0a6089..f088cdad83 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -56,6 +56,8 @@ const ( SupportMeshHTTPRouteRedirectPort FeatureName = "MeshHTTPRouteRedirectPort" // This option indicates mesh support for HTTPRoute path redirect (extended conformance) SupportMeshHTTPRouteRedirectPath FeatureName = "MeshHTTPRouteRedirectPath" + // This option indicates support for HTTPRoute backend request header modification + SupportMeshHTTPRouteBackendRequestHeaderModification FeatureName = "MeshHTTPRouteBackendRequestHeaderModification" ) var ( @@ -93,6 +95,12 @@ var ( Name: SupportMeshHTTPRouteRedirectPath, Channel: FeatureChannelStandard, } + + // MeshHTTPRouteRedirectPath contains metadata for the MeshHTTPRouteRedirectPath feature. + MeshHTTPRouteBackendRequestHeaderModification = Feature{ + Name: SupportMeshHTTPRouteBackendRequestHeaderModification, + Channel: FeatureChannelStandard, + } ) // MeshExtendedFeatures includes all the supported features for the service mesh at @@ -103,4 +111,5 @@ var MeshExtendedFeatures = sets.New( MeshHTTPRouteRewritePath, MeshHTTPRouteSchemeRedirect, MeshHTTPRouteRedirectPath, + MeshHTTPRouteBackendRequestHeaderModification, ) From 268d2f435968be788cb1b640a92447c55f061c9d Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Mon, 2 Jun 2025 06:28:36 +0200 Subject: [PATCH 026/224] docs: Add v1.3 conformance report table (#3810) * docs: Add v1.3 conformance report table Signed-off-by: Norwin Schnyder * Automatically update conformance table files Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- hack/mkdocs-generate-conformance.py | 4 ++ mkdocs.yml | 1 + site-src/implementations.md | 2 +- site-src/implementations/v1.0.md | 44 +++++++++--------- site-src/implementations/v1.1.md | 71 +++++++++++++++-------------- site-src/implementations/v1.2.md | 66 +++++++++++++++------------ site-src/implementations/v1.3.md | 45 ++++++++++++++++++ 7 files changed, 147 insertions(+), 86 deletions(-) create mode 100644 site-src/implementations/v1.3.md diff --git a/hack/mkdocs-generate-conformance.py b/hack/mkdocs-generate-conformance.py index 0486c530da..bec9ecdef1 100644 --- a/hack/mkdocs-generate-conformance.py +++ b/hack/mkdocs-generate-conformance.py @@ -58,6 +58,10 @@ def on_files(files, config, **kwargs): # Add the generated file to the site files.append(file) + # Write the generated file to the site-src directory + with open(os.path.join("site-src", file.src_uri), "w") as f: + f.write(file.content_string) + return files diff --git a/mkdocs.yml b/mkdocs.yml index 228a0cccc4..4a4a7de35d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -85,6 +85,7 @@ nav: - Implementations: - List: implementations.md - Comparisons: + - v1.3: implementations/v1.3.md - v1.2: implementations/v1.2.md - v1.1: implementations/v1.1.md - v1.0: implementations/v1.0.md diff --git a/site-src/implementations.md b/site-src/implementations.md index 6f42e00e65..efdffc5c63 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -10,7 +10,7 @@ cover, and documentation to help users get started. !!! info "Compare extended supported features across implementations" - [View a table to quickly compare supported features of projects](implementations/v1.1.md). These outline Gateway controller implementations that have passed core conformance tests, and focus on extended conformance features that they have implemented. + [View a table to quickly compare supported features of projects](implementations/v1.2.md). These outline Gateway controller implementations that have passed core conformance tests, and focus on extended conformance features that they have implemented. ## Gateway Controller Implementation Status diff --git a/site-src/implementations/v1.0.md b/site-src/implementations/v1.0.md index ec3e6db233..e268964115 100644 --- a/site-src/implementations/v1.0.md +++ b/site-src/implementations/v1.0.md @@ -1,6 +1,6 @@ The following tables are populated from the conformance reports [uploaded by project implementations](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). They are separated into the extended features that each project supports listed in their reports. -Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. +Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. Implementations that submit conformance reports with skipped tests won't appear in the tables. @@ -16,27 +16,27 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | HTTPRouteMethodMatching | HTTPRouteQueryParamMatching | HTTPRouteResponseHeaderModification | HTTPRouteBackendTimeout | HTTPRoutePortRedirect | HTTPRoutePathRedirect | HTTPRouteHostRewrite | HTTPRouteSchemeRedirect | HTTPRoutePathRewrite | HTTPRouteParentRefPort | HTTPRouteRequestMirror | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | -|:----------------|:-----------------------------------|:--------------|:--------------------------|:------------------------------|:--------------------------------------|:--------------------------|:------------------------|:------------------------|:-----------------------|:--------------------------|:-----------------------|:-------------------------|:-------------------------|:----------------------------------|:--------------------------| -| Kong | kubernetes-ingress-controller | v3.0.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.1.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Microsoft Azure | Application Gateway for Containers | v1.0.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.15.0-pre.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v0.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kumahq | kuma | 2.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | -| nginx | nginx-gateway-fabric | v1.1.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | -| nginx | nginx-gateway-fabric | v1.2.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | -| projectcontour | contour | v1.28.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.28.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.28.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.28.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.28.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.28.6 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.29.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.29.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.29.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| solo.io | gloo-gateway | v1.17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | +| Organization | Project | Version | HTTPRoute Method Matching | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | HTTPRoute Backend Timeout | HTTPRoute Port Redirect | HTTPRoute Path Redirect | HTTPRoute Host Rewrite | HTTPRoute Scheme Redirect | HTTPRoute Path Rewrite | HTTPRoute Parent Ref Port | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | +|:----------------|:-----------------------------------|:--------------|:----------------------------|:---------------------------------|:-----------------------------------------|:----------------------------|:--------------------------|:--------------------------|:-------------------------|:----------------------------|:-------------------------|:----------------------------|:---------------------------|:-------------------------------------|:----------------------------| +| Kong | kubernetes-ingress-controller | v3.0.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.1.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | v1.0.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.15.0-pre.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v0.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kumahq | kuma | 2.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.1.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.2.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.28.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.6 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| solo.io | gloo-gateway | v1.17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | ## Mesh Profile diff --git a/site-src/implementations/v1.1.md b/site-src/implementations/v1.1.md index 443ea07fbc..bc97fc01fb 100644 --- a/site-src/implementations/v1.1.md +++ b/site-src/implementations/v1.1.md @@ -1,6 +1,6 @@ The following tables are populated from the conformance reports [uploaded by project implementations](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). They are separated into the extended features that each project supports listed in their reports. -Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. +Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. Implementations that submit conformance reports with skipped tests won't appear in the tables. @@ -16,44 +16,49 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | GatewayPort8080 | HTTPRouteHostRewrite | HTTPRoutePathRedirect | HTTPRouteRequestMirror | HTTPRouteResponseHeaderModification | HTTPRouteSchemeRedirect | HTTPRouteMethodMatching | HTTPRoutePathRewrite | HTTPRouteQueryParamMatching | HTTPRouteParentRefPort | GatewayHTTPListenerIsolation | GatewayStaticAddresses | HTTPRouteBackendProtocolH2C | HTTPRouteBackendProtocolWebSocket | HTTPRouteBackendRequestHeaderModification | HTTPRouteBackendTimeout | HTTPRoutePortRedirect | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | -|:---------------|:------------------------------|:-------------------|:---------------------------------|:-------------------|:-----------------------|:------------------------|:-------------------------|:--------------------------------------|:--------------------------|:--------------------------|:-----------------------|:------------------------------|:-------------------------|:-------------------------------|:-------------------------|:------------------------------|:------------------------------------|:--------------------------------------------|:--------------------------|:------------------------|:----------------------------------|:--------------------------| -| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-global-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | v4.4.0 | default | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.3.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | -| nginx | nginx-gateway-fabric | v1.4.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | -| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| traefik | traefik | v3.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | +| Organization | Project | Version | Mode | Gateway Port 8080 | HTTPRoute Host Rewrite | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Port Redirect | HTTPRoute Parent Ref Port | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | +|:----------------|:-----------------------------------|:-------------------|:---------------------------------|:--------------------|:-------------------------|:--------------------------|:---------------------------|:-----------------------------------------|:----------------------------|:----------------------------|:-------------------------|:---------------------------------|:--------------------------|:----------------------------|:----------------------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------------------|:----------------------------| +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-global-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | v4.4.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.3.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| solo.io | gloo-gateway | v1.18.0-beta30 | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| traefik | traefik | v3.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | ### GRPCRoute -| Organization | Project | Version | Mode | GatewayHTTPListenerIsolation | GatewayPort8080 | GatewayStaticAddresses | -|:---------------|:------------------------------|:----------|:------------|:-------------------------------|:-------------------|:-------------------------| -| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :x: | :x: | -| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.3.0 | default | :x: | :x: | :x: | -| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | -| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Port 8080 | Gateway Static Addresses | +|:----------------|:-----------------------------------|:----------|:------------|:----------------------------------|:--------------------|:---------------------------| +| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :x: | :x: | +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.3.0 | default | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | ### TLSRoute -| Organization | Project | Version | Mode | GatewayHTTPListenerIsolation | GatewayPort8080 | GatewayStaticAddresses | -|:---------------|:---------------------|:----------|:--------|:-------------------------------|:-------------------|:-------------------------| -| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | -| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:--------|:----------------------------------|:--------------------|:---------------------------| +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | ## Mesh Profile diff --git a/site-src/implementations/v1.2.md b/site-src/implementations/v1.2.md index 21bb980689..1c38f3351d 100644 --- a/site-src/implementations/v1.2.md +++ b/site-src/implementations/v1.2.md @@ -1,6 +1,6 @@ The following tables are populated from the conformance reports [uploaded by project implementations](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). They are separated into the extended features that each project supports listed in their reports. -Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. +Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. Implementations that submit conformance reports with skipped tests won't appear in the tables. @@ -16,43 +16,49 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | GatewayPort8080 | HTTPRouteHostRewrite | HTTPRouteMethodMatching | HTTPRoutePathRewrite | HTTPRouteQueryParamMatching | HTTPRouteResponseHeaderModification | GatewayHTTPListenerIsolation | GatewayInfrastructurePropagation | GatewayStaticAddresses | HTTPRouteBackendProtocolH2C | HTTPRouteBackendProtocolWebSocket | HTTPRouteBackendRequestHeaderModification | HTTPRouteBackendTimeout | HTTPRouteDestinationPortMatching | HTTPRoutePathRedirect | HTTPRoutePortRedirect | HTTPRouteRequestMirror | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | HTTPRouteSchemeRedirect | HTTPRouteParentRefPort | -|:---------------|:------------------------------|:----------------------|:------------|:-------------------|:-----------------------|:--------------------------|:-----------------------|:------------------------------|:--------------------------------------|:-------------------------------|:-----------------------------------|:-------------------------|:------------------------------|:------------------------------------|:--------------------------------------------|:--------------------------|:-----------------------------------|:------------------------|:------------------------|:-------------------------|:----------------------------------|:--------------------------|:--------------------------|:-------------------------| -| Kong | gateway-operator | v1.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.2.0-244-gea4944bb0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17.0-pre.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | -| envoyproxy | envoy-gateway | v1.2.0-rc.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | -| solo.io | gloo-gateway | v1.18.0 | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | -| traefik | traefik | v3.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | +| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Parent Ref Port | HTTPRoute Port Redirect | HTTPRoute Request Timeout | HTTPRoute Scheme Redirect | HTTPRoute Path Redirect | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | +|:---------------|:------------------------------|:----------|:-----------------------|:-------------------------|:----------------------------|:-------------------------|:---------------------------------|:-----------------------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:----------------------------|:--------------------------|:----------------------------|:----------------------------|:--------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | ### GRPCRoute -| Organization | Project | Version | Mode | GatewayHTTPListenerIsolation | GatewayInfrastructurePropagation | GatewayPort8080 | GatewayStaticAddresses | -|:---------------|:------------------------------|:----------------------|:------------|:-------------------------------|:-----------------------------------|:-------------------|:-------------------------| -| Kong | kubernetes-ingress-controller | v3.2.0-244-gea4944bb0 | expressions | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17.0-pre.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.2.0-rc.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.5.0 | default | :x: | :x: | :x: | :x: | -| traefik | traefik | v3.2 | default | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | ### TLSRoute -| Organization | Project | Version | Mode | GatewayHTTPListenerIsolation | GatewayInfrastructurePropagation | GatewayPort8080 | GatewayStaticAddresses | -|:---------------|:---------------------|:--------------|:--------|:-------------------------------|:-----------------------------------|:-------------------|:-------------------------| -| cilium | cilium | v1.17.0-pre.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.2.0-rc.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.5.0 | default | :x: | :x: | :x: | :x: | -| traefik | traefik | v3.2 | default | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:--------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | ## Mesh Profile ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRouteBackendProtocolH2C | HTTPRouteBackendProtocolWebSocket | HTTPRouteBackendRequestHeaderModification | HTTPRouteBackendTimeout | HTTPRouteDestinationPortMatching | HTTPRouteHostRewrite | HTTPRouteMethodMatching | HTTPRoutePathRedirect | HTTPRoutePathRewrite | HTTPRoutePortRedirect | HTTPRouteQueryParamMatching | HTTPRouteRequestMirror | HTTPRouteRequestMultipleMirrors | HTTPRouteRequestTimeout | HTTPRouteResponseHeaderModification | HTTPRouteSchemeRedirect | MeshClusterIPMatching | HTTPRouteParentRefPort | MeshConsumerRoute | -|:---------------|:----------|:--------------|:--------|:------------------------------|:------------------------------------|:--------------------------------------------|:--------------------------|:-----------------------------------|:-----------------------|:--------------------------|:------------------------|:-----------------------|:------------------------|:------------------------------|:-------------------------|:----------------------------------|:--------------------------|:--------------------------------------|:--------------------------|:------------------------|:-------------------------|:--------------------| -| cilium | cilium | v1.17.0-pre.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | HTTPRoute Parent Ref Port | Mesh Consumer Route | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------------|:----------------------| +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/implementations/v1.3.md b/site-src/implementations/v1.3.md new file mode 100644 index 0000000000..0ce9516a8e --- /dev/null +++ b/site-src/implementations/v1.3.md @@ -0,0 +1,45 @@ + +The following tables are populated from the conformance reports [uploaded by project implementations](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). They are separated into the extended features that each project supports listed in their reports. +Implementations only appear in this page if they pass Core conformance for the resource type, and the features listed should be Extended features. Implementations that submit conformance reports with skipped tests won't appear in the tables. + + + +???+ warning + + + This page is under active development and is not in its final form, + especially for the project name and the names of the features. + However, as it is based on submitted conformance reports, the information is correct. + + +## Gateway Profile + +### HTTPRoute + +| Organization | Project | Version | Mode | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | +|:---------------|:--------------|:----------|:--------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------| +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +### GRPCRoute + +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | + +### TLSRoute + +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | + +## Mesh Profile + +### HTTPRoute + +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | \ No newline at end of file From cdcca5f1eb2b541016a7c88fd7498f2fb21473c5 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Tue, 3 Jun 2025 13:18:43 -0400 Subject: [PATCH 027/224] chore: remove inactive reviewers (#3829) Signed-off-by: Shane Utt --- OWNERS_ALIASES | 2 -- 1 file changed, 2 deletions(-) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 8bdeafe24c..6e461c1596 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -32,9 +32,7 @@ aliases: gateway-api-conformance-reviewers: - candita - - michaelbeaumont - sunjayBhatia - - xunzhuo gateway-api-conformance-approvers: - arkodg From 69a4a5fe594924837bf5397f8a59b0e3bad277f5 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Tue, 3 Jun 2025 16:34:37 -0700 Subject: [PATCH 028/224] add httproute weight based routing mesh conformance tests (#3827) * add httproute weights mesh conformance tests * gofmt --- conformance/tests/mesh/httproute-weight.go | 143 +++++++++++++++++++ conformance/tests/mesh/httproute-weight.yaml | 19 +++ conformance/utils/echo/pod.go | 19 +++ 3 files changed, 181 insertions(+) create mode 100644 conformance/tests/mesh/httproute-weight.go create mode 100644 conformance/tests/mesh/httproute-weight.yaml diff --git a/conformance/tests/mesh/httproute-weight.go b/conformance/tests/mesh/httproute-weight.go new file mode 100644 index 0000000000..09ef3465b5 --- /dev/null +++ b/conformance/tests/mesh/httproute-weight.go @@ -0,0 +1,143 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "cmp" + "errors" + "fmt" + "math" + "slices" + "strings" + "sync" + "testing" + + "golang.org/x/sync/errgroup" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteWeight) +} + +var MeshHTTPRouteWeight = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteWeight", + Description: "An HTTPRoute with weighted backends", + Manifests: []string{"tests/mesh/httproute-weight.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + t.Run("Requests should have a distribution that matches the weight", func(t *testing.T) { + host := "echo" + expected := http.ExpectedResponse{ + Request: http.Request{Path: "/", Host: host}, + Response: http.Response{StatusCode: 200}, + Namespace: "gateway-conformance-mesh", + } + + // Assert request succeeds before doing our distribution check + client.MakeRequestAndExpectEventuallyConsistentResponse(t, expected, s.TimeoutConfig) + for i := 0; i < 10; i++ { + if err := testDistribution(t, client, expected); err != nil { + t.Logf("Traffic distribution test failed (%d/10): %s", i+1, err) + } else { + return + } + } + t.Fatal("Weighted distribution tests failed") + }) + }, +} + +func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedResponse) error { + const ( + concurrentRequests = 10 + tolerancePercentage = 0.05 + totalRequests = 500.0 + ) + var ( + g errgroup.Group + seenMutex sync.Mutex + seen = make(map[string]float64, 2 /* number of backends */) + expectedWeights = map[string]float64{ + "echo-v1": 0.7, + "echo-v2": 0.3, + } + ) + g.SetLimit(concurrentRequests) + for i := 0.0; i < totalRequests; i++ { + g.Go(func() error { + _, cRes, err := client.CaptureRequestResponseAndCompare(t, expected) + if err != nil { + return fmt.Errorf("failed: %w", err) + } + + seenMutex.Lock() + defer seenMutex.Unlock() + + for expectedBackend := range expectedWeights { + if strings.HasPrefix(cRes.Hostname, expectedBackend) { + seen[expectedBackend]++ + return nil + } + } + + return fmt.Errorf("request was handled by an unexpected pod %q", cRes.Hostname) + }) + } + + if err := g.Wait(); err != nil { + return fmt.Errorf("error while sending requests: %w", err) + } + + var errs []error + if len(seen) != 2 { + errs = append(errs, fmt.Errorf("expected only two backends to receive traffic")) + } + + for wantBackend, wantPercent := range expectedWeights { + gotCount, ok := seen[wantBackend] + + if !ok && wantPercent != 0.0 { + errs = append(errs, fmt.Errorf("expect traffic to hit backend %q - but none was received", wantBackend)) + continue + } + + gotPercent := gotCount / totalRequests + + if math.Abs(gotPercent-wantPercent) > tolerancePercentage { + errs = append(errs, fmt.Errorf("backend %q weighted traffic of %v not within tolerance %v (+/-%f)", + wantBackend, + gotPercent, + wantPercent, + tolerancePercentage, + )) + } + } + slices.SortFunc(errs, func(a, b error) int { + return cmp.Compare(a.Error(), b.Error()) + }) + return errors.Join(errs...) +} diff --git a/conformance/tests/mesh/httproute-weight.yaml b/conformance/tests/mesh/httproute-weight.yaml new file mode 100644 index 0000000000..870c8a41dd --- /dev/null +++ b/conformance/tests/mesh/httproute-weight.yaml @@ -0,0 +1,19 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-weighted-backends + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - backendRefs: + - name: echo-v1 + port: 8080 + weight: 70 + - name: echo-v2 + port: 8080 + weight: 30 diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index 3861f53c73..0222ff12dd 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -105,6 +105,9 @@ func makeRequest(t *testing.T, exp *http.ExpectedResponse) []string { } func compareRequest(exp http.ExpectedResponse, resp Response) error { + if exp.ExpectedRequest == nil { + exp.ExpectedRequest = &http.ExpectedRequest{} + } wantReq := exp.ExpectedRequest wantResp := exp.Response if fmt.Sprint(wantResp.StatusCode) != resp.Code { @@ -220,3 +223,19 @@ func ConnectToAppInNamespace(t *testing.T, s *suite.ConformanceTestSuite, app Me rcfg: s.RestConfig, } } + +func (m *MeshPod) CaptureRequestResponseAndCompare(t *testing.T, exp http.ExpectedResponse) ([]string, Response, error) { + req := makeRequest(t, &exp) + + resp, err := m.request(req) + if err != nil { + tlog.Logf(t, "Request %v failed, not ready yet: %v", req, err.Error()) + return []string{}, Response{}, err + } + tlog.Logf(t, "Got resp %v", resp) + if err := compareRequest(exp, resp); err != nil { + tlog.Logf(t, "Response expectation failed for request: %v not ready yet: %v", req, err) + return []string{}, Response{}, err + } + return req, resp, nil +} From a879542fff1b622e63355cafde4da1a86545bdcc Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Wed, 4 Jun 2025 15:58:37 -0700 Subject: [PATCH 029/224] same-namespace-attachment-mesh-conformance (#3833) --- .../mesh/httproute-simple-same-namespace.go | 52 +++++++++++++++++++ .../mesh/httproute-simple-same-namespace.yaml | 15 ++++++ 2 files changed, 67 insertions(+) create mode 100644 conformance/tests/mesh/httproute-simple-same-namespace.go create mode 100644 conformance/tests/mesh/httproute-simple-same-namespace.yaml diff --git a/conformance/tests/mesh/httproute-simple-same-namespace.go b/conformance/tests/mesh/httproute-simple-same-namespace.go new file mode 100644 index 0000000000..77813f29af --- /dev/null +++ b/conformance/tests/mesh/httproute-simple-same-namespace.go @@ -0,0 +1,52 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteSimpleSameNamespace) +} + +var MeshHTTPRouteSimpleSameNamespace = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteSimpleSameNamespace", + Description: "A single HTTPRoute in the gateway-conformance-mesh namespace attaches to a Service in the same namespace", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + }, + Manifests: []string{"tests/mesh/httproute-simple-same-namespace.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + t.Run("Simple HTTP request should reach infra-backend", func(t *testing.T) { + client.MakeRequestAndExpectEventuallyConsistentResponse(t, http.ExpectedResponse{ + Request: http.Request{Path: "/", Host: "echo"}, + Response: http.Response{StatusCode: 200}, + Backend: "echo-v1", + Namespace: ns, + }, s.TimeoutConfig) + }) + }, +} diff --git a/conformance/tests/mesh/httproute-simple-same-namespace.yaml b/conformance/tests/mesh/httproute-simple-same-namespace.yaml new file mode 100644 index 0000000000..974d819d92 --- /dev/null +++ b/conformance/tests/mesh/httproute-simple-same-namespace.yaml @@ -0,0 +1,15 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: gateway-conformance-mesh-test + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - backendRefs: + - name: echo-v1 + port: 8080 From 77baa438dc3cb7be41c89fcaf6f9dc9407489234 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Wed, 4 Jun 2025 19:16:37 -0700 Subject: [PATCH 030/224] add httproute matching conformance (#3831) --- conformance/tests/mesh/httproute-matching.go | 93 +++++++++++++++++++ .../tests/mesh/httproute-matching.yaml | 32 +++++++ 2 files changed, 125 insertions(+) create mode 100644 conformance/tests/mesh/httproute-matching.go create mode 100644 conformance/tests/mesh/httproute-matching.yaml diff --git a/conformance/tests/mesh/httproute-matching.go b/conformance/tests/mesh/httproute-matching.go new file mode 100644 index 0000000000..e0673c3a1d --- /dev/null +++ b/conformance/tests/mesh/httproute-matching.go @@ -0,0 +1,93 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteMatching) +} + +var MeshHTTPRouteMatching = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteMatching", + Description: "A single HTTPRoute with path and header matching for different backends", + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + }, + Manifests: []string{"tests/mesh/httproute-matching.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{{ + Request: http.Request{Path: "/"}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/example"}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/", Headers: map[string]string{"Version": "one"}}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/v2"}, + Backend: "echo-v2", + Namespace: ns, + }, { + Request: http.Request{Path: "/v2/example"}, + Backend: "echo-v2", + Namespace: ns, + }, { + Request: http.Request{Path: "/", Headers: map[string]string{"Version": "two"}}, + Backend: "echo-v2", + Namespace: ns, + }, { + Request: http.Request{Path: "/v2/"}, + Backend: "echo-v2", + Namespace: ns, + }, { + // Not a path segment prefix so should not match /v2. + Request: http.Request{Path: "/v2example"}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/foo/v2/example"}, + Backend: "echo-v1", + Namespace: ns, + }} + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-matching.yaml b/conformance/tests/mesh/httproute-matching.yaml new file mode 100644 index 0000000000..fceec95b85 --- /dev/null +++ b/conformance/tests/mesh/httproute-matching.yaml @@ -0,0 +1,32 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-matching + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - path: + type: PathPrefix + value: / + - headers: + - name: version + value: one + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /v2 + - headers: + - name: version + value: two + backendRefs: + - name: echo-v2 + port: 8080 From d7b4030b2e536d900460c7d73ed291288429e3fb Mon Sep 17 00:00:00 2001 From: Craig Brookes Date: Thu, 5 Jun 2025 15:38:40 +0100 Subject: [PATCH 031/224] GEP-2627 DNS Configuration - Initial Provisional PR (#2712) * draft dns configuration for gateway API GEP-2627 minor tweaks Update geps/gep-2627/index.md Co-authored-by: Candace Holman Update geps/gep-2627/index.md Co-authored-by: Candace Holman Update geps/gep-2627/index.md Co-authored-by: Candace Holman * changes post review * rewording * Update geps/gep-2627/index.md Co-authored-by: Nick Young * Update geps/gep-2627/index.md Co-authored-by: Nick Young * Update geps/gep-2627/index.md Co-authored-by: Nick Young * Update geps/gep-2627/index.md Co-authored-by: Nick Young * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * Update geps/gep-2627/index.md Co-authored-by: Shane Utt * minor tweaks to the text and link to kuadrant as an example of a DNSPolicy type API * fix new line * move kuadrant to a reference --------- Co-authored-by: Candace Holman Co-authored-by: Nick Young Co-authored-by: Shane Utt --- geps/gep-2627/index.md | 51 +++++++++++++++++++++++++++++++++++++ geps/gep-2627/metadata.yaml | 7 +++++ 2 files changed, 58 insertions(+) create mode 100644 geps/gep-2627/index.md create mode 100644 geps/gep-2627/metadata.yaml diff --git a/geps/gep-2627/index.md b/geps/gep-2627/index.md new file mode 100644 index 0000000000..86a36152a8 --- /dev/null +++ b/geps/gep-2627/index.md @@ -0,0 +1,51 @@ +# GEP-2627: DNS configuration within Gateway API + +* Issue: [#2627](https://github.com/kubernetes-sigs/gateway-api/issues/2627) +* Status: Provisional + +## TLDR + +For gateway infrastructure to be valuable we need to be able to connect clients to these gateways. A common way to achieve this is to use domain names/hostnames and DNS. The guidelines for DNS configuration are a critical piece of service networking, but this is currently not expressible as part of Gateway API. Instead of leaving this unspecified and having implementations likely to do this in different ways, the purpose of this proposal is to provide a standard way to specify DNS for Gateways. + +## Goals +* Provide DNS specification for Gateway resources +* Support multiple DNS providers and a selection mechanism for Gateways +* Provide Gateway status to communicate the state of provisioned DNS +* Increase portability and supportability between Gateway API implementations and third party controllers offering DNS integration. + +## Non-Goals + +* Providing any upstream hostname validation mechanisms. We can provide status for validation failure, but implementations are responsible for validation. +* Multi-cluster DNS for multi-cluster ingress solutions (at least not as part of the initial API) + +## Use Cases + +As a cluster administrator, I manage a set of domains and a set of gateways. I would like to declaratively define which gateways should be used for provisioning DNS records, and, if necessary, which DNS provider to use to configure connectivity for clients accessing these domains and my gateway so that I can see and configure which DNS provider is being used. + +As a cluster administrator, I would like to have the DNS names automatically populated into my specified DNS zones as a set of records based on the assigned addresses of my gateways so that I do not have to undertake external automation or management of this essential task. + +As a cluster administrator I would have the status of the DNS records reported back to me, so that I can leverage existing kube based monitoring tools to know the status of the integration. + +As a cluster administrator, I would like the DNS records to be updated automatically if the `spec` of assigned gateways changes, whether those changes are for IP address or hostname. + +As a DNS administrator, I should be able to ensure that only approved External DNS controllers can make changes to DNS zone configuration. (This should in general be taken care of by DNS system <-> External DNS controller interactions like user credentials and operation status responses, but it is important to remember that it needs to happen). + +## API + +Initial draft will not offer an API yet until the use cases are agreed. Some thoughts worth thinking about: +- I think it is important that we try to move away from APIs based on annotations which, while convenient, are not a full API and suffer from several limitations. An example: I want to configure a listener with a domain I own that is in a different provider than the domains of the other listeners. I want to add a new option to configure a particular weighting and so on. Soon you end up with a large set of connected annotations that often grow in complexity that really should be expressed as an API. + +- It is also important that this API can be delegated to controllers other than the Gateway API provider/implementor. This is because there are existing solutions that may want to support whatever API decided upon. It should not **have** to be a gateway provider that has to integrate with many DNS providers. + +## Conformance Details + +TBD + +## Alternatives + +it is possible to use `external-dns` to manage dns based on HTTPRoutes and Gateways https://github.com/kubernetes-sigs/external-dns/blob/7f3c10d65297ec1c4bcc8dd6f88c189b7f3e80d0/docs/tutorials/gateway-api.md. The aim of this GEP is not remove this as an option, but instead provide a common API that could then be leveraged by something like external-dns. + + +## References + +The Kuadrant project, offers a [DNSPolicy API](https://docs.kuadrant.io/1.2.x/kuadrant-operator/doc/reference/dnspolicy/#dnspolicy) which in part was the basis and inspiration for opening this GEP. The DNSPolicy offered by Kuadrant goes beyond what is outlined here as it also handles multi-cluster ingress and offers common routing options such as GEO and Weighted responses. \ No newline at end of file diff --git a/geps/gep-2627/metadata.yaml b/geps/gep-2627/metadata.yaml new file mode 100644 index 0000000000..17dfb34248 --- /dev/null +++ b/geps/gep-2627/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2627 +name: DNS configuration for Gateway API +status: Provisional +authors: + - maleck13 From b3e0aa92d9ea636f41e6b82adf6dd2d68b51f3ff Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Fri, 6 Jun 2025 17:24:45 -0500 Subject: [PATCH 032/224] Add Istio report for 1.3.0 (#3808) Signed-off-by: Keith Mattix II --- .../reports/v1.3.0/istio-istio/README.md | 11 ++ .../experimental-1.26.1-default-report.yaml | 131 ++++++++++++++++++ site-src/implementations/v1.1.md | 2 +- site-src/implementations/v1.2.md | 28 ++-- site-src/implementations/v1.3.md | 10 +- 5 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 conformance/reports/v1.3.0/istio-istio/README.md create mode 100644 conformance/reports/v1.3.0/istio-istio/experimental-1.26.1-default-report.yaml diff --git a/conformance/reports/v1.3.0/istio-istio/README.md b/conformance/reports/v1.3.0/istio-istio/README.md new file mode 100644 index 0000000000..e188b4f7e9 --- /dev/null +++ b/conformance/reports/v1.3.0/istio-istio/README.md @@ -0,0 +1,11 @@ +# Istio + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|x|[1.26.1](https://github.com/istio/istio/releases/tag/1.26.1)|x|[1.26.1 report](./experimental-1.26.1-default-report.yaml)| + +## Reproduce + +Istio conformance tests can be reproduced by running `prow/integ-suite-kind.sh test.integration.pilot.kube` from within the [Istio repo](https://github.com/istio/istio). diff --git a/conformance/reports/v1.3.0/istio-istio/experimental-1.26.1-default-report.yaml b/conformance/reports/v1.3.0/istio-istio/experimental-1.26.1-default-report.yaml new file mode 100644 index 0000000000..e55868fe2f --- /dev/null +++ b/conformance/reports/v1.3.0/istio-istio/experimental-1.26.1-default-report.yaml @@ -0,0 +1,131 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-27T17:51:14Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - '@istio/maintainers' + organization: istio + project: istio + url: https://istio.io/ + version: "1.26.1" +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 3 + Skipped: 0 + supportedFeatures: + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - MeshConsumerRoute + unsupportedFeatures: + - MeshClusterIPMatching + name: MESH-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 25 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 2 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure +- HTTPRouteRequestPercentageMirror diff --git a/site-src/implementations/v1.1.md b/site-src/implementations/v1.1.md index bc97fc01fb..21063b28e6 100644 --- a/site-src/implementations/v1.1.md +++ b/site-src/implementations/v1.1.md @@ -18,9 +18,9 @@ Implementations only appear in this page if they pass Core conformance for the r | Organization | Project | Version | Mode | Gateway Port 8080 | HTTPRoute Host Rewrite | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Port Redirect | HTTPRoute Parent Ref Port | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | |:----------------|:-----------------------------------|:-------------------|:---------------------------------|:--------------------|:-------------------------|:--------------------------|:---------------------------|:-----------------------------------------|:----------------------------|:----------------------------|:-------------------------|:---------------------------------|:--------------------------|:----------------------------|:----------------------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------------------|:----------------------------| -| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-global-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | diff --git a/site-src/implementations/v1.2.md b/site-src/implementations/v1.2.md index 1c38f3351d..c26434b418 100644 --- a/site-src/implementations/v1.2.md +++ b/site-src/implementations/v1.2.md @@ -16,26 +16,26 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Parent Ref Port | HTTPRoute Port Redirect | HTTPRoute Request Timeout | HTTPRoute Scheme Redirect | HTTPRoute Path Redirect | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | -|:---------------|:------------------------------|:----------|:-----------------------|:-------------------------|:----------------------------|:-------------------------|:---------------------------------|:-----------------------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:----------------------------|:--------------------------|:----------------------------|:----------------------------|:--------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | -| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Path Rewrite | HTTPRoute Response Header Modification | HTTPRoute Method Matching | HTTPRoute Query Param Matching | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Parent Ref Port | HTTPRoute Port Redirect | HTTPRoute Request Timeout | HTTPRoute Scheme Redirect | HTTPRoute Path Redirect | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | +|:---------------|:------------------------------|:----------|:-----------------------|:-------------------------|:-------------------------|:-----------------------------------------|:----------------------------|:---------------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:----------------------------|:--------------------------|:----------------------------|:----------------------------|:--------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | ### GRPCRoute | Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | |:---------------|:------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | | cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | | istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/site-src/implementations/v1.3.md b/site-src/implementations/v1.3.md index 0ce9516a8e..552e98cd54 100644 --- a/site-src/implementations/v1.3.md +++ b/site-src/implementations/v1.3.md @@ -21,6 +21,7 @@ Implementations only appear in this page if they pass Core conformance for the r | airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | ### GRPCRoute @@ -28,6 +29,7 @@ Implementations only appear in this page if they pass Core conformance for the r |:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| | cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | ### TLSRoute @@ -35,11 +37,13 @@ Implementations only appear in this page if they pass Core conformance for the r |:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| | cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | ## Mesh Profile ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | -|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------| -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | \ No newline at end of file +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | HTTPRoute Parent Ref Port | Mesh Consumer Route | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------------|:----------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file From 1b895febbb4acb2864f8ee1bab2750df7f31217f Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Fri, 6 Jun 2025 23:46:38 +0100 Subject: [PATCH 033/224] Add Kubvernor conformance report (#3813) * Kubevernor conformance report * Adding Kubvernor section to implementations section --- .../reports/v1.2.1/kubvernor/README.md | 51 +++++++++++++++++++ .../kubvernor-conformance-output-1.2.1.yaml | 30 +++++++++++ site-src/implementations.md | 9 ++++ 3 files changed, 90 insertions(+) create mode 100644 conformance/reports/v1.2.1/kubvernor/README.md create mode 100644 conformance/reports/v1.2.1/kubvernor/kubvernor-conformance-output-1.2.1.yaml diff --git a/conformance/reports/v1.2.1/kubvernor/README.md b/conformance/reports/v1.2.1/kubvernor/README.md new file mode 100644 index 0000000000..56b93da84f --- /dev/null +++ b/conformance/reports/v1.2.1/kubvernor/README.md @@ -0,0 +1,51 @@ +# Kubvernor + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|:-------------:|:------------------------------------------------------------------:|:-------------:|:--------------------------------------------------:| +|standard |[v0.1.0](https://github.com/kubvernor/kubvernor/releases/tag/0.1.0) |default |[Report](./kubvernor-conformance-output-1.2.1.yaml) | + + + + +## Reproduce + +0. Install Docker and Kind + +1. Clone the Kubvernor GitHub repository + + ```bash + git clone https://github.com/kubvernor/kubvernor && cd kubvernor + ``` + +2. Deploy your cluster + + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://github.com/kubernetes-sigs/gateway-api/blob/main/hack/implementations/common/create-cluster.sh | sh + + ``` + +3. Compile and run Kubvernor + + ```bash + # Install Rust + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + + # Start Kubvernor + export CONTROL_PLANE_IP= + ./run_kubvernor.sh + + ``` + +4. Run conformance tests + + ```bash + ./run_conformance_tests.sh + ``` + +5. Check the results + + ```bash + cat conformance/kubvernor-conformance-output-1.2.1.yaml + ``` diff --git a/conformance/reports/v1.2.1/kubvernor/kubvernor-conformance-output-1.2.1.yaml b/conformance/reports/v1.2.1/kubvernor/kubvernor-conformance-output-1.2.1.yaml new file mode 100644 index 0000000000..c5002fbec1 --- /dev/null +++ b/conformance/reports/v1.2.1/kubvernor/kubvernor-conformance-output-1.2.1.yaml @@ -0,0 +1,30 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-05-24T16:25:25+01:00" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.1 +implementation: + contact: + - nowakd@gmail.com + organization: kubvernor + project: kubvernor + url: https://github.com/kubvernor/kubvernor + version: 0.1.0 +kind: ConformanceReport +mode: default +profiles: + - core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + name: GATEWAY-GRPC + summary: Core tests succeeded. + - core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + name: GATEWAY-HTTP + summary: Core tests succeeded. diff --git a/site-src/implementations.md b/site-src/implementations.md index efdffc5c63..e65f26aa4f 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -35,6 +35,7 @@ cover, and documentation to help users get started. - [kgateway][37] (GA) - [Kong Ingress Controller][10] (GA) - [Kong Gateway Operator][35] (GA) +* [Kubvernor][39](work in progress) - [Kuma][11] (GA) - [LiteSpeed Ingress Controller][19] - [LoxiLB][36] (beta) @@ -97,6 +98,7 @@ cover, and documentation to help users get started. [36]:#loxilb [37]:#kgateway [38]:#google-cloud-service-mesh +[39]:#kubvernor [gamma]:/concepts/gamma/ @@ -418,6 +420,12 @@ For help and support with Kong Gateway operator please feel free to [create an i [kgo-issue-new]:https://github.com/Kong/gateway-operator/issues/new [kgo-disc-new]:https://github.com/Kong/gateway-operator/discussions/new + +### Kubvernor +[Kubvernor][kubvernor] is an open-source, highly experimental implementation of API controller in Rust programming language. Currently, Kubernor supports Envoy Proxy. The project aims to be as generic as possible so Kubvernor can be used to manage/deploy different gateways (Envoy, Nginx, HAProxy, etc.). + +[kubvernor]:https://github.com/kubvernor/kubvernor + ### Kuma [![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-Kuma-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/kumahq-kuma) @@ -599,3 +607,4 @@ For help and support with Kuadrant's implementation please feel free to [create [kuadrant]:https://kuadrant.io/ [kuadrant-issue-new]:https://github.com/Kuadrant/kuadrant-operator/issues/new [kuadrant-slack]:https://kubernetes.slack.com/archives/C05J0D0V525 + From c3dd6c38f7c798aeb6ac0525a2189c10ac2e75a8 Mon Sep 17 00:00:00 2001 From: Saylor Berman Date: Fri, 6 Jun 2025 16:46:45 -0600 Subject: [PATCH 034/224] Add NGINX Gateway Fabric v2.0 conformance report (#3836) Adding conformance report for the v2.0 NGINX Gateway Fabric release. Now supporting Gateway API v1.3. --- .../nginx-nginx-gateway-fabric/README.md | 23 +++++ .../experimental-2.0.0-default-report.yaml | 97 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md create mode 100644 conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml diff --git a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md new file mode 100644 index 0000000000..ae54954fae --- /dev/null +++ b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md @@ -0,0 +1,23 @@ +# Nginx NGINX Gateway Fabric + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|--------------|-----------------------------------------------------------------------------|---------|--------------------------------------------------| +| experimental | [v2.0.0](https://github.com/nginx/nginx-gateway-fabric/releases/tag/v2.0.0) | default | [v2.0.0 report](./experimental-2.0.0-default-report.yaml) | + +## Reproduce + +To reproduce results, clone the NGF repository: + +```shell +git clone https://github.com/nginx/nginx-gateway-fabric.git && cd nginx-gateway-fabric/tests +``` + +Follow the steps in the [NGINX Gateway Fabric Testing](https://github.com/nginx/nginx-gateway-fabric/blob/main/tests/README.md) document to run the conformance tests. If you are running tests on the `edge` version, then you don't need to build any images. Otherwise, you'll need to check out the specific release tag that you want to test, and then build and load the images onto your cluster, per the steps in the README. + +After running, see the conformance report: + +```shell +cat conformance-profile.yaml +``` diff --git a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml new file mode 100644 index 0000000000..d6d0353a10 --- /dev/null +++ b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml @@ -0,0 +1,97 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-06-05T16:32:34Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/nginx/nginx-gateway-fabric/discussions/new/choose + organization: nginx + project: nginx-gateway-fabric + url: https://github.com/nginx/nginx-gateway-fabric + version: v2.0.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 14 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteParentRefPort + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure From 3fa0912a5d1ef46a55084ad3f8b8feb5478aedf0 Mon Sep 17 00:00:00 2001 From: Siyi Wang <32469039+syw14@users.noreply.github.com> Date: Mon, 9 Jun 2025 14:50:24 -0700 Subject: [PATCH 035/224] Fix godoc comment for GatewaySpecAddress (#3845) * Update naming * fix failures --- apis/v1beta1/gateway_types.go | 2 +- pkg/generated/openapi/zz_generated.openapi.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go index 80c746fcdd..1998c2ac27 100644 --- a/apis/v1beta1/gateway_types.go +++ b/apis/v1beta1/gateway_types.go @@ -131,7 +131,7 @@ type RouteNamespaces = v1.RouteNamespaces // +k8s:deepcopy-gen=false type RouteGroupKind = v1.RouteGroupKind -// GatewayAddress describes an address that can be bound to a Gateway. +// GatewaySpecAddress describes an address that can be bound to a Gateway. // +k8s:deepcopy-gen=false type GatewaySpecAddress = v1.GatewaySpecAddress diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 60e2caa920..f4a7d0d4f2 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -4007,7 +4007,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpecAddress(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "GatewayAddress describes an address that can be bound to a Gateway.", + Description: "GatewaySpecAddress describes an address that can be bound to a Gateway.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { From 962d22f43dd30e80752cc586a971a71d308526b9 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Mon, 9 Jun 2025 15:06:23 -0700 Subject: [PATCH 036/224] add mesh conformance for httproute-queryparmas-match (#3834) --- .../mesh/httproute-query-param-matching.go | 135 ++++++++++++++++++ .../mesh/httproute-query-param-matching.yaml | 85 +++++++++++ pkg/features/mesh.go | 8 ++ 3 files changed, 228 insertions(+) create mode 100644 conformance/tests/mesh/httproute-query-param-matching.go create mode 100644 conformance/tests/mesh/httproute-query-param-matching.yaml diff --git a/conformance/tests/mesh/httproute-query-param-matching.go b/conformance/tests/mesh/httproute-query-param-matching.go new file mode 100644 index 0000000000..53316d9bc8 --- /dev/null +++ b/conformance/tests/mesh/httproute-query-param-matching.go @@ -0,0 +1,135 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteQueryParamMatching) +} + +var MeshHTTPRouteQueryParamMatching = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteQueryParamMatching", + Description: "A single HTTPRoute with query param matching for different backends", + Manifests: []string{"tests/mesh/httproute-query-param-matching.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteQueryParamMatching, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{{ + Request: http.Request{Path: "/?animal=whale"}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/?animal=dolphin"}, + Backend: "echo-v2", + Namespace: ns, + }, { + Request: http.Request{Path: "/?animal=whale&otherparam=irrelevant"}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/?animal=dolphin&color=yellow"}, + Backend: "echo-v2", + Namespace: ns, + }, { + Request: http.Request{Path: "/?color=blue"}, + Response: http.Response{StatusCode: 404}, + }, { + Request: http.Request{Path: "/?animal=dog"}, + Response: http.Response{StatusCode: 404}, + }, { + Request: http.Request{Path: "/?animal=whaledolphin"}, + Response: http.Response{StatusCode: 404}, + }, { + Request: http.Request{Path: "/"}, + Response: http.Response{StatusCode: 404}, + }} + + // Combinations of query param matching with other core matches. + testCases = append(testCases, []http.ExpectedResponse{ + { + Request: http.Request{Path: "/path1?animal=whale"}, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{Headers: map[string]string{"version": "one"}, Path: "/?animal=whale"}, + Backend: "echo-v2", + Namespace: ns, + }, + }...) + + // Ensure that combinations of matches which are OR'd together match + // even if only one of them is used in the request. + testCases = append(testCases, []http.ExpectedResponse{ + { + Request: http.Request{Path: "/path3?animal=shark"}, + Backend: "echo-v1", + Namespace: ns, + }, + { + Request: http.Request{Headers: map[string]string{"version": "three"}, Path: "/path4?animal=kraken"}, + Backend: "echo-v1", + Namespace: ns, + }, + }...) + + // Ensure that combinations of match types which are ANDed together do not match + // when only a subset of match types is used in the request. + testCases = append(testCases, []http.ExpectedResponse{ + { + Request: http.Request{Path: "/?animal=shark"}, + Response: http.Response{StatusCode: 404}, + }, + { + Request: http.Request{Path: "/path4?animal=kraken"}, + Response: http.Response{StatusCode: 404}, + }, + }...) + + // For requests that satisfy multiple matches, ensure precedence order + // defined by the Gateway API spec is maintained. + testCases = append(testCases, []http.ExpectedResponse{ + { + Request: http.Request{Path: "/path5?animal=hydra"}, + Backend: "echo-v1", + Namespace: ns, + }, + }...) + + for i := range testCases { + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-query-param-matching.yaml b/conformance/tests/mesh/httproute-query-param-matching.yaml new file mode 100644 index 0000000000..0dd5ee4a80 --- /dev/null +++ b/conformance/tests/mesh/httproute-query-param-matching.yaml @@ -0,0 +1,85 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-query-param-matching + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - matches: + - queryParams: + - name: animal + value: whale + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - queryParams: + - name: animal + value: dolphin + backendRefs: + - name: echo-v2 + port: 8080 + + # Combinations with core match types. + - matches: + - path: + type: PathPrefix + value: /path1 + queryParams: + - name: animal + value: whale + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - headers: + - name: version + value: one + queryParams: + - name: animal + value: whale + backendRefs: + - name: echo-v2 + port: 8080 + + # Match of the form (cond1 AND cond2) OR (cond3 AND cond4 AND cond5) + - matches: + - path: + type: PathPrefix + value: /path3 + queryParams: + - name: animal + value: shark + - path: + type: PathPrefix + value: /path4 + headers: + - name: version + value: three + queryParams: + - name: animal + value: kraken + backendRefs: + - name: echo-v1 + port: 8080 + + # Matches for checking precedence. + - matches: + - path: + type: PathPrefix + value: /path5 + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - queryParams: + - name: animal + value: hydra + backendRefs: + - name: echo-v2 + port: 8080 diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index f088cdad83..d191dc3846 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -58,6 +58,8 @@ const ( SupportMeshHTTPRouteRedirectPath FeatureName = "MeshHTTPRouteRedirectPath" // This option indicates support for HTTPRoute backend request header modification SupportMeshHTTPRouteBackendRequestHeaderModification FeatureName = "MeshHTTPRouteBackendRequestHeaderModification" + // This option indicates mesh support for HTTPRoute query param matching (extended conformance). + SupportMeshHTTPRouteQueryParamMatching FeatureName = "MeshHTTPRouteQueryParamMatching" ) var ( @@ -101,6 +103,11 @@ var ( Name: SupportMeshHTTPRouteBackendRequestHeaderModification, Channel: FeatureChannelStandard, } + // MeshHTTPRouteRedirectPath contains metadata for the MeshHTTPRouteRedirectPath feature. + MeshHTTPRouteQueryParamMatching = Feature{ + Name: SupportMeshHTTPRouteQueryParamMatching, + Channel: FeatureChannelStandard, + } ) // MeshExtendedFeatures includes all the supported features for the service mesh at @@ -112,4 +119,5 @@ var MeshExtendedFeatures = sets.New( MeshHTTPRouteSchemeRedirect, MeshHTTPRouteRedirectPath, MeshHTTPRouteBackendRequestHeaderModification, + MeshHTTPRouteQueryParamMatching, ) From 270d637886ff72a5c24431dba45e0f4b88fdeb17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:56:23 -0700 Subject: [PATCH 037/224] build(deps): bump google.golang.org/grpc from 1.71.1 to 1.73.0 (#3842) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.1 to 1.73.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.73.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.73.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 46c6618d28..4bf07ec2f5 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/stretchr/testify v1.10.0 golang.org/x/net v0.39.0 golang.org/x/sync v0.13.0 - google.golang.org/grpc v1.71.1 + google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 k8s.io/api v0.32.3 @@ -70,14 +70,14 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/oauth2 v0.25.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/sys v0.32.0 // indirect golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 6c92e7ba96..b380233c61 100644 --- a/go.sum +++ b/go.sum @@ -142,16 +142,16 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -173,8 +173,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -207,10 +207,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= +google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From 17a60f668a0d0ff6dd5bdbbfb91fd74702a84532 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Wed, 11 Jun 2025 04:26:59 -0700 Subject: [PATCH 038/224] fix meshredirectport and schemeredirect mesh conformance features (#3847) * include meshredirectport in extended * Update mesh.go --- pkg/features/mesh.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index d191dc3846..4d7ca20b29 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -82,7 +82,7 @@ var ( // MeshHTTPRouteSchemeRedirect contains metadata for the MeshHTTPRouteSchemeRedirect feature. MeshHTTPRouteSchemeRedirect = Feature{ - Name: SupportMeshHTTPRouteRewritePath, + Name: SupportMeshHTTPRouteSchemeRedirect, Channel: FeatureChannelStandard, } @@ -117,6 +117,7 @@ var MeshExtendedFeatures = sets.New( MeshConsumerRouteFeature, MeshHTTPRouteRewritePath, MeshHTTPRouteSchemeRedirect, + MeshHTTPRouteRedirectPort, MeshHTTPRouteRedirectPath, MeshHTTPRouteBackendRequestHeaderModification, MeshHTTPRouteQueryParamMatching, From 6cd1558a9ed65ab0afb036a869f8a8530b8d68d8 Mon Sep 17 00:00:00 2001 From: Bob Tian Date: Wed, 11 Jun 2025 10:02:56 -0700 Subject: [PATCH 039/224] Add body to http.Request and roundTripper.request to extend conformance util. (#3853) --- conformance/utils/http/http.go | 2 ++ conformance/utils/roundtripper/roundtripper.go | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index 7866790321..18b5e1feb0 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -70,6 +70,7 @@ type Request struct { Headers map[string]string UnfollowRedirect bool Protocol string + Body string } // ExpectedRequest defines expected properties of a request that reaches a backend. @@ -139,6 +140,7 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch Protocol: expected.Request.Protocol, Headers: map[string][]string{}, UnfollowRedirect: expected.Request.UnfollowRedirect, + Body: expected.Request.Body, } if expected.Request.Headers != nil { diff --git a/conformance/utils/roundtripper/roundtripper.go b/conformance/utils/roundtripper/roundtripper.go index c37f4500aa..f79508784f 100644 --- a/conformance/utils/roundtripper/roundtripper.go +++ b/conformance/utils/roundtripper/roundtripper.go @@ -29,6 +29,7 @@ import ( "net/http/httputil" "net/url" "regexp" + "strings" "testing" "golang.org/x/net/http2" @@ -59,6 +60,7 @@ type Request struct { CertPem []byte KeyPem []byte Server string + Body string } // String returns a printable version of Request for logging. Note that the @@ -194,7 +196,12 @@ func (d *DefaultRoundTripper) defaultRoundTrip(request Request, transport http.R ctx, cancel := context.WithTimeout(context.Background(), d.TimeoutConfig.RequestTimeout) defer cancel() ctx = withT(ctx, request.T) - req, err := http.NewRequestWithContext(ctx, method, request.URL.String(), nil) + + var reqBody io.Reader + if request.Body != "" { + reqBody = strings.NewReader(request.Body) + } + req, err := http.NewRequestWithContext(ctx, method, request.URL.String(), reqBody) if err != nil { return nil, nil, err } From 7d8e56bfda71e77acb23b664643cc22619af4d1e Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 11 Jun 2025 14:52:55 -0400 Subject: [PATCH 040/224] Initial Linkerd 1.3.0 conformance reports (#3839) * Conformance reports for Linkerd and Buoyant Enterprise for Linkerd Signed-off-by: Flynn * Tell people where to stand to run the tests. Signed-off-by: Flynn * Wordsmithing. Signed-off-by: Flynn * Update conformance report (with standard report names and reproduction scripts) Signed-off-by: Flynn * Clean up lint failures. Signed-off-by: Flynn * Correctly mark unsupported features, and clean up run-conformance scripts a touch Signed-off-by: Flynn * Fix typos :man_facepalming: Signed-off-by: Flynn * Linkerd's Gateway API support is not experimental. Signed-off-by: Flynn * Update conformance results now that all the mesh tests are correctly being run Signed-off-by: Flynn * Update READMEs to note that these tests used the v1.3.0 CRDs, but the main branch. (There are better MESH-profile tests on main that I wanted to take advantage of.) Signed-off-by: Flynn --------- Signed-off-by: Flynn --- .../buoyant-enterprise-for-linkerd/README.md | 32 +++++++++ .../run-conformance.sh | 65 ++++++++++++++++++ .../standard-2.18-default-report.yaml | 64 ++++++++++++++++++ .../reports/v1.3.0/linkerd-linkerd/README.md | 65 ++++++++++++++++++ .../v1.3.0/linkerd-linkerd/run-conformance.sh | 66 +++++++++++++++++++ .../standard-2.18-default-report.yaml | 64 ++++++++++++++++++ site-src/implementations.md | 2 +- 7 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/README.md create mode 100644 conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/run-conformance.sh create mode 100644 conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/standard-2.18-default-report.yaml create mode 100644 conformance/reports/v1.3.0/linkerd-linkerd/README.md create mode 100644 conformance/reports/v1.3.0/linkerd-linkerd/run-conformance.sh create mode 100644 conformance/reports/v1.3.0/linkerd-linkerd/standard-2.18-default-report.yaml diff --git a/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/README.md b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/README.md new file mode 100644 index 0000000000..e598c55fd2 --- /dev/null +++ b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/README.md @@ -0,0 +1,32 @@ +# Buoyant Enterprise for Linkerd + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|--------------|-------------------------------------------|---------|--------------------------------------------------------| +| standard | [enterprise-2.18](https://docs.buoyant.io/buoyant-enterprise-linkerd/latest/overview//) | default | [enterprise-2.18 report](./standard-2.18-default-report.yaml) | + +## Notes + +This report uses the v1.3.0 Gateway API CRDs, but was run using the tests on +the `main` branch at commit `6cd1558a9e`, in order to take advantage more +effective tests for the `MESH` conformance profile that landed after v1.3.0 +was cut. + +## Reproduce + +To reproduce a Buoyant Enterprise for Linkerd conformance test report: + +0. `cd` to the top level of this repository. + +1. Create an empty cluster. + +2. Run `bash conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/run-conformance.sh`. + + You can set `LINKERD_VERSION`, `GATEWAY_API_CHANNEL`, and + `GATEWAY_API_VERSION` if you want to try different versions of things. + (Note that if you set `GATEWAY_API_VERSION`, you'll need to be on a + matching Gateway API branch.) + +3. The conformance report will be written to the + `conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/` directory. diff --git a/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/run-conformance.sh b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/run-conformance.sh new file mode 100644 index 0000000000..fc9efcd444 --- /dev/null +++ b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/run-conformance.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# Copyright 2025 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Set these as needed. +LINKERD_VERSION=${LINKERD_VERSION:-enterprise-2.18} +GATEWAY_API_CHANNEL=${GATEWAY_API_CHANNEL:-standard} +GATEWAY_API_VERSION=${GATEWAY_API_VERSION:-v1.3.0} + +UNSUPPORTED_FEATURES="MeshHTTPRouteRedirectPath,MeshHTTPRouteRewritePath" + +CONFORMANCE_PRODUCT=buoyant-enterprise-for-linkerd +CONFORMANCE_VERSION=$(echo $LINKERD_VERSION | cut -d- -f2-) +GATEWAY_API_BASE_URL=https://github.com/kubernetes-sigs/gateway-api/releases/download + +echo "Using Buoyant Enterprise for Linkerd version $LINKERD_VERSION" +echo "Using Gateway API $GATEWAY_API_VERSION $GATEWAY_API_CHANNEL" + +# Install the Linkerd CLI. +curl --proto '=https' --tlsv1.2 -sSfL https://enterprise.buoyant.io/install \ + | env LINKERD2_VERSION=${LINKERD_EDGE_VERSION} sh + +export PATH=$HOME/.linkerd2/bin:$PATH + +# Install the Gateway API CRDs. + +kubectl apply -f ${GATEWAY_API_BASE_URL}/${GATEWAY_API_VERSION}/${GATEWAY_API_CHANNEL}-install.yaml + +# Install the Linkerd control plane. +linkerd install --crds | kubectl apply -f - +linkerd install | kubectl apply -f - +linkerd check + +# Run the conformance tests. + +REPORT_NAME=${GATEWAY_API_CHANNEL}-${CONFORMANCE_VERSION}-default-report.yaml +REPORT_PATH=reports/${GATEWAY_API_VERSION}/${CONFORMANCE_PRODUCT}/${REPORT_NAME} + +go test \ + -p 4 \ + ./conformance \ + -run TestConformance \ + -args \ + --organization Buoyant \ + --project "Buoyant Enterprise for Linkerd" \ + --url https://buoyant.io/ \ + --version ${LINKERD_VERSION} \ + --contact "gateway-api@buoyant.io" \ + --report-output ${REPORT_PATH} \ + --conformance-profiles=MESH-HTTP,MESH-GRPC \ + --all-features \ + --exempt-features=Gateway,ReferenceGrant,${UNSUPPORTED_FEATURES} \ + --namespace-annotations=linkerd.io/inject=enabled diff --git a/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/standard-2.18-default-report.yaml b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/standard-2.18-default-report.yaml new file mode 100644 index 0000000000..90e4e77a22 --- /dev/null +++ b/conformance/reports/v1.3.0/buoyant-enterprise-for-linkerd/standard-2.18-default-report.yaml @@ -0,0 +1,64 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-06-11T14:31:02-04:00" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - gateway-api@buoyant.io + organization: Buoyant + project: Buoyant Enterprise for Linkerd + url: https://buoyant.io/ + version: enterprise-2.18 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + name: MESH-GRPC + summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 7 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 8 + Skipped: 0 + supportedFeatures: + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - MeshClusterIPMatching + - MeshConsumerRoute + - MeshHTTPRouteBackendRequestHeaderModification + - MeshHTTPRouteQueryParamMatching + - MeshHTTPRouteRedirectPort + - MeshHTTPRouteSchemeRedirect + unsupportedFeatures: + - MeshHTTPRouteRedirectPath + - MeshHTTPRouteRewritePath + name: MESH-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/conformance/reports/v1.3.0/linkerd-linkerd/README.md b/conformance/reports/v1.3.0/linkerd-linkerd/README.md new file mode 100644 index 0000000000..19a73bc729 --- /dev/null +++ b/conformance/reports/v1.3.0/linkerd-linkerd/README.md @@ -0,0 +1,65 @@ +# Linkerd + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|--------------|-------------------------------------------|---------|--------------------------------------------------------| +| standard | [version-2.18](https://github.com/linkerd/linkerd2/releases/tag/version-2.18/) | default | [version-2.18 report](./standard-2.18-default-report.yaml) | + +## Notes + +This report uses the v1.3.0 Gateway API CRDs, but was run using the tests on +the `main` branch at commit `6cd1558a9e`, in order to take advantage of more +effective tests for the `MESH` conformance profile that landed after v1.3.0 +was cut. + +### Linkerd Versioning + +The Linkerd project publishes and announces _versions_ that correspond to +specific project milestones and sets of new features. This report is for +Linkerd 2.18. + +Linkerd versions are available in different types of _release artifacts_: + +- _Edge releases_ are published on a weekly or near-weekly basis by the + Linkerd open-source project. Their names are `edge-y.m.n`, where `y` is the + two-digit year, `m` is the numeric month, and `n` is the number of the edge + release in that month (e.g. `edge-25.5.1` is the first edge release in May + of 2025). + + Each major version of Linkerd has a corresponding edge release, indicated by + a `version-2.X` tag. For example, Linkerd 2.18 corresponds to `edge-25.4.4`, + and therefore the `version-2.18` tag and the `edge-25.4.4` tag are on the + same commit. + +- _Stable releases_ of Linkerd follow semantic versioning, and are published + by the vendor community around Linkerd. + +For more information on Linkerd versioning, see the Linkerd [Releases and +Versions] documentation. + +Since Gateway API conformance tests require semantic versioning for the +implementation version, the Linkerd project reports conformance using the +`version` tags. However, the `run_conformance.sh` script referenced below +installs the corresponding `edge` tag, because the Linkerd CLI is actually +published using the `edge` tag. + +[Releases and Versions]: https://linkerd.io/releases/ + +## Reproduce + +To reproduce a Linkerd conformance test report: + +0. `cd` to the top level of this repository. + +1. Create an empty cluster. + +2. Run `bash conformance/reports/v1.3.0/linkerd-linkerd/run-conformance.sh`. + + You can set `LINKERD_VERSION`, `LINKERD_EDGE_VERSION`, + `GATEWAY_API_CHANNEL`, and `GATEWAY_API_VERSION` if you want to try + different versions of things. (Note that if you set `GATEWAY_API_VERSION`, + you'll need to be on a matching Gateway API branch.) + +3. The conformance report will be written to the + `conformance/reports/v1.3.0/linkerd-linkerd/` directory. diff --git a/conformance/reports/v1.3.0/linkerd-linkerd/run-conformance.sh b/conformance/reports/v1.3.0/linkerd-linkerd/run-conformance.sh new file mode 100644 index 0000000000..93d0b210f2 --- /dev/null +++ b/conformance/reports/v1.3.0/linkerd-linkerd/run-conformance.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# Copyright 2025 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Set these as needed. +LINKERD_VERSION=${LINKERD_VERSION:-version-2.18} +LINKERD_EDGE_VERSION=${LINKERD_EDGE_VERSION:-edge-25.4.4} +GATEWAY_API_CHANNEL=${GATEWAY_API_CHANNEL:-standard} +GATEWAY_API_VERSION=${GATEWAY_API_VERSION:-v1.3.0} + +UNSUPPORTED_FEATURES="MeshHTTPRouteRedirectPath,MeshHTTPRouteRewritePath" + +CONFORMANCE_PRODUCT=linkerd-linkerd +CONFORMANCE_VERSION=$(echo $LINKERD_VERSION | cut -d- -f2-) +GATEWAY_API_BASE_URL=https://github.com/kubernetes-sigs/gateway-api/releases/download + +echo "Using Linkerd version $LINKERD_VERSION (AKA $LINKERD_EDGE_VERSION)" +echo "Using Gateway API $GATEWAY_API_VERSION $GATEWAY_API_CHANNEL" + +# Install the Linkerd CLI. +curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install-edge \ + | env LINKERD2_VERSION=${LINKERD_EDGE_VERSION} sh + +export PATH=$HOME/.linkerd2/bin:$PATH + +# Install the Gateway API CRDs. + +kubectl apply -f ${GATEWAY_API_BASE_URL}/${GATEWAY_API_VERSION}/${GATEWAY_API_CHANNEL}-install.yaml + +# Install the Linkerd control plane. +linkerd install --crds | kubectl apply -f - +linkerd install | kubectl apply -f - +linkerd check + +# Run the conformance tests. + +REPORT_NAME=${GATEWAY_API_CHANNEL}-${CONFORMANCE_VERSION}-default-report.yaml +REPORT_PATH=reports/${GATEWAY_API_VERSION}/${CONFORMANCE_PRODUCT}/${REPORT_NAME} + +go test \ + -p 4 \ + ./conformance \ + -run TestConformance \ + -args \ + --organization Linkerd \ + --project Linkerd \ + --url https://github.com/linkerd/linkerd2 \ + --version ${LINKERD_VERSION} \ + --contact https://github.com/linkerd/linkerd2/blob/main/MAINTAINERS.md \ + --report-output ${REPORT_PATH} \ + --conformance-profiles=MESH-HTTP,MESH-GRPC \ + --all-features \ + --exempt-features=Gateway,ReferenceGrant,${UNSUPPORTED_FEATURES} \ + --namespace-annotations=linkerd.io/inject=enabled diff --git a/conformance/reports/v1.3.0/linkerd-linkerd/standard-2.18-default-report.yaml b/conformance/reports/v1.3.0/linkerd-linkerd/standard-2.18-default-report.yaml new file mode 100644 index 0000000000..54d0503085 --- /dev/null +++ b/conformance/reports/v1.3.0/linkerd-linkerd/standard-2.18-default-report.yaml @@ -0,0 +1,64 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-06-11T14:21:05-04:00" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/linkerd/linkerd2/blob/main/MAINTAINERS.md + organization: Linkerd + project: Linkerd + url: https://github.com/linkerd/linkerd2 + version: version-2.18 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + name: MESH-GRPC + summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 7 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 8 + Skipped: 0 + supportedFeatures: + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - MeshClusterIPMatching + - MeshConsumerRoute + - MeshHTTPRouteBackendRequestHeaderModification + - MeshHTTPRouteQueryParamMatching + - MeshHTTPRouteRedirectPort + - MeshHTTPRouteSchemeRedirect + unsupportedFeatures: + - MeshHTTPRouteRedirectPath + - MeshHTTPRouteRewritePath + name: MESH-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/site-src/implementations.md b/site-src/implementations.md index e65f26aa4f..06b0e7926e 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -51,7 +51,7 @@ cover, and documentation to help users get started. - [Google Cloud Service Mesh][38] (GA) - [Istio][9] (GA) - [Kuma][11] (GA) -- [Linkerd][28] (experimental) +- [Linkerd][28] (GA) ## Integrations From 8185c7df9362607773ed74ff629e3a00593d2007 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Wed, 11 Jun 2025 18:18:55 -0400 Subject: [PATCH 041/224] GEP-1713 Revisions (#3744) * formatting * clarify optional port semantics * clarify listener name semantics * clarify attachment/grants semantics - Route attachment without sectionName - re-order policy attachment section - include a section about ReferenceGrants * set proper min/max value for listenerentry.port We had to drop the use of the PortNumber type because of limitations with overriding min max using kubebuilder annotations * Update geps/gep-1713/index.md Co-authored-by: Nick Young * Drop validation markers this is handled in another PR See: https://github.com/kubernetes-sigs/gateway-api/pull/3750 * address Nick's feedback * remove stray backtick * address Rob's feedback * incorporate gep changes into godoc --------- Co-authored-by: Nick Young --- apis/v1/gateway_types.go | 31 ++++++++++ apisx/v1alpha1/xlistenerset_types.go | 33 ++++++++-- ...way.networking.x-k8s.io_xlistenersets.yaml | 33 ++++++++-- geps/gep-1713/index.md | 60 +++++++++++-------- pkg/generated/openapi/zz_generated.openapi.go | 4 +- 5 files changed, 126 insertions(+), 35 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 3e1ec4c7ea..f54e5d10ce 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -1062,6 +1062,37 @@ const ( GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" ) +const ( + // AttachedListenerSets is a condition that is true when the Gateway has + // at least one ListenerSet attached to it. + // + // Possible reasons for this condition to be True are: + // + // * "ListenerSetsAttached" + // + // Possible reasons for this condition to be False are: + // + // * "NoListenerSetsAttached" + // * "ListenerSetsNotAllowed" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionAttachedListenerSets GatewayConditionType = "AttachedListenerSets" + + // This reason is used with the "AttachedListenerSets" condition when the + // Gateway has at least one ListenerSet attached to it. + GatewayReasonListenerSetsAttached GatewayConditionReason = "ListenerSetsAttached" + + // This reason is used with the "AttachedListenerSets" condition when the + // Gateway has no ListenerSets attached to it. + GatewayReasonNoListenerSetsAttached GatewayConditionReason = "NoListenerSetsAttached" + + // This reason is used with the "AttachedListenerSets" condition when the + // Gateway has ListenerSets attached to it, but the ListenerSets are not allowed. + GatewayReasonListenerSetsNotAllowed GatewayConditionReason = "ListenerSetsNotAllowed" +) + // ListenerStatus is the status associated with a Listener. type ListenerStatus struct { // Name is the name of the Listener that this status corresponds to. diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index 529b7f3508..92cca1b735 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -29,8 +29,33 @@ import ( // +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// XListenerSet defines a set of additional listeners -// to attach to an existing Gateway. +// XListenerSet defines a set of additional listeners to attach to an existing Gateway. +// This resource provides a mechanism to merge multiple listeners into a single Gateway. +// +// The parent Gateway must explicitly allow ListenerSet attachment through its +// AllowedListeners configuration. By default, Gateways do not allow ListenerSet +// attachment. +// +// Routes can attach to a ListenerSet by specifying it as a parentRef, and can +// optionally target specific listeners using the sectionName field. +// +// Policy Attachment: +// - Policies that attach to a ListenerSet apply to all listeners defined in that resource +// - Policies do not impact listeners in the parent Gateway +// - Different ListenerSets attached to the same Gateway can have different policies +// - If an implementation cannot apply a policy to specific listeners, it should reject the policy +// +// ReferenceGrant Semantics: +// - ReferenceGrants applied to a Gateway are not inherited by child ListenerSets +// - ReferenceGrants applied to a ListenerSet do not grant permission to the parent Gateway's listeners +// - A ListenerSet can reference secrets/backends in its own namespace without a ReferenceGrant +// +// Gateway Integration: +// - The parent Gateway's status will include an "AttachedListenerSets" condition +// - This condition will be: +// - True: when AllowedListeners is set and at least one child ListenerSet is attached +// - False: when AllowedListeners is set but no valid listeners are attached, or when AllowedListeners is not set or false +// - Unknown: when no AllowedListeners config is present type XListenerSet struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -63,10 +88,10 @@ type ListenerSetSpec struct { // // 1. "parent" Gateway // 2. ListenerSet ordered by creation time (oldest first) - // 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. + // 3. ListenerSet ordered alphabetically by "{namespace}/{name}". // // An implementation MAY reject listeners by setting the ListenerEntryStatus - // `Accepted`` condition to False with the Reason `TooManyListeners` + // `Accepted` condition to False with the Reason `TooManyListeners` // // If a listener has a conflict, this will be reported in the // Status.ListenerEntryStatus setting the `Conflicted` condition to True. diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 5176322413..2454521c2e 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -34,8 +34,33 @@ spec: schema: openAPIV3Schema: description: |- - XListenerSet defines a set of additional listeners - to attach to an existing Gateway. + XListenerSet defines a set of additional listeners to attach to an existing Gateway. + This resource provides a mechanism to merge multiple listeners into a single Gateway. + + The parent Gateway must explicitly allow ListenerSet attachment through its + AllowedListeners configuration. By default, Gateways do not allow ListenerSet + attachment. + + Routes can attach to a ListenerSet by specifying it as a parentRef, and can + optionally target specific listeners using the sectionName field. + + Policy Attachment: + - Policies that attach to a ListenerSet apply to all listeners defined in that resource + - Policies do not impact listeners in the parent Gateway + - Different ListenerSets attached to the same Gateway can have different policies + - If an implementation cannot apply a policy to specific listeners, it should reject the policy + + ReferenceGrant Semantics: + - ReferenceGrants applied to a Gateway are not inherited by child ListenerSets + - ReferenceGrants applied to a ListenerSet do not grant permission to the parent Gateway's listeners + - A ListenerSet can reference secrets/backends in its own namespace without a ReferenceGrant + + Gateway Integration: + - The parent Gateway's status will include an "AttachedListenerSets" condition + - This condition will be: + - True: when AllowedListeners is set and at least one child ListenerSet is attached + - False: when AllowedListeners is set but no valid listeners are attached, or when AllowedListeners is not set or false + - Unknown: when no AllowedListeners config is present properties: apiVersion: description: |- @@ -73,10 +98,10 @@ spec: 1. "parent" Gateway 2. ListenerSet ordered by creation time (oldest first) - 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. + 3. ListenerSet ordered alphabetically by "{namespace}/{name}". An implementation MAY reject listeners by setting the ListenerEntryStatus - `Accepted`` condition to False with the Reason `TooManyListeners` + `Accepted` condition to False with the Reason `TooManyListeners` If a listener has a conflict, this will be reported in the Status.ListenerEntryStatus setting the `Conflicted` condition to True. diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index f51f044dda..4cad39fde1 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -36,8 +36,8 @@ Thus updating a single `Gateway` resource with this many certificates is a conte More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. -The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but does not define any specific requirements for how that should work. -https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78 +The [spec currently has language](https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78) to indicate implementations `MAY` merge `Gateways` resources but does not define any specific requirements for how that should work. + ## Feature Details @@ -164,15 +164,8 @@ type ListenerEntry struct { // Port is the network port. Multiple listeners may use the // same port, subject to the Listener compatibility rules. // - // If the port is specified as zero, the implementation will assign - // a unique port. If the implementation does not support dynamic port - // assignment, it MUST set `Accepted` condition to `False` with the - // `UnsupportedPort` reason. - // // Support: Core - // - // +optional - Port *PortNumber `json:"port,omitempty"` + Port PortNumber `json:"port,omitempty"` // Protocol specifies the network protocol this listener expects to receive. // @@ -385,8 +378,7 @@ spec: ``` ### ListenerEntry -`ListenerEntry` is currently a copy of the `Listener` struct with some changes -1. `Port` is now a pointer to allow for dynamic port assignment. +`ListenerEntry` is currently a copy of the `Listener` struct with some changes noted in the below sections ## Semantics @@ -399,7 +391,7 @@ When there are no listeners the `Gateway`'s `status.listeners` should be empty o Implementations, when creating a `Gateway`, may provision underlying infrastructure when there are no listeners present. The status conditions `Accepted` and `Programmed` conditions should reflect state of this provisioning. -### Gateway <> ListenerSet Handshake +### Gateway & ListenerSet Handshake By default a `Gateway` MUST NOT allow `ListenerSets` to be attached. Users can enable this behaviour by configuring their `Gateway` to allow `ListenerSet` attachment: @@ -413,7 +405,7 @@ spec: - from: Same ``` -### Route Attaching +### Route Attachment Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners in the `ListenerSet`. @@ -461,10 +453,36 @@ spec: sectionName: foo ``` +#### Optional Section Name + +If a `sectionName` in a Route's `parentRef` is not set then the Route MUST attach to only the listeners in the referenced parent. As an example given a `Gateway` and it's child `ListenerSets` a route attaching to the `Gateway` with an empty `sectionName` shall only attach to the listeners in the `Gateways` immediate `spec.listeners` list. In other words, the Route will not attach to any listeners in the `ListenerSets`. This is necessary because, for UX reasons, the `name` field does not have to be unique across all Listeners merged into a Gateway (see the section below for details). + +### Policy Attachment + +Policy attachment is [under discussion] in https://github.com/kubernetes-sigs/gateway-api/discussions/2927 + +Similar to Routes, `ListenerSet` can inherit policy from a Gateway. +Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway`. This allows `ListenerSets` attached to the same `Gateway` to have different policies. +If the implementation cannot apply the policy to only specific listeners, it should reject the policy. + +### ReferenceGrant Semantics + +When a `ReferenceGrant` is applied to a `Gateway` it MUST NOT be inherited by child `ListenerSets`. Thus a `ListenerSet` listener MUST NOT access secrets granted to the `Gateway` listeners. + +When a `ReferenceGrant` is applied to a `ListenerSet` it MUST NOT grant permission to the parent `Gateway`'s listeners. Thus a `Gateway` listener MUST NOT access secrets granted to the `ListenerSet` listeners. + +A `ListenerSet` must be able to reference a secret/backend in the same namespace as itself without a `ReferenceGrant`. + + ### Listener Validation -Implementations MUST treat the parent `Gateway`s as having the merged list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. -Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. +Within a single resource such as a `Gateway` or `ListenerSet` the list of listeners MUST have unique names. Implementations MUST allow listeners from a child `ListenerSet` to be merged into a parent `Gateway` when listeners have the same name. Likewise implementations MUST allow sibling `ListenerSets` listeners with matching names to be merged into a parent `Gateway`. This allows for authors of Routes to simply attach to their desired parentRef and listener without having to worry about naming conflicts across resources. + +It is up to the implementations how unique names are generated internally. One example would be to hash the `ListenerSet` name+namespace and prepend it to the listener entry `name`. + +Implementations MUST treat the parent `Gateway`s as having the merged list of all listeners from itself and attached `ListenerSets` and validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway` with the relaxed listener name constraints. + +Ordering will follow the semantics defined in [Listener Precedence](#listener-precedence). From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. @@ -514,7 +532,7 @@ Listeners should be merged using the following precedence: Conflicts are covered in the section 'ListenerConditions within a ListenerSet' -### Gateway Conditions +### Gateway Conditions `Gateway`'s `Accepted` and `Programmed` top-level conditions remain unchanged and reflect the status of the local configuration. @@ -555,14 +573,6 @@ If a listener has a conflict, this should be reported in the `ListenerEntryStatu Implementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc. -### Policy Attachment - -Policy attachment is [under discussion] in https://github.com/kubernetes-sigs/gateway-api/discussions/2927 - -Similar to Routes, `ListenerSet` can inherit policy from a Gateway. -Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway`. This allows `ListenerSets` attached to the same `Gateway` to have different policies. -If the implementation cannot apply the policy to only specific listeners, it should reject the policy. - ## Alternatives ### Re-using Gateway Resource diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index f4a7d0d4f2..96ac164691 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7882,7 +7882,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerSetSpec(ref common.Refe }, }, SchemaProps: spec.SchemaProps{ - Description: "Listeners associated with this ListenerSet. Listeners define logical endpoints that are bound on this referenced parent Gateway's addresses.\n\nListeners in a `Gateway` and their attached `ListenerSets` are concatenated as a list when programming the underlying infrastructure. Each listener name does not need to be unique across the Gateway and ListenerSets. See ListenerEntry.Name for more details.\n\nImplementations MUST treat the parent Gateway as having the merged list of all listeners from itself and attached ListenerSets using the following precedence:\n\n1. \"parent\" Gateway 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by “{namespace}/{name}”.\n\nAn implementation MAY reject listeners by setting the ListenerEntryStatus `Accepted`` condition to False with the Reason `TooManyListeners`\n\nIf a listener has a conflict, this will be reported in the Status.ListenerEntryStatus setting the `Conflicted` condition to True.\n\nImplementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc.", + Description: "Listeners associated with this ListenerSet. Listeners define logical endpoints that are bound on this referenced parent Gateway's addresses.\n\nListeners in a `Gateway` and their attached `ListenerSets` are concatenated as a list when programming the underlying infrastructure. Each listener name does not need to be unique across the Gateway and ListenerSets. See ListenerEntry.Name for more details.\n\nImplementations MUST treat the parent Gateway as having the merged list of all listeners from itself and attached ListenerSets using the following precedence:\n\n1. \"parent\" Gateway 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by \"{namespace}/{name}\".\n\nAn implementation MAY reject listeners by setting the ListenerEntryStatus `Accepted` condition to False with the Reason `TooManyListeners`\n\nIf a listener has a conflict, this will be reported in the Status.ListenerEntryStatus setting the `Conflicted` condition to True.\n\nImplementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -8161,7 +8161,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XListenerSet(ref common.Referen return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "XListenerSet defines a set of additional listeners to attach to an existing Gateway.", + Description: "XListenerSet defines a set of additional listeners to attach to an existing Gateway. This resource provides a mechanism to merge multiple listeners into a single Gateway.\n\nThe parent Gateway must explicitly allow ListenerSet attachment through its AllowedListeners configuration. By default, Gateways do not allow ListenerSet attachment.\n\nRoutes can attach to a ListenerSet by specifying it as a parentRef, and can optionally target specific listeners using the sectionName field.\n\nPolicy Attachment: - Policies that attach to a ListenerSet apply to all listeners defined in that resource - Policies do not impact listeners in the parent Gateway - Different ListenerSets attached to the same Gateway can have different policies - If an implementation cannot apply a policy to specific listeners, it should reject the policy\n\nReferenceGrant Semantics: - ReferenceGrants applied to a Gateway are not inherited by child ListenerSets - ReferenceGrants applied to a ListenerSet do not grant permission to the parent Gateway's listeners - A ListenerSet can reference secrets/backends in its own namespace without a ReferenceGrant\n\nGateway Integration: - The parent Gateway's status will include an \"AttachedListenerSets\" condition - This condition will be:\n - True: when AllowedListeners is set and at least one child ListenerSet is attached\n - False: when AllowedListeners is set but no valid listeners are attached, or when AllowedListeners is not set or false\n - Unknown: when no AllowedListeners config is present", Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { From ed2bd6b55c38cca9c265131c5fd71376b60d2778 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:56:58 -0700 Subject: [PATCH 042/224] Infer SupportedFeatures in Conformance Tests (GEP-2162) [#3759] (#3848) * SupportedFeatures * Added inferredSupportedFeatures to determine and report if feature for tests were manually supplied or inferred from GatewayClass * Corrected suite unit tests after addition of a new field. * Added logic of determining if supportedFeatures are inferred or supplied and refactored some code around it. * moved SupportedFeatures init after scheme addition * Cleaned up and organized code to properly determine features we are testing and if they were inferred or not. * Cleanup v2 * Make inferring supportedFeatures to take precedence over all other feature flags. * Fix when no profile was setting inferred to false. * remove debug log * Switched args arrangement so ctx is the first argument passed to fetchSupportedFeatures function. * Updated context as it's unclear where it should be supplied from * removed SupportedFeatures struct and method for determining supported features. * Refactored logic of determining supported features and add flag for the report in cSuite. * Reversed flag parsing for some values. * Tweaked logging options. * Cleaned up last places for SupportedFeatures struct. * Wrote unit tests for supported features determination logic in conformance suite. * Formatting fixes. * Resolved comments. * Fixed formatting. * Updated conformance docs. * Removed doc update so it can be submitted as a seperate PR. --- conformance/apis/v1/conformancereport.go | 4 + conformance/conformance.go | 5 + conformance/utils/suite/conformance.go | 6 +- conformance/utils/suite/reports.go | 6 +- conformance/utils/suite/suite.go | 100 ++++++++++++----- conformance/utils/suite/suite_test.go | 133 ++++++++++++++++++++++- 6 files changed, 217 insertions(+), 37 deletions(-) diff --git a/conformance/apis/v1/conformancereport.go b/conformance/apis/v1/conformancereport.go index 7f4f4d5325..dcea92dffc 100644 --- a/conformance/apis/v1/conformancereport.go +++ b/conformance/apis/v1/conformancereport.go @@ -50,6 +50,10 @@ type ConformanceReport struct { // SucceededProvisionalTests is a list of the names of the provisional tests that // have been successfully run. SucceededProvisionalTests []string `json:"succeededProvisionalTests,omitempty"` + + // InferredSupportedFeatures indicates whether the supported features were + // automatically detected by the conformance suite. + InferredSupportedFeatures bool `json:"inferredSupportedFeatures"` } // Implementation provides metadata information on the downstream diff --git a/conformance/conformance.go b/conformance/conformance.go index ce264a9441..12e5884968 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -29,11 +29,14 @@ import ( "sigs.k8s.io/gateway-api/conformance/tests" conformanceconfig "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/flags" + "sigs.k8s.io/gateway-api/conformance/utils/suite" "github.com/stretchr/testify/require" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + clientset "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/yaml" @@ -63,6 +66,7 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { supportedFeatures := suite.ParseSupportedFeatures(*flags.SupportedFeatures) exemptFeatures := suite.ParseSupportedFeatures(*flags.ExemptFeatures) + skipTests := suite.ParseSkipTests(*flags.SkipTests) namespaceLabels := suite.ParseKeyValuePairs(*flags.NamespaceLabels) namespaceAnnotations := suite.ParseKeyValuePairs(*flags.NamespaceAnnotations) @@ -144,6 +148,7 @@ func logOptions(t *testing.T, opts suite.ConformanceOptions) { t.Logf(" Enable All Features: %t", opts.EnableAllSupportedFeatures) t.Logf(" Supported Features: %v", opts.SupportedFeatures.UnsortedList()) t.Logf(" ExemptFeatures: %v", opts.ExemptFeatures.UnsortedList()) + t.Logf(" ConformanceProfiles: %v", opts.ConformanceProfiles.UnsortedList()) } func writeReport(logf func(string, ...any), report confv1.ConformanceReport, output string) error { diff --git a/conformance/utils/suite/conformance.go b/conformance/utils/suite/conformance.go index 3bbbbc1c23..12db14d6df 100644 --- a/conformance/utils/suite/conformance.go +++ b/conformance/utils/suite/conformance.go @@ -21,8 +21,6 @@ import ( "strings" "testing" - "k8s.io/apimachinery/pkg/util/sets" - "sigs.k8s.io/gateway-api/conformance/utils/tlog" "sigs.k8s.io/gateway-api/pkg/features" ) @@ -81,11 +79,11 @@ func (test *ConformanceTest) Run(t *testing.T, suite *ConformanceTestSuite) { // ParseSupportedFeatures parses flag arguments and converts the string to // sets.Set[features.FeatureName] -func ParseSupportedFeatures(f string) sets.Set[features.FeatureName] { +func ParseSupportedFeatures(f string) FeaturesSet { if f == "" { return nil } - res := sets.Set[features.FeatureName]{} + res := FeaturesSet{} for _, value := range strings.Split(f, ",") { res.Insert(features.FeatureName(value)) } diff --git a/conformance/utils/suite/reports.go b/conformance/utils/suite/reports.go index 4b03d67733..4efcc4e77f 100644 --- a/conformance/utils/suite/reports.go +++ b/conformance/utils/suite/reports.go @@ -22,7 +22,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1" - "sigs.k8s.io/gateway-api/pkg/features" ) // ----------------------------------------------------------------------------- @@ -107,7 +106,7 @@ func (p profileReportsMap) list() (profileReports []confv1.ProfileReport) { return } -func (p profileReportsMap) compileResults(supportedFeaturesMap map[ConformanceProfileName]sets.Set[features.FeatureName], unsupportedFeaturesMap map[ConformanceProfileName]sets.Set[features.FeatureName]) { +func (p profileReportsMap) compileResults(supportedFeaturesMap map[ConformanceProfileName]FeaturesSet, unsupportedFeaturesMap map[ConformanceProfileName]FeaturesSet) { for key, report := range p { // report the overall result for core features switch { @@ -162,7 +161,8 @@ func (p profileReportsMap) compileResults(supportedFeaturesMap map[ConformancePr // isTestExtended determines if a provided test is considered to be supported // at an extended level of support given the provided conformance profile. // -// TODO: right now the tests themselves don't indicate the conformance +// TODO(#3759) Update this method to be based on Features inferred. +// Right now the tests themselves don't indicate the conformance // support level associated with them. The only way we have right now // in this prototype to know whether a test belongs to any particular // conformance level is to compare the features needed for the test to diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index e6a5cb1264..f1164fa2fe 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -31,11 +31,13 @@ import ( "github.com/stretchr/testify/require" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1beta1" confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/config" @@ -69,7 +71,7 @@ type ConformanceTestSuite struct { BaseManifests string MeshManifests string Applier kubernetes.Applier - SupportedFeatures sets.Set[features.FeatureName] + SupportedFeatures FeaturesSet TimeoutConfig config.TimeoutConfig SkipTests sets.Set[string] SkipProvisionalTests bool @@ -79,6 +81,11 @@ type ConformanceTestSuite struct { UsableNetworkAddresses []v1beta1.GatewaySpecAddress UnusableNetworkAddresses []v1beta1.GatewaySpecAddress + // If SupportedFeatures are automatically determined from GWC Status. + // This will be required to report in future iterations as the passing + // will be determined based on this. + isInferredSupportedFeatures bool + // mode is the operating mode of the implementation. // The default value for it is "default". mode string @@ -142,8 +149,8 @@ type ConformanceOptions struct { // CleanupBaseResources indicates whether or not the base test // resources such as Gateways should be cleaned up after the run. CleanupBaseResources bool - SupportedFeatures sets.Set[features.FeatureName] - ExemptFeatures sets.Set[features.FeatureName] + SupportedFeatures FeaturesSet + ExemptFeatures FeaturesSet EnableAllSupportedFeatures bool TimeoutConfig config.TimeoutConfig // SkipTests contains all the tests not to be run and can be used to opt out @@ -172,6 +179,8 @@ type ConformanceOptions struct { ConformanceProfiles sets.Set[ConformanceProfileName] } +type FeaturesSet = sets.Set[features.FeatureName] + const ( // undefinedKeyword is set in the ConformanceReport "GatewayAPIVersion" and // "GatewayAPIChannel" fields in case it's not possible to figure out the actual @@ -181,16 +190,23 @@ const ( // NewConformanceTestSuite is a helper to use for creating a new ConformanceTestSuite. func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, error) { - // test suite callers are required to provide either: - // - one conformance profile via the flag '-conformance-profiles' - // - a list of supported features via the flag '-supported-features' - // - an explicit test to run via the flag '-run-test' - // - all features are being tested via the flag '-all-features' - if options.SupportedFeatures.Len() == 0 && - options.ConformanceProfiles.Len() == 0 && - !options.EnableAllSupportedFeatures && - options.RunTest == "" { - return nil, fmt.Errorf("no conformance profile, supported features, explicit tests were provided so no tests could be selected") + supportedFeatures := options.SupportedFeatures.Difference(options.ExemptFeatures) + isInferred := false + switch { + case options.EnableAllSupportedFeatures: + supportedFeatures = features.SetsToNamesSet(features.AllFeatures) + case shouldInferSupportedFeatures(&options): + var err error + supportedFeatures, err = fetchSupportedFeatures(options.Client, options.GatewayClassName) + if err != nil { + return nil, fmt.Errorf("Cannot infer supported features: %w", err) + } + isInferred = true + } + + // If features were not inferred from Status, it's a GWC issue. + if isInferred && supportedFeatures.Len() == 0 { + return nil, fmt.Errorf("no supported features were determined for test suite") } config.SetupTimeoutConfig(&options.TimeoutConfig) @@ -224,19 +240,6 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, mode = options.Mode } - // test suite callers can potentially just run all tests by saying they - // cover all features, if they don't they'll need to have provided a - // conformance profile or at least some specific features they support. - if options.EnableAllSupportedFeatures { - options.SupportedFeatures = features.SetsToNamesSet(features.AllFeatures) - } else if options.SupportedFeatures == nil { - options.SupportedFeatures = sets.New[features.FeatureName]() - } - - for feature := range options.ExemptFeatures { - options.SupportedFeatures.Delete(feature) - } - suite := &ConformanceTestSuite{ Client: options.Client, ClientOptions: options.ClientOptions, @@ -254,7 +257,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, NamespaceAnnotations: options.NamespaceAnnotations, AddressType: options.AddressType, }, - SupportedFeatures: options.SupportedFeatures, + SupportedFeatures: supportedFeatures, TimeoutConfig: options.TimeoutConfig, SkipTests: sets.New(options.SkipTests...), RunTest: options.RunTest, @@ -270,6 +273,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, mode: mode, apiVersion: apiVersion, apiChannel: apiChannel, + isInferredSupportedFeatures: isInferred, Hook: options.Hook, } @@ -288,12 +292,12 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, for _, f := range conformanceProfile.ExtendedFeatures.UnsortedList() { if options.SupportedFeatures.Has(f) { if suite.extendedSupportedFeatures[conformanceProfileName] == nil { - suite.extendedSupportedFeatures[conformanceProfileName] = sets.New[features.FeatureName]() + suite.extendedSupportedFeatures[conformanceProfileName] = FeaturesSet{} } suite.extendedSupportedFeatures[conformanceProfileName].Insert(f) } else { if suite.extendedUnsupportedFeatures[conformanceProfileName] == nil { - suite.extendedUnsupportedFeatures[conformanceProfileName] = sets.New[features.FeatureName]() + suite.extendedUnsupportedFeatures[conformanceProfileName] = FeaturesSet{} } suite.extendedUnsupportedFeatures[conformanceProfileName].Insert(f) } @@ -390,6 +394,10 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) } } +func (suite *ConformanceTestSuite) IsInferredSupportedFeatures() bool { + return suite.isInferredSupportedFeatures +} + func (suite *ConformanceTestSuite) setClientsetForTest(test ConformanceTest) error { featureNames := []string{} for _, v := range test.Features { @@ -544,6 +552,7 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) { GatewayAPIChannel: suite.apiChannel, ProfileReports: profileReports.list(), SucceededProvisionalTests: succeededProvisionalTests, + InferredSupportedFeatures: suite.IsInferredSupportedFeatures(), }, nil } @@ -573,6 +582,39 @@ func ParseConformanceProfiles(p string) sets.Set[ConformanceProfileName] { return res } +func fetchSupportedFeatures(client client.Client, gatewayClassName string) (FeaturesSet, error) { + if gatewayClassName == "" { + return nil, fmt.Errorf("GatewayClass name must be provided to fetch supported features") + } + gwc := &gatewayv1.GatewayClass{} + err := client.Get(context.TODO(), types.NamespacedName{Name: gatewayClassName}, gwc) + if err != nil { + return nil, fmt.Errorf("fetchSupportedFeatures(): %w", err) + } + + fs := FeaturesSet{} + for _, feature := range gwc.Status.SupportedFeatures { + fs.Insert(features.FeatureName(feature.Name)) + } + fmt.Printf("Supported features for GatewayClass %s: %v\n", gatewayClassName, fs.UnsortedList()) + return fs, nil +} + +// shouldInferSupportedFeatures checks if any flags were supplied for manually +// picking what to test. Inferred supported features are only used when no flags +// are set. +func shouldInferSupportedFeatures(opts *ConformanceOptions) bool { + if opts == nil { + return false + } + return !opts.EnableAllSupportedFeatures && + opts.SupportedFeatures.Len() == 0 && + opts.ExemptFeatures.Len() == 0 && + opts.ConformanceProfiles.Len() == 0 && + len(opts.SkipTests) == 0 && + opts.RunTest == "" +} + // getAPIVersionAndChannel iterates over all the crds installed in the cluster and check the version and channel annotations. // In case the annotations are not found or there are crds with different versions or channels, an error is returned. func getAPIVersionAndChannel(crds []apiextensionsv1.CustomResourceDefinition) (version string, channel string, err error) { diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index 951571f7aa..ccb259adb0 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -22,9 +22,13 @@ import ( "github.com/stretchr/testify/assert" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1" "sigs.k8s.io/gateway-api/pkg/consts" "sigs.k8s.io/gateway-api/pkg/features" @@ -217,7 +221,7 @@ var ( func TestSuiteReport(t *testing.T) { testCases := []struct { name string - features sets.Set[features.FeatureName] + features FeaturesSet extendedSupportedFeatures map[ConformanceProfileName]sets.Set[features.FeatureName] profiles sets.Set[ConformanceProfileName] skipProvisionalTests bool @@ -276,6 +280,7 @@ func TestSuiteReport(t *testing.T) { coreProvisionalTest.ShortName, extendedProvisionalTest.ShortName, }, + InferredSupportedFeatures: true, }, }, { @@ -385,6 +390,7 @@ func TestSuiteReport(t *testing.T) { }, }, }, + InferredSupportedFeatures: true, }, }, } @@ -407,3 +413,128 @@ func TestSuiteReport(t *testing.T) { }) } } + +var statusFeatureNames = []string{ + "Gateway", + "GatewayPort8080", + "HTTPRoute", + "HTTPRouteHostRewrite", + "HTTPRouteMethodMatching", + "HTTPRoutePathRewrite", + "TTPRouteQueryParamMatching", + "HTTPRouteResponseHeaderModification", + "ReferenceGrant", +} + +func TestInferSupportedFeatures(t *testing.T) { + testCases := []struct { + name string + allowAllFeatures bool + supportedFeatures FeaturesSet + exemptFeatures FeaturesSet + ConformanceProfile sets.Set[ConformanceProfileName] + expectedFeatures FeaturesSet + expectedIsInferred bool + }{ + { + name: "properly infer supported features", + expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedIsInferred: true, + }, + { + name: "no features", + supportedFeatures: sets.New[features.FeatureName]("Gateway"), + expectedFeatures: sets.New[features.FeatureName]("Gateway"), + }, + { + name: "remove exempt features", + supportedFeatures: sets.New[features.FeatureName]("Gateway", "HTTPRoute"), + exemptFeatures: sets.New[features.FeatureName]("HTTPRoute"), + expectedFeatures: sets.New[features.FeatureName]("Gateway"), + }, + { + name: "allow all features", + allowAllFeatures: true, + expectedFeatures: features.SetsToNamesSet(features.AllFeatures), + }, + { + name: "supports conformance profile - core", + ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), + expectedFeatures: namesToFeatureSet([]string{"Gateway", "HTTPRoute", "ReferenceGrant"}), + }, + } + + gwcName := "ochopintre" + gwc := &gatewayv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: gwcName, + }, + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "example.com/gateway-controller", + }, + Status: gatewayv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: string(gatewayv1.GatewayConditionAccepted), + Status: metav1.ConditionTrue, + Reason: "Accepted", + Message: "GatewayClass is accepted and ready for use", + }, + }, + SupportedFeatures: featureNamesToSet(statusFeatureNames), + }, + } + scheme := runtime.NewScheme() + scheme.AddKnownTypes(gatewayv1.SchemeGroupVersion, &gatewayv1.GatewayClass{}) + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(gwc). + WithLists(&apiextensionsv1.CustomResourceDefinitionList{}). + Build() + + gatewayv1.Install(fakeClient.Scheme()) + apiextensionsv1.AddToScheme(fakeClient.Scheme()) + + for _, tc := range testCases { + options := ConformanceOptions{ + AllowCRDsMismatch: true, + GatewayClassName: gwcName, + EnableAllSupportedFeatures: tc.allowAllFeatures, + SupportedFeatures: tc.supportedFeatures, + ExemptFeatures: tc.exemptFeatures, + ConformanceProfiles: tc.ConformanceProfile, + Client: fakeClient, + } + + t.Run(tc.name, func(t *testing.T) { + cSuite, err := NewConformanceTestSuite(options) + if err != nil { + t.Fatalf("error initializing conformance suite: %v", err) + } + + if cSuite.IsInferredSupportedFeatures() != tc.expectedIsInferred { + t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.IsInferredSupportedFeatures(), tc.expectedIsInferred) + } + + if equal := cSuite.SupportedFeatures.Equal(tc.expectedFeatures); !equal { + t.Errorf("SupportedFeatures mismatch: got %v, want %v", cSuite.SupportedFeatures.UnsortedList(), tc.expectedFeatures.UnsortedList()) + } + }) + } +} + +func featureNamesToSet(set []string) []gatewayv1.SupportedFeature { + var features []gatewayv1.SupportedFeature + for _, feature := range set { + features = append(features, gatewayv1.SupportedFeature{Name: gatewayv1.FeatureName(feature)}) + } + return features +} + +func namesToFeatureSet(names []string) FeaturesSet { + featureSet := FeaturesSet{} + for _, name := range names { + featureSet.Insert(features.FeatureName(name)) + } + return featureSet +} From 66539b9ad348fdabd3dfd7cd5956c828675b187d Mon Sep 17 00:00:00 2001 From: Nick Young Date: Mon, 16 Jun 2025 16:56:58 +1000 Subject: [PATCH 043/224] Make feature name required for Experimental (#3859) We have discussed this in community meetings and Slack, and have informally agreed that a conformance Feature Name must be set for a GEP to graduate to Experimental. This commit adds changes to the GEP process page and the GEP template to make this official. Signed-off-by: Nick Young --- geps/gep-696/index.md | 2 ++ geps/overview.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/geps/gep-696/index.md b/geps/gep-696/index.md index bedcc6e658..4a4a97dd19 100644 --- a/geps/gep-696/index.md +++ b/geps/gep-696/index.md @@ -47,6 +47,8 @@ Every feature should: 3. Not exceed 128 characters. 4. Contain only letters and numbers +GEPs cannot move to Experimental without a Feature Name. + ### Conformance tests Conformance tests file names should try to follow the `pascal-case-name.go` format. diff --git a/geps/overview.md b/geps/overview.md index 808cdb0a80..d270e820a7 100644 --- a/geps/overview.md +++ b/geps/overview.md @@ -151,6 +151,8 @@ use the `experimental` Golang build tag to denote experimental functionality. Some other requirements must be met before marking a GEP `Experimental`: - the graduation criteria to reach `Standard` MUST be filled out +- the GEP must have at least one Feature Name for features described inside that + will need to be tested by conformance tests. - a proposed probationary period (see next section) must be included in the GEP and approved by maintainers. From 1a9fdd310de40f83c5ad58c1215d1c6c2c6832cb Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Mon, 16 Jun 2025 13:57:02 -0700 Subject: [PATCH 044/224] GEP 91: Update Goals and Prior Art (#3838) * GEP 91: Update Goals and Prior Art Relates to https://github.com/kubernetes-sigs/gateway-api/discussions/3760#discussioncomment-12997389 Signed-off-by: Arko Dasgupta * fix table Signed-off-by: Arko Dasgupta * moves prior art to the end of the file Signed-off-by: Arko Dasgupta * rewrite prior art section description Signed-off-by: Arko Dasgupta --------- Signed-off-by: Arko Dasgupta --- geps/gep-91/index.md | 67 +++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/geps/gep-91/index.md b/geps/gep-91/index.md index 6fddddb59f..4216a2674e 100644 --- a/geps/gep-91/index.md +++ b/geps/gep-91/index.md @@ -1,4 +1,4 @@ -# GEP-91: Client Certificate Validation for TLS terminating at the Gateway Listener +# GEP-91: Client Certificate Validation for TLS terminating at the Gateway * Issue: [#91](https://github.com/kubernetes-sigs/gateway-api/issues/91) * Status: Implementable @@ -8,31 +8,18 @@ ## TLDR This GEP proposes a way to validate the TLS certificate presented by the frontend client to the server -(Gateway Listener in this case) during a [TLS Handshake Protocol][]. +(Gateway in this case) during a [TLS Handshake Protocol][]. ## Goals -* Define an API field to specify the CA Certificate within the Gateway Listener configuration that can be used as a trust anchor to validate the certificates presented by the client. This use case has been highlighted in the [TLS Configuration GEP][] under segment 1 and in the [Gateway API TLS Use Cases][] document under point 7. +* Define an API field to specify the CA Certificate within the Gateway configuration that can be used as a trust anchor to validate the certificates presented by the client. +This use case has been highlighted in the [TLS Configuration GEP][] under segment 1 and in the [Gateway API TLS Use Cases][] document under point 7. +* Ensure the configuration mitigates the authentication bypass risks associated with HTTP/2 connection coalesing as described in [GEP-3567](https://gateway-api.sigs.k8s.io/geps/gep-3567/#interaction-with-client-cert-validation). +* Supporting a mode where validating client certificates is optional, useful for debugging and migrating to strict TLS. ## Non-Goals * Define other fields that can be used to verify the client certificate such as the Certificate Hash. -## Existing support in Implementations - -This feature is widely supported in implementations that support Gateway API. -This table highlights the support. Please feel free to add any missing implementations not mentioned below. - -| Implementation | Support | -|----------------|------------| -| Apache APISIX | [ApisixTls.Client.CASecret](https://apisix.apache.org/docs/ingress-controller/tutorials/mtls/#mutual-authentication) | -| Contour | [HTTPProxy.Spec.VirtualHost.Tls.ClientValidation.CASecret](https://projectcontour.io/docs/v1.17.1/config/tls-termination/) | -| Emissary Ingress| [TlSContext.Spec.Secret](https://www.getambassador.io/docs/emissary/latest/topics/running/tls/mtls) | -| Gloo Edge | [VirtualService.Spec.SSLConfig.SecretRef](https://docs.solo.io/gloo-edge/latest/guides/security/tls/server_tls/#configuring-downstream-mtls-in-a-virtual-service) | -| Istio | [Gateway.Spec.Servers.TLS.Mode](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway) | -| Kong | [mTLS Plugin](https://docs.konghq.com/hub/kong-inc/mtls-auth/) | -| Traefik | [TLSOption.Spec.ClientAuth](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls) | -| NGINX Ingress Controller | [ingressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#ingressmtls) | - ### API * Introduce a `FrontendValidation` field of type `FrontendTLSValidation` within [GatewayTLSConfig][] that can be used to validate the peer (frontend) with which the TLS connection is being made. @@ -151,10 +138,50 @@ spec: This section highlights use cases that may be covered in a future iteration of this GEP * Using system CA certificates as the trust anchor to validate the certificates presented by the frontend client. -* Supporting a mode where validating client certificates is optional, useful for debugging and migrating to strict TLS. * Supporting an optional `subjectAltNames` field within `FrontendTLSValidation` that can be used to specify one or more alternate names to verify the subject identity in the certificate presented by the client. This field falls under Authorization, the initial focus here is on Client Authentication and will be revisited when Authorization is tackled as a whole in the project. * Specifying the verification depth in the client certificate chain. This is being deferred because the default verification depth differs across implementations. +## Existing support in Implementations + +This feature is already widely supported by implementations that conform to the Gateway API. +The table below summarizes current support. Please feel free to add any implementations that are missing. +This GEP aims to standardize this behavior as an official part of the upstream specification. + +| Implementation | Support | Granularity | Inline vs Policy | +|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|------------------| +| Acnodal EPIC | | | | +| Airlock Microgateway | [SidecarGateway.spec.applications[].downstream.tls.clientCertificate](https://docs.airlock.com/microgateway/latest/index/api/crds/sidecar-gateway/v1alpha1/index.html#sidecargatewayspecapplicationsdownstreamtls) | Per Listener | Inline | +| Amazon Elastic Kubernetes Service | | | | +| Apache APISIX | [ApisixTls.Client.CASecret](https://apisix.apache.org/docs/ingress-controller/tutorials/mtls/#mutual-authentication) | Per SNI | | +| Avi Kubernetes Operator | | | | +| Azure Application Gateway for Containers | [FrontendTLSPolicy](https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/api-specification-kubernetes#alb.networking.azure.io/v1.FrontendTLSPolicy) | Per Gateway & Per Listener | Policy | +| Cilium | | | | +| Contour | [HTTPProxy.Spec.VirtualHost.Tls.ClientValidation.CASecret](https://projectcontour.io/docs/v1.17.1/config/tls-termination/) | Per SNI | Inline | +| Easegress | | | | +| Emissary Ingress | [TlSContext.Spec.CASecret](https://www.getambassador.io/docs/emissary/latest/howtos/client-cert-validation) | Per SNI | Policy | +| Envoy Gateway | [ClientTrafficPolicy.Spec.TLS.ClientValidation](https://gateway.envoyproxy.io/docs/api/extension_types/#clientvalidationcontext) | Per Gateway & Per Listener | Policy | +| Flomesh Service Mesh | | | | +| Gloo Gateway | [VirtualService.Spec.SSLConfig.SecretRef](https://docs.solo.io/gloo-edge/latest/guides/security/tls/server_tls/#configuring-downstream-mtls-in-a-virtual-service) | Per SNI | Inline | +| Google Cloud Service Mesh | | | | +| Google Kubernetes Engine | | | | +| HAProxy Ingress | | | | +| HAProxy Kubernetes Ingress Controller | [ca-file](https://www.haproxy.com/documentation/haproxy-configuration-tutorials/security/authentication/client-certificate-authentication/#sidebar) | Per SNI | Inline | +| HashiCorp Consul | [file-system-certificate](https://developer.hashicorp.com/consul/docs/north-south/api-gateway/secure-traffic/encrypt) | Per Listener | Policy | +| Istio | [Gateway.Spec.Servers.TLS.Mode](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway) | Per Server | Inline | +| kgateway | | | | +| Kong Kubernetes Ingress Controller | [mTLS Plugin](https://docs.konghq.com/hub/kong-inc/mtls-auth/) | Per HTTP Proxy (Host/Port) | Policy | +| Kong Gateway Operator | [mTLS Plugin](https://docs.konghq.com/hub/kong-inc/mtls-auth/) | Per HTTP Proxy (Host/Port) | Policy | +| Kuma | | | | +| Linkerd | | | | +| LiteSpeed Ingress Controller | | | | +| LoxiLB | | | | +| NGINX Gateway Fabric | [ingressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#ingressmtls) | Per Listener | Policy | +| ngrok Kubernetes Operator | [TrafficPolicy.Terminate-TLS.Config.MutualTLSCertificateAuthorities](https://ngrok.com/docs/traffic-policy/actions/terminate-tls/#configuration-reference) | Per Endpoint (Host:Port) | Policy | +| STUNner | | | | +| Traefik Proxy | [TLSOption.Spec.ClientAuth](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls) | Per EntryPoint | Inline | +| Tyk | [Enable Client Certificate](https://tyk.io/docs/basic-config-and-security/security/mutual-tls/client-mtls/#why-use-mutual-tls) | Per Gateway | Policy | +| WSO2 APK | [Authentication.Spec.Default.AuthTypes.MTLS](https://apk.docs.wso2.com/en/latest/catalogs/crds/authentication_types/#dp.wso2.com/v1alpha2.MutualSSLConfig) | Per API | Policy | +| Ingress-NGINX | [nginx.ingress.kubernetes.io/auth-tls-verify-client](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#client-certificate-authentication) | Per Ingress | Inline | ## References From b4794ff3cfee5e49910aa1ba55eb1b8336695ce9 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Tue, 17 Jun 2025 17:24:52 -0700 Subject: [PATCH 045/224] GEP 3779 - East/West Identity-Based Authorization (#3822) * add draft authz gep e/w * add a table * fix * add cilium content * add all mesh authz model * small nits * fix * newline * Apply suggestions from code review Co-authored-by: Nick Young * move cluster-admin non-overridable case to stretch goals * change stretch to tbd --------- Co-authored-by: Aryan Gupta Co-authored-by: Nick Young --- geps/gep-3779/index.md | 266 ++++++++++++++++++++++++++++++++++++ geps/gep-3779/metadata.yaml | 19 +++ 2 files changed, 285 insertions(+) create mode 100644 geps/gep-3779/index.md create mode 100644 geps/gep-3779/metadata.yaml diff --git a/geps/gep-3779/index.md b/geps/gep-3779/index.md new file mode 100644 index 0000000000..49464b16d6 --- /dev/null +++ b/geps/gep-3779/index.md @@ -0,0 +1,266 @@ +# GEP-3779: Identity Based Authz for East-West Traffic + +* Issue: [#3779](https://github.com/kubernetes-sigs/gateway-api/issues/3779) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + + +## TLDR + +Provide a method for configuring Gateway API Mesh implementations to enforce east-west identity-based Authorization controls. At the time of writing this we leave Authentication for specific implementation and outside of this proposal scope. + + +## Goals + +(Using the [Gateway API Personas](../../concepts/roles-and-personas.md)) + +* A way for Ana the Application Developer to configure a Gateway API for Mesh implementation to enforce authorization policy that **allows** or **denies** identity or multiple identities to talk with some set (could be namespace or more granualr) of the workloads she controls. + +* A way for both Ana and Chihiro to restrict the scope of the policies they deploy to specific ports. + +## TBD Goals + +* A way for Chihiro, the Cluster Admin, to configure a Gateway API for Mesh implementation to enforce non-overridable cluster-wide, authorization policies that **allows** or **denies** identity or multiple identities to talk with some set of the workloads in the cluster. + +* A way for Chihiro, the Cluster Admin, to configure a Gateway API for Mesh implementation to enforce default, overridable, cluster-wide, authorization policies that **allows** or **denies** identity or multiple identities to talk with some set of the workloads in the cluster. + +## Non-Goals + +* Support identity based authorization for north-south traffic or define the composition with this API. + +## Deferred Goals + +* (Potentially) Support enforcement on attributes beyond identities and ports. + + +## Introduction + +Authorization is positioned as one of core mesh values. Every mesh supports some kind of east/west authorization between the workloads it controls. + +Kubernetes core provides NetworkPolicies as one way to do it. Network Policies however falls short in many ways including: + +* Network policies leverage labels as identities. + * Labels are mutable at runtime. This opens a path for escalating privileges + * Most implementations of network policies translate labels to IPs, this involves an eventual consistency nature which can and has lea to over permissiveness in the past. + +* Scale. Network Policies are enforced using IPs (different selectors in the APIs get translated to IPs). This does not scale well with large clusters or beyond a single cluster + +An identity-based authorization API is essential because it provides a structured way to control authorization between identities within the cluster. + + +### State of the World + + +| Aspect | Istio | Linkerd | Cilium | +| ----- | ----- | ----- | ----- | +| **Policy CRDs** | `AuthorizationPolicy` (APIs `security.istio.io/v1`) | `AuthorizationPolicy` (CRD `policy.linkerd.io/v1alpha1`), plus supporting CRDs (`Server`, `HTTPRoute`, `MeshTLSAuthentication`) | `CiliumNetworkPolicy` and `CiliumClusterwideNetworkPolicy` (superset of K8s NetworkPolicy) | +| **Identity model** | Identities derived from mTLS peer certificates (bound to SA):
  • SPIFFE-like principal `/ns//sa/`.
  • ServiceAccount name
  • Namespaces

identity within JWT derived from `request.auth.principal`

IPBlocks and x-forwarded-for ipBlocks | Identities derived from mTLS peer certificates (bound to SA trust domain `identity.linkerd.cluster.local`. Policies reference service accounts or explicit mesh identities (e.g. `webapp.identity.linkerd.cluster.local`).

Policies use `requiredAuthenticationRefs` to reference the entities who get authorization. This is a list of targetRefs and it can include:
  • ServiceAccounts
  • `MeshTLSAuthentication` - which represents a set of mesh identities either with a mesh identities strings or reference to serviceAccounts
  • `NetworkAuthentication` - represents sets of IPs or subnets.
|Cilium service mesh can leverage SPIFFE identities in certs that are used for handshake. These SPIFFEE identities are mapped to CiliumIdentities. You can read more about cilium identities in [CiliumIdentity](#CiliumIdentity).

Policies target abstractions like service accounts in the form of labels, pod labels, namespace label, node selectors, CIDR blocks and Cilium predefined [entities](https://docs.cilium.io/en/stable/security/policy/language/#entities-based). All policy targeting is coalesced by Cilium into one or more Cilium Identities for translation into the BPF datapath| +| **Enforcement** | For Istio with sidecars - a proxy on each pod. For ambient, ztunnel node agent enforces mTLS based L4 authorization, L7 authorization is being enforced in waypoints if any.

Istio supports ALLOW, DENY, CUSTOM (often used for external authorization), and AUDIT. DENY policies in istio's context are used to enforce higher priority deny policies. The allow semantics is that whatever is not allowed explicitly (and assuming there is any policy for the same match) is implicitly denied | Linkerd data-plane proxy (injected into each pod). The proxy enforces policies via mTLS identity checks.

Linkerd supports AUDIT and ALLOW. There is not DENY policies, whats not allowed (and assuming there is any policy for the same match) is implicitly denied. | For L3/4 Ingress Rules, CiliumNetworkPolicy enforcement - an eBPF-based datapath in the Linux kernel on the destination node. If L7 http rules are specified, the packet is redirected for a node-local envoy for further enforcement.

Cilium supports ALLOW and DENY semantics - all policies generate audit logs.

Cilium service mesh also offers a kind of AuthN where a Cilium agent on the src node validates a workloads SPIFFE identity by talking to another agent on the destination node, performing the initial TLS handshake to do authentication.| +| **Request Match criteria** | Policies can target a group of pods using label selector, a Gateway/Service (this means targeting a waypoint proxy) or a GatewayClass - meaning all the gateways created from this class. Policies without a label selector in a namespace implies the whole namespace is targeted.

Fine-grained L7 and L4 matching: HTTP/gRPC methods, paths, headers, ports, SNI, etc.Policies use logical OR over rules.

All match criterias are inline in the policy. See https://istio.io/latest/docs/reference/config/security/authorization-policy/#Rule-To and https://istio.io/latest/docs/reference/config/security/authorization-policy/#Rule-when | Policies can target:
  • A `Server` which describes a set of pods (using fancy label match expressions), and a single port on those pods.
  • A user can optionally restrict the authorization to a smaller subset of the traffic by targeting an HTTPRoute. (TODO: any plans to support sectionNames?)
  • A namespace - this indicates that the policy applies to all traffic to all Servers and HTTPRoutes defined in the namespace.
Note: We leave `ServerAuthorization` outside the scope as it planned to be deprecated (per linkerd website) | Policies can target groups of pods using label selector (`endpointSelector`), or by node-labels (`nodeSelector`). Cilium supports L7 via built-in HTTP parsing: rules can match HTTP methods, paths, etc. For example, a CiliumNetworkPolicy can allow only specific HTTP methods/paths on a port. | +| **Default policies and admin policies** | If **no** ALLOW policy matches, traffic is **allowed** by default. You can deploy an overridable - default deny by default by deploying an **allow-nothing** policy in either the namespace or istio-system

AuthorizationPolicies in the `istio-system` namespace apply to the whole mesh and take precedence. These are not overridable by namespace-level policies. | Default inbound policy can be set at install time using `proxy.defaultInboundPolicy`. Supported values are:
  • `all-unauthenticated:` allow all traffic. This is the default.
  • `all-authenticated:` allow traffic from meshed clients in the same or from a different cluster (with multi-cluster).
  • `cluster-authenticated:` allow traffic from meshed clients in the same cluster.
  • `cluster-unauthenticated:` allow traffic from both meshed and non-meshed clients in the same cluster.
  • `deny:` all traffic are denied.
  • `audit:` Same as all-unauthenticated but requests get flagged in logs and metrics.

Users can override the default policies for namespaces/pods or by setting the [config.linkerd.io/default-inbound-policy](http://config.linkerd.io/default-inbound-policy) annotation There is no support for admin, non overridable policies. | Follows Kubernetes NetworkPolicy semantics by default: if no `CiliumNetworkPolicy` allows the traffic, it is allowed (no implicit deny). Once at least one `CiliumNetworkPolicy` or `CiliumClusterwideNetworkPolicy` allows some traffic, all other traffic is implicitly denied. +

Operators must apply explicit deny rules or “default-deny” policies to block traffic in the absence of allow rules.

`CiliumClusterwideNetworkPolicy` exists for whole-cluster enforcement.)| + + +Every mesh vendor has their own API of such authorization. Below we describe brief UX for different implementations: + +#### Istio +For the full spec and sematics of Istio AuthorizationPolicy: [Istio authorization policy docs](https://istio.io/latest/docs/reference/config/security/authorization-policy/) + +Istio's AuthorizationPolicy can enforce access control by specifying allowed istio-formatted identities using the `source.principals` field, which matches authenticated service account identities via mTLS. You can also use other source constructs which are described in the table above and in https://istio.io/latest/docs/reference/config/security/authorization-policy/#Source. + +``` +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: allow-sleep + namespace: default +spec: + selector: + matchLabels: + app: httpbin # The policy applies to pods with this label + action: ALLOW + rules: + - from: + - source: + principals: ["cluster.local/ns/default/sa/sleep"] +``` + +OR targeting a gateway for example. + +``` +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: allow-sleep + namespace: default +spec: + targetRefs: + - name: waypoint + kind: Gateway # note: supported target Refs are Gateway, GatewayClass, Service, and ServiceEntry + group: gateway.networking.k8s.io + action: ALLOW + rules: + - from: + - source: + principals: ["cluster.local/ns/default/sa/sleep"] +``` +#### Linkerd + +For the full spec and sematics of Linkerd AuthorizationPolicy: [Linkerd authorization policy docs](https://linkerd.io/2-edge/reference/authorization-policy/) + +In Linkerd, identity-based authorization is enforced using AuthorizationPolicy and MeshTLSAuthentication, where MeshTLSAuthentication specifies allowed ServiceAccounts or mTLS identities (e.g., sleep.default.serviceaccount.identity.linkerd.cluster.local), ensuring that only authenticated workloads can access a resource. + +Linkerd Policy can by applied to two different targets. + +##### Pod Labels with Server Resource + +``` +apiVersion: policy.linkerd.io/v1beta1 +kind: Server +metadata: + namespace: default + name: httpbin-server +spec: + podSelector: + matchLabels: + app: httpbin + port: 8080 + proxyProtocol: HTTP/2 + +---- +apiVersion: policy.linkerd.io/v1beta1 +kind: MeshTLSAuthentication +metadata: + name: sleep-authn + namespace: default +spec: + identities: + - sleep.default.serviceaccount.identity.linkerd.cluster.local +---- + +apiVersion: policy.linkerd.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: allow-sleep + namespace: default +spec: + targetRef: + group: policy.linkerd.io + kind: Server + name: httpbin-server + requiredAuthenticationRefs: + - name: sleep-authn + kind: MeshTLSAuthentication + group: policy.linkerd.io/v1beta1 + +--- +``` + +##### HTTPRoutes + +``` +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httpbin-route + namespace: default +spec: + parentRefs: + - name: httpbin + kind: Service + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: httpbin + port: 80 + +----- + +apiVersion: policy.linkerd.io/v1beta1 +kind: MeshTLSAuthentication +metadata: + name: sleep-authn + namespace: default +spec: + identities: + - sleep.default.serviceaccount.identity.linkerd.cluster.local +----- + +apiVersion: policy.linkerd.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: allow-sleep-http + namespace: default +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httpbin-route + requiredAuthenticationRefs: + - name: sleep-authn + kind: MeshTLSAuthentication + group: policy.linkerd.io/v1beta1 +--- +``` + + +#### Cilium + +For the full spec and sematics of CiliumNetworkPolicy: https://docs.cilium.io/en/stable/network/kubernetes/policy/#ciliumnetworkpolicy & https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/gateway-api/#cilium-s-ingress-config-and-ciliumnetworkpolicy + +Beyond what's explained in the table above, Cilium also automatically labels each pod with its associated service account using the label io.cilium.k8s.policy.serviceaccount. This label can be used in CiliumNetworkPolicy to enforce identity-based access controls using [ServiceAccounts Based Identities](https://docs.cilium.io/en/latest/security/policy/kubernetes/#serviceaccounts) within CiliumNetworkPolicy; + +See below for example. + +``` +apiVersion: "cilium.io/v2" +kind: CiliumNetworkPolicy +metadata: + name: "k8s-svc-account-policy" +spec: + endpointSelector: + matchLabels: + io.cilium.k8s.policy.serviceaccount: httpbin + ingress: + - fromEndpoints: + - matchLabels: + io.cilium.k8s.policy.serviceaccount: sleep + toPorts: + - ports: + - port: '80' + protocol: TCP + rules: + http: + - method: GET + path: "/" +``` + + +##### CiliumIdentity +Cilium has the concept of CiliumIdentity. Pods are assigned identities derived from their Kubernetes labels (namespace, app labels, etc.). Cilium’s policy matches based on these label-derived identities. The CiliumIdentity implementation maps an integer to a group of IP addresses (the pod IPs associated with a group of pods). This “integer” and its mapping to pod IP addresses represents the core identity primitive in Cilium. + +More on https://docs.cilium.io/en/stable/internals/security-identities/ & https://docs.cilium.io/en/stable/security/network/identity/ + + + +## API + + + +## Conformance Details + + +#### Feature Names + + +### Conformance tests + + +## Alternatives + + +## References \ No newline at end of file diff --git a/geps/gep-3779/metadata.yaml b/geps/gep-3779/metadata.yaml new file mode 100644 index 0000000000..3c5b9af7d2 --- /dev/null +++ b/geps/gep-3779/metadata.yaml @@ -0,0 +1,19 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3779 +name: Identity Based Authz for east-west traffic +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - liorlieberman + - aryan16 +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} From 9d59dd814c5df82a0cc57730167cf4679854be4f Mon Sep 17 00:00:00 2001 From: Tim Flannagan Date: Wed, 18 Jun 2025 16:40:51 -0400 Subject: [PATCH 046/224] Add kgateway 1.3 conformance report (#3865) * Add kgateway 1.3 conformance report Signed-off-by: timflannagan * Override VERSION variable, update conformance report, etc Signed-off-by: timflannagan --------- Signed-off-by: timflannagan --- conformance/reports/v1.3.0/kgateway/README.md | 40 ++++++++++++++ .../v1.3.0/kgateway/v2.1.0-main-report.yaml | 53 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 conformance/reports/v1.3.0/kgateway/README.md create mode 100644 conformance/reports/v1.3.0/kgateway/v2.1.0-main-report.yaml diff --git a/conformance/reports/v1.3.0/kgateway/README.md b/conformance/reports/v1.3.0/kgateway/README.md new file mode 100644 index 0000000000..ddd082e545 --- /dev/null +++ b/conformance/reports/v1.3.0/kgateway/README.md @@ -0,0 +1,40 @@ +# kgateway + +## Table of contents + +| API channel | Implementation version | Mode | Report | +|--------------|-------------------------------------------------------------------------------|---------|-----------------------------------------------------------| +| experimental | [main](https://github.com/kgateway-dev/kgateway) | default | [Link](./v2.1.0-main-report.yaml) | + +## Reproduce + +### Steps + +1. Clone the kgateway repository: + + ```sh + git clone https://github.com/kgateway-dev/kgateway.git && cd kgateway + ``` + +2. Override the version Makefile variable: + + > Note: The main branch defaults to version `1.0.1-dev` for Helm chart validation purposes. For conformance testing, + > we need to override this with a more descriptive version that reflects the main branch: + + ```sh + export VERSION="v2.1.0-main" + ``` + +3. Bootstrap a KinD cluster: + + ```sh + make run + ``` + +4. Run the conformance tests: + + ```sh + make conformance + ``` + +5. View and verify the conformance report: `cat _test/conformance/v2.1.0-main-report.yaml` diff --git a/conformance/reports/v1.3.0/kgateway/v2.1.0-main-report.yaml b/conformance/reports/v1.3.0/kgateway/v2.1.0-main-report.yaml new file mode 100644 index 0000000000..6724903275 --- /dev/null +++ b/conformance/reports/v1.3.0/kgateway/v2.1.0-main-report.yaml @@ -0,0 +1,53 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-06-18T15:07:19-04:00" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - github.com/kgateway-dev/kgateway/issues/new/choose + organization: kgateway-dev + project: kgateway + url: github.com/kgateway-dev/kgateway + version: v2.1.0-main +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 13 + Skipped: 0 + supportedFeatures: + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteDestinationPortMatching + - HTTPRouteParentRefPort + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. From 80200b8745a92a944a57b1a55297ce9ef7e7b86d Mon Sep 17 00:00:00 2001 From: Arihant Bachhawat Date: Mon, 2 Jun 2025 12:17:14 +0000 Subject: [PATCH 047/224] Adding GEP-3798 client ip based session persistence --- geps/gep-3798/index.md | 133 ++++++++++++++++++++++++++++++++++++ geps/gep-3798/metadata.yaml | 37 ++++++++++ 2 files changed, 170 insertions(+) create mode 100644 geps/gep-3798/index.md create mode 100644 geps/gep-3798/metadata.yaml diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md new file mode 100644 index 0000000000..80df3a4e05 --- /dev/null +++ b/geps/gep-3798/index.md @@ -0,0 +1,133 @@ +# GEP-3798: Client IP-Based Session Persistence + +* Issue: [#3798](https://github.com/kubernetes-sigs/gateway-api/issues/3798) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +### What + This GEP proposes the addition of Client IP-based session persistence to the Gateway API. This feature will allow Gateway API implementations to ensure that requests originating from a specific client IP address (or a subnet defined by an IP mask) are consistently routed to the same backend endpoint for a configurable duration. This aims to provide a standardized and centralized mechanism for client IP persistence across various Gateway API implementations. As per the nomenclature established in [#1619](https://gateway-api.sigs.k8s.io/geps/gep-1619), this feature is being referred as Session Affinity . + + +## Goals + +* Define an API extension within Gateway API to enable client IP-based session persistence. + +* Allow configuration of a session duration for which a client IP should stick to a backend. + +* Provide an optional mechanism to specify an IP mask for subnet-based persistence, allowing multiple clients from the same subnet to be routed to the same backend. + +* Ensure the solution is generic enough to be implemented by various Gateway API controllers. + +* Improve portability of applications requiring client IP persistence across different Gateway API implementations. + +## Non-Goals + +This GEP does not dictate the specific algorithm or implementation details for how an individual Gateway controller maintains the client IP-to-backend mapping (e.g., in-memory, distributed cache). + +## Introduction + +### Why: The Problem This Solves +Currently, achieving client IP-based session persistence within Kubernetes Gateway API environments often requires vendor-specific annotations or out-of-band configurations on the underlying load balancer or ingress controller. This approach has several drawbacks: + +* Lack of Portability: Configurations are not easily transferable between different Gateway API implementations, leading to vendor lock-in and increased operational overhead when migrating or using multiple controllers. + +* Inconsistent User Experience: Users have to learn different methods for configuring the same logical feature depending on their chosen Gateway API implementation. + +* Limited API Expressiveness: Important traffic management capabilities are not directly exposed or controlled through the Gateway API, making it less comprehensive for certain application requirements. + +* Reduced Visibility: The desired session persistence behavior is not explicitly declared within the Gateway API resources, making it harder to audit, manage, and understand the routing logic from a single source of truth. + +This GEP addresses these issues by providing a first-class API mechanism for client IP-based session persistence, enhancing the Gateway API's capabilities and promoting consistency and portability. + +### Who: Beneficiaries +* Application Developers: Can define session persistence requirements directly in their Gateway API configurations, ensuring consistent behavior regardless of the underlying Gateway implementation. This simplifies application deployment and management for stateful workloads. + +* Platform Operators/Administrators: Gain a standardized way to configure and manage client IP-based session persistence across their clusters, reducing the need for custom scripts or deep knowledge of individual controller implementations. This improves operational efficiency and consistency. + +* Gateway API Implementers: Receive a clear specification for implementing client IP-based session persistence, fostering interoperability and reducing divergent approaches. + +* Users with Stateful Applications: Applications that rely on client IP affinity (e.g., certain legacy applications, gaming servers, or applications with in-memory session stores) will directly benefit from a reliable and configurable persistence mechanism. + +## API + +As mentioned in the [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api), `SessionPersistence` can be applied via `BackendLBPolicy` and `RouteRule` API .Similar [edge case behaviour](https://gateway-api.sigs.k8s.io/geps/gep-1619/#edge-case-behavior) and [API Granularity](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api-granularity) for ClientIP Persistence type should be applicable as well. + +Requirement is to introduce a new `SessionPersistenceType` called `ClientIP` + +Example (illustrative, exact field names and structure are subject to review): + +``` +# Existing SessionPersistence (simplified for example) +# apiVersion: gateway.networking.k8s.io/v1beta1 +# kind: HTTPRoute + +spec: + rules: + - backendRefs: + - name: my-service + port: 80 + sessionPersistence: + # New field for client IP based persistence + type: "ClientIP" + absoluteTimeout: "5m" + ipMask: 24 # Optional: IP mask for subnet persistence (e.g., "24" for /24 subnet) +``` +``` +type SessionPersistence struct { + ... + + // IPMask defines the IP mask to be applied on client this may be + // used to persist clients from a same subnet to stick to same session + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=128 + IPMask *uint32 `json:"ipMask,omitempty"` + +} + +type SessionPersistenceType string + +const ( + // CookieBasedSessionPersistence specifies cookie-based session + // persistence. + // + // Support: Core + CookieBasedSessionPersistence SessionPersistenceType = "Cookie" + + // HeaderBasedSessionPersistence specifies header-based session + // persistence. + // + // Support: Extended + HeaderBasedSessionPersistence SessionPersistenceType = "Header" + + // ClientIPBasedSessionPersistence specifies Client IP based session + // persistence. + // + // Support: Implementation-specific + ClientIPBasedSessionPersistence SessionPersistenceType = "ClientIP" +) +``` + +### Conformance tests + +NA + +## Alternatives + +Yet to do + +## References + +Below are references showing how ClientIP persistence is currently supported across some implementations: + +* [AVI](https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-load-balancer/30-2/load-balancing-overview/persistence.html) +* [Envoy](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction-hashpolicy-connectionproperties) (the connection property hash policy can be used with Ring Hash load balancing to ensure session persistence for a particular source IP) +* [Nginx](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash) +* [Native k8s](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) + diff --git a/geps/gep-3798/metadata.yaml b/geps/gep-3798/metadata.yaml new file mode 100644 index 0000000000..375caf7558 --- /dev/null +++ b/geps/gep-3798/metadata.yaml @@ -0,0 +1,37 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3798 +name: Client IP-Based Session Persistence +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - arihantg +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: + - number: 1619 + name: Session Persistence + description: Session Persistence via BackendLBPolicy + +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} From ff7e2e8aed2e48156aa85c9e5418c2275ab1bb4a Mon Sep 17 00:00:00 2001 From: Arihant Bachhawat Date: Tue, 10 Jun 2025 09:42:39 +0000 Subject: [PATCH 048/224] address some review comments --- geps/gep-3798/index.md | 7 ++----- geps/gep-3798/metadata.yaml | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index 80df3a4e05..ae89cc1f01 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -8,8 +8,7 @@ ## TLDR ### What - This GEP proposes the addition of Client IP-based session persistence to the Gateway API. This feature will allow Gateway API implementations to ensure that requests originating from a specific client IP address (or a subnet defined by an IP mask) are consistently routed to the same backend endpoint for a configurable duration. This aims to provide a standardized and centralized mechanism for client IP persistence across various Gateway API implementations. As per the nomenclature established in [#1619](https://gateway-api.sigs.k8s.io/geps/gep-1619), this feature is being referred as Session Affinity . - + This GEP proposes the addition of Client IP-based session persistence to the Gateway API. This feature will allow Gateway API implementations to ensure that requests originating from a specific client IP address (or a subnet defined by an IP mask) are consistently routed to the same backend endpoint for a configurable duration. This aims to provide a standardized and centralized mechanism for client IP persistence across various Gateway API implementations. ## Goals @@ -49,7 +48,7 @@ This GEP addresses these issues by providing a first-class API mechanism for cli * Gateway API Implementers: Receive a clear specification for implementing client IP-based session persistence, fostering interoperability and reducing divergent approaches. -* Users with Stateful Applications: Applications that rely on client IP affinity (e.g., certain legacy applications, gaming servers, or applications with in-memory session stores) will directly benefit from a reliable and configurable persistence mechanism. +* Users with Stateful Applications: Applications that rely on client IP Persistence (e.g., certain legacy applications, gaming servers, or applications with in-memory session stores) will directly benefit from a reliable and configurable persistence mechanism. ## API @@ -127,7 +126,5 @@ Yet to do Below are references showing how ClientIP persistence is currently supported across some implementations: * [AVI](https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-load-balancer/30-2/load-balancing-overview/persistence.html) -* [Envoy](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction-hashpolicy-connectionproperties) (the connection property hash policy can be used with Ring Hash load balancing to ensure session persistence for a particular source IP) -* [Nginx](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash) * [Native k8s](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) diff --git a/geps/gep-3798/metadata.yaml b/geps/gep-3798/metadata.yaml index 375caf7558..e7d33a7c8b 100644 --- a/geps/gep-3798/metadata.yaml +++ b/geps/gep-3798/metadata.yaml @@ -21,9 +21,9 @@ relationships: # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. seeAlso: - - number: 1619 - name: Session Persistence - description: Session Persistence via BackendLBPolicy + - number: 1619 + name: Session Persistence + description: Session Persistence via BackendLBPolicy # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. From dfcdf5bd54142eb840ab71e88279812ee8c7f30f Mon Sep 17 00:00:00 2001 From: Arihant Bachhawat Date: Mon, 16 Jun 2025 09:02:19 +0000 Subject: [PATCH 049/224] Removed API section and add examples of load balancers using subnet mask to implement session persistence --- geps/gep-3798/index.md | 70 ++++++------------------------------------ 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index ae89cc1f01..682a091db2 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -10,6 +10,8 @@ ### What This GEP proposes the addition of Client IP-based session persistence to the Gateway API. This feature will allow Gateway API implementations to ensure that requests originating from a specific client IP address (or a subnet defined by an IP mask) are consistently routed to the same backend endpoint for a configurable duration. This aims to provide a standardized and centralized mechanism for client IP persistence across various Gateway API implementations. + As mentioned in the [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api), `SessionPersistence` can be applied via `BackendLBPolicy` and `RouteRule` API. Similar [edge case behaviour](https://gateway-api.sigs.k8s.io/geps/gep-1619/#edge-case-behavior) and [API Granularity](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api-granularity) for ClientIP Persistence type should be applicable as well. + ## Goals * Define an API extension within Gateway API to enable client IP-based session persistence. @@ -52,66 +54,7 @@ This GEP addresses these issues by providing a first-class API mechanism for cli ## API -As mentioned in the [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api), `SessionPersistence` can be applied via `BackendLBPolicy` and `RouteRule` API .Similar [edge case behaviour](https://gateway-api.sigs.k8s.io/geps/gep-1619/#edge-case-behavior) and [API Granularity](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api-granularity) for ClientIP Persistence type should be applicable as well. - -Requirement is to introduce a new `SessionPersistenceType` called `ClientIP` - -Example (illustrative, exact field names and structure are subject to review): - -``` -# Existing SessionPersistence (simplified for example) -# apiVersion: gateway.networking.k8s.io/v1beta1 -# kind: HTTPRoute - -spec: - rules: - - backendRefs: - - name: my-service - port: 80 - sessionPersistence: - # New field for client IP based persistence - type: "ClientIP" - absoluteTimeout: "5m" - ipMask: 24 # Optional: IP mask for subnet persistence (e.g., "24" for /24 subnet) -``` -``` -type SessionPersistence struct { - ... - - // IPMask defines the IP mask to be applied on client this may be - // used to persist clients from a same subnet to stick to same session - // - // Support: Implementation-specific - // - // +optional - // +kubebuilder:validation:Minimum=0 - // +kubebuilder:validation:Maximum=128 - IPMask *uint32 `json:"ipMask,omitempty"` - -} - -type SessionPersistenceType string - -const ( - // CookieBasedSessionPersistence specifies cookie-based session - // persistence. - // - // Support: Core - CookieBasedSessionPersistence SessionPersistenceType = "Cookie" - - // HeaderBasedSessionPersistence specifies header-based session - // persistence. - // - // Support: Extended - HeaderBasedSessionPersistence SessionPersistenceType = "Header" - - // ClientIPBasedSessionPersistence specifies Client IP based session - // persistence. - // - // Support: Implementation-specific - ClientIPBasedSessionPersistence SessionPersistenceType = "ClientIP" -) -``` +TBD ### Conformance tests @@ -128,3 +71,10 @@ Below are references showing how ClientIP persistence is currently supported acr * [AVI](https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-load-balancer/30-2/load-balancing-overview/persistence.html) * [Native k8s](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) +Below are some implementations of ClientIP persistence which allows configuring subnet Mask + +* [F5](https://techdocs.f5.com/content/kb/en-us/products/big-ip_ltm/manuals/product/ltm-concepts-11-5-1/11.html#:~:text=is%20persisted%20properly.-,Source%20address%20affinity%20persistence,-Source%20address%20affinity) +* [Fortinet](https://help.fortinet.com/fadc/4-8-0/olh/Content/FortiADC/handbook/slb_persistence.htm) +* [Huwaei](https://info.support.huawei.com/hedex/api/pages/EDOC1100149308/AEJ0713J/18/resources/cli/session_persistence.html) +* [NetScaler](https://docs.netscaler.com/en-us/citrix-adc/current-release/load-balancing/load-balancing-persistence/no-rule-persistence#:~:text=For%20IP%2Dbased%20persistence%2C%20you%20can%20also%20set%20the%20persistMask%20parameter) +* [AVI](https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-load-balancer/30-2/load-balancing-overview/persistence/client-ip-persistence.html) From 71aee26d97ce2880c9b217982ec65c9090290e5d Mon Sep 17 00:00:00 2001 From: Arihant Bachhawat Date: Tue, 17 Jun 2025 05:52:27 +0000 Subject: [PATCH 050/224] Merge similar points as per review --- geps/gep-3798/index.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index 682a091db2..0daef3e58a 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -10,7 +10,9 @@ ### What This GEP proposes the addition of Client IP-based session persistence to the Gateway API. This feature will allow Gateway API implementations to ensure that requests originating from a specific client IP address (or a subnet defined by an IP mask) are consistently routed to the same backend endpoint for a configurable duration. This aims to provide a standardized and centralized mechanism for client IP persistence across various Gateway API implementations. - As mentioned in the [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api), `SessionPersistence` can be applied via `BackendLBPolicy` and `RouteRule` API. Similar [edge case behaviour](https://gateway-api.sigs.k8s.io/geps/gep-1619/#edge-case-behavior) and [API Granularity](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api-granularity) for ClientIP Persistence type should be applicable as well. + As mentioned in the [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api), `SessionPersistence` can be applied via `BackendLBPolicy` and `RouteRule` API. Similar [edge case behaviour](https://gateway-api.sigs.k8s.io/geps/gep-1619/#edge-case-behavior) and [API Granularity](https://gateway-api.sigs.k8s.io/geps/gep-1619/#api-granularity) for ClientIP Persistence type should be applicable as well. + + An important addition/difference compared to [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619) is that the identity of the backend assigned to a client (or a group of clients in the same subnet) is stored on the server (load balancer / gateway) side as opposed to the client side. ## Goals @@ -33,11 +35,7 @@ This GEP does not dictate the specific algorithm or implementation details for h ### Why: The Problem This Solves Currently, achieving client IP-based session persistence within Kubernetes Gateway API environments often requires vendor-specific annotations or out-of-band configurations on the underlying load balancer or ingress controller. This approach has several drawbacks: -* Lack of Portability: Configurations are not easily transferable between different Gateway API implementations, leading to vendor lock-in and increased operational overhead when migrating or using multiple controllers. - -* Inconsistent User Experience: Users have to learn different methods for configuring the same logical feature depending on their chosen Gateway API implementation. - -* Limited API Expressiveness: Important traffic management capabilities are not directly exposed or controlled through the Gateway API, making it less comprehensive for certain application requirements. +* Inconsistent User Experience: Users have to learn different methods for configuring the same logical feature depending on their chosen Gateway API implementation. Configurations are not easily transferable between different Gateway API implementations, leading to vendor lock-in and increased operational overhead when migrating or using multiple controllers. * Reduced Visibility: The desired session persistence behavior is not explicitly declared within the Gateway API resources, making it harder to audit, manage, and understand the routing logic from a single source of truth. @@ -50,7 +48,7 @@ This GEP addresses these issues by providing a first-class API mechanism for cli * Gateway API Implementers: Receive a clear specification for implementing client IP-based session persistence, fostering interoperability and reducing divergent approaches. -* Users with Stateful Applications: Applications that rely on client IP Persistence (e.g., certain legacy applications, gaming servers, or applications with in-memory session stores) will directly benefit from a reliable and configurable persistence mechanism. +* Users with Stateful/Legacy Applications: Applications that rely on client IP Persistence (e.g., certain legacy applications, gaming servers, or applications with in-memory session stores) will directly benefit from a reliable and configurable persistence mechanism. ## API From 961b4f3739f58c7487b616afaba6954e53763f28 Mon Sep 17 00:00:00 2001 From: Arihant Bachhawat Date: Tue, 17 Jun 2025 20:14:43 +0530 Subject: [PATCH 051/224] Apply suggestions from code review Co-authored-by: Shane Utt --- geps/gep-3798/index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index 0daef3e58a..9afe230b9f 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -22,8 +22,6 @@ * Provide an optional mechanism to specify an IP mask for subnet-based persistence, allowing multiple clients from the same subnet to be routed to the same backend. -* Ensure the solution is generic enough to be implemented by various Gateway API controllers. - * Improve portability of applications requiring client IP persistence across different Gateway API implementations. ## Non-Goals @@ -52,7 +50,7 @@ This GEP addresses these issues by providing a first-class API mechanism for cli ## API -TBD +TODO: when we get to the implementation iterations, we need to consider whether we can implement this using functionality established in [GEP-1619](https://gateway-api.sigs.k8s.io/geps/gep-1619). ### Conformance tests From 46d3d0b4f8019f7905fd5b75d6c142ec49fde8d2 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 18 Jun 2025 18:42:16 -0400 Subject: [PATCH 052/224] Update geps/gep-3798/index.md --- geps/gep-3798/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index 9afe230b9f..84b4a603c8 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -5,6 +5,10 @@ (See [status definitions](../overview.md#gep-states).) +## Notes and Disclaimers + +* This is currently targeting release as `Experimental` in [v1.4.0](https://github.com/kubernetes-sigs/gateway-api/milestone/22). However there was notable concern in [PR#3844](https://github.com/kubernetes-sigs/gateway-api/pull/3844) that it may be difficult to get multiple implementations who will be ready to implement this and move it forward. As such, the primary focus at this point should be finding representatives of implementations who may be interested in implementing this. Otherwise, this GEP may need to be `Deferred` and revisited as part of a later release. + ## TLDR ### What From c9720d935605ca3f56cb204974bbd2620f0da185 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 18 Jun 2025 19:52:52 -0400 Subject: [PATCH 053/224] GEP-3792: Off-Cluster Gateways (#3851) * GEP-3792 Signed-off-by: Flynn * Wordsmith feature name. Signed-off-by: Flynn * Address review feedback. Signed-off-by: Flynn --------- Signed-off-by: Flynn --- geps/gep-3792/index.md | 264 ++++++++++++++++++++++++++++++++++++ geps/gep-3792/metadata.yaml | 33 +++++ 2 files changed, 297 insertions(+) create mode 100644 geps/gep-3792/index.md create mode 100644 geps/gep-3792/metadata.yaml diff --git a/geps/gep-3792/index.md b/geps/gep-3792/index.md new file mode 100644 index 0000000000..3306958554 --- /dev/null +++ b/geps/gep-3792/index.md @@ -0,0 +1,264 @@ +# GEP-3792: External Gateways + +* Issue: [#3792](https://github.com/kubernetes-sigs/gateway-api/issues/3792) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + +## User Story + +**[Chihiro] and [Ian] want a way for out-of-cluster Gateways to be able to +usefully participate in a GAMMA-compliant in-cluster service mesh.** + +Historically, API gateways and ingress controllers have often been implemented +using a Service of type LoadBalancer fronting a Kubernetes pod running a +proxy. This is simple to reason about, easy to manage for sidecar meshes, and +will presumably be an important implementation mechanism for the foreseeable +future. Some cloud providers, though, are moving the proxy outside of the +cluster, for various reasons which are out of the scope of this GEP. Chihiro +and Ian want to be able to use these out-of-cluster proxies effectively and +safely, though they recognize that this may require additional configuration. + +[Chihiro]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro +[Ian]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian + +### Nomenclature and Background + +In this GEP: + +1. We will use _out-of-cluster Gateway_ (OCG) to refer to a conformant + implementation of Gateway API's `GATEWAY` profile that's running outside of + the cluster. This would most commonly be a managed implementation from a + cloud provider, but of course there are many other possibilities -- and in + fact it's worth noting that anything we define here to support OCGs could + also be used by workloads that run in-cluster but which, for whatever + reason, can't be brought into the mesh in the mesh's usual way. + +2. We'll also distinguish between _mTLS meshes_, which rely on standard mTLS + for secure communication (authentication, encryption, and integrity + checking) between workloads, and _non-mTLS meshes_, which do anything else. + We'll focus on mTLS meshes in this GEP; this isn't because of a desire to + exclude non-mTLS meshes, but because we'll have enough trouble just + wrangling the mTLS meshes! Supporting non-mTLS meshes will be a separate + GEP. + + **Note:** It's important to separate mTLS and HTTPS here. Saying that the + mTLS meshes use mTLS for secure communication does not preclude them from + using custom protocols on top of mTLS, and certainly does not mean that + they must use only HTTPS. + +3. _Authentication_ is the act of verifying the identity of some _principal_; + what the principal actually is depends on context. For this GEP we will + primarily be concerned with _workload authentication_, in which the + principal is a workload, as opposed to _user authentication_, in which the + principal is the human on whose behalf a piece of technology is acting. We + expect that the OCG will handle user auth, but of course meshed workloads + can't trust what the OCG says about the user unless the OCG successfully + authenticates itself as a workload. + + **Note:** A single workload will have only one identity, but in practice we + often see a single identity being used for multiple workloads (both because + multiple replicas of a single workload need to share the same identity, and + because some low-security workloads may be grouped together under a single + identity). + +4. Finally, we'll distinguish between _inbound_ and _outbound_ behaviors. + + Inbound behaviors are those that are applied to a request _arriving_ at a + given workload. Authorization and rate limiting are canonical examples + of inbound behaviors. + + Outbound behaviors are those that are applied to a request _leaving_ a + given workload. Load balancing, retries, and circuit breakers are canonical + examples of outbound behaviors. + +## Goals + +- Allow Chihiro and Ian to configure an OCG and a mesh such that the OCG can + usefully participate in the mesh, including: + + - The OCG must be able to securely communicate with meshed workloads in + the cluster, where "securely communicate" includes encryption, + authentication, and integrity checking. + + - The OCG must have a proper identity within the mesh, so that the mesh + can apply authorization policy to requests from the OCG. + + - Whatever credentials the OCG and the mesh use to authenticate each other + must be able to be properly maintained over time (for example, if they + use mTLS, certificates will need rotation over time). + + - The OCG must be able to distinguish meshed workloads from non-meshed + workloads, so that it can communicate appropriately with each. + +- Allow Ana to develop and operate meshed applications without needing to know + whether the Gateway she's using is an OCG or an in-cluster Gateway. + +- Define a basic set of requirements for OCGs and meshes that want to + interoperate with each other (for example, the OCG and the mesh will likely + need to agree on how workload authentication principals are represented). + +- Define how responsibility is shared between the OCG and the mesh for + outbound behaviors applied to requests leaving the OCG. (Note that "the OCG + has complete responsibility and authority over outbound behaviors for + requests leaving the OCG" is very much a valid definition.) + +## Non-Goals + +- Support multicluster operations. It may be the case that functional + multicluster (with, e.g., a single OCG fronting multiple clusters) ends up + falling out of this GEP, but it is not a goal. + +- Support meshes interoperating with each other. It's possible that this GEP + will lay a lot of groundwork in that direction, but it is not a goal. + +- Support non-mTLS meshes in Gateway API 1.4. We'll make every effort not to + rule out non-mTLS meshes, but since starting with the mTLS meshes should + tackle a large chunk of the industry with a single solution, that will be + the initial focus. + +- Solve the problem of extending a mesh to cover non-Kubernetes workloads (AKA + _mesh expansion_). In many ways, mesh expansion is adjacent to the OCG + situation, but the where the OCG is aware of the cluster and mesh, mesh + expansion deals with a non-Kubernetes workload that is largely not aware of + either. + +- Solve the problem of how to support an OCG doing mTLS directly to a + _non_-meshed workload (AKA the _backend TLS problem_). Backend TLS to + non-meshed workloads is also adjacent to the OCG situation, but its + configuration has different needs: backends terminating TLS on their own are + likely to need per-workload configuration of certificates, cipher suites, + etc., where the mesh as a whole should share a single configuration. + +- Prevent the OCG API from being used by an in-cluster workload. We're not + going to make in-cluster workloads a primary use case for this GEP, but + neither are we disallowing them. + +## Overview + +Making an OCG work with an in-cluster mesh at the most basic level doesn't +really require any special effort. As long as the OCG has IP connectivity to +pods in the cluster, and the mesh is configured with permissive security, the +OCG can simply forward traffic from clients directly to meshed pods, and +things will "function" in that requests from clients, through the OCG, can be +handled by workloads in the cluster. + +Of course, this sort of non-integration has obvious and terrible security +implications, since the traffic between the OCG and the application pods in +the cluster will be cleartext in the scenario above. The lack of encryption is +awful in its own right, but the fact that any mTLS mesh uses mTLS for +_authentication_ also means that the mesh loses any way to enforce +authorization policy around the OCG. Combined, these items amount to a major +problem. + +An additional concern is that the OCG needs to be able to implement features +(e.g. sticky sessions) which require it to speak directly to endpoint IPs, +which can limit what the mesh will be able to do. This is likely a more minor +concern since a conformant OCG should itself be able to provide advanced +functionality; however, at minimum it can create some friction in +configuration. + +### The Problems + +To allow the OCG to _usefully_ participate in the mesh, we need to solve at +least four significant problems. Thankfully, these are mostly problems for +Chihiro -- if we do our jobs correctly, Ana will never need to know. + +#### 1. The Trust Problem + +The _trust problem_ is fairly straightforward to articulate: the OCG and the +mesh both need access to whatever information will allow each of them to trust +the other. + +In the case of mTLS meshes, we are helped by the fact that basically every OCG +candidate already speaks mTLS, so the trust problem becomes "only" one of +setting things up for the OCG and the mesh to each include the other's CA +certificate in their trust bundle. (They may be using the same CA certificate, +but we shouldn't rely on that.) + +In the case of non-mTLS meshes, the trust problem is more complex; this is the +major reason that this GEP is focused on mTLS meshes. + +#### 2. The Protocol Problem + +The _protocol problem_ is that the data-plane elements of the mesh may assume +that they'll always be talking only to other mesh data-plane elements, which +the OCG will not be. If the mesh data-plane elements use a specific protocol, +then either the OCG will need to speak that protocol, or the mesh will need to +relax its requirements (perhaps on a separate port?) to accept requests +directly from the OCG. + +For example, Linkerd and Istio Legacy both use standard mTLS for +proxy-to-proxy communication -- however, both also use ALPN to negotiate +custom (and distinct!) "application" protocols during mTLS negotiation, and +depending on the negotiated protocol, both can require the sending proxy to +send additional information after mTLS is established, before any client data +is sent. (For example, Linkerd requires the originating proxy to send +transport metadata right after the TLS handshake, and it will reject a +connection which doesn't do that correctly.) + +#### 4. The Discovery Problem + +When using a mesh, not every workload in the cluster is required to be meshed +(for example, it's fairly common to have some namespaces meshed and other +namespaces not meshed, especially during migrations). The _discovery problem_ +here is that the OCG needs to be know which workloads are meshed, so that it +can choose appropriate communication methods for them. + +#### 4. The Outbound Behavior Problem + +The OCG will need to speak directly to endpoints in the cluster, as described +above. This will prevent most meshes from being able to tell which service was +originally requested, which makes it impossible for the mesh to apply outbound +behaviors. This is the _outbound behavior problem_: it implies that either the +OCG must be responsible for outbound behaviors for requests leaving the OCG +for a meshed workload, or that the OCG must supply the mesh with enough +information about the targeted service to allow the mesh to apply those +outbound behaviors (if that's even possible: sidecar meshes may very well +simply not be able to do this.) + +This is listed last because it shouldn't be a functional problem to simply +declare the OCG solely responsible for outbound behaviors for requests leaving +the OCG. It is a UX problem: if a given workload needs to be used by both the +OCG or other meshed workloads, you'll need to either provide two Routes with +the same configuration, or you'll need to provide a single Route with multiple +`parentRef`s. + +## API + +Most of the API work for this GEP is TBD at this point, but there are two +important points to note: + +First, Gateway API has never defined a Mesh resource because, to date, it's +never been clear what would go into it. This may be the first configuration +item that causes us to need a Mesh resource. + +Second, since the API should affect only Gateway API resources, it is not a +good candidate for policy attachment. It is likely to be much more reasonable +to simply provide whatever extra configuration we need inline in the Gateway +or Mesh resources. + +## Graduation Criteria + +In addition to the [general graduation +criteria](../concepts/versioning.md#graduation-criteria), this GEP must also +guarantee that **all four** of the problems listed above need resolutions, and +must have implementation from at least two different Gateways and two +different meshes. + +### Gateway for Ingress (North/South) + +### Gateway For Mesh (East/West) + +## Conformance Details + +#### Feature Names + +This GEP will use the feature name `MeshOffClusterGateway`, under the +assumption that we will indeed need a Mesh resource. + +### Conformance tests + +## Alternatives + +## References diff --git a/geps/gep-3792/metadata.yaml b/geps/gep-3792/metadata.yaml new file mode 100644 index 0000000000..2551cb0aca --- /dev/null +++ b/geps/gep-3792/metadata.yaml @@ -0,0 +1,33 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3792 +name: GEP template +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - kflynn +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} From b4055ba1611daac73fddfd2b005ae85b68733c8a Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 19 Jun 2025 06:46:51 -0400 Subject: [PATCH 054/224] GEP-3793: Default Gateways (#3852) * GEP-3793 Signed-off-by: Flynn * Review feedback. Signed-off-by: Flynn * Review feedback. Signed-off-by: Flynn --------- Signed-off-by: Flynn --- geps/gep-3793/index.md | 217 ++++++++++++++++++++++++++++++++++++ geps/gep-3793/metadata.yaml | 33 ++++++ 2 files changed, 250 insertions(+) create mode 100644 geps/gep-3793/index.md create mode 100644 geps/gep-3793/metadata.yaml diff --git a/geps/gep-3793/index.md b/geps/gep-3793/index.md new file mode 100644 index 0000000000..0c8ba3e6ae --- /dev/null +++ b/geps/gep-3793/index.md @@ -0,0 +1,217 @@ +# GEP-3793: Default Gateways + +* Issue: [#3793](https://github.com/kubernetes-sigs/gateway-api/issues/3793) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + +## User Story + +**[Ana] wants a concept of a default Gateway.** + +Gateway API currently requires every north/south Route object to explicitly +specify its parent Gateway. This is helpful in that it removes ambiguity, but +it's less helpful in that [Ana] is stuck constantly explicitly configuring a +thing that she probably doesn't care much about: in a great many cases, Ana +just wants to create a Route that "works from the outside world" and she +really doesn't care what the Gateway is called. + +Therefore, Ana would like a way to be able to rely on a default Gateway that +she doesn't have to explicitly name, and can simply trust to exist. + +[Ana]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana + +## Goals + +- Give Ana a way to use Gateway API without having to explicitly specify a + Gateway for every Route, ideally without mutating Routes. + +- Give Ana an easy way to determine which Gateway is the default, and which of + her Routes are bound to it. + +- Continue supporting multiple Gateways in a cluster, while allowing exactly + one of them to be the default Gateway. + +- Allow [Chihiro] to retain control over which Gateway is the default, so that + they can ensure that it meets their requirements for security, performance, + and other operational concerns. + +- Allow Chihiro to choose not to provide a default Gateway. + +- Allow Chihiro to rename, reconfigure, or replace the default Gateway at + runtime. + + - If Chihiro renames the default Gateway, Routes using the default Gateway + MUST remain bound to the new default Gateway. Ana shouldn't need to go + recreate all her Routes just because Chihiro is being indecisive. + + - Determine how (or if) to signal changes in functionality if the default + Gateway implementation is changed. For example, suppose that Chihiro + switches the default Gateway from an implementation that supports the + `HTTPRoutePhaseOfTheMoon` filter to an implementation that does not. + + (Note that this problem is not unique to default Gateways; it affects + explicitly-named Gateways as well.) + +- Allow Chihiro to control which Routes may bind to the default Gateway, and + to enumerate which Routes are currently bound to the default Gateway. + +- Support easy interoperation with common CI/CD and GitOps workflows. + +- Define how (or if) listener and Gateway merging applies to a default + Gateway. + +## Non-Goals + +- Support multiple "default" Gateways in a single cluster. If Ana has to make + a choice about which Gateway she wants to use, she'll need to be explicit + about that. + + Loosening this restriction later is a possibility. For example, we may later + want to consider allowing a default Gateway per namespace, or a default + Gateway per implementation running in a cluster. However, these examples are + not in scope for this GEP, in order to have a fighting chance of getting + functionality into Gateway API 1.4. + +- Allow Ana to override Chihiro's choice for the default Gateway for a given + Route without explicitly specifying the Gateway. + +- Require that every possible routing use case be met by a Route using the + default Gateway. There will be a great many situations that require Ana to + explicitly choose a Gateway; the existence of a default Gateway is not a + guarantee that it will be correct for any given use case. + +- Allow for "default Gateway" functionality without a Gateway controller + installed. Just as with any other Gateway, a default Gateway requires an + implementation to be installed. + +## Overview + +Gateway API currently requires every north/south Route object to explicitly +specify its parent Gateway. This is a wonderful example of a fundamental +tension in Gateway API: + +- [Chihiro] and [Ian] value _explicit definition_ of everything, because it + makes it easier for them to reason about the system and ensure that it meets + the standards they set for it. + +- [Ana], on the other hand, values _simplicity_ and _ease of use_, because + she just wants to get her job done without having to think about every little + detail. + +At present, Gateway API is heavily weighted towards the point of view of +Chihiro and Ian. This causes friction for Ana: for example, she can't write +examples or documentation for her colleagues (or her counterparts at other +companies) without telling them that they'll need to be sure to edit the +Gateway name in every Route. Nor can she write a Helm chart that includes a +Route without requiring the person using the chart to know the specific name +for the Gateway to use. + +The root cause of this friction is a difference in perspective: to Chihiro and +Ian, the Gateway is a first-class thing that they think about regularly, while +to Ana, it's an implementation detail that she doesn't care about. Neither +point of view is wrong, but they are in tension with each other. + +### Prior Art + +This is very much not a new problem: there are many other systems out there +where being unambiguous is crucial, but where being completely explicit is a +burden. One of the simplest examples is the humble URL, where the port number +is not always explicit, but it _is_ always unambiguous. Requiring everyone to +type `:80` or `:443` at the end of the host portion of every URL wouldn't +actually help anyone, though allowing it to be specified explicitly when +needed definitely does help people. + +The Ingress resource, of course, is another example of prior art: it permitted +specifying a default IngressClass, allowing users to create Ingress resources +that didn't specify the IngressClass explicitly. As with a great many things +in the Ingress API, this caused problems: + +1. Ingress never defined how conflicts between multiple Ingress resources + should be handled. Many (most?) implementations merged conflicting + resources, which is arguably the worst possible choice. + +2. Ingress also never defined a way to allow users to see which IngressClass + was being used by a given Ingress resource, which made it difficult for + users to understand what was going on if they were using the default + IngressClass. + +(Oddly enough, Ingress' general lack of attention to separation of concerns +wasn't really one of the problems here, since IngressClass was a separate +resource.) + +It's rare to find systems that are completely explicit or completely implicit: +in practice, the trick is to find a usable balance between explicitness and +simplicity, while managing ambiguity. + +### Debugging and Visibility + +It's also critical to note that visibility is critical when debugging: if Ana +can't tell which Gateway is being used by a given Route, then her ability to +troubleshoot problems is _severely_ hampered. Of course, one of the major +strengths of Gateway API is that it _does_ provide visibility into what's +going on in the `status` stanzas of its resources: every Route already has a +`status` showing exactly which Gateways it is bound to. Making certain that +Ana has easy access to this information, and that it's clear enough for her to +understand, is clearly important for many more reasons than just default +Gateways. + +[Chihiro]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro +[Ian]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian + +## API + +Most of the API work for this GEP is TBD at this point. The challenge is to +find a way to allow Ana to use Routes without requiring her to specify the +Gateway explicitly, while still allowing Chihiro and Ian to retain control +over the Gateway and its configuration. + +An additional concern is CD tools and GitOps workflows. In very broad terms, +these tools function by applying manifests from a Git repository to a +Kubernetes cluster, and then monitoring the cluster for changes. If a tool +like Argo CD or Flux detects a change to a resource in the cluster, it will +attempt to reconcile that change with the manifest in the Git repository -- +which means that changes to the `spec` of an HTTPRoute that are made by code +running in the cluster, rather than by a user with a Git commit, can +potentially trip up these tools. + +These tools generally ignore strict additions: if a field in `spec` is not +present in the manifest in Git, but is added by code running in the cluster, +the tools know to ignore it. So, for example, if `spec.parentRefs` is not +present at all in the manifest in Git, CD tools can probably tolerate having a +Gateway controller write a new `parentRefs` stanza to the resource. + +There has been (much!) [discussion] about whether the ideal API for this +feature will mutate the `parentRefs` of a Route using a default Gateway to +reflect the Gateway chosen, or whether it should not, relying instead on the +`status` stanza to carry this information. This is obviously a key point that +will need resolution before this GEP can graduate. + +[discussion]: https://github.com/kubernetes-sigs/gateway-api/pull/3852#discussion_r2140117567 + +### Gateway for Ingress (North/South) + +### Gateway For Mesh (East/West) + +## Conformance Details + +#### Feature Names + +The default-gateway feature will be named `HTTPRouteDefaultGateway` and +`GRPCRouteDefaultGateway`. It is unlikely that an implementation would support +one of these Route types without the other, but `GatewayDefaultGateway` does +not seem like a good choice. + +### Conformance tests + +## Alternatives + +A possible alternative API design is to modify the behavior of Listeners or +ListenerSets; rather than having a "default Gateway", perhaps we would have +"[default Listeners]". One challenge here is that the Route `status` doesn't +currently expose information about which Listener is being used, though it +does show which Gateway is being used. + +[default Listeners]: https://github.com/kubernetes-sigs/gateway-api/pull/3852#discussion_r2149056246 + +## References diff --git a/geps/gep-3793/metadata.yaml b/geps/gep-3793/metadata.yaml new file mode 100644 index 0000000000..d7db3ffebf --- /dev/null +++ b/geps/gep-3793/metadata.yaml @@ -0,0 +1,33 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3793 +name: GEP template +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - kflynn +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} From 9e413ccb0ae77eccf61b48a509884addfbfd1945 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 19 Jun 2025 18:26:55 -0400 Subject: [PATCH 055/224] docs: note about expectations when a gep misses a release timeline (#3866) Signed-off-by: Shane Utt --- site-src/contributing/release-cycle.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site-src/contributing/release-cycle.md b/site-src/contributing/release-cycle.md index 43a811dfff..f25686d1d7 100644 --- a/site-src/contributing/release-cycle.md +++ b/site-src/contributing/release-cycle.md @@ -79,6 +79,21 @@ candidates. These release candidates will enable implementations to test against our release, work out any bugs, and gather early feedback on the viability of the release. +## What happens when GEPs are unable to meet a timeline? + +There will be situations where the above phases and timelines can't be met by +a GEP for one reason or another. In special circumstances (particularly, when it +is is anticipated that only a little bit more time is needed to meet the goal) a +time extension _might_ be granted if requested by the GEP authors, at the +discretion of the maintainers. + +In the normal case however, when a GEP misses the timeline for a phase it will +be pulled out of the release to maximize bandwidth and reduce disruptions to the +overall release timeline. In such a case the Gateway API maintainers will stop +progression and set the status of the GEP to a halted status (such as `Deferred` +or `Declined`) with a note on the GEP explaining why it reached this status and +what it would take to get it re-approved for work in a later iteration. + ## Contributions Welcome in Each Phase The following table illustrates when different kinds of contributions will be From 8ed3a0652b3cb0b295b890ede81d24b72d0e34a0 Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 19 Jun 2025 18:42:52 -0400 Subject: [PATCH 056/224] GEP-3792 and GEP-3793 title fixes :man_facepalming: (#3870) * GEP-3792 and GEP-3793 title fixes :man_facepalming: Signed-off-by: Flynn * It's really annoying to have to constantly update this file. Signed-off-by: Flynn * May as well include Lior's GEP too. Signed-off-by: Flynn --------- Signed-off-by: Flynn --- geps/gep-3792/index.md | 2 +- geps/gep-3792/metadata.yaml | 2 +- geps/gep-3793/metadata.yaml | 2 +- mkdocs.yml | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/geps/gep-3792/index.md b/geps/gep-3792/index.md index 3306958554..b0c5d80b6b 100644 --- a/geps/gep-3792/index.md +++ b/geps/gep-3792/index.md @@ -1,4 +1,4 @@ -# GEP-3792: External Gateways +# GEP-3792: Out-of-Cluster Gateways * Issue: [#3792](https://github.com/kubernetes-sigs/gateway-api/issues/3792) * Status: Provisional diff --git a/geps/gep-3792/metadata.yaml b/geps/gep-3792/metadata.yaml index 2551cb0aca..4478b32b1e 100644 --- a/geps/gep-3792/metadata.yaml +++ b/geps/gep-3792/metadata.yaml @@ -1,7 +1,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 3792 -name: GEP template +name: Out-of-Cluster Gateways status: Provisional # Any authors who contribute to the GEP in any way should be listed here using # their GitHub handle. diff --git a/geps/gep-3793/metadata.yaml b/geps/gep-3793/metadata.yaml index d7db3ffebf..060426f033 100644 --- a/geps/gep-3793/metadata.yaml +++ b/geps/gep-3793/metadata.yaml @@ -1,7 +1,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 3793 -name: GEP template +name: Default Gateways status: Provisional # Any authors who contribute to the GEP in any way should be listed here using # their GitHub handle. diff --git a/mkdocs.yml b/mkdocs.yml index 4a4a7de35d..4688e7f585 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -130,6 +130,9 @@ nav: - geps/gep-1494/index.md - geps/gep-1651/index.md - geps/gep-2648/index.md + - geps/gep-3379/index.md + - geps/gep-3792/index.md + - geps/gep-3793/index.md - Implementable: - geps/gep-91/index.md - geps/gep-3567/index.md From 6f56152752710213525101ea8ce4be964512df73 Mon Sep 17 00:00:00 2001 From: Yoon Seoyul Date: Sat, 21 Jun 2025 03:36:52 +0900 Subject: [PATCH 057/224] docs: fix typo and add contents about "ngrok Kubernetes Operator" (#3874) --- site-src/implementations.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index 06b0e7926e..6531b831f0 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -496,11 +496,12 @@ If you have any suggestions or experience issues with NGINX Gateway Fabric, plea ### ngrok Kubernetes Operator [ngrok Kubernetes Operator][ngrok-k8s-operator] After adding preliminary support last year, the [ngrok Kubernetes Operator][ngrok-k8s-operator] supports the entire core Gateway API. This includes: --Routes (HTTPRoute, TCPRoute, TLSRoute) + RouteMatches (Header, Path, +more) --Filters: Header, Redirect, Rewrite + more --Backends: Backend Filters + Weighted balancing --ReferenceGrant: RBAC for multi-tenant clusters handling --Traffic Policy as an extensionRef or annotation when the Gateway API isn’t flexible enough + +- Routes (HTTPRoute, TCPRoute, TLSRoute) + RouteMatches (Header, Path, +more) +- Filters: Header, Redirect, Rewrite + more +- Backends: Backend Filters + Weighted balancing +- ReferenceGrant: RBAC for multi-tenant clusters handling +- Traffic Policy as an extensionRef or annotation when the Gateway API isn’t flexible enough You can read our [docs][ngrok-k8s-gwapi-docs] for more information. If you have any feature requests or bug reports, please [create an issue][ngrok-issue-new]. You can also reach out for help on [Slack][ngrok-slack] @@ -508,7 +509,7 @@ You can read our [docs][ngrok-k8s-gwapi-docs] for more information. If you have [ngrok]:https://ngrok.com [ngrok-k8s-gwapi-docs]:https://ngrok.com/docs/k8s/ [ngrok-issue-new]: https://github.com/ngrok/ngrok-operator/issues/new/choose - +[ngrok-slack]:https://ngrokcommunity.slack.com/channels/general ### STUNner From 7f29273e9307f81d5560d2d41c6d54d228b44973 Mon Sep 17 00:00:00 2001 From: Blake Covarrubias Date: Fri, 20 Jun 2025 11:52:51 -0700 Subject: [PATCH 058/224] docs: Fix links to nonexistent anchors (#3862) --- geps/gep-1324/index.md | 2 +- geps/gep-1619/index.md | 4 ++-- geps/gep-1686/index.md | 2 +- geps/gep-1709/index.md | 6 +++--- geps/gep-1867/index.md | 2 +- geps/gep-1897/index.md | 2 -- geps/gep-2722/index.md | 2 +- geps/gep-91/index.md | 4 ++-- geps/gep-995/index.md | 2 +- site-src/api-types/backendtlspolicy.md | 12 ++++++------ site-src/api-types/backendtrafficpolicy.md | 4 ++-- site-src/api-types/grpcroute.md | 2 +- site-src/api-types/httproute.md | 2 +- site-src/blog/2021/introducing-v1alpha2.md | 2 +- site-src/blog/2022/graduating-to-beta.md | 18 +++++++++--------- site-src/blog/2023/0829-mesh-support.md | 16 ++++++++-------- site-src/blog/index.md | 2 +- site-src/concepts/api-overview.md | 6 +++--- site-src/concepts/use-cases.md | 8 ++++---- site-src/faq.md | 3 ++- site-src/guides/crd-management.md | 2 +- site-src/guides/migrating-from-ingress.md | 2 +- site-src/guides/multiple-ns.md | 2 +- site-src/implementations.md | 4 ++-- site-src/index.md | 14 +++++++------- site-src/mesh/gamma.md | 2 +- site-src/mesh/index.md | 2 +- site-src/mesh/service-facets.md | 2 +- 28 files changed, 65 insertions(+), 66 deletions(-) diff --git a/geps/gep-1324/index.md b/geps/gep-1324/index.md index a80d6c8615..5384beced3 100644 --- a/geps/gep-1324/index.md +++ b/geps/gep-1324/index.md @@ -33,7 +33,7 @@ Gateway API represents the next generation of traffic routing APIs in Kubernetes ## Versioning -Features or other modifications to the Gateway API spec that fall under this GEP will be subject to the same [versioning guidelines](../../concepts/versioning.md#graduation-criteria) as the rest of the Gateway API. For example, to move changes concerning a beta feature (e.g. HTTPRoute) from experimental to standard, all of the [beta criteria](../../concepts/versioning.md#experimental-standard) must be met (e.g. implemented by several implementations). +Features or other modifications to the Gateway API spec that fall under this GEP will be subject to the same [versioning guidelines](../../concepts/versioning.md#graduation-criteria) as the rest of the Gateway API. For example, to move changes concerning a beta feature (e.g. HTTPRoute) from experimental to standard, all of the [graduation criteria](../../concepts/versioning.md#graduation-criteria) must be met (e.g. implemented by several implementations). ## Use-Cases diff --git a/geps/gep-1619/index.md b/geps/gep-1619/index.md index 04451eb948..1abed57476 100644 --- a/geps/gep-1619/index.md +++ b/geps/gep-1619/index.md @@ -21,7 +21,7 @@ Before this GEP graduates to Implementable, we must fulfill the following criter - **Answer**: Yes. We adjusted the API to use `BackendLBPolicy`. See [API](#api) for more details. 2. Should we leave room for configuring different forms of Session Persistence? If so, what would that look like? - - **Answer**: Yes. See the [BackendLBPolicy API](#BackendLBPolicy-api) and [API Granularity](#api-granularity) + - **Answer**: Yes. See the [BackendLBPolicy API](#backendlbpolicy-api) and [API Granularity](#api-granularity) sections for more details. 3. What name appropriately describe the API responsible for configuring load-balancing options for backend traffic? - **Answer**: We decided on `BackendLBPolicy` since it is aligned with `BackendTLSPolicy`, describes configuration @@ -668,7 +668,7 @@ functionality of their applications. ### Prior Art -Referring to our [Implementations](#Implementations) table on session persistence, the majority of Gateway API +Referring to our [Implementations](#implementations) table on session persistence, the majority of Gateway API implementations designed session persistence in their APIs to be attached to a service or backends. This should be considered cautiously, as making associations to Gateway API's notion of Gateway, Route, and Service to other implementation's objects is hard to directly translate. The idea of a route in Gateway API is often not the same as a diff --git a/geps/gep-1686/index.md b/geps/gep-1686/index.md index e986ee619f..50e6e7a756 100644 --- a/geps/gep-1686/index.md +++ b/geps/gep-1686/index.md @@ -16,7 +16,7 @@ This testing plan specifies a new set of tests to define a "Mesh" [conformance p ## Focus Currently the GAMMA spec consists of two Gateway API GEPs [defining terminology and goals of Gateway API for service meshes](../gep-1324/index.md) -and specifically [how route resources work in a service mesh context](/geps/gep-1426/). +and specifically [how route resources work in a service mesh context](../gep-1294/index.md). The goal of the initial conformance testing is to check the essential behavior as defined by GEP-1426, as it differs from the wider Gateway API spec. This GEP focuses on using a `Service` object as an `xRoute` `parentRef` to control how the GAMMA implementation directs traffic to the endpoints specified by the `Services` in `backendRefs` and how the traffic is filtered and modified. ## Conformance Profile diff --git a/geps/gep-1709/index.md b/geps/gep-1709/index.md index b4e29acc92..b370805fc8 100644 --- a/geps/gep-1709/index.md +++ b/geps/gep-1709/index.md @@ -69,7 +69,7 @@ steps: 1. select a [profile](#profiles) 2. [integrate](#integration) tests in the downstream project -3. [report results and get certified](#certification) +3. [report results][#reporting-process] and get certified][#certification-process] The goal is to make selecting a conformance profile as simple and automatic of a process as feasible and support both the existing command line integration @@ -164,7 +164,7 @@ for i := 0; i < len(tests.ConformanceTests); i++ { > but when used in conjunction with `Profile` this will result in a report that > the profile is not valid for reporting. Implementations in this state may be > able to report themselves as "in progress", see the -> [certification section](#certification) for details. +> [certification section](#certification-process) for details. Alternatively for an `Extended` conformance profile where not all of the features are implemented (as described in the [profiles](#profiles) section @@ -234,7 +234,7 @@ support, or opt-out of the features you _don't_ support using `UnsupportedFeatures`. Once an implementation has integrated with the conformance test suite, they can -move on to [certification](#certification) to report the results. +move on to [certification](#certification-process) to report the results. [go-test]:https://go.dev/doc/tutorial/add-a-test [go]:https://go.dev diff --git a/geps/gep-1867/index.md b/geps/gep-1867/index.md index cf66436290..eba4f6e24c 100644 --- a/geps/gep-1867/index.md +++ b/geps/gep-1867/index.md @@ -36,7 +36,7 @@ This has been previously discussed in [this issue](https://github.com/kubernetes As a cluster scoped resource, `GatewayClass` does not meet this requirement. This restricts customization use cases to either a few pre-provisioned classes by the admin, or running in an environment where the "Infrastructure Provider" and "Cluster Operator" are the same roles. -The distinction between these roles is explicitly called out on the [homepage](../../index.md#what-is-the-gateway-api). +The distinction between these roles is explicitly called out on the [homepage](../../index.md#personas). ### Custom Resource diff --git a/geps/gep-1897/index.md b/geps/gep-1897/index.md index 9f2a9918f9..3203d34d95 100644 --- a/geps/gep-1897/index.md +++ b/geps/gep-1897/index.md @@ -405,8 +405,6 @@ the implementation would be required to fully implement the policy or mark the b [GEP-713: Metaresources and PolicyAttachment](../gep-713/index.md) -[Policy Attachment](../../reference/policy-attachment.md#direct-policy-attachment) - [Gateway API TLS](../../guides/tls.md) [SIG-NET Gateway API: TLS to the K8s.Service/Backend](https://docs.google.com/document/d/1RTYh2brg_vLX9o3pTcrWxtZSsf8Y5NQvIG52lpFcZlo) diff --git a/geps/gep-2722/index.md b/geps/gep-2722/index.md index 135e2c7670..fc6a609d20 100644 --- a/geps/gep-2722/index.md +++ b/geps/gep-2722/index.md @@ -387,7 +387,7 @@ distribution mechanisms will be provided: for visualizing data and presenting information in a visually appealing manner. * Evaluate how gwctl can be extended to support [Mesh use - cases](/concepts/gamma/#how-the-gateway-api-works-for-service-mesh) + cases](../../mesh/index.md) ## References diff --git a/geps/gep-91/index.md b/geps/gep-91/index.md index 4216a2674e..5d28c9a117 100644 --- a/geps/gep-91/index.md +++ b/geps/gep-91/index.md @@ -69,7 +69,7 @@ type GatewayTLSConfig struct { ...... // FrontendValidation holds configuration information for validating the frontend (client). // Setting this field will require clients to send a client certificate - // required for validation during the TLS handshake. In browsers this may result in a dialog appearing + // required for validation during the TLS handshake. In browsers this may result in a dialog appearing // that requests a user to specify the client certificate. // The maximum depth of a certificate chain accepted in verification is Implementation specific. FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` @@ -187,7 +187,7 @@ This GEP aims to standardize this behavior as an official part of the upstream s [TLS Handshake Protocol]: https://www.rfc-editor.org/rfc/rfc5246#section-7.4 [Certificate Path Validation]: https://www.rfc-editor.org/rfc/rfc5280#section-6 -[GatewayTLSConfig]: /references/spec/#gateway.networking.k8s.io/v1.GatewayTLSConfig +[GatewayTLSConfig]: ../../reference/spec.md#gateway.networking.k8s.io/v1.GatewayTLSConfig [BackendTLSPolicy]: ../../api-types/backendtlspolicy.md [TLS Configuration GEP]: ../gep-2907/index.md [Gateway API TLS Use Cases]: https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit?pli=1#heading=h.cxuq8vo8pcxm diff --git a/geps/gep-995/index.md b/geps/gep-995/index.md index 6236d1a279..972fde1080 100644 --- a/geps/gep-995/index.md +++ b/geps/gep-995/index.md @@ -9,7 +9,7 @@ Add a new optional `name` field to the route rule types ([GRPCRouteRule](../../r ## Goals -* Support referencing individual route rules by name from other resources, such as from metaresources ([GEP-2648](../gep-2648/index.md#apply-policies-to-sections-of-a-resource).) +* Support referencing individual route rules by name from other resources, such as from metaresources ([GEP-2648](../gep-2648/index.md#section-names).) * Support referencing individual route rules by name from condition messages propagated in the status stanza of route resources as suggested in https://github.com/kubernetes-sigs/gateway-api/issues/1696#issuecomment-1666258188. * Support referencing individual route rules by name at other observability and networking tools that are part of the ecosystem based on Gateway API. * Provide a rather intuitive API for users of Kubernetes who are familiar with the same pattern employed already by other kinds of resources where lists of complex elements can be declared – e.g. service [ports](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec), pod [containers](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#containers) and pod [volumes](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#volumes). diff --git a/site-src/api-types/backendtlspolicy.md b/site-src/api-types/backendtlspolicy.md index c0645d444b..ac57bd04ec 100644 --- a/site-src/api-types/backendtlspolicy.md +++ b/site-src/api-types/backendtlspolicy.md @@ -139,10 +139,10 @@ Status defines the observed state of the BackendTLSPolicy and is not user-config way you do for other Gateway API objects to verify correct operation. Note that the status in BackendTLSPolicy uses `PolicyAncestorStatus` to allow you to know which parentReference set that particular status. -[backendtlspolicy]: /references/spec/#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy -[validation]: /references/spec/#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy.Validation -[caCertificateRefs]: /references/spec/#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.CACertificateRefs -[wellKnownCACertificates]: /references/spec/#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.WellKnownCACertificates -[hostname]: /references/spec/#gateway.networking.k8s.io/v1.PreciseHostname +[backendtlspolicy]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy +[validation]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy.Validation +[caCertificateRefs]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.CACertificateRefs +[wellKnownCACertificates]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.WellKnownCACertificates +[hostname]: ../reference/spec.md#gateway.networking.k8s.io/v1.PreciseHostname [rfc-3986]: https://tools.ietf.org/html/rfc3986 -[targetRefs]: /references/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReference +[targetRefs]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha2.PolicyTargetReference diff --git a/site-src/api-types/backendtrafficpolicy.md b/site-src/api-types/backendtrafficpolicy.md index b64bc110ee..61dd645229 100644 --- a/site-src/api-types/backendtrafficpolicy.md +++ b/site-src/api-types/backendtrafficpolicy.md @@ -86,8 +86,8 @@ backendRef. TargetRefs is a required object reference, specifying a Backend via its Name, Kind, and Group. Currently, TargetRefs can not be scoped to specific ports on a service. -[backendtrafficpolicy]: /references/specx/#xbackendtrafficpolicy +[backendtrafficpolicy]: /references/specx.md#xbackendtrafficpolicy [localpolicytargetreference]: /references/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReference -[retryConstraint]: /references/specx/#retryconstraint +[retryConstraint]: /references/specx.md#retryconstraint [sessionPersistence]: /references/spec/#gateway.networking.k8s.io/v1.SessionPersistence [httproute]: /references/spec/#https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute diff --git a/site-src/api-types/grpcroute.md b/site-src/api-types/grpcroute.md index 69dcfb4082..2b6188ad47 100644 --- a/site-src/api-types/grpcroute.md +++ b/site-src/api-types/grpcroute.md @@ -225,7 +225,7 @@ on `weight` and other fields. For more information on release channels, refer to our [versioning guide](../concepts/versioning.md). -GRPCRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#apply-policies-to-sections-of-a-resource)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from GRPCRoute Rule, etc. +GRPCRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#section-names)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from GRPCRoute Rule, etc. If specified, the value of the name field must comply with the [`SectionName`](https://github.com/kubernetes-sigs/gateway-api/blob/v1.0.0/apis/v1/shared_types.go#L607-L624) type. diff --git a/site-src/api-types/httproute.md b/site-src/api-types/httproute.md index c9d96deef1..0551a37c3d 100644 --- a/site-src/api-types/httproute.md +++ b/site-src/api-types/httproute.md @@ -271,7 +271,7 @@ Reference the [timeouts][timeouts] API documentation for additional details. For more information on release channels, refer to our [versioning guide](../concepts/versioning.md). -HTTPRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#apply-policies-to-sections-of-a-resource)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from HTTPRoute Rule, etc. +HTTPRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#section-names)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from HTTPRoute Rule, etc. If specified, the value of the name field must comply with the [`SectionName`](https://github.com/kubernetes-sigs/gateway-api/blob/v1.0.0/apis/v1/shared_types.go#L607-L624) type. diff --git a/site-src/blog/2021/introducing-v1alpha2.md b/site-src/blog/2021/introducing-v1alpha2.md index fe231f9f40..55f5231efa 100644 --- a/site-src/blog/2021/introducing-v1alpha2.md +++ b/site-src/blog/2021/introducing-v1alpha2.md @@ -146,4 +146,4 @@ We still have lots more to work on. Some of our next items to discuss include: * L4 Route matching If these kinds of topics interest you, we'd love to have your input. Refer to -our [community page](/contributing/community) to see how you can get involved. +our [community page](../../contributing/index.md) to see how you can get involved. diff --git a/site-src/blog/2022/graduating-to-beta.md b/site-src/blog/2022/graduating-to-beta.md index 70064b7fc8..7b0e011560 100644 --- a/site-src/blog/2022/graduating-to-beta.md +++ b/site-src/blog/2022/graduating-to-beta.md @@ -70,12 +70,12 @@ page][community] which includes links to the Slack channel and community meeting [crd]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ [concepts]:../../concepts/api-overview.md -[guides]:/guides/getting-started/ +[guides]:../../guides/index.md [impl]:../../implementations.md -[install-crds]:/guides/getting-started/#install-the-crds +[install-crds]:../../guides/index.md#installing-gateway-api [issue]:https://github.com/kubernetes-sigs/gateway-api/issues/new/choose [disc]:https://github.com/kubernetes-sigs/gateway-api/discussions -[community]:/contributing/community/ +[community]:../../contributing/index.md ## Release highlights @@ -128,7 +128,7 @@ For this release we've added the following experimental features: - [Routes can attach to Gateways by specifying port numbers](../../geps/gep-957/index.md) - [URL rewrites and path redirects](../../geps/gep-726/index.md) -[ch]:../../concepts/versioning.md#release-channels-eg-experimental-standard +[ch]:../../concepts/versioning.md#release-channels ### Other improvements @@ -146,12 +146,12 @@ possible integration. We are pleased to announce that the service mesh community, including representatives from Cilium Service Mesh, Consul, Istio, Kuma, Linkerd, NGINX Service Mesh and Open Service Mesh, is coming together to form the [GAMMA -Initiative](/concepts/gamma/), a dedicated +Initiative](../../mesh/index.md), a dedicated workstream within the Gateway API subproject focused on Gateway API for Mesh Management and Administration. This group will deliver [enhancement -proposals](/v1beta1/contributing/gep/) consisting +proposals](../../contributing/enhancement-requests.md) consisting of resources, additions, and modifications to the Gateway API specification for mesh and mesh-adjacent use-cases. @@ -169,11 +169,11 @@ As we continue to mature the API for production use cases, here are some of the - [Route delegation][pr1085] - Layer 4 API maturity: Graduating [TCPRoute][tcpr], [UDPRoute][udpr] and [TLSRoute][tlsr] to beta -- [GAMMA Initiative](/concepts/gamma/) - Gateway API for Service Mesh +- [GAMMA Initiative](../../mesh/index.md) - Gateway API for Service Mesh If there's something on this list you want to get involved in, or there's something not on this list that you want to advocate for to get on the roadmap -please join us in the #sig-network-gateway-api channel on Kubernetes Slack or our weekly [community calls](/contributing/community/#meetings). +please join us in the #sig-network-gateway-api channel on Kubernetes Slack or our weekly [community calls](../../contributing/index.md#meetings). [gep1016]:https://github.com/kubernetes-sigs/gateway-api/blob/master/geps/gep-1016.md [grpc]:https://grpc.io/ @@ -181,4 +181,4 @@ please join us in the #sig-network-gateway-api channel on Kubernetes Slack or ou [tcpr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/tcproute_types.go [udpr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/udproute_types.go [tlsr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/tlsroute_types.go -[community]:/contributing/community/ +[community]:../../contributing/index.md diff --git a/site-src/blog/2023/0829-mesh-support.md b/site-src/blog/2023/0829-mesh-support.md index 6b79dc633a..7bc15c4429 100644 --- a/site-src/blog/2023/0829-mesh-support.md +++ b/site-src/blog/2023/0829-mesh-support.md @@ -185,21 +185,21 @@ Although these are [Experimental][status] patterns, note that they are available in the [`standard` release channel][ch], since the GAMMA initiative has not needed to introduce new resources or fields to date. -[gamma]:/concepts/gamma/ -[status]:../../geps/overview.md#status -[ch]:../../concepts/versioning.md#release-channels-eg-experimental-standard +[gamma]:../../mesh/index.md +[status]:../../geps/overview.md#gep-states +[ch]:../../concepts/versioning.md#release-channels [cel]:https://kubernetes.io/docs/reference/using-api/cel/ [crd]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ [concepts]:../../concepts/api-overview.md [geps]:../../contributing/enhancement-requests.md -[guides]:/guides/getting-started/ +[guides]:../../guides/index.md [impl]:../../implementations.md -[install-crds]:/guides/getting-started/#install-the-crds +[install-crds]:../../guides/index.md#installing-gateway-api [issue]:https://github.com/kubernetes-sigs/gateway-api/issues/new/choose [disc]:https://github.com/kubernetes-sigs/gateway-api/discussions -[community]:/contributing/community/ -[mesh-routing]:/concepts/gamma/#how-the-gateway-api-works-for-service-mesh -[GEP-1426]:/geps/gep-1426/ +[community]:../../contributing/index.md +[mesh-routing]:../../mesh/index.md +[GEP-1426]:../../geps/gep-1294/index.md [GEP-1324]:../../geps/gep-1324/index.md [GEP-1686]:../../geps/gep-1686/index.md [GEP-1709]:../../geps/gep-1709/index.md diff --git a/site-src/blog/index.md b/site-src/blog/index.md index 98f4bcb109..85027e3d40 100644 --- a/site-src/blog/index.md +++ b/site-src/blog/index.md @@ -17,7 +17,7 @@ your feedback! [:octicons-arrow-right-24: Continue reading][Gateway API: Introducing Service Mesh Support!] -[status]:../geps/overview.md#status +[status]:../geps/overview.md#gep-states [Gateway API: Introducing Service Mesh Support!]:2023/0829-mesh-support.md ## [Gateway API Graduates to Beta] diff --git a/site-src/concepts/api-overview.md b/site-src/concepts/api-overview.md index d04f893bf3..20db51b0ab 100644 --- a/site-src/concepts/api-overview.md +++ b/site-src/concepts/api-overview.md @@ -219,7 +219,7 @@ The following is required for a Route to be attached to a Gateway: The `Port` field described below is currently only included in the "Experimental" channel of Gateway API. For more information on release - channels, refer to the [related documentation](versioning.md#adding-experimental-fields). + channels, refer to the [related documentation](versioning.md#release-channels). A Route can reference a Gateway by specifying the namespace (optional if the Route and the Gateway are in the same namespace) and name of the Gateway in @@ -326,8 +326,8 @@ to any traffic directed to the Service. How and which Routes attach to a given Service is controlled by the Routes themselves (working with Kubernetes RBAC), as covered in the [GAMMA routing documentation]. -[GAMMA]:/concepts/gamma -[GAMMA routing documentation]:/concepts/gamma#gateway-api-for-mesh +[GAMMA]:../mesh/index.md +[GAMMA routing documentation]:../mesh/index.md#connecting-routes-and-services [service mesh]:glossary.md#service-mesh ## Extension points diff --git a/site-src/concepts/use-cases.md b/site-src/concepts/use-cases.md index dfe68d2aad..3199e0a62e 100644 --- a/site-src/concepts/use-cases.md +++ b/site-src/concepts/use-cases.md @@ -14,9 +14,9 @@ organizations, they all have distinct concerns that we need to consider separately.) [roles and personas]:roles-and-personas.md -[Ana]:roles-and-personas.md#ana -[Chihiro]:roles-and-personas.md#chihiro -[Ian]:roles-and-personas.md#ian +[Ana]:roles-and-personas.md#key-roles-and-personas +[Chihiro]:roles-and-personas.md#key-roles-and-personas +[Ian]:roles-and-personas.md#key-roles-and-personas ## The Use Cases @@ -148,7 +148,7 @@ advantage of the service mesh, with custom routing logic, without any bottlenecks in requests to Chihiro or Ian. [east/west]:glossary.md#eastwest-traffic -[GAMMA]:/concepts/gamma/ +[GAMMA]:../mesh/index.md [service mesh]:glossary.md#service-mesh ## Gateway and mesh use case diff --git a/site-src/faq.md b/site-src/faq.md index 0e58068968..e02f9032c2 100644 --- a/site-src/faq.md +++ b/site-src/faq.md @@ -1,7 +1,8 @@ # Frequently Asked Questions (FAQ) #### How can I get involved with Gateway API? -The [community](/contributing/community) page keeps track of how to get involved + +The [community](contributing/index.md) page keeps track of how to get involved with the project. #### Will Gateway API replace the Ingress API? diff --git a/site-src/guides/crd-management.md b/site-src/guides/crd-management.md index d2cfd5884c..7a9c05cc0f 100644 --- a/site-src/guides/crd-management.md +++ b/site-src/guides/crd-management.md @@ -33,7 +33,7 @@ explores one possible approach implementations could use to accomplish this. ## Upgrading to a new version Gateway API releases CRDs in two [release -channels](../concepts/versioning.md#release-channels-eg-experimental-standard). +channels](../concepts/versioning.md#release-channels). Sticking with standard channel CRDs will ensure CRD upgrades are both simpler and safer. diff --git a/site-src/guides/migrating-from-ingress.md b/site-src/guides/migrating-from-ingress.md index bef5a6c4a7..77fef68de0 100644 --- a/site-src/guides/migrating-from-ingress.md +++ b/site-src/guides/migrating-from-ingress.md @@ -251,7 +251,7 @@ In contrast, Gateway API specifies how to merge rules and resolve conflicts: * A Gateway implementation must merge the routing rules from all HTTPRoutes attached to a listener. * Conflicts must be handled as - prescribed in [API Design Guide: Conflicts](/guides/api-design/#conflicts). For example, more specific + prescribed in [API Design Guide: Conflicts](../guides/api-design.md#conflicts). For example, more specific matches in a routing rule win over the less specific ones. #### Default Backend diff --git a/site-src/guides/multiple-ns.md b/site-src/guides/multiple-ns.md index dce09dc695..6805f2c5d1 100644 --- a/site-src/guides/multiple-ns.md +++ b/site-src/guides/multiple-ns.md @@ -158,7 +158,7 @@ After these three Routes are deployed, they will all be attached to the list of routing rules. [Routing precedence](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule) between these routing rules is determined by most specific match and conflicts are handled according to [conflict -resolution](/concepts/guidelines#conflicts). This provides predictable and +resolution](api-design.md#conflicts). This provides predictable and deterministic merging of routing rules between independent users. Thanks to cross-Namespace routing, the Foobar Corporation can distribute diff --git a/site-src/implementations.md b/site-src/implementations.md index 6531b831f0..7460c920ad 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -101,7 +101,7 @@ cover, and documentation to help users get started. [39]:#kubvernor -[gamma]:/concepts/gamma/ +[gamma]:mesh/index.md @@ -222,7 +222,7 @@ For help and support with Contour's implementation, [create an issue][contour-is [contour]:https://projectcontour.io [contour-release]:https://github.com/projectcontour/contour/releases/tag/v1.30.0 -[contour-standard]:concepts/versioning.md#release-channels-eg-experimental-standard +[contour-standard]:concepts/versioning.md#release-channels [contour-guide]:https://projectcontour.io/docs/1.30/guides/gateway-api/ [contour-issue-new]:https://github.com/projectcontour/contour/issues/new/choose [contour-slack]:https://kubernetes.slack.com/archives/C8XRH2R4J diff --git a/site-src/index.md b/site-src/index.md index 417c3f23ab..088315b24d 100644 --- a/site-src/index.md +++ b/site-src/index.md @@ -69,15 +69,15 @@ individual route resources (such as [HTTPRoute](api-types/httproute.md)) are mesh to manage traffic from any traffic directed to that Service while preserving the role-oriented nature of Gateway API. -To date, [GAMMA](mesh/gamma.md) has been able to support mesh functionality with +To date, [GAMMA](mesh/index.md) has been able to support mesh functionality with fairly minimal changes to Gateway API. One particular area that has rapidly become critical for GAMMA, though, is the definition of the different [facets of the Service resource][service-facets]. -[gamma]:/concepts/gamma/ +[gamma]:mesh/index.md [service-mesh]:concepts/glossary.md#service-mesh -[service-facets]:/concepts/service-facets -[mesh-attachment]:/concepts/gamma#gateway-api-for-mesh +[service-facets]:mesh/service-facets.md +[mesh-attachment]:mesh/index.md ## Getting started @@ -89,7 +89,7 @@ you the necessary background: - [User guides](guides/index.md) - [Implementations](implementations.md) - [API reference spec](reference/spec.md) -- [Community links](/contributing/community) and [developer guide](contributing/devguide.md) +- [Community links](contributing/index.md) and [developer guide](contributing/devguide.md) ## Gateway API concepts The following design goals drive the concepts of Gateway API. These @@ -189,7 +189,7 @@ It allows organizations to move key functions, such as authentication and authorization or limiting the number of requests between applications, to a centrally managed location. An API gateway functions as a common interface to (often external) API consumers. -Gateway API is an interface, defined as a set of Kubernetes resources, that +Gateway API is an interface, defined as a set of Kubernetes resources, that models service networking in Kubernetes. One of the main resources is a `Gateway`, which declares the Gateway type (or class) to instantiate and its configuration. As a Gateway provider, you can implement Gateway API to model Kubernetes service @@ -205,7 +205,7 @@ project being built to improve and standardize service networking in Kubernetes. Check out the [implementations reference](implementations.md) to see the latest projects & products that support Gateway. If you are interested in contributing to or building an implementation using Gateway API then don’t hesitate to [get -involved!](/contributing/community) +involved!](contributing/index.md) [sig-network]: https://github.com/kubernetes/community/tree/master/sig-network diff --git a/site-src/mesh/gamma.md b/site-src/mesh/gamma.md index 6071711ce2..fd4b62a89e 100644 --- a/site-src/mesh/gamma.md +++ b/site-src/mesh/gamma.md @@ -44,5 +44,5 @@ The simplest way to get started is to attend one of the regular Gateway API [role-oriented]:../concepts/roles-and-personas.md [geps]:../geps/overview.md [contributor-ladder]:../contributing/contributor-ladder.md -[meetings]:/contributing/community/#meetings +[meetings]:../contributing/index.md/#meetings [GAMMA leads]:https://github.com/kubernetes-sigs/gateway-api/blob/main/OWNERS_ALIASES#L23 diff --git a/site-src/mesh/index.md b/site-src/mesh/index.md index 988919091f..0d56793f7f 100644 --- a/site-src/mesh/index.md +++ b/site-src/mesh/index.md @@ -36,7 +36,7 @@ Service. [TCPRoute]: ../concepts/api-overview.md#tcproute-and-udproute [Service]: https://kubernetes.io/docs/concepts/services-networking/service/ [service-mesh]:../concepts/glossary.md#service-mesh -[service-facets]:/concepts/service-facets +[service-facets]:service-facets.md ## Connecting routes and services diff --git a/site-src/mesh/service-facets.md b/site-src/mesh/service-facets.md index 9b5f880bc5..96633fca81 100644 --- a/site-src/mesh/service-facets.md +++ b/site-src/mesh/service-facets.md @@ -46,5 +46,5 @@ formalize guidance for this use case. [Service]: https://kubernetes.io/docs/concepts/services-networking/service/ [north/south]:../concepts/glossary.md#northsouth-traffic [east/west traffic]:../concepts/glossary.md#eastwest-traffic -[gamma]:/concepts/gamma/ +[gamma]:gamma.md [Ana]:../concepts/roles-and-personas.md#ana From 392be7c235c4cd516a9765abe7dd30e9dca6c4ee Mon Sep 17 00:00:00 2001 From: carson <127476216+carsontham@users.noreply.github.com> Date: Sun, 22 Jun 2025 09:50:52 +0800 Subject: [PATCH 059/224] Improve distribution tests in conformance for MeshHTTPRouteWeight (#3855) * added entropy to mesh weight test Signed-off-by: carsontham * added nolint:gosec to skip linter issues for conformance test * move creation of header map to entropy func to avoid concurrent map writes * use crypto/rand instead of math/rand * handle error checking and add default in switch * return error in default for switch case --------- Signed-off-by: carsontham --- conformance/tests/mesh/httproute-weight.go | 60 +++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/conformance/tests/mesh/httproute-weight.go b/conformance/tests/mesh/httproute-weight.go index 09ef3465b5..cc296d92d5 100644 --- a/conformance/tests/mesh/httproute-weight.go +++ b/conformance/tests/mesh/httproute-weight.go @@ -18,13 +18,16 @@ package meshtests import ( "cmp" + "crypto/rand" "errors" "fmt" "math" + "math/big" "slices" "strings" "sync" "testing" + "time" "golang.org/x/sync/errgroup" @@ -89,7 +92,11 @@ func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedR g.SetLimit(concurrentRequests) for i := 0.0; i < totalRequests; i++ { g.Go(func() error { - _, cRes, err := client.CaptureRequestResponseAndCompare(t, expected) + uniqueExpected := expected + if err := addEntropy(&uniqueExpected); err != nil { + return fmt.Errorf("error adding entropy: %w", err) + } + _, cRes, err := client.CaptureRequestResponseAndCompare(t, uniqueExpected) if err != nil { return fmt.Errorf("failed: %w", err) } @@ -141,3 +148,54 @@ func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedR }) return errors.Join(errs...) } + +// addEntropy adds jitter to the request by adding either a delay up to 1 second, or a random header value, or both. +func addEntropy(exp *http.ExpectedResponse) error { + randomNumber := func(limit int64) (*int64, error) { + number, err := rand.Int(rand.Reader, big.NewInt(limit)) + if err != nil { + return nil, err + } + n := number.Int64() + return &n, nil + } + + // adds a delay + delay := func(limit int64) error { + randomSleepDuration, err := randomNumber(limit) + if err != nil { + return err + } + time.Sleep(time.Duration(*randomSleepDuration) * time.Millisecond) + return nil + } + // adds random header value + randomHeader := func(limit int64) error { + randomHeaderValue, err := randomNumber(limit) + if err != nil { + return err + } + exp.Request.Headers = make(map[string]string) + exp.Request.Headers["X-Jitter"] = fmt.Sprintf("%d", *randomHeaderValue) + return nil + } + + random, err := randomNumber(3) + if err != nil { + return err + } + + switch *random { + case 0: + return delay(1000) + case 1: + return randomHeader(10000) + case 2: + if err := delay(1000); err != nil { + return err + } + return randomHeader(10000) + default: + return fmt.Errorf("invalid random value: %d", *random) + } +} From 4e9978a686090d6fdf45adce9ec2912694c39930 Mon Sep 17 00:00:00 2001 From: Rob Scott Date: Tue, 24 Jun 2025 03:36:29 -0700 Subject: [PATCH 060/224] Adding Lior to Mesh Leads (#3877) --- OWNERS_ALIASES | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 6e461c1596..207dd1d776 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -26,6 +26,7 @@ aliases: - howardjohn - mikemorris - kflynn + - LiorLieberman emeritus-gateway-api-mesh-leads: - keithmattix From b58707ce59f2cbbd2e1f1c292d7180212a57748e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 06:06:30 -0700 Subject: [PATCH 061/224] build(deps): bump the k8s-io group with 6 updates (#3819) * build(deps): bump the k8s-io group with 6 updates Bumps the k8s-io group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.32.3` | `0.33.1` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.32.3` | `0.33.1` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.32.3` | `0.33.1` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.32.3` | `0.33.1` | | [k8s.io/code-generator](https://github.com/kubernetes/code-generator) | `0.32.3` | `0.33.1` | | [k8s.io/kube-openapi](https://github.com/kubernetes/kube-openapi) | `0.0.0-20241105132330-32ad38e42d3f` | `0.0.0-20250318190949-c8a335a9a2ff` | Updates `k8s.io/api` from 0.32.3 to 0.33.1 - [Commits](https://github.com/kubernetes/api/compare/v0.32.3...v0.33.1) Updates `k8s.io/apiextensions-apiserver` from 0.32.3 to 0.33.1 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.32.3...v0.33.1) Updates `k8s.io/apimachinery` from 0.32.3 to 0.33.1 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.3...v0.33.1) Updates `k8s.io/client-go` from 0.32.3 to 0.33.1 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.32.3...v0.33.1) Updates `k8s.io/code-generator` from 0.32.3 to 0.33.1 - [Commits](https://github.com/kubernetes/code-generator/compare/v0.32.3...v0.33.1) Updates `k8s.io/kube-openapi` from 0.0.0-20241105132330-32ad38e42d3f to 0.0.0-20250318190949-c8a335a9a2ff - [Commits](https://github.com/kubernetes/kube-openapi/commits) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/code-generator dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/kube-openapi dependency-version: 0.0.0-20250318190949-c8a335a9a2ff dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io ... Signed-off-by: dependabot[bot] * chore(clients): make generate Signed-off-by: Mattia Lavacca --------- Signed-off-by: dependabot[bot] Signed-off-by: Mattia Lavacca Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mattia Lavacca --- go.mod | 23 ++++----- go.sum | 51 ++++++++++--------- .../versioned/fake/clientset_generated.go | 13 ++++- .../versioned/typed/apis/v1/apis_client.go | 12 ++--- .../typed/apis/v1alpha2/apis_client.go | 12 ++--- .../typed/apis/v1alpha3/apis_client.go | 12 ++--- .../typed/apis/v1beta1/apis_client.go | 12 ++--- .../typed/apisx/v1alpha1/apisx_client.go | 12 ++--- .../externalversions/apis/v1/gateway.go | 16 +++++- .../externalversions/apis/v1/gatewayclass.go | 16 +++++- .../externalversions/apis/v1/grpcroute.go | 16 +++++- .../externalversions/apis/v1/httproute.go | 16 +++++- .../apis/v1alpha2/grpcroute.go | 16 +++++- .../apis/v1alpha2/referencegrant.go | 16 +++++- .../apis/v1alpha2/tcproute.go | 16 +++++- .../apis/v1alpha2/tlsroute.go | 16 +++++- .../apis/v1alpha2/udproute.go | 16 +++++- .../apis/v1alpha3/backendtlspolicy.go | 16 +++++- .../externalversions/apis/v1beta1/gateway.go | 16 +++++- .../apis/v1beta1/gatewayclass.go | 16 +++++- .../apis/v1beta1/httproute.go | 16 +++++- .../apis/v1beta1/referencegrant.go | 16 +++++- .../apisx/v1alpha1/xbackendtrafficpolicy.go | 16 +++++- .../apisx/v1alpha1/xlistenerset.go | 16 +++++- pkg/generated/openapi/zz_generated.openapi.go | 42 ++++++++++++--- 25 files changed, 323 insertions(+), 122 deletions(-) diff --git a/go.mod b/go.mod index 4bf07ec2f5..a9db23934e 100644 --- a/go.mod +++ b/go.mod @@ -11,12 +11,12 @@ require ( google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 - k8s.io/api v0.32.3 - k8s.io/apiextensions-apiserver v0.32.3 - k8s.io/apimachinery v0.32.3 - k8s.io/client-go v0.32.3 - k8s.io/code-generator v0.32.3 - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f + k8s.io/api v0.33.2 + k8s.io/apiextensions-apiserver v0.33.2 + k8s.io/apimachinery v0.33.2 + k8s.io/client-go v0.33.2 + k8s.io/code-generator v0.33.2 + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/controller-tools v0.17.3 @@ -40,12 +40,10 @@ require ( github.com/gobuffalo/flect v1.0.3 // indirect github.com/goccy/go-yaml v1.11.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.11 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -74,7 +72,7 @@ require ( golang.org/x/sys v0.32.0 // indirect golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect @@ -82,7 +80,8 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 // indirect + k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 // indirect k8s.io/klog/v2 v2.130.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index b380233c61..2b6eb53c72 100644 --- a/go.sum +++ b/go.sum @@ -51,20 +51,18 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= @@ -120,8 +118,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= @@ -130,6 +128,8 @@ github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -193,8 +193,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -230,22 +230,22 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= -k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= -k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= -k8s.io/code-generator v0.32.3 h1:31p2TVzC9+hVdSkAFruAk3JY+iSfzrJ83Qij1yZutyw= -k8s.io/code-generator v0.32.3/go.mod h1:+mbiYID5NLsBuqxjQTygKM/DAdKpAjvBzrJd64NU1G8= -k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 h1:si3PfKm8dDYxgfbeA6orqrtLkvvIeH8UqffFJDl0bz4= -k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= +k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= +k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= +k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= +k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= +k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= +k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= +k8s.io/code-generator v0.33.2 h1:PCJ0Y6viTCxxJHMOyGqYwWEteM4q6y1Hqo2rNpl6jF4= +k8s.io/code-generator v0.33.2/go.mod h1:hBjCA9kPMpjLWwxcr75ReaQfFXY8u+9bEJJ7kRw3J8c= +k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= +k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= @@ -254,8 +254,9 @@ sigs.k8s.io/controller-tools v0.17.3 h1:lwFPLicpBKLgIepah+c8ikRBubFW5kOQyT88r3Ew sigs.k8s.io/controller-tools v0.17.3/go.mod h1:1ii+oXcYZkxcBXzwv3YZBlzjt1fvkrCGjVF73blosJI= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index ecf37e8b51..b1600ecbd3 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -19,6 +19,7 @@ limitations under the License. package fake import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/discovery" @@ -58,9 +59,13 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} cs.AddReactor("*", "*", testing.ObjectReaction(o)) cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchActcion, ok := action.(testing.WatchActionImpl); ok { + opts = watchActcion.ListOptions + } gvr := action.GetResource() ns := action.GetNamespace() - watch, err := o.Watch(gvr, ns) + watch, err := o.Watch(gvr, ns, opts) if err != nil { return false, nil, err } @@ -107,9 +112,13 @@ func NewClientset(objects ...runtime.Object) *Clientset { cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} cs.AddReactor("*", "*", testing.ObjectReaction(o)) cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchActcion, ok := action.(testing.WatchActionImpl); ok { + opts = watchActcion.ListOptions + } gvr := action.GetResource() ns := action.GetNamespace() - watch, err := o.Watch(gvr, ns) + watch, err := o.Watch(gvr, ns, opts) if err != nil { return false, nil, err } diff --git a/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go index 1742ff45eb..7ed0bc4d55 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go @@ -60,9 +60,7 @@ func (c *GatewayV1Client) HTTPRoutes(namespace string) HTTPRouteInterface { // where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*GatewayV1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) httpClient, err := rest.HTTPClientFor(&config) if err != nil { return nil, err @@ -74,9 +72,7 @@ func NewForConfig(c *rest.Config) (*GatewayV1Client, error) { // Note the http client provided takes precedence over the configured transport values. func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) client, err := rest.RESTClientForConfigAndClient(&config, h) if err != nil { return nil, err @@ -99,7 +95,7 @@ func New(c rest.Interface) *GatewayV1Client { return &GatewayV1Client{c} } -func setConfigDefaults(config *rest.Config) error { +func setConfigDefaults(config *rest.Config) { gv := apisv1.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" @@ -108,8 +104,6 @@ func setConfigDefaults(config *rest.Config) error { if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - - return nil } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go index 97b6ad062f..c25ef87c96 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha2/apis_client.go @@ -65,9 +65,7 @@ func (c *GatewayV1alpha2Client) UDPRoutes(namespace string) UDPRouteInterface { // where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*GatewayV1alpha2Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) httpClient, err := rest.HTTPClientFor(&config) if err != nil { return nil, err @@ -79,9 +77,7 @@ func NewForConfig(c *rest.Config) (*GatewayV1alpha2Client, error) { // Note the http client provided takes precedence over the configured transport values. func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1alpha2Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) client, err := rest.RESTClientForConfigAndClient(&config, h) if err != nil { return nil, err @@ -104,7 +100,7 @@ func New(c rest.Interface) *GatewayV1alpha2Client { return &GatewayV1alpha2Client{c} } -func setConfigDefaults(config *rest.Config) error { +func setConfigDefaults(config *rest.Config) { gv := apisv1alpha2.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" @@ -113,8 +109,6 @@ func setConfigDefaults(config *rest.Config) error { if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - - return nil } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go index 0a546b5538..681d5090ed 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go @@ -45,9 +45,7 @@ func (c *GatewayV1alpha3Client) BackendTLSPolicies(namespace string) BackendTLSP // where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*GatewayV1alpha3Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) httpClient, err := rest.HTTPClientFor(&config) if err != nil { return nil, err @@ -59,9 +57,7 @@ func NewForConfig(c *rest.Config) (*GatewayV1alpha3Client, error) { // Note the http client provided takes precedence over the configured transport values. func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1alpha3Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) client, err := rest.RESTClientForConfigAndClient(&config, h) if err != nil { return nil, err @@ -84,7 +80,7 @@ func New(c rest.Interface) *GatewayV1alpha3Client { return &GatewayV1alpha3Client{c} } -func setConfigDefaults(config *rest.Config) error { +func setConfigDefaults(config *rest.Config) { gv := apisv1alpha3.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" @@ -93,8 +89,6 @@ func setConfigDefaults(config *rest.Config) error { if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - - return nil } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/client/clientset/versioned/typed/apis/v1beta1/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1beta1/apis_client.go index d9b158d567..498e0373a4 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1beta1/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1beta1/apis_client.go @@ -60,9 +60,7 @@ func (c *GatewayV1beta1Client) ReferenceGrants(namespace string) ReferenceGrantI // where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*GatewayV1beta1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) httpClient, err := rest.HTTPClientFor(&config) if err != nil { return nil, err @@ -74,9 +72,7 @@ func NewForConfig(c *rest.Config) (*GatewayV1beta1Client, error) { // Note the http client provided takes precedence over the configured transport values. func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1beta1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) client, err := rest.RESTClientForConfigAndClient(&config, h) if err != nil { return nil, err @@ -99,7 +95,7 @@ func New(c rest.Interface) *GatewayV1beta1Client { return &GatewayV1beta1Client{c} } -func setConfigDefaults(config *rest.Config) error { +func setConfigDefaults(config *rest.Config) { gv := apisv1beta1.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" @@ -108,8 +104,6 @@ func setConfigDefaults(config *rest.Config) error { if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - - return nil } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go index 582ef47b3d..234356e48e 100644 --- a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go @@ -50,9 +50,7 @@ func (c *ExperimentalV1alpha1Client) XListenerSets(namespace string) XListenerSe // where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*ExperimentalV1alpha1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) httpClient, err := rest.HTTPClientFor(&config) if err != nil { return nil, err @@ -64,9 +62,7 @@ func NewForConfig(c *rest.Config) (*ExperimentalV1alpha1Client, error) { // Note the http client provided takes precedence over the configured transport values. func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ExperimentalV1alpha1Client, error) { config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } + setConfigDefaults(&config) client, err := rest.RESTClientForConfigAndClient(&config, h) if err != nil { return nil, err @@ -89,7 +85,7 @@ func New(c rest.Interface) *ExperimentalV1alpha1Client { return &ExperimentalV1alpha1Client{c} } -func setConfigDefaults(config *rest.Config) error { +func setConfigDefaults(config *rest.Config) { gv := apisxv1alpha1.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" @@ -98,8 +94,6 @@ func setConfigDefaults(config *rest.Config) error { if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() } - - return nil } // RESTClient returns a RESTClient that is used to communicate diff --git a/pkg/client/informers/externalversions/apis/v1/gateway.go b/pkg/client/informers/externalversions/apis/v1/gateway.go index 9df059e555..6884889ecd 100644 --- a/pkg/client/informers/externalversions/apis/v1/gateway.go +++ b/pkg/client/informers/externalversions/apis/v1/gateway.go @@ -62,13 +62,25 @@ func NewFilteredGatewayInformer(client versioned.Interface, namespace string, re if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().Gateways(namespace).List(context.TODO(), options) + return client.GatewayV1().Gateways(namespace).List(context.Background(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().Gateways(namespace).Watch(context.TODO(), options) + return client.GatewayV1().Gateways(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().Gateways(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().Gateways(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1.Gateway{}, diff --git a/pkg/client/informers/externalversions/apis/v1/gatewayclass.go b/pkg/client/informers/externalversions/apis/v1/gatewayclass.go index 7ad2c7f400..f601378bd9 100644 --- a/pkg/client/informers/externalversions/apis/v1/gatewayclass.go +++ b/pkg/client/informers/externalversions/apis/v1/gatewayclass.go @@ -61,13 +61,25 @@ func NewFilteredGatewayClassInformer(client versioned.Interface, resyncPeriod ti if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().GatewayClasses().List(context.TODO(), options) + return client.GatewayV1().GatewayClasses().List(context.Background(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().GatewayClasses().Watch(context.TODO(), options) + return client.GatewayV1().GatewayClasses().Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GatewayClasses().List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GatewayClasses().Watch(ctx, options) }, }, &gatewayapiapisv1.GatewayClass{}, diff --git a/pkg/client/informers/externalversions/apis/v1/grpcroute.go b/pkg/client/informers/externalversions/apis/v1/grpcroute.go index 5633d5b408..34fb735149 100644 --- a/pkg/client/informers/externalversions/apis/v1/grpcroute.go +++ b/pkg/client/informers/externalversions/apis/v1/grpcroute.go @@ -62,13 +62,25 @@ func NewFilteredGRPCRouteInformer(client versioned.Interface, namespace string, if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().GRPCRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1().GRPCRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().GRPCRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1().GRPCRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GRPCRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().GRPCRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1.GRPCRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1/httproute.go b/pkg/client/informers/externalversions/apis/v1/httproute.go index 697d15013f..06da9daea4 100644 --- a/pkg/client/informers/externalversions/apis/v1/httproute.go +++ b/pkg/client/informers/externalversions/apis/v1/httproute.go @@ -62,13 +62,25 @@ func NewFilteredHTTPRouteInformer(client versioned.Interface, namespace string, if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().HTTPRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1().HTTPRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1().HTTPRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1().HTTPRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().HTTPRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().HTTPRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1.HTTPRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go b/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go index 4317e8cd0d..cda505ce19 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/grpcroute.go @@ -62,13 +62,25 @@ func NewFilteredGRPCRouteInformer(client versioned.Interface, namespace string, if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().GRPCRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().GRPCRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().GRPCRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().GRPCRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().GRPCRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().GRPCRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha2.GRPCRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go b/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go index a3ba093c67..8519c9eb23 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/referencegrant.go @@ -62,13 +62,25 @@ func NewFilteredReferenceGrantInformer(client versioned.Interface, namespace str if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().ReferenceGrants(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().ReferenceGrants(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().ReferenceGrants(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().ReferenceGrants(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().ReferenceGrants(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().ReferenceGrants(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha2.ReferenceGrant{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/tcproute.go b/pkg/client/informers/externalversions/apis/v1alpha2/tcproute.go index 850d5e2f59..da3c1292e4 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/tcproute.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/tcproute.go @@ -62,13 +62,25 @@ func NewFilteredTCPRouteInformer(client versioned.Interface, namespace string, r if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().TCPRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().TCPRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().TCPRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().TCPRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().TCPRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().TCPRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha2.TCPRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/tlsroute.go b/pkg/client/informers/externalversions/apis/v1alpha2/tlsroute.go index 9a729348b0..fbc9d1fe83 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/tlsroute.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/tlsroute.go @@ -62,13 +62,25 @@ func NewFilteredTLSRouteInformer(client versioned.Interface, namespace string, r if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().TLSRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().TLSRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().TLSRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().TLSRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().TLSRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().TLSRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha2.TLSRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha2/udproute.go b/pkg/client/informers/externalversions/apis/v1alpha2/udproute.go index 10a40c087f..1eb0f23e6f 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha2/udproute.go +++ b/pkg/client/informers/externalversions/apis/v1alpha2/udproute.go @@ -62,13 +62,25 @@ func NewFilteredUDPRouteInformer(client versioned.Interface, namespace string, r if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().UDPRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1alpha2().UDPRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha2().UDPRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha2().UDPRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().UDPRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha2().UDPRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha2.UDPRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1alpha3/backendtlspolicy.go b/pkg/client/informers/externalversions/apis/v1alpha3/backendtlspolicy.go index 28ec827d80..933c815e0a 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha3/backendtlspolicy.go +++ b/pkg/client/informers/externalversions/apis/v1alpha3/backendtlspolicy.go @@ -62,13 +62,25 @@ func NewFilteredBackendTLSPolicyInformer(client versioned.Interface, namespace s if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha3().BackendTLSPolicies(namespace).List(context.TODO(), options) + return client.GatewayV1alpha3().BackendTLSPolicies(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1alpha3().BackendTLSPolicies(namespace).Watch(context.TODO(), options) + return client.GatewayV1alpha3().BackendTLSPolicies(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().BackendTLSPolicies(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().BackendTLSPolicies(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1alpha3.BackendTLSPolicy{}, diff --git a/pkg/client/informers/externalversions/apis/v1beta1/gateway.go b/pkg/client/informers/externalversions/apis/v1beta1/gateway.go index 112506f9f3..6f60141696 100644 --- a/pkg/client/informers/externalversions/apis/v1beta1/gateway.go +++ b/pkg/client/informers/externalversions/apis/v1beta1/gateway.go @@ -62,13 +62,25 @@ func NewFilteredGatewayInformer(client versioned.Interface, namespace string, re if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().Gateways(namespace).List(context.TODO(), options) + return client.GatewayV1beta1().Gateways(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().Gateways(namespace).Watch(context.TODO(), options) + return client.GatewayV1beta1().Gateways(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().Gateways(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().Gateways(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1beta1.Gateway{}, diff --git a/pkg/client/informers/externalversions/apis/v1beta1/gatewayclass.go b/pkg/client/informers/externalversions/apis/v1beta1/gatewayclass.go index ed422ffa79..846bee3e28 100644 --- a/pkg/client/informers/externalversions/apis/v1beta1/gatewayclass.go +++ b/pkg/client/informers/externalversions/apis/v1beta1/gatewayclass.go @@ -61,13 +61,25 @@ func NewFilteredGatewayClassInformer(client versioned.Interface, resyncPeriod ti if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().GatewayClasses().List(context.TODO(), options) + return client.GatewayV1beta1().GatewayClasses().List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().GatewayClasses().Watch(context.TODO(), options) + return client.GatewayV1beta1().GatewayClasses().Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().GatewayClasses().List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().GatewayClasses().Watch(ctx, options) }, }, &gatewayapiapisv1beta1.GatewayClass{}, diff --git a/pkg/client/informers/externalversions/apis/v1beta1/httproute.go b/pkg/client/informers/externalversions/apis/v1beta1/httproute.go index 1aaf2e0ec3..c2217d1d2d 100644 --- a/pkg/client/informers/externalversions/apis/v1beta1/httproute.go +++ b/pkg/client/informers/externalversions/apis/v1beta1/httproute.go @@ -62,13 +62,25 @@ func NewFilteredHTTPRouteInformer(client versioned.Interface, namespace string, if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().HTTPRoutes(namespace).List(context.TODO(), options) + return client.GatewayV1beta1().HTTPRoutes(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().HTTPRoutes(namespace).Watch(context.TODO(), options) + return client.GatewayV1beta1().HTTPRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().HTTPRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().HTTPRoutes(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1beta1.HTTPRoute{}, diff --git a/pkg/client/informers/externalversions/apis/v1beta1/referencegrant.go b/pkg/client/informers/externalversions/apis/v1beta1/referencegrant.go index 5dea76f78d..f6209ffca2 100644 --- a/pkg/client/informers/externalversions/apis/v1beta1/referencegrant.go +++ b/pkg/client/informers/externalversions/apis/v1beta1/referencegrant.go @@ -62,13 +62,25 @@ func NewFilteredReferenceGrantInformer(client versioned.Interface, namespace str if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().ReferenceGrants(namespace).List(context.TODO(), options) + return client.GatewayV1beta1().ReferenceGrants(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.GatewayV1beta1().ReferenceGrants(namespace).Watch(context.TODO(), options) + return client.GatewayV1beta1().ReferenceGrants(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().ReferenceGrants(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1beta1().ReferenceGrants(namespace).Watch(ctx, options) }, }, &gatewayapiapisv1beta1.ReferenceGrant{}, diff --git a/pkg/client/informers/externalversions/apisx/v1alpha1/xbackendtrafficpolicy.go b/pkg/client/informers/externalversions/apisx/v1alpha1/xbackendtrafficpolicy.go index 44747690af..a1ef9b1c17 100644 --- a/pkg/client/informers/externalversions/apisx/v1alpha1/xbackendtrafficpolicy.go +++ b/pkg/client/informers/externalversions/apisx/v1alpha1/xbackendtrafficpolicy.go @@ -62,13 +62,25 @@ func NewFilteredXBackendTrafficPolicyInformer(client versioned.Interface, namesp if tweakListOptions != nil { tweakListOptions(&options) } - return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).List(context.TODO(), options) + return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).Watch(context.TODO(), options) + return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XBackendTrafficPolicies(namespace).Watch(ctx, options) }, }, &gatewayapiapisxv1alpha1.XBackendTrafficPolicy{}, diff --git a/pkg/client/informers/externalversions/apisx/v1alpha1/xlistenerset.go b/pkg/client/informers/externalversions/apisx/v1alpha1/xlistenerset.go index f959180852..189f25bf3a 100644 --- a/pkg/client/informers/externalversions/apisx/v1alpha1/xlistenerset.go +++ b/pkg/client/informers/externalversions/apisx/v1alpha1/xlistenerset.go @@ -62,13 +62,25 @@ func NewFilteredXListenerSetInformer(client versioned.Interface, namespace strin if tweakListOptions != nil { tweakListOptions(&options) } - return client.ExperimentalV1alpha1().XListenerSets(namespace).List(context.TODO(), options) + return client.ExperimentalV1alpha1().XListenerSets(namespace).List(context.Background(), options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.ExperimentalV1alpha1().XListenerSets(namespace).Watch(context.TODO(), options) + return client.ExperimentalV1alpha1().XListenerSets(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XListenerSets(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XListenerSets(namespace).Watch(ctx, options) }, }, &gatewayapiapisxv1alpha1.XListenerSet{}, diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 96ac164691..c91725bc50 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -2733,16 +2733,46 @@ func schema_k8sio_apimachinery_pkg_version_Info(ref common.ReferenceCallback) co Properties: map[string]spec.Schema{ "major": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Major is the major version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "minor": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Minor is the minor version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMajor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMajor is the major version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMinor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMinor is the minor version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMajor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMajor is the major version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMinor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMinor is the minor version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", }, }, "gitVersion": { From e1310bbd66c54b757d28ee65cf363825f6189ca5 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Fri, 27 Jun 2025 14:18:28 +1000 Subject: [PATCH 062/224] Update implementations.md with removal policy (#3863) This commit updates the "Implementations" page with details on what implementations need to do in order to stay a current and registered implementation of Gateway API. This includes a policy about when implementations will be removed from the page. Signed-off-by: Nick Young --- site-src/implementations.md | 126 +++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index 7460c920ad..1b11204072 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -5,8 +5,77 @@ and provides status and resource references for them. Implementors and integrators of Gateway API are encouraged to update this document with status information about their implementations, the versions they -cover, and documentation to help users get started. +cover, and documentation to help users get started. This status information should +be no longer than a few paragraphs. +## Conformance levels + +There are three levels of Gateway API conformance: + +### Conformant implementations + +These implementations have submitted at least one conformance report that has passes for: + + * All core conformance tests for at least one combination of Route type and + Profile + * All claimed Extended features + +for one of the two (2) most recent Gateway API releases. + +So, it's conformant to support Mesh + HTTPRoute, or Gateway + HTTPRoute, or +Gateway + TLSRoute, or Gateway + Mesh + HTTPRoute, plus any extended features +the implementation claims. But implementaions _must_ support at least one +Profile and one Route type in that profile, and must pass all Core conformance +tests for that Profile and Route type in addition to all claimed Extended +features. + +### Partially Conformant implementations + +These implementations are aiming for full conformance but are not currently +achieving it. They have submitted at least one conformance report passing some +of the tests to be Conformant (as above) for one of the three (3) most recent +Gateway API releases. Note that the requirements to be considered "partially +conformant" may be tightened in a future release of Gateway API. + +### Stale implementations + +These implementations may not be being actively developed and will be removed +from this page on the next page review unless they submit a conformance report +moving them to one of the other categories. + +Page reviews are performed at least one month after every Gateway API release, +with the first being performed after the release of Gateway API v1.3, in late +June 2025. Following the Gateway API v1.5 review process, due in mid-2026, +stale implementations will no longer be listed. + +## Implementation profiles + +Implementations also generally fall into two categories, which are called +_profiles_: + +* **Gateway** controllers reconcile the Gateway resource and are intended to +handle north-south traffic, mainly concerned with coming from outside the +cluster to inside. +* **Mesh** controllers reconcile Service resources with HTTPRoutes attached +and are intended to handle east-west traffic, within the same cluster or +set of clusters. + +Each profile has a set of conformance tests associated with it, that lay out +the expected behavior for implementations to be conformant (as above). + +Implementations may also fit both profiles. + +## Integrations + +Also listed on this page are **integrations**, which are other software +projects that are able to make use of Gateway API resources to perform +other functions (like managing DNS or creating certificates). + +!!! note + This page contains links to third party projects that provide functionality + required for Gateway API to work. The Gateway API project authors aren't + responsible for these projects, which are listed alphabetically within their + class. !!! info "Compare extended supported features across implementations" @@ -609,3 +678,58 @@ For help and support with Kuadrant's implementation please feel free to [create [kuadrant-issue-new]:https://github.com/Kuadrant/kuadrant-operator/issues/new [kuadrant-slack]:https://kubernetes.slack.com/archives/C05J0D0V525 + +## Adding new entries + +Implementations are free to make a PR to add their entry to this page; however, +in order to meet the requirements for being Partially Conformant or Conformant, +the implementation must have had a conformance report submission PR merged. + +Part of the review process for new additions to this page is that a maintainer +will check the conformance level and verify the state. + +## Page Review Policy + +This page is intended to showcase actively developed and conformant implementations +of Gateway API, and so is subject to regular reviews. + +These reviews are performed at least one month after every Gateway API release +(starting with the Gateway API v1.3 release). + +As part of the review, a maintainer will check: + +* which implementations are **Conformant** - as defined above in this document. +* which implementations are **Partially Conformant**, as defined above in this + document. + +If the maintainer performing the review finds that there are implementations +that no longer satisfy the criteria for Partially Conformant or Conformant, or +finds implementations that are in the "Stale" state, then that maintainer will: + +* Inform the other maintainers and get their agreement on the list of stale and +to-be-removed implementations +* Post on the #sig-network-gateway-api channel informing the maintainers of +implementations that are no longer at least partially conformant should contact +the Gateway API maintainers to discuss the implementation's status. This period +is called the "**right-of-reply**" period, is at least two weeks long, and functions +as a lazy consensus period. +* Any implementations that do not respond within the right-of-reply period will be +downgraded in status, either by being moved to "Stale", or being removed +from this page if they are already "Stale". + +Page review timeline, starting with the v1.3 Page Review: + +* Gateway API v1.3 release Page Review: a maintainer will move anyone who hasn't + submitted a conformance report using the rules above to "Stale". They will also + contact anyone who moves to Stale to inform them about this rule change. +* Gateway API v1.4 release Page Review (at least one month after the actual + release): A maintainer will perform the Page Review process again, removing + any implementations that are are still Stale (after a right-of-reply period). +* Gateway API v1.5 release Page Review (at least one month after the actual + release): We will remove the Stale category, and implementation maintainers + will need to be at least partially conformant on each review, or during the + right-of-reply period, or be removed from the implementations page. + +This means that, after the Gateway API v1.5 release, implementations cannot be +added to this page unless they have submitted at least a Partially Conformant +conformance report. From de6d664c4eccead11e34387a99439522292450fe Mon Sep 17 00:00:00 2001 From: John Howard Date: Fri, 27 Jun 2025 11:28:30 -0700 Subject: [PATCH 063/224] Enhancements to the BackendTLSPolicy GEP (#3835) * Enhancements to the BackendTLSPolicy GEP Fixes https://github.com/kubernetes-sigs/gateway-api/issues/3516 * Update GEP with new semantics * Add 'from' * revert go type changes * Address some comments * Revert changes to Go types * Address Candace's comments * Revert everything again * Minimal changes * Address comments * Reference system certs * Address TLS passthrough * clarify persona --- geps/gep-1897/images/mesh.png | Bin 0 -> 69082 bytes geps/gep-1897/index.md | 116 ++++++++++++++++++---------------- 2 files changed, 62 insertions(+), 54 deletions(-) create mode 100644 geps/gep-1897/images/mesh.png diff --git a/geps/gep-1897/images/mesh.png b/geps/gep-1897/images/mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..c82ced3089b6c2004ae00e7c0a7d8590832f7e32 GIT binary patch literal 69082 zcma%jbyU>b_cjaz3?MLofb`HPVbLHA9g>Qa64KqB1BjH864Irh(jgrR3aFHHw{#;N z?-{)Jet&=5weIVhr2@m}oU_l~&-3hk_L(p>6*)qDYJ3a~3_=BY=?54XumTJW%x^FV z_|6B#K_T!DrttH1@MrjT60ns!Hy*VAIEZ_Fl!%QBLt*^a3$+3}z3<8`8HB`u{^yGe9^gRs|M5(G zJS6nNjEqd&e?Ae3!35vHgk${ION|jT6nUdQ--7hN7K8yqLOxor5p=i7IU@-HW<%(~|neT_pG z3Li$Ap5dG%1~Snz)cwfk`Rnl>QQ+~LrE(qrI`bQ>$O`-$>+l+>4+EsO&lWw2LVTdQ z*VRR*n2-%SmHDa{huY-f&XtQK?H5G698JXDayR66EOY_F(tfcnsTm z&;Pcc%pI#&NUT?>V%vTb5!F}5bK?oKLl&c`tDCbEf~k8~cYU>Tj!W>ba6#GuyUnwO zpZ;t3yi!Ky^$AtQ5R+h$lDV|LVOxC|_ZypvZT9`%uNw_DSzSh*F|hs9!kc^<_bhq7 z@zYJ(-w-+dnI`)5PJe^TAW@ln45xp*Z|`XSM0s9;3Qr>xXNZjxjp51|(uu<*KW3AddC z;~yyB#EvrX^H~ptOG=ZN>SNPXG7Xq5(EjAn?01YSV*W03HB>5#v7WhVY_(b%|4vFL zKXT@kFbwt#S99i2j>7Y3YScuqqsC>>Y+9jf%-gqnCW8hh4`B}&EQ*=OW(|lv!0?V! z6ZfW6Z<>&u^<9)b# zmru3)8)2zYxtX2O$uD$ZcqCxNr-g?2-r%Dqu%&lGVZv6DAx3Ba-KmEuLF2qPa8&DP!KQ znqg1f+0^?y_iu=dt$vC?Wsggu$Wyf|!{n8{8YWHdyxTM-AZZW8`ZxO{O`!k>Wc$9Z zJXW8fjxRiV%MpwfUz&kRvx?TugWmJAW4yaxp=+BG#l6@TqWvaw7MEPzXwh;m&ZXb7 zZ?B(~G6l*rVL0hN23cf-EaQ~(u~)aZ>h#TG(gfwjQt8U`2;1M~SIo}cY>(>`Z zTlBm`9L6CEJ6@P8QX{kr3o%zQj1i~(^ zD)Ta?sVqj=8-^k&X#W+7-!mF|<5l;-8xbw@3gu$oAeeG^!_3&rF2Wh!W(?w0Py7vg z4S3twm!E&FxUC-5atT+8tkcecaA^bq(Vv)%Coy!tAUjze%!EW4%1P`q*KH%V%gs%< z32wCbT@?s;mcRBsOXz>&PYYv~kNnuxq-+Q{oy)%(a5%}@^Y-dIXC0JeJ@0ho{(6Y> z3fSt9uNK1{v?iroWuX*0juCpj_v>*e_3R=%pw_mfLSRl%XThasS5}^y8^W6&c1kkA zF#;$cvu)vGj;$?XNo#k%i*>EVbv5F)p9DOMK4cNl>9@$x&L?Av{!5jiDDg`0aX3qd}U`&HZ^J zGGB_Tl?>$MA;1&U5`sO_hpZ~Y^{x{!!H@sq*fNq^DV=O_VHS8Ax`qq5?-d*bPf-{( z;~LJ{pJO{r0IroyxV6Ln7ZO|)4f@?W;w9%P&O2BSu7{uqugkv{?wMOmSlQ&>Zx?q- zh{}HPxsg?{rubt)$K*$YpR-eD2=XiA>rWT(XWiYyVvnlur0)dU?#vgQY+zpe5SlO? ze7l_1_YBN#^|#_`vIO+OD7l0$ns%B6U?pCFOg}xLB?_5?hAQ&<6`0LD9;M4z=}zbM zpE9XAC|pQnxFnCiDHhN&>K@eQ2PQt@3_yj2q#boKxI-|~C~#n*|5dpRm?}kIRKg*P zoY$-J% z|JJ-ibr|w*`smGAt|@8$&lD-C+%M$C zt4Qhd-nTkw3Ai(D#D$9%cVPKp7_S*kny7PA)5Z{x$_>$3vP*k}2o+nj9Uke19j|ogQxY5c-d(KV$`isTl>Tyq5Lp$A>;)F*LRmyt#rrNUwi# z+L>(os$JZw3_FJ#IN-Sws)(|!(v`zR5d>t@8e7h#TlP=@0kPzwsYNqQDKcqd^Vq|g#`8Ch%tru$GaI}<^@GMRvcPZatF)t?g`BoU7a9JvWdJy3J{~>O3 z23}I9S=YA!A!NmUoG4wqT((6ArA*Q86eYH(1`Hb| z41A)w(uJsS+bIh)53(ZJa7HF!FXsdcHLdwm?(O@T5d^|of1;)+Fw19&AFfJS{;tHP zTtp(NpzUi6UE4ujJ0wcm+cgqbZ>({nSyJNpb-?LO2x+ZwW>-629R&9EIhjD+zcphB zOnWS!6hFGk%Y|cz6I!s0O!p*e@-!*s$K()Gkn7CZLcbH00q=RcTv!<1(I8x3c|Y1p z2BCo2{8cN{#D{cPSI6Qgx5{a0O|Zh2j#`9h@>9^b)#2(Yl(v4YFni4LFj(Vq zF~^gpNTUVJSRy;mt+lNYkJK-DHuV%s*Bx(=N;2m+&!wJ9B`kh^!ccr=zhBQHeo~1I zPiJg5!I;R2ffNxPsIet1N%oguY^H|{euM-CvY*SjRU21#nJM;fG>nAcNanv!hDHCLot+yUE(}+cc**v?!Jhkn0HC4J zoXm%j_K45*qK85bkA)3}>%Q^WCI9q&1>_m)^l4l3%LI@{3`-#<3?tLb2O_ijmPH3u zcUeh7EyQD+4nPipo){C}mZ<74Je{jVU8|x* z5@~LUJMsI!Gm9e9l8IcinM&*iRa}KR%(+ zZ8`&5Vd=GP9p~-pVYsZaL!ng*lYYifIQZU3)??--8j3hFFkY{{d$uewDBHy)WhHwM zhDm&5IRx5%$8k-Wb1UTe7Eu36cxBUn=Si+4(Wg&2K0+a`cC1AV7VCH1uf5wN_v3kp zSZpl)@s{o`jNa{&+D(bQ+^{l9Y(#|t% zTi`Q>qqW7Wq)hAla-S)a-FM9j|0EI&jE3u!*+_cng!?##4w|^n;sNmEdv@+EY zt2vc+bUE^7qf>O0I9aGFY0(%6NYPBJ>*~-lgL6Ehxv&nwn&DS=w>bCdNt05-*0pWk zC-B-nE)RQr_idbmf>eDaa%|t1JhgJrL8QetCqdMD{k;xBV*TDMa{Hb!x3tgqFsZ92 z^@lEBV2krc4}D@)%AA$-H|C2M-2=+Cxqz++I-Tp7q52jZgPI?u+;b#A6X7q}xc`-v zP{m}^xkNiD#8h<@=&(pcnY3vqbReTL9%mcz&C0>?qg82ct9gP&6O%>v2Y95rAJj^G zBMn%K@z39yo8f#mdr8mgXeG<9Y;Q~;7&#}(hCMO~h3!Ob678xvDTMHhW;-H?k0^+?TrkcwlILv!x7Ndh|e8&sForgkg*GAVhCBWB7M-t24E&*-*5RhasfBhqTTg&n*{CZ*M1ArRdLsN z-akjZ9GD6HIbuVH-ZNW z5`&rnz|6O85*!PH3$99LD%yYKXXUspflJr!HUu~SOS>aqLs`~wKqedPBCbXVSG$Ti z!j2WzRs#H8jF(jI5&CUNOXyERv+bK-CaQ#@4`dM5C&H5F>Z65W$6)^L^2n68lx$T2EuqB#TCTSnVA^-GL^zEzT#lk4fAXF2H zyg(A`8w8cXaV%$^Gi?a#w8q_9DX9Vyi-)*nX2z0#EQYr3PnaQfbR`k-X9)o5HEdWD z=TWW6GQ;@oQ#OgH!#`q*2+A1C}uTPi7czU3$c-J9I>>maF6Uvf@`BcaFk=tYs2Nhmxn`O;l z2-$a)&4rL3FTA z-@**lcl7{Xbov@K|JFf86_51$x*Dop1V?IFp9P>LK-AQw(5Sxi?Vj{=(pj|gUcNkD zqUMjkCgIF~Nhc5AXM})swCMNKJFnOLlfDEg+DuJ%vk_F#0Zvthw(cYI+#SpJpC9DI zSl(egg+!-p(3=ok8igefDwKs4CbFuA^0CN&{=PN{#Ybn+i7RZK#_}u(Y-G|s*CbKD zC33eVhr>IV#N*0E;!G;yor>N!J>QCn-aKW+_4>H6#Koxkh?JupuCh?-FH`NU%JpOw zi{R5yb_}K~4kp@g9bXFdhssoOc2Z$1ny6ct?d*0E8l+%)yU^GOcOA!rEyIZ!K#Q(T9P__)EE+pm>-gmR{C-ukbLEB* zubqfT72Pb&6-Km;r@0|S4J$THj$=NZW9JE_`|D=wDe9+hxXhB03+(gDLz~VB?kKf( z{Om-sAu@>|fgMQdmtT#hvIg+0u72i4bkpFfF##97fQP0HtrT)@njnb7kVe=rafYo7 zk!#%8m~e+cl*bK@Hb=J=WS}Kd4b^|!W4A^VUZ(`=9JeJBlQJXlhva$M+4xrx|EEIw zgdI-(8EogaS{&z{lZHelI>MxB_r`LpUm&lO*;TaLUTpHc= zb#5>R)le|dTK&&Z;LI2hF3jyghy5kwtR?c=#d6A={8{~U119``hgpW>BbIZIy?Z{q|io-a35!C z2Z9V44^8a}fEJIpLeq+gb=CYc5XcIKAHTPYo)WzI3rc}-QNXZ@R^7X$u22Jmc`ff3 zz}P1v?#DCR@m}KNRT-oxRl5!U<9Wex9!TM7{y;_F^eugL6Ll)|D%AurONm-{>pM(h zPx0YOSmF3X?R+*!F@)huWc(zTw)wcq9Kj`#{&9U2DAn@i17IB-kPw9BqmVvNKKQbY zJ~5Inrc}WSPs@9B*i1Emg_eGB8Zyry#$w|n?Xpsq+i$9ncQ+!m?%@N~C*`Fb>T-Rx z9a5ajw^h{@lO<_ulo}7+k6zR`01G;iY<&UnE6h1h$EiaY8VfZU{}WbXV15ikj3+M>?^;RFt@`U2K_YU3qo~mIeSCrs$GIc zT5=4p;-WX_Tmfl_W%KZ({rxjf-^rIuJq_#$)3?&e13>7Udv5nwq3!4pgPImW%?WN_ z_50LaSwbEi!OY51B>^ai;xsk-td`wRjOE3(ITdq?5#urm+CL74{yRFc`QhA<`|76u zql;Wcdlluus_QV2nk`9=En&{S+60bOHEL7e*I7nR6m+@36+y;>B}5JPAyvB_rlLXruyvC~(N#$44xY+ORHnIg4+_o>opDYC6{3 z@3lFCGWQm9F(EcGBdXb+k4gFvm$cMU!j>D zB)u}%EsL&ML{nTo(Nkhr5A|Oo`BR`2=)OM z`|}c2Kq*QLzJ)#&i|*5tW6@y4lrWzhWg`nD3@D*U-6@3TGXiKlhQSK_L9JA!v`v@y zNG9{9;^PsfQh4g|hGYe(5jEGL#T;Jk@;6$iOwGpo({;ykvG{5$Wh|m@wSmIHbJ97?eM$VIsuIS4Qx)Oy(-Ft}@nV zNr!XKsO$k?20K7zAf$Q{!J**;}2~pirsatr6J2wn(FEsWvxhx&*lNo9~%Sn+4of>m{-hLed>bkve zmvtVS09k+joRRJFnW!`-CBleAduoAL40{VW>?4$k7qdKQgis+?h*bCZiWHT0& znn<4<(R3~J?_PkU?^048E*}R*Pkv{(;hEJe|MntqPEso5C;ZGqEM~=ltOSa_Um8{U zBQ)Oo7y0CKt@PK(A%==kLJNx*vdRU$6qlI76#zipkHIho|AMN%rt;0yfVdSuzj9>g z+bUp2u)m^)wh|=3>Hm6V(n2VSCQa(3XxpByn^x^h#?;`#u9{TDdb$YHS@ZR;KDG_T zCXp|7!_c?_qS7B$5`p1q02SVO8N5#ObWZT1hNSla82KhCpvjdSW3`n4^*HgXy*4(& zX*#Wbg~p763)(qqWdFEu6p4q`>G8yJ#IOoUnd`FRfUoqhZjwbV}S44r(-x zz|j6VN>0LYKp{s&Wd`xxZ70ph&8Y-QuVc(#IDM%~ z0YMLLLuRP#4+I^_MBbw(RMLpPC-7vCaHf=|2=Vteq7MSn1GYX^!o9J4eoe zaDu{p#~1GJ9y_AljTLk|-w_bJ!N8WpXUsqw4HM<_qa!cMYG5vaEzS_#2#-s{@D?AV2%x3QU=sU-JZm5~ z)q3trR66Zbp7dQh6#+-&YDVA`G0xmER^^TX^E z9==a!9E8NhVrbF}FsZ9X}G%N4wm@>`6MjytqFyGrf4 z4nFeNDjjoq?mvj!#^%GsWQBWZy2ptjXxrkK_XX8IG_BZOS)SUtJC+^wGqt@{Sz)kK zHIwkPayC0f(UPCvSMSNaTNUEmAC$XuxAH|oRwlF&;U{T$EG3f1_#*w6N6(eLOL*AZ);JC+8gPC?KmV!0ZuW>Jfn8p-W4-$u5&g>!!2GbCL@jj%b2+zAuk6vqT?)U%8l4!+b4wGx5s2=lJPmg zv?j#VuH#w#n4W>E@AbsQlE7gQ1cCsw02VS?W(6C*4gn{?Vz+r@Sug85zoFVB@*f6t zfx(mU_BxpfsGOpkKpkx*E9WvAGT{&ii9DY%DQ_z$lzKH?fF@;lb1(ZUHn%!!#5&Gv z6lxXP%A_XWJuMfXxZW+auzoO%3r-*W$pVHmegfd#mUER#*(+LzZxnDA8x$_b!Dou* zy92|;9KnNqRB5#@ssCv$lT}0p^2U+L&|slqhfpLw)nN|xWvuy?gp(B>!D-xQ`)Yc5M07%t z5wxPB9Jiub4g^Rn=CT)D4jqghC!{UGJ8?iu7XS40RapCdRD5YEceMCH>Z2aFW4#}a zseh(IPcxc>KvPeNGHN1HE~ocau`O;rPbXBjtkF~szX03(#A=2Mjfdb7 ziKoxvP<4L3L*+c8o>4DL2FhJ4h^>Ni3ST9B0Xu??!JxV7$aRr%A(J5-T@d1o9Und} zLa}j3nwr9p_NwU;ROddYsls+wHa|j`qTP>jT$-2=+9W);B^JMQ(S+k*YQcIojcAxa zfmdM?lgsHc&xAWfqCknx?KV>=vP(}U_p&Us2rHp;UsGEB28UVFtZ)%uaR++a>)}%= zMAIG1tWqE`WioRz%>2@;V?_DDOf2ul5qRI1pWkL?N`9&A7LN2Em=HX4Jbtl+*MfUx zZLsG4CjC8Qxfhew7DqLp407M+sRgf(e$vjq_e0sXdJ@vn8mYFe0I6T9Ngq8GW|x03 zb)31P5o9yKfRl%xCMBJQI?85*kK1WHvjj6u*u{sL#pT;ll5&I=?>xPAIV6@OLDjxD zg<-6eBGrU#w)tdXu}`ZYn`)?cL1``TKm+3i#pB?r&_5r3i#tyO3k8OWW z=Kt&c)kgc_Q@p;7_;gmr-x-?`48@F;Ui~Rjjhvo^Tw?EP65x~!Kks^cDF{}zwvTQ< zi4!NY;gPvX``g84>gl6X5rFueU*D=G7Ojlk_1GU)@E?3asU-`Kt@5+BD4x8V!#;j9 zNO6b-6%>VNw#y8q7xe0FypQtJ0j*nhw<0wz9bExXH{0>#ewPwr-+d{GW2M77stjPo zX)3ZdYe2Z`THx^ph7u#+MdudX`h)uMT#$!RJw3$2!~^lUq|jLjIFh+rMN0pj?buTF z3<=AxqkFjPR|DR=&;Q=+OZ4T}@qaS!L4)5G+`!6w^vT92z@J5Y$wap(vkUxwSC*IX zcj;)+Og-dr`0v2^eIF%*(f~8pr<;u4u@zM8>u0WdBCc;o%F+RM#XC=)pUpp_d7V0( zz*ph_fm{jTLvWXP^9*Y&tWmdu_e&52m2*c%kJk#*up>V0qb*Nx~XO|KX&7zNg>L$Vejsm z54GTb+w8yAr$lP2zoy~zzVkJ5Z0hlMv3Otw`g<0`!%t`E#@sV!?$x=~z4Fyo(=0Dt z9&Fs9*Q@QdkO+{FI^KpZ4VnN!z-(&^1ORLKL{+J&t2IAEfd4{j zmF3QxzS)kE%w_~N$G%CCV%F;?-Qr!c)dp^n>7#G;?lF5o&g4b!)w)>UC_pGg=54$+ zU*=If;a_35HB4B}5QTTBsk2AM_+KJ}sK)L~EK zcckb~idY}nJ*Y<>0<+FR%XSm+$4Rs>sGh0kkfb;- zl<>-Wlb?iSubid%orvN4Y}X;Z-+&J<*%U5iF^@P5s@h+RoZ~TzFUf zvk3-A0ha`L0xAc4Z$3FbiJvSOo}>e(2ZQKtO?76B_k=*CRzbCCGAX4I4f?9y;^4%_ z&zq{p0nJleqL}*xs7skt$s-1iKIkEH%tp)Z!u-&{7y@Vk2|NPX`ISw$(p296ytsDg z@y8M&pVAfP9iIjPV|v0WMu@N01Jy-0t~3hO1%~7V4+^Ch%p+_~g{G=!i-z33sfD(> zyW>68z~C*5!8V^k;>`(hq^zGnVU4vH z2+JL?vfN~MOCO9+Kyd%ba-^WcH!(ty;nWY0EKHXukH3#u>W~(Qf=!BrvdCnb8TY;F zy*!zwB%l>M9PXX)jk`0pe@EEd)TYxX* z#5;Yo9Xn*7yAX9&v^(-=o3gOQoi4se`5`-2cTA>h2iUMQ&*sFGG5|_W_KGJ0)^B6; zQ@XzKex3WW)%v%e>yhXgmj9~FWIF`X5DDwK{yZsiGv`cSV@!plJ!|_q)1R7pbvy=L zjRUQ@qT7o!|FkFQ6E;< z1{ASTQVQwU8^d2--v>@Iax?r3iG2Iemw}4d3?4mG?&P!?Von}lt@mlS?Z>xZfe~gZ zq7nfCDHO$UuFAx6Hv*xt%7=^miv>Lci;cZQ(Yj|k&JDh5@D2$w5@Yj63cQ{&nWZhC zZ4-Gw<-A~nO|Q-VbH2P|mgi~}DFSmHa-LI6E{6m;4+dj2$a6)xlJIhqyGok)piI#Q zBZNKLz%s7zOkd)gKcGh6HF1?IF6$rQH2Q?}YkI{wzf)XQ!@Cadlv77qTr#we@Im;c zGr^wWVB^G^PHoV773MbPyjGYT0HKZTsY@21@^+!D*j?mIM0~jUSJPQTCGXQAl{Bp% zx*l6|dtJ_@vAp^c&;Ytk>s}q=X_JGsDa(d_<|ReNKY9AclpCtCSgut02SYM-Y32O z2FwjVJc9O4VCqYTVv^L)=(g7_%73E&``!uIk!l^CIF0D=}DtsbsZ#(LZ z`N&~^cQ~?1^GWUuBQqdCbxHp z2wWREh<-HAYt0l5?h+jECj{*d-eOol-!}l!zJF%JpTZr%4B-KF@I;|_|(1w2-f+IZwaG( zZOO1#4Q6+J=|Mh}+Qntnr}yJVOzN!j)6Fd6Dc$ipIn`vw-_QyI?Iwqj%|}{L-m9#T znA&*zvHKs+W*$da1}}4cc#1V?Lq-zjaDx0kDJg*e&EjLEirJ1HN&d(%um5M>pIg%# z_eMFvkUhmKO5ax>{UkmEP00%?dT%4C*xQu@nAFNk zuUDT~(^-S4)}8rHKq~*(>tIO%YyIHVrQY;WP!)T3iTG1+7^p(Bba$Ov@v+18&BU~v zJW(MsuuzS-bkzv4`XlF`TT`m~>yvLd@w%VH&%z0%aWKVM9E8h5#pK`tr-fq$k^7R+ zGXB;-jV2rk80+31y3n7?x_*4LBB~#>k@?rqG?*Wcae|#0*$bw^4Jm+Wyo&u5GDyoy z1zlt5c?;Xi-*K8s|Fm|ZQ=&%0-JT4Sri_^rEK;fp`I`8>Pus)jQ>&nEORTE?cMKMP z({N-CE+I2H5y6I(P;T)s^6_@&DTJ`9Z})SLJf&;|75}#`4VF>wyNi9<7w_ZL4&^IM z9qoH9?8pO{aEaNmWr(PH&7}0NQG=Wgv7IOPCHC-W^`V0NA`ugHb^CZ-0GsBXfSvFJTLFQ`#rZ>-OG zef{;|muA3m>h?s8@k*)Xp`BnOdxCZdUYVmM=10nMefyeL$JF^iZ{D|jsvseYbyhQ+ z_9q(DjbI~E^{X@8p9c)qN+K^0N;eh1z>USH!2<*v!uWbpxGq z9Q=KW*^{k2RGBr=|7fo!Hx!#}Zdmjl0>YhsN5pGM-dL9LaS`DKZaL)x>Qzb}W8(+Q z*{V_cO{vxG>1A!jQ?FE<^+ioT-cyjLbt8Q+d0ZHa*X^gSbazp(tB|P&WaSn*;&cKE zgCT_V27ZmsA(1Q{32!)y=V{+`r0iGOq_naHpcf0SeaH)?Y4^7ZLD0Iu(6P zyXtReafRW~i%sn~oN(>Bdjyiu^UYrH-Me0rza#6-e^(9Tmz;-?C-QUaOU!}H!GcTl zlWac7{<>8nXb&E3E9`Uq28>l{pJO+ZyA1jC3ncRBY?#(*$WJk@B>nB@@HM^^ke2Xn z^%r6B4#@j$0ZqJoef9_x#tkj}soN%);3DPbKo{ODP!codtT7t2w&bqR+5|~D+oJ*L z))GfF;gm?Ae48yp@afS>+@Lff?wx6iXylv;Lo<^Uz&G$(gu%eKJ4_r;4-@AU^xyVa z=q5x4z~;w)OWi=f0|?|c+QvJR$b0b$sG4{|ntdX4-%-g!Xc_J+LNvCz7(J#qG2}_* zJwtxm=M<95=zn6(&wu8y*B`@OXC|wf=?LnR7Fkj!O{rr;h0ck}5mQYGT8b@Ui=QWB zK~2^|@{g4y26w)LC1N?%dmoy97i|1m{*fIV_crcyDqS?_t?yF{TK;KeT{{qhZzqm3B2&`) zpVawgmKg>WS?6`pw#5)gWY@T|^?*pVFcpmKlWwIw;obE+Ix3F%5FxNG*tCc!6#9Lt zdfg-relgQo$RC;=GXt7{;bevx2-E!yHBPV};C2;fi$m_^$!s^-)>~NX?#+BI|Lmu*LU=qO9`MNiRZ4s-U zy57u;Jd?7z`~BfM1S1u#29@_hEck7dN)4hlOGZ-!&kK^mKr+?4MT2c>(|ho}tM{RT z^OUJ-*jd{{_r7+JyoE7?#Fn4OiloKDWcKw{de+x0X2Tr(W=+%4AlG3vW&(#oNaQro zB`1d!BfXMPxEeKpDL*>}Y!l| zPp#JM(`*5wVQ%(7aW?Qu$DHa4}D#XcIZh}>@c zYZp`YwoqgW`Q2?tS1DyLF+y-uW%+TBoo{IA9q@H?V6C?k+#&)`zKL-~f|CDnPHn&h zRj8Q?8;$~-P;^<^%a43d<4t&>KwE{P)mLd$)aE{hx^olyn%j^vX1+MkTumfsUvcv~ zeJL_}d61}xXl@KSbHfOFUZ(=OY|J)ULy<<0i6sF{Zhd(l^*Qi_D_L~T(G`nkBi|pK zhh#N)b!XgKKX}jiu`hkp)ezt~IIh_THNqc+E0b?lPs1ET1k8t%Y9*vYx$kT7q~8Gw zBow47Zks<{)rL`^zRJ&|d%nBv92@Kh&Vsm|o<#9XfN$|o1>kIW`0HsqWPpRWsrddr zq})B=D|GTB=aFW=LIrRtiSe^Hvw`5uO()D=SSujkuGoL>_wYE?F|GxdC@WB{X_7I_ znIi2hdsz1d_4(%>?FQyey3QZHLC=Htu565F8Lx%*g5XW8+wTKmX~7$?IBs_aCY(D8 zPTX*U36se0#=H*#MOv=(J0Ii{?baSR@rHoYLSO_Xy1Rp;nzFpVoTcVKc@O9;nMkr# zH(uTH(sxQ#<||1))_L0ip|95-Q#>*LmE)PE>s|mqF)+uV z4-#2>56I2t>n15>h|<{s8{xHh_G6-x;x+J9yOB6oD-;c?;8q!K255L)#3klXrvoQb zYM@`swgtBfEuVp?LNx;oyHs>PBJYQ$L_`l1zI82N;qI@pGY3}}STBAP6L_>~0wymw z-bMZf>8S+tvZjB*+Ds(I2ss)kQJ(xN3EfHRgkgiTTU@QB{=a(x&{a^tQc5DEd2V!S zDqq0yxtbUVxSf5On3P4({J*rMh0*2+x@UG)dR8A(AQl8we#<`My*#`12?qC7FZj-n zzugP>0#mJy!WeT5fz2P4##t$Hwcjc|cmN863p565f02h4to{}+5zQ8x=Mgc(t)BP- z(ARVtjln?rbw5p`k6l{oGz2{HfbeI`WlKnP5cnz-c^T(T(BV()U^J@oj>!iA5G)!b z(Z`se_BgOlI~vihS2fUWnR$em<^Z!VbC-+B3PE3a4hf_1yv#vP(7Yua)HmC{eN&F9 zs&yf$#g|*U3;k>iP%(psZ0{*wA!%>HV&@}ghX*8dC#~jRhi?DLP<$eqe=OnU67&K( z0yS8l4?FqXXmPY2Ko*r;8*CAg0Y|}1Y(rmOR@T(m0_JBmIjcRCp^5@Y@p!O5jm_j_ zAXQ)w;&m5zh=71LiTzqzZ1PJ^g*z|=08V&^=Y19kJs^LUDuFD7E|CGbIWeIzzsZKa z3U0%C*?yv-00`lN2kXr@8tRu|lN~~Vi3AA4Pq`n5BCYt;v-Hp_LMUX;$90D-2>+>& z#yXoPa%luHO_Ulf+OyFw)Fvs1qCyaCzWbiJYsEw|EVplY zc@Ra`U0Xj~KgKbw98CVPnu&3zh`#-?e9Dbum!{ zfDW9x0k6Qns$Q4Yl*0qZ=SDV+Hyf5z1HqLnFqPIN8ijrdMAde2{MT@S9d>N&ez60t4nMG2gUWz=YI(H&78wl_p07`nVh#RNGobP8e=F;k25+t8 zVg2ljc0X4d{2pN%=*K7ZML zdan(=p{VdMt`x`ipQ}$8m^Co2jN4kbf^|D4MEeOre+Y1+qzMY_>n~AhOz`;NOq}cM z_{X-s;C^xO_K>~37cVV3uR+0BgmPnUZ&|HRQQpW%=e{_5@+B_fQ8$lPQ?>4i|D9jO z(FLGxXG$*lzgGPBXh>$fr>)U)DRv7rzgwlcOyd#5@}D=Sr$mujMI0}_%)1knMxQV7 zz6RH)f>DtK-NY)U2p_o2_orAv`Uo0}w4P(ib1GyW_e>~%*quy1KR?;D8%c2D5O2}Y zIc+H28|pKS3gvQnvv1$=tdX39A^nhPhOU1j2gpJ1_YSzI7$w#FdiOm5v=k z%+Sr~dR};bL%DIgM>vmW=keJ9i|+$@H^ENjpJZ|3+>66qi(h5)2p%|oMt6QL-r{|h zSh^clfNZ`Cyr@IumYiLq45I0s(A;Rlqp#tmA)4}jc%xLqBAlYU0>3%~ujhnQbaCCE za5*otcSPFyMxgkWyWPYQkf*MKmvF}n@O1p1tnP(`S;n;A8f9U#DsPrhUxI(x$7XkI zM)1Ke{2E!7f0!YieQSI;e?*{7g)H`^1(vf>$zw;i&0BmK!cOE-5`y>14k=y1YEmlr(&z@llFU%yb; z@$GDAZc5qBbo^VfBwZS`w;$2_+EmMOZq~x~rbf$KoQy4Ne9M_B=sgblVwJJq)UBw} ziu#C}x5a>aJgucij=U-kgY8SFmK8)>aA3qIn?6jq#b{asH;{N!S&?rta~}?rfB#5$ zJ+;FROL&F-duv0CxMOR8XP=@#;Vs&>JC0nohkC##VNCFU;Eev7Seo#;!)~oFb4cX+ z=o>jh!)Wc3m@CVZm0EjC?>3w2-gs<2TKFIV4=^0K6gFTRRY{Zl4R7;tkLVOdF!c}^ z&+UEotmx4R-tDY3FCf?R&9>M$uTq%z8!;~7NX57cIA^a}{aGE}pX?Rv23vH5rY_5Y z3=__8<#i&F0e!@s-EFuIX6!|Bj0XmOduKEtJ_Ba|lINgj|W*L^IgY zClN&rG0Z!+E!rOKCil5ItNPIEpB^8;_XzsciR+YT*>J93;HY^JGX78eff={V@i1X? zCzV^l#ot>e(ys>zS6C0JATqR1@gG=X&=! zr;5bAtsGs`Bdnqgje5S8n;%S`PSEkmrLVC4G2%*Nd9N@qqBoETPQIsePl%)mllhm| z!Dll#=N0X*U6Yo3xHg{I*T#@u?BfMcbMZZ+@eSR3vjCs$R>^fQZy6w__0T3vxXPWw z)YI)sSwH4uaFdQH`h}jF$pSaJV)N-~{XOFct(cgVq#kc@?u~ixx>F5g_KYVzJy}!| zN_Y__Vbx$eKEwl_+H1k}Khy&sVK6=OgZ8~V`xwPfdB9kz3*p8(CERM zh@r!LYZ!sJ_D5U)+D|`Z&CY6uE|NK zlPcmPTKBfTePYAq%gib}=fvWQpjdCNp$V)B!5f&78i%(-{Nx7#`Y zA6ah!Rb|(_59<*LQR$Fw5TubVC8a|^X#oYKyGyzoq)R|Rx*KVb?(Xi6Lw)<;^FHtU z`~GX)>nzWbbKm>kd-lvVGuO->AHhLBg#{OQ%U^)1^tM_AK!Qvm4^uG4<8p9CPDC@7cB2XftmuhTwM~j8@eb1i7 zb6X7d^>zTHQfQ1f^5Hy@AFowN1onE-t5^Cs41PT+EU!4mxH!n{-rCPm*wy;gb%kFl z&a9^&XNS=FMa~8@erGP$j@dDFT$~X>i0Rym!7>~tP^T}v`l+Wo6)wAKqeXDj!}VK% zC3=T8Yv)^L-4jZ$ca0^VGm7WP797xMmio$?m9XmH5FFzP>3$ipHE{2XUu z-dJzlcks)$r}}eZ8>QHyq`6{vtIVlxd~7<&CzuV^%WIz)lINyL0aaH-0Pw227HVe= z)P5(C62eoy8!FTxGiiA3;bK=fr6ChZ@mZ-P+ZmQ@$?yrzqq&ta%s{T-Uq!fOCH*2} zfY@lUO2n@I`Bt%mcx{)r)cVa4iR=5yf_iS79i2NJi$~CBX$kNSmT^^uTPcV=FW$q| zs4KDS-!+H*GWV@1_1m$5xRi)`e-Z24Yc3H(>GY2nKja$pv~2I*hF=e{k|~OkqO1*g zS*!iB@a@Y&rkAxuFALFM*22Hcc<{0iN>g}(I6G)V*>X%Kr*!!cI?I+}K8LKEv7LV~ zO#oLOWRAFhUPF1hG}`vsc~(o+b6JKpw-xYZSPqt>ktqaHPY#{G4U}dU2u2 zC$y77B+UMd>`!YF|Lws0+m6Yj`TnRITj)iGVkSy(hbuFIi=5rcIyB=PKo*P4tjW_U z5TSR?sV%$OI4jy2e158fc3+!A^KkN1+#yOGIv+2`$ zv{BtZ+FQ-YSs^@_0()}K6CsFrxWDlEjos>~X9sRdeKGq^Y&h)aPdpwgD(wJ2;z;zC zf>T0U@V2#R<~#o+TG^wWL>Tn{us4B*utqt8S?u%b;*C3STvu?cNX%<1){sov@HM$`)$y3|)rSBr zW~KG!N!KMn-zs0@8I>BVtdAT_y6X8-Mqhoer)2~AGvoOJ4W58zAK#yEkk_3r#!k+& zWi@%(Egf6^J~Z4Fh0WdY*zU~K8x`Jtwy!%d8lR@a_Mj3I20T*Ng4!@!`#>v=4}YnO zz;d8q$c1chmYTcX_FmAEej8u6T%POU;%{!-=j?i!qx#N{I>$B5!F1=pK9rp1Z|N~2`F2Rsed-iI9I%dQf;JJSDmImnir1N3)Uq|?W!K3Ty%XlJ91!HsLO4-pw8lpH3c@}+Ggz>MFJ|Uaxrn!@z z`)Vxau>i2z3e~&#m7svSNerRClY^-TRViGR+ulR?{c2JzVn|RTW|g;{--;pVR65`%oHX zI5KGOW%m$P8?l$F)?T^n*w5;#`DzUf@|<&V__uJ)CilglK!KE?ZX{vx-&|m;7;A~= zNkBlag)z4Owd%b6R(Avw7~;{DICzgCn$%68$StvBrkbPq{p3X1F2p35K7C`cwBk~FC9$hFKy5U#77=>OG86UQ1O8^hFH0LK5s0>H8RS0p_x7XsXoWV|d^>2nQde;!)MZo|R$^)ns>F_|4! zZMmzEBuDRhW}WMk%kAOet-T4w$o$Wh*p&M1eNJZPBR^y`YVCF>YwwB%2U+JG?5z55 z)`>s-`K0ki;+k$u2dgTai&p)%z8nw}x!q5OOPU zMkE7m%3e54orAiv%gd^9ycgz?;dHh!T&-A{_DHNl){RlusBLu%C*sfuWj^o)A3fVj zFiPxxSdbuu@%_zfr>T;>LJ*$sJa6!*#1WPE($F)c&h zkNG^;{s`Q)f6Hk=)CI(;K%7vy&B3(JW_zV;MmMEjpy&e$qKiUAb9>pEFXE4HSJ={j z!$Wcq4}b-Ku_%9FeL*^726GMoNil>Na933EYv%cJ4XU^ifAtn-j9o4+XI0P9_zI^w zY};CI%tR}@pMru;X;&vD+ZK#2+SNJx3ghWpS0VBV3W!_fLfGr-(TFYtF=?{!4E=`E z{fgE6(UfvzMD0jf)v}}GVY^9G{M&&r4mcgb&xhw|pAn*eb^IhoNnp`D>78N z-I>DLi^)a$o01N>K7HDdA~cE{R1X>kSeExbl4S^abVU8?=S-5#cJYsTM2}l3&`I?K zAE@F{^zVnaR9`>2tuNOXG;RYbv1P#xm*bYRDqDwzh9evb9xJK!!ht&=q4H~Ae4oW} z#Tu6gi&?HpeNKoFLNsqCZV%+x@aT+?XPfqpUIzRTF1r3o>qo2ctig-cVFr?gdP0Qr z*$SzTC0{Nss-Exi6r(jm8@Ozx2)5bt`*cs;>!-JCY&YLT!okDW54vr9myetP9I;lG z{>dW&sP}UUB+qYClHDjNzvxrBWRr@*qMWqPR}bY`-$lO_QpH9K4*1?Yrij7gHjAKj zf`Tt)b-*E8Yx{6_s@$k_6ilV{#=vHUHH;?Lx(w zh@>P%dMHeeckxU~2KG#U>B&X%c z4&OomhQb1Z6PZd=H}5t+F1;Y&3Qr_t`_ep3>{495qwK27$`x&Qd^wW2ZIB@5;Yb-6#D&ZuMm)T!7KiYp{P<3Ph(#_ST z?j9HPl4IhI$iM$~DoUk+EKBeYXxv)v_X->(XeNYy_=9pyQnX+3m<;tjEJ84fp8EAk zhs88)qxDUuStw#ul+ru;eaXr-N$hy5UBmvcTZ*Zz#K>=)o2T>r^F>x-vv%Liq0EkJ zIuYzlKkMxo(6Btj30&U?mDBqLn0?&A@c^MrTxJTN6)q5SQ_O6X_zK^ZcNW1(?i-9D zCO)q&(Ps&G;3F$^uX`y%7B@Wkf8TWG05cnnKtrKx3p-3BqBC?sE z*eh&+b{cGH6QwjbEU9`kT#|@%=;IFF_{&u;RL+(pesHInit-P0Pw? zoia#bOlV>XZJ#I!lz|Q5{Ompdp18)TVM+E4>+Yp}`Pse|mTU-)YtqrDvxG;gdsYGA z_EY7^8zaTY^KRdHzT6d^)~UIFR4l z_?H)6!9zsI@jnQMvHm0>48t5mbHccFpr2dnKacIZ6mfuazu|kO*>1!=tANpqn(0rhlR(kA3m$9RnD1r z;GWKI>2bO2s^$9E2S;`QcAS1n6TcP_Eadl$x7 zxUuH6@lb18oS!WozbfPS_-Wy4u-gGr3kW=h3Qv$g-mx4zJaK#4-}~%+;yb z9N$NhLbdnRb~2Z?4znlAYE(oY>1y#+B5>2RUe)4*BvHa+#hFFu`Ww)kR=DfoB?ibC z?bTn_n(&~5R4r&S-RIHN3t0C9W(IKO{>U+Jte(pxkPVz|nHl&SSsEEfMQGmf`A?=< zjbE!V8n-g@!`;B-%$PhJDt0kI6CoD z<;GYBekZVW8-t35H>?%Pui_fRU9Ytbb2*Wo71KjpY8IRDZ+y7fkUNl&e3Sf^0|JEb zSHsr-$%xRpe5l!%#8-6V4A~xN&^y?bcvFRUq`h=J$01SFmi7`DA7CPW`2C zooRpXyzTsjlID5asg|wA-ACJ4i{0#`@xAW7A$->fi&H1NsB=O(P6$-G_8c#1Y$DK?MV4+MN>1(zzcyQKqe~7a^c|AoT+INKR>O;hm@4byKRge>R;Bnt@%XOj!#@=ds<4aaw*MO|!W)P7BaEx(@ksZ?HPHTseBl$?hN{xz z*BbTZZt}hUOY5R}$4x|IT9fKWXuxqzMiKYv?YQ(@8GmBdL|lZ%2Yy*Ryt|y zU{mA)I#}^sdlADWLRNZr{=)?zmovZGugk*Ov#k#9Pegr18M)JNXfS+9#~NzpLhhy@ z-iHhI-th7@5cp$+V$x{2e(XbhK4VXTDrSY3!YziC15)|IBt0W)#V(>Rs94%aiQ8C1QX(#?6E!`BA+ITGSi9jlN# zCZ({L0Kxhz6wE|)=Q7X)z;20I?Pt=hzwUB=u#yCF!_H7OenNi}hbYMOwWvCyo2tQ; zB#qhiYZe&tE1s!sHZV@BU*-$>%9x$tL;KW>_+ElWi8^QoAky7n5cMYMuUrFH0kMh( z(koDOA=MVnKD)bx_jXxx_i|uo@Ym^A`#rBwgvfxNyN9y;qOQ*wS+cq1=S#525QWNc>M&wJ>=xiO%{YI9XEH^%R{|>d$U4U zLq0b?BRs;`)qiKRxE9F4Z+5}F9WyF&s}zd)EGitPKjIrd*GYz9AzsitRF3#q#oThL z47j9iJ&v)vr&G%)h))5bV6tX))|vm)?ZVL>!~(b4|+ z8{*2lKWLyUGQck2!Vw|4l9opjQGI*W-j(~p`*=qdH}N$K1rP7}#Cp{S9S{>WKB2Yf zRsqof^w2`IrG7Zux(GK>9LBvAjs{siZ#$M&r1)9c%@h zg;&*`dZE+Gr&wym-?AEgLqju0*EkFM-G7G<czI2)i%(!VgDO^k)D)0!@*`|(+3$ySU&UD^uGvv@Y;gnI%}ZqN`ZB~)Ynl}D zi3%1ca6*#1@sZ#ZZUn|YcYX&%2=z39}CON8~f3GZGAq`=0oNu{+i_L z&f~$+4@I8s%^FJ@=nP%^40Dv#Y#D<$ZBO|_=J)qXPUury4u|yDuX=h|_iy(0dYo;) z@YC?{6&Bg9O_g*J8_UF}blfdv(c^MiD2p2_h`M$qZ{OvbD5|&~B_w6As^Gz^eTbQJ z9&14vmJvxs`k3cn^PFLCHjmD!<4uI<+hv6@qK5opf}>4hw2f~6JB45e$v;l~!f{Mg zo=+$;^!{+oQYO?PQV?A)uVYB)QNRmabWC=cNOU*f&R4$0I z?e7Y+FE%Yt?R7~Zr@JTT?u|`|58xbS+}{&4JQ0&c5-XSw^J+Q8mv1J$p(3GWAfYw= zsa5nx&MY=N7OIEF0~=p+MND zJM5H&r`Z^R;x*EO8Hgiua||K-=2T(ri@fO4?t+so#GnB@AcIt>tQtTmg=3!@Uwwg8 zdJMjPNCsLrqcT}QC>F)BmkegarPck&RV*%O3HT@z_cl3nVvDCMXdqYwH7{dIOGHN_ zLpP&e)6$wO7LXsMkGWWf608~jisG@3PnUx~L~rhp8Ct8$+QS*Vb?##@F zbqXlnM`xGwWz{zEn$_D|sc$?TDNQ3;_;KVIM{x^pfUN_{^eB~lcNgUlcUg~vGMuR%U4P@dUNb1rZvO;#L(`^ zuHe{Z?S1EpTdTdsPoL?rhH#RC4q%P^+mv;pBJm8`bDQLz)?O?|!C&=()GFmt}e8!0G$KCcvwBGcw=HYCg7`tx4^Ch-R&=mD)Kh8BV zAsnMG9HJUcgdS`r8sY0KNp3Cz*>_~P*rWeI+_ zS{F5^c`Nvf0ZMX~i{Apo#CQE!qc-xNbj!K~fYd%eV{qjs^{GA)gAkCRN^k#1>A{RU zjN0|iF~a_95S%cYc+UIWJ7;Yk&dUqJmsw)k)3e#jAq7K<50{Q)E4DiK#>~$6u8W~v z`&kHZ^eosAA2LXr^!DaQ!uGcW7T?^H;egW7Dmo7HZ5(S^G-RK7@QlzhM0gN3{RHU? z0ncNtC<6LMR;O8yB!P@FGH?|`Tj;j=Yijp0YNr#DmCJ6^sk^4wPk}+e!{(EL`}|oK zM}SX%>uC2Rw#J~|?ftKf$m+&5Rtm^>s7HixBsgSJp_C!&T;`95gUNyGNOU(OH!S z3C%D8g9B}S@7Vfd)V;B7GE`k-35mYjq}YW1Yiol$&u=pUSuI+JpWf*T)kf-y)dv+X zG@)Heo{wX4Xz`p1~QoPY?wY_ z;k9Su!ZhI|wOEjK;q?s<^=;+=mCca|{I$+I9}O2Tca1{7_ULf>tKV{+E-Dft-1$km zNj$+9;J+nq@z)Zg(9(h`vm|*$3)bknnPdGE=Mro(MiO_Fo_H=JMvW2sGzQ>DyzCYx z4hR&qFo5cs+Ih>D;gF$Lcs_dgh_c9f{zYM`c>F$*pisfa!6?^kBy3sEva)Lnoo6XU zvYk@$M?*DbzE|c-;Ed~xMmbB(^?=Z7s%Zr*) z^z>of>=GnB5(|>QXuuG#v~^oqVUM~x@kXQ=>%&!}L1Zs?GOen1lptW^w<)s24&9xs z+7hx194=W@8(u8*t#UNyFfy9PC{O9`;LY?7ejhSZWwWQ^fGs3GD0a(SkSTzki|Wy1 zi--K|Uqa^wtq1g)P)7ipEbND_f3_&BK0*&OGZQ1SdGTHZq{YndbZ@0Em@)7S6otz zfkjAomG6&ieX*735n<(cg#PPSHJjyOTur6J$` zI`8tq8_8f8&HItYW1UwVs7pIM5GOM?4wqBYes?BGIwOm$1mo&-@@_8cZz0K7`4%GC z(^vVYguV?l)hq3#llW($y&urA1uTAQg=Llp|B*{^|5;UKh`eU}b7JbkFgtp$0ctaJ zT^BY%!6Sy#{=HUKP}8N9S7o#X2RZP$7{w2V$089VE9nPB3B?qRi#{`2Qj_M_u3PD+ z9)r3LqR5hYKMyyzLuOX_k1NL;C-XsB%y@^EfA!bt5xQIksE?=>_)NW7Ehp+GSHteouO8b^223Z{3D-kqeMfj7^g_jg5IQe=+=o z#mZ~g8&LxA0`+;yYn#WquLc;8KAd7)DlvcVsL^HU+l#?g<{2Zz7#6t_U(I-jQS#~z z^Y|5g{#&2mAmZ1C$6Jnr9p*c=IIiH=-YYxA1vi{rHPA~RytW*H8i#I?R3Oh^cuGBe z{ua~U!>i|Db*$}PS&Y&k8en?FC(Q4f^x@(!!Ixyk54m}Xw@Sm&&D z>Xsc~o_oxlb$<92lRm;vFmN3Uug$(?;~Vek;_!uhBmxRi5AO0*sAqj(ifrevmvqmg zW@;SHa59X-dA0onxv3n@|L2@IVTg+4+;w6g5zt6;mBImwfFh@dDdY+_X$SXpN>hp7 zRrBn?w?wv~qb8+cIVi#@5Qvp$^38sJ?2A=g9*_FUMm0sd;KISlxsx*DkbY)c9X~Bu z2z6*(B|0LR9C2`YLE<$7M{VagPv_w8Xd?ki@8F2tBk0d9SGu!6$$7~T&UOhBivk4p z{~`|1{WCyzcQVu;5iO`9xn(2kwgAe&|C3bzP7QwIGZrnvI}77y&3r)_ z&;-Ug1F+=&p+|m)vAt(;cS!hpMMP^1#*Q#1Pj#NB4)9 z(LStuTN7N2-uW}z2aOlJC>N>$R3RxWOfY47#=y)>#qRJhmH}#4#kz>bK|f94mk|te zQnfkZ@bCeApK3x-X-A*Sj&&{QpC@(BWBmoU)gFaf^4}3Z0^?~PY7Pn=1eerO>iskS zy2k@b;Js=_`n^g&0hZ$k4!L#IeT>URxXE2OHB}zTWkekFzI=%!6&4_AA&`5a3)rV6$+4mBI?2aBFM*KE8!{BLf2@d(W6!6>}^I0`8l3Jn(RZ&1s++Y#p1N0i!%3 zNbjI*8Z1%VE*m!9eG^sKL<~HGED3Y%V7@>IbLS^Rb={rqkF5I%cpneo%FqUA zAg?(%@@g+OyjeZcmy6Ilo%PepXH&(2irwIWAQ0z}LY^)B>^jMfF-8~DGQ^2m(~a<$$0?#YAg8phll^Npr7EE*TLTH|I%Nqqk+Ja z?;esFlabiozJsHE^~wv;D+m7mMuOm%B#?V$7KhF`nm!kCK8I3{-B0&}pYJK^2JJ%& z0#1R?UsbZ-F8qfh1D*y@l56+-c)AXW)B;8fNi|fV>pIfSc5!| zWK`HbXJh+Wd(i~jGs1gay}qy~Jpx4#aeXC8{f(S}bj8`=wy(~;=9mWO^o1oOdF?JxJi_PQMfce7 zgTp%-UEkl>dXISh??M6Xhd8pnpBjQu;km7lg3$*L4(F7s6kF=Nm&O}#m?JDe0~1w6 zm~84@=&^hPnm)yWt_<@(en+Y=n5{S|;t6AXGSf%y(SkPuDS>$ZC@`>l91nWH?x{VA z|9!869KD+|@xLC9s|7Iw+&xXIUdTp3CWk`p8FoKGe|0jVI(-h1O3lr0>0urqNbpld zbd~1*WB@3vB(PHkw$9pF;K9#E?7QA?V~M2ZQJ$```g_98BKkYE?t&^{4Om7QiZ9C~ zGZ3SalBBn&fHF_<*BAjN`2hq9ERtSUWFvHj-~cFDCKJeb!6(YFDQ9@Yn*k6situs% ze|I++3$bJN&vaSXy>~YuWiSe0Dn4V_&*(ZZ(s|O@;soY$Xp%{dfiD`8sG6o z_rKE)G`ldGAM+O<4KcRK3D}*Ak#u0?noVUevB~aI9&QL8fN|n=VFf!A9U4B^0x&&( z({w+F_mh-}?sp0$Sk;q#z2;#i*dV5J^kCIfO}I#~*Krd_*nIzsd5+r;JhN#6Y33GJAF?Qw zI!8fr8;>>p+r|(N@gD&M_gWJLTk+Eqd_M^{aL*u@w+{}1Rr!tu1{IccKVB(thY$3& zGcR-v-%Ud8po>TlbVxd)p6M~?-}VxJm(4obeZnrnI`04z?rDmkwJ>D1<*xz-pHZE- z$avA(%2vM&?t5qAzVgVP&x@AGyg=*4H8L<*NSTA)UE$nlh{&GZKBDt@dM5ft8w@TB z2KN?2e+ALKJ)|R~11kI3|EO#$a+0&8puBNkgEy&4nP55{72ynk_HakSu!q*G?%12x z78S|Owjl_Uuxh;1Zr*>!_6$xc8O-q0ImcLcd#Zua2uG`gjyF#KU132t$mu1I0Yke` z+Rm)z3yDV_t}sxyqW^S25G<=Anf3>=0a?cXssRsWEU*WAF)W~;Qa>*!3BnDz%^@Vi z7U}-_A|r_Dkxq{Ov@XH-Ku{3&4ILf*Lbj`zF!81Iiwt_$TmGX4;)kR?E5KxahqWm^ z3V*8L_!j(mh2CoXWzX~Y|Iz>4h&{4#5_BHsO!~4lshvD>Fac>Vd!P!=y40ouU;Zf^ zW(9!CAhlgGOSO>mxfeijLkO|3CH;E|<{Wq->gCq!uo}irTxLfLA|WAJ>$1Xh)c39( z+P_&!cp0z)aWc1f7cTw>;D=BTFnz2ql26rG+bkBUI>W!u{0}rj9S{X02Igz0@;N>& z#A6O-^2+@MErv_3K4}Ni{(UkxB~uugoRd>6XlL2}UG>>J`1>KHrT{Rym4ArRy$E-2 zoJ?5xVSwx&8v=DcFW^ch<0A<7)@}+H$uG&xPcTWQvH89X8y;+%RM&W8!im@yFi_;~ zo(P7iOJMZEvS*1?F6W^2`o8+@9|hws3R`5DNzwEqJwHUnM>L=yAwqnDCeA-2`UIwi zaADoz{;5nQKq7GdVXBnV_R*;wx9`U&XWg6hWVoS-lD5sK!HPuUe@o;3juJp+{d06v zA3&=Mdn3J1h6@}0fOOM>aB7BZuLZmEd7xJwOfm+x!7{x#a_<(`RpTv`!}KVK8PN^+ z5628PPl7TqBVRl|GBIHKV^+Y+q!0Y!6iPz)_#V#81F!?vd+)dPz#z31QPHXVv{67p z+h!2`$Lgb(C_nyr+k3rAgO#jPm=g;9LW2zlg;~9ZgglY1e@7Cxykb^3FG>Swa7`O9 zXBCJn)H>0q<)V58BV#Xc<(^9>UeBnBF?=PML97~ozeTi6$iqw$G-)mE@K2dp6KaOgaH zFzYy^U-pQY5bi5jjCaBJae>DF6BiJL=;$LMKsGl%EJb)=pms!nod=L664JiOYv9n; zt_!I|{Z$~~uKxl=F4!C`=+cruD=bdaNF2w-;Zpejjh7c`L6D?g`orUYxd6MXWX4<% z<>3@)qt#&_OXk4B^{<=ALttWl^5mf>Xjj+B+%Y+!=|C?J>-&bdA-nMYPXen)YY2}r zqzi#vd=viRVODdo;2KxGw=!&Z-CqXeB$LPm#c3|PCA28sX5!i>i#I9O8QX28W$Mm+ zln!a7k!qIBiTL`iTee*F$%odn^UI=Hj?Yi&I`cP9n{%4#)e;~#WI~V(No4$&#j?TV z(V;Q)6R#O;<0F?*+rKyWW}EKM^5+jeK*nh!@)LxHwgSro7WomtI;d>au${#u2Bzn! zIl*T<(oD+Ffsfu2ApbCVj=1@+D0~qITJA@(g0=A5KW*bNG0ME3-;a2ip2G)nB&F%t znedM8S~~LSp8a~p%Y=;lr&gNLsoq&rThD;EkkWeMCx7m@fO=PGN1S2|nhA^Y3T9+z z9PWs1JFal*!?+=ldoLsv2C3ILFZ1qh9?F72DZ;#1srD~7^HN31zV_lt_ges&-aRTq20J(kDAM~n z24LRBfhKwwk|9O)W5dsG{kM)7XE27~e{~j<5M)Wyoao8tJPCR<59j)Cdm0z@c`nU$ znX60IyZ{_SM&{kl%A&m-PyC`lSOse85P2*AEQ&e}2&2Sss{!yc-E+{HIMFtKv%+@k z=rr;!ARjQn+C{>DEz)~_YT9Ll+Tlfgp7^@uBN1pJ_K*1iX9mEvJ|Bt^7~d8bCTahm z(%)C@3Kdhq@&3RfoXWptMm%+=J&^jFz~-&GBk`z?a9e;KVTC8_goj(@qiGOyyqI_= zbn^{omuqbIEj+L8s^|LQuvOwLAI2BPJjaW-y1e+ZyokY)7UmYn_>ncMJs83KK8Xf9 zhxjaN7=h3Jj|c@BIDfWIld$zlNaj8F{i7vL^#;J0e+SwV;9m7~BQzQ#_}T7Jv|tdk z3QpVUu)x;*&7W=>)b*tox&V!3k5l&dytwp&8jLP8tiFDypAG{3RP2iCAgfe$mzNMr zT;EEUt0X$r4pO0C+v01C@YK+lO<68mrTRuTbUXdqi5f{uUl&iX1qi}`69fP4kjNd! z-tO-1&W)Ip6WEM#6NEl%VE5rtJ!F8?-@WJoT3X7|`J3pefJfW$lg+&&IU3?TP)~ZO z|K;_d=YM@r_XlVf0L^aUF}DM|j23 zIoN{p28XtD)l`olj%a2nclmjf()}q00BH7*y2+-;*MGWmDm0tuOpaoAcMzCxipPsk zbCuDhcqnhNf`J#CKBzB8LKPd!{s3`;#mmV&u0;TBPWC~JI4;s+O#GtMj=-@DwJky zYyb-wetA9nzsu0HPb@GQ5iOZSW-8Y&jp-4ClFPqKJOf;0uqKGVQQG?H>AeUQ1GfIB3d4mFm5C5puD&O z`6N&(D51f;FKcUQEhezAGct&4SXq7=q{GvcG65mr>pFCqxh1lW?-5vTKFo%}aR15D zF|g0vEp0{-E$CEhrQ^d)x=*n1~bmPZE{s>tnh zj;tcvaS-0BM%*0S%6^0RC}ObTg{K{6Kj&S2VfLCog`2s<#czD(&-X-pR^E4uYbN^J8|(OZ94xOnoYwv08{fTUNz5jD zmWaeAS6bsD&xl05$Nvzil!w1TltTYRM8idcs@$77%Y;(SB%$VDM(cPhp_1KoYW#3R z%XPE&Zb0pop=N_mX>%;2IGAd3H=yAba z%E;gn+I8;8lHo zHe#7st;FIQxxa66dyqK4+Ff;p#P-?TGdZ8g(wT$vXLQrHZz426%VPF2qv7}P&+zJu ze>1$ZL`YxcGeXOC<6rTvmBV(0VkPHeUCVfHjumv6DCK5;?FBUYug#o1} z6$(I-C*GU5uS~$>TUrR)cRo7JH0#x$Lx7z__|N?4Ln1QV?Hhk)RmDMFm*NC@#)-|8 zaySY%QG-P{c=N5seIo11ysE48li~U2cZm}w z(Tk4U6wV2r$b?Mq=t7kNKR>ukyQ2L3N13ecA@6yAsOQs`)1;5=*5?U*Tk_s0C3*KM zWx7U$BqB*iEDPI&^G#}NQJ1ZSWg{>ixl3}FH^3|cA=mMt4!71b{M4p+(Ri3amBf4S zqQAsxxb~5_ZGphv>Y^;A6*))&nGQ?t)qSoOo?=EU;$jj3 zi<7ze?VC{L1)b4nT@}~;jwyB&yxIyW>~;AZRqnEbT(H*^IFDil&d?7Ae-8n@Macg*#CtC zx;-EzIO0o)A0A$jb|{s)Yb1~^E*dJHGh=f)=RNPR2sRgZuaBZrEPJWu#|_RqaX&Ow z^L5PDs~l`@f=dM=g#hST9LfFXeLxI$^S#&)?!7AM5H)T}n3 z(tDf;NKsEgHW22Oef%%_+nu<_=g4~Jz4thl&*+ie!P(QEGBfkaRiCLHgzcmD=*u1h#1jU>Ab1m`k(VP3$xkU{oCOhB zA}<+Xr+eS~Dm{_zqL2NUsTdwDA+!(tLexSU$yJEOPG0wK(0o(&Rd|Q5K(i#4N9vuX z_$Ie-YP*ly)O0yzbpKC90$2po%PuQ4sQ~3g+uTf1iMbN?Z~@!6|RpM8lWuf z{kYBGS8*QM05Ky_tGxk=QpRXHGtv}H2>pk<4xPFGzeBv>Wp;=a>nwWBe-W&ixfgT*km=88*o0C@1gsZ83gTUT)em`n`s`H(Bm+3lQhDQP2+c6WJW5DHQ~8? z5lzKmt9~su@%_DBN)t%oUyjC87h+=(Bl}BRo+Fi&6x*DhJj09rUSn|6j)Af=8Lq<# z_f!TB+L+RNNPX#JB}4){?G%>FF=#@N`GW4Q=iG^#;c_5Qe^Tnu_atrfUmqe%I+fqe zm-CYt`{}oz#57t+t&AdKR7dJYF;U^H93Yt)0vO&VpRE=Ql7-@Gc<$IbOn>q%}7_E5Q57IsmbNnPP*o@`Hy58p#8oIIX_|}n6W_y zP^uji+4TT=$HgBU%t)FF7^jeTc5qaqQc7VuOVefH$?T);&^fy5!&fAEM@ideSQ)bU0J5~|E6jok=g-sP(F7nsyqXuQi5DsvMyTUXE>U6~Xpj zUpZJ$)!pO^D8{9S*ZkD&P4^6R0#>FAaQ=gTHp3H|eZOF)WjLLrjicK*BhnuIGlDenbVvU+G`Nnzk z|G1d7x#y-PPfh}#A_eVLrl1n#IF}j!F0d#brofLs?gKW}yRH~$X4jhw*5PFMx7+`N z_M2jUsRx(px+NwIO$;z>?i*rwJl}O|Lbk9ZAS03=&Q;Kt>0gdr%PK^Z9HxS4?$@p5 zy4Wm6YpTqFGiP$vJqvCh91{wNXd7kexs`9chEAD5u<0fM&*WpSomMt&%^)3EZf^Oj zoC@4l*2oZLzL;7YB^Z-0f{`l%Cy&QFK8D*h*|guaftFYju(|;B{>e4Z@L17y-AUmi zb}RwT@m~GSEU_5eA;;#miOmvaHT@O?S8b>xoYzs1GJD0`Z~3`5^4BkK@X-@~$h(qc zlG0FFj7_l|*~!}@gy8Dx&KK8&Khdh$|Fx%W`KP~&@Z=+X+3klw&p`agsl5k?i1`jj z@hbAC2j0u5-mSxZgIr9GznbkPw2>ui*hUzumTnm_KP=6xk`})MSNfM_z_7#EoCo@X zCJ<3w7k`|%etls{=Ji+BIv){C4byC$uJ24{Sp7Pm49m+86~RuPl33V$>}x8oi3=|R zTvRR)VjQ9O(*~;m?*$SK?WC}IH8C`7CD(2LUNJjbt6?w8GNinK zjUBVZ$l#=q#cKvUc70rKP=f;`$-1YKzAwJx&D~3ip~xOodkH*dJ@)VF~r^stOKfGJ1OgLRroW^(^>Q_&e514aKD$0xPW?WY3-f`(L;XRI! z5lJ0NxU)Dt$y5c4q_+|a^t7_=`qfZEKRZEVN*&4kR3D5xV2$W{ z074Ir1~fuv+UiE@4Kv|(BChUcUcd(Wi%gC?p=he!{tWBtwA$c^3r`(%9BjflKm%F2 zEd=DAq>pm66*4dQ1L6g-!Vz0>kDmp93F4}%lKog=B0XDvLoa}(b@OG^BeZSJt36Zh zuVnluk0l0aCxiGu(ry1>F>dF(kdPm^-uspJRb{1*kOsXN0WOTkr&7ATS?HwwOP>^4 z^*ZJ9o$$>UYHOouG&Ce~GV~c=dwIqf{4(-x-BDx$G`$F`PX?I(#InAlz(^Po);6u# zAO+lB5H&HL$?8$Ho`aI2dVOhRVMK?o`ZkK!l%4U+^Vea&R*8eT9JA!C@_hg*IC`21$5|(EkAYQ z(E^sI`}n!`69CZTr*|EgfO+Ml<8C)nj5UkJsoGo-a`b#vSVv-)iYXtd9RxJ90WXXG zagLbv2;fA{ik<(2GYvy*-6rHPdYQx|oID!pMx0U|0a?cH7#x*(OtkkB{uNGuXm)SL z5yqGGZrz_Iim@~H?7Gs2N8MD#TXoPiu*J`2Z&JRC+qT_k&DLGpcLAFmB_nDEPAk8D zcYM48(FB+c5NPG_sTn7QnazbT0Wbo^LG+F18Lim>trUJjd+(>G&+E^c{2Uf$2eC6A zIXnChjyC?-c> zA*7NIQzCxE{+Hun%PM1!elFtwcqq>xDa6%m0-tm1QpmI9e8q-lhk#be9bu(nT=k}) z?lDx#0bbgwtcC{WQHxEPzo1d9l0R5eGp(y|+$})K1uH6^JU-WF0b*ZuC}%k#w`wQU zV5eJOFXXrhlgt_|IcdN}{B&#;W>co81>DF8&**I2Ktu|E0)5DfzNhYc;%jF6ACUAv z87d83=Zmg?BFDJc#>Y$eHRwSd5dTEiSfpGc;kY@y#k!?cwm-bepG;2heWK`TW`(rI z&4t~RMF_yGRh!j_WtSu50ZiKVbrrZ2;oFx{F`75>-s;MmSZLxw0&MIb3mzQG!J-uU zIFnr5D*W~g>~AnVW?Ud=mH!`W?;Ve2`~Q#E)m2tzL`Eng8A*|>D|=*BMrKjjl)brb zQQ0!fjAVsGL}pgVCfUi}dvjgC*U9^SzwgiI^ZkB5|NQ>BA0FM;c^=2{I$q=Xn&%#y z0eh@9Yh8?<(s?1eWAaEUBGCX7$$tf<%OF9@EMk^!xRfkbe_}~<;XyZ)WkYkqQ^(C) zF=g0~5){Hz$ImH12LY-HF+s#%Bu9>SZ^Y2{l zwcW`R6oLr4Ur^VCX8(K7e0TV;SG3upsPq+D4u4GXIDO0R+gG&FaY>a|RunnQCeNw$ zb@1F>>G&jI)F4(w8(pgF@g;jY<6WfzCAMY@LKW;9FH|Qj-8Yq4g((%Ou~&+^UKC4< zRE(U+dz1fGvJ~BqLCUhO)Yf7a7>K3xD${jG(zyN1K73GbPwPekhdzOHLa*JSI^BGY ze@xmqWH_{!-q^D45~{d_lPztuSfn~;QO_Fkk%XC(FJB9+5Ph!ewAa-z54u5N z{6p&PyKTxjGLw}%k4;(rr34|t0!pwC!c$_*OnzI&v@T9cMTFoeP5v1CLE>b$KIRAR zdHgEhm<#}-niT$!yW+1*=FAnFYPICD&eBd?`=MaSw4oXOC$Av{Qj70M`K&hU>F&4^ zEcQA3pKc4dH+2hg+jZBc1fycK?pDN7=(=qc7JkfPE_+8hAgkKYF>%2kW2RJOYBxG< zR=oI5tsx{^0sX0<@a^iet5KT!Q{zchOcJt;!cPmQ&YwuJa`7ii3~fKP^*q)$HS(cH zptjQHT5`CygP8rD+w!?DFw_-30lMp>!wAVY_3*UE1;p)AofW9DD-6~zqNUxQ z&)9K2SRsh5Rr*N!48k5SFk!!&b zTM>9vj+y02rsIB9b$sMB7xy9eF2e#r`aQ82F^jV6S34dgifpkDD~nuzf*!uh)L%7S z*v;Lm5 zG=nUtmsh3TdjHZ#EBCjiL7bEY&$(~{Dj@2bs>}Hb8H{q2rPXCzK8Jz_&|n|x?c$5e>t6%%$}%wL!PVHI7f5vmgq%hVV&FMV`k0a zJ*IjR@fQvYK#vf#$r2cPlq zoDTIR;8O9J>7ERD(Belt^y8)vfr(9SPueffrHn6llB%AvuD;8oiv-f?lIO8XLR~8Y zIyac!`;SK9@)q^C;un?<0>#5?Q8k@U9iE51iD}4R9PE2%b^pWHXXWLYla*hdKbR8d zE_&{JXQO6oI<64%P>NlqQ*BsL>c)b1mLG_}71&l#wIx3&Ey4TdR8)BGEA9@@wpPrK zE#k|)vPTzp6Ahh~RrhBDc=s}vFSDWaUFV0Ke$I-wKTT8Mb#NW_#AOHfv@VgTt2(gYAuXVdRZ_X<}90`zO9Ufj-Ay^Tm>0`5r+GF`whenFVTVO zXs*5|MlvmDhxinff6UpBNlCZ`627$3$oNbe$UZ*s|A?L|h>olNzoX}mgU&l{SAH4) zlNCQ3Qh!o)W#eQ)Vd1*kmaN=`$E`YErubtnL9XxHJ`U8|#fU0xlWBx{-F;~4u0PG> zxei@-T4QrBPX=jyae+YRmh17_;9L6TPn@7xg1wh~5zoeX|I5NztB0n08OKyz>U4uz z(^P&uW&T5RmN82t+F7%$J7qp?BhKTt7tyMZtODjjo@vYlPebK)u0;6@AGYr(8@+ri zEFDAu*^oR+XTvqB;Xa+?mxGw8uXrfsze!c7>EJeWP?xyesA^NNJj&tT-nti&@nM$y zsYm|1T{iJr5)XFv77@SM+Z6m_Dz&uxcAO;O9?vz%z_`H-a&%A^tQ0^Ib#WkAOGWRUjn7 z;Tz)rT2#o)(?HhKtYsm^VkW2Az)*$EgAJv=2VQ1;-K|LhmlJ*gEfiR3dRZ%>fhhmY zz`VIRO9xtJujynw!{)?+cQ6P&Sy%O7v)JWhv?dI`O`uw-)^iSN;He0{Kr$eqJDEeODs^0P*R5 zRC=Y~npPr{l>RZ8e3i)9q%gA!i0)N?>l)CB$#>zddpAPV&#}=gu8(e_3>x&Ynl$a}X*1mXZO6 zi7QBEngWXiGjr2S0$torXr9(@*G4T8sJsb{6c$qzO`P~$9tEvempE`)JX(Mfu%1k5 zU-=Bb=-Qv!_3u&HXEC6%0^a(WoBnp!0?G)&P87AC-IE+3qBz&)9r#AMyyH*Sa9iWq z64rI0$2o(SsUK7YRSbip>rL};wLB9>!QmQ>; z45>;8MT46fF;rDpNEQ*#@A&S|+ZcUDx}N`^G9PAKNczv>m2%`lPtn+o zsIk~LB^2P2)oi-NCSK9VSeo0;N}5Em%qTYOme^-xop2Z-UZo#%Q7Vi(r7QH{R^7z4 zb<*){NV^qfb|IMxyZvQI?u^-$PUPNwk?RCF7JM_@4~JJd+<4ZmFTczp)IW8|&&^7r z&%Mj$T89*UU+)cDYX}oHou+Po{ifN(lk0o-@7S&FZ9iLPNYY5u2-Xqaq0LScvJpBd z#8)vR$Hz`eo7Pijk`tj9DXOerfSuvFZm(3T2rY#l)+Pj&U)Av1Y`=W>0lc9<8vHTV zFEI8xRK~aJRZNY725`pjBZ@3w=GjV?s0?-G*txbLT|E00g?knSG!TdV*vL9QR1EV#az{O}RhhoN;~C^4g6BHLE)SJ& zoS#_>JR5c!+NjG&DppZo{%*MZ&Igxi;O5AL$M!FQ%m9YGb|w?EzJ6hA1AQ+54r6V$ z%MRPYN(FuI3&$?#n?nU0HZQR?R@oUGW~B+MtUibNy4Q)kjN6Zg9cgSxa>WE)lVkK% zbyX?94+{l`$Ur)6B`S(}pvN|AdHZ#Vmu0iWEs~FP#!8cmUD`I1dN;^BdK;8ep#74^ zA4AE?B=U`vgzhYjVANLiVUF?OzbWUTJnI1zp%wCm7Or`o!UCNAYd~>^e724u>12f+ z?szSuKx`u ziBo5-mhEVYNGM?wen7T~C43m@V|^^77~)ip!MuAX0^;9fdld+O9S(|z`jQI`oGQ7+ zyXd=O?yOHK63HOGc2v7xc+ShqP8d2sxI|edUi~6*D(k=gRB=Ibd8Uz`rmX4o!i{qV z=X6hMpQBdR&-3}@upWLxR^?QHqhv;8nAoZmCK`)1(R(`9DJH4S>8 zrb$vJ8nR?+>m`lCA=Hs=X{j&f;Umlbo>!-0x#k%3ajXd(9i>6|rQ_S`p62E{F;!7! z(u3|9cDLf{h%w&?`IL*>x#t-eaAr0=%TlFX%d7IZx1|F~Wla;!-)Z^c#kP)@tqbO6 z(DH>1+AeoPPI#qRs0Pb#%+3B_p*wu|4zIPI@HW%@@dpncxIoH}>bXkd%th3)CO6nP zmEU`Bb4_LLYO4j-(SPMa@gwyqnqzY#;l}|VK#!iR92>EHcT(j zr`tRqoypMqY@0YT!XzQ+&wTBk zXXNe1Lj5E#z5VzVF(3Egh$oFde z81^bK`9c+4Y<}MDKNwZoIm@IYNT|`?`o+0WXek8_W+&S->#mM|$A-ALxmFggiW;V| z>D0%fUSMi_a3L2YL}&^)MLj&T^jF6s^|-q&1D z<>t+kgjt?@UqwY!&zu$ucGJ<;f$*}dy$>N<$7OSvx8uY{k>c6l#=eE*&C;aQez=Lq zs2G;Triql4%tk3d>uDCb-dpmNb-BgJ0q4^cG;$ZIAjo1=O!2Ls>MB>5h}?x+8CG{p ztaA!Kv%W9pw@*v`GN#7`5eHOzXwUBj9>Vb|jO6w%lPAt+ywk5Y)d z>LudRaDhXJyjUQ0>)A=#<8;e*aqd^?!Lg!#Yp|SXbv}WfgfU*w#%s3q?t9a=D+UD7 zLb0i*^{r_u@@qRzke>Z8+CyRV`r~e}w|W4=2=))_8N8ZbU1=bkY;0KEdOr!X1HfiV zX*s;W+!N?o(e3(AN^(E%{Ojv428;FwTLWt7Gt8O%I8lJ#{FPqR=pmLe*0gmZ{|~!| zCH?#^*uNER^(_I zlFfUrS+Sp#hoXXVhRjXX1_&<}yEw!ZUV7cz$>D8wX~-&-_cimWv>rO+;G6}h4_vt- z6z?woyzO!w%t=xGbN;m&I7QLSGOQ(FDXs~o!1&le-;j7VgKU_(BjMVc;eY-FHzgLh z6$Z*olW=;v2G=o1M+1YINcnE%+nC7I7Z*aEBoee|%Y@pM#=lTpnz4k`*KmU>v5?DY zA{n{3Q!gQC{1gKEW8*)*_e)hF!RYJIUU`InC=IDUc6g0}puWPRdwRBdrMsI$xM0EZ zxQc9*QnsSn){MA8IfY|IpYqnpf|Ey^rouVd1Qk;DFoq{@^1sag85LF$@J-}N4IRU7 zu;J#a{UwI})ZLaDGFjZ)*8N)VYdaq#e*XFWNA{?xfGA4RBB6BRktP^g&-rC;$KV!d z52q=whN(igS>X`1zbQFI65lqgf!HRMMCgXVg$5Knd-44*SM3X zY(;34PI&NZYwK89?R7m$4=JQ_E_qm?#YG^ChuUq*sWu$Jo~-TvNa)H*_em!~?VR5i z$MlaNH~#m=3ZF|hkl;VA3F?c10_M0<7px)i*52c!I$Eb9Syne{X0Rv2|E~dJE9<_F zby}=SmuF@+#qy7LDHL zc{V|_{dTv=#J$4ZMy;#W7fx^|&i2F173-lzvQHlQB&=UAw})X`2$4$dmUXsVnTlAhOJAJDirI+ zPo3HWhuJ*(^lHLb7z)Y<;M{nO4Xwj!JN^3Gu09P#i2w>Nm@x3)eL zJNC?h1!=HUT!gO$yYKG|q$j-V5m60=K_NDX)kCA6yaV*|icjsIw8^ESGMFLq>c-U* z+@2~fC(4CKs()6Q$qps>?^f92VFb_P#p|4z*H3-YYzj!`^Mm!>pBIGwdPiEnXx9qm zB}H+bjJS=_$B5hap1!!z*`|yKOX?wzMr(O!bJzecSQq9Q`{s4Q@qS zZ-z_SDT(|9soV2Zcb?@jafH9DxCAAtlV77ijVk#n;(UpRKHi(2S8x_rCfL0}Leb5Bsv*7}D6 zH*34cWxL&U#(_3rZ|jczt6&QPCWG9}gOckPI!$5k8blS^BN)G9| zI@2#&3l@;cZkDirKaMI>N`ikb!&f>!*_TLPR0z7dzBn0oWS7 zQ2{MmX8!v@t5_JzM7Hi`H}-Mix#St?$OW7IduPNI*PPDG2ynZ`rC8LH=Vs3{M$Ox> z5d@u6gRH}T%8lT5cGW8vczWNN>@frn_mpi@@O8?JlqowiW$^sb8!i`-P%Ei{ubv$> z@>V5PLYteKs%5=xq`QiR0Y#=7qaZ@#n``gG$*0eoxr`q#K9>3-F+Y$Wki*k?wqh&s z^%sH+-6k)mzT8uqe#Xl64hH6o3W#iUJPKS68lB2aFhRXM+EhV@z$`zGA1#sfYW?qd zil0k>|$%SaDbWwHP%=0%jukSkN`nTC*5Hd|GZ`QIqq{LDQQc1ee;CS zFM@mh?4yiUFb!{CXfQ6G{*tYK?Mki26^L}d3*?=i^Kp1ZXNQGq5^34r? z6TP{Dk&#homspT0{g6G}zunnJ)&%ijlUpuA%Vh(tzodjRM6Jdn2DinpJmo5G2!h&) zWU4xjBh}A_Qv&Wm&sZ3fTEt$SPtFgUJ(sL&T83Lv8K0h_w#Yfi^aHHNWJoZ ztqG=2EZ?2!xtnWxOK0F|L2R~9c%j`5TwIyEQ$cLuXmpLygH4H}kZ2DUzh+AF4sXcj zllc_45p4LEuC@+f%`ASw9e45|<)2fPr)v35)Wy^(OBSbnLEkPHWB1^{T!%{jb2XFC z#u4SQCo+G%p6(Rwz?vSq&wYl{!~4X^ke<^%Wb`+9+dHx(GDB^!T%Il*&8?m4!GwC} zj9xB7aJPwu#lRBK!_?$4Fxju{wxyAb&wZ~ZReGPdx=?pXB$XmTwfn-G=mo~+LN5p3 zxJ}vEGhsljgF|2UGO_|BJ--ACQkp^t&=o&pV+sDob=eY^g=p~K8}j@6g@ezAz1pl2 z?{4=Bz&(WTgnhn)NX-;8C8zx_PKB~Rod&d6DC^~o%569JoZeM6q(G*bfcnRkdsphB zY!CYV>RL`99bP5S>JGC=I(O54fnopGgSfVp=QiWPYAsc*> z`peg`S?gxs7P1V1U{IL&$9`oG+C;ZHe z@gw8eYurWz=_vJNn+mO>?B_&MjahFOF#`rFNgkm6@KN6cl3cvnz z&eP&>972<0bME|5rj^SDL4cD%O1%!-i7Q$1XP%&TbBhFe&x?rcTJ}9EjT&teerx3y?$iILVj%3lR1C;n0X+BDfRocY^n-NQHpk<- zqX#>`)THICsX*N{EeENI1u6YiXX_pMZQ(Ks>{u>!Dt8O_7#}CT=l@nRz?3z|ipp62 zcZ|vz#tBe3q~AZBmD1I7%yE>*Fm86Xf!xb1Cq$ZM^wD46Z&p$qlrFcihy|n0g|ZHu zx?!ZP4z=3Mh|4%}Z-0v2>bIb)Vw9lJasaE<^l2+=Q8Av)!Mnes1XQI>c8oq26vA*p zPGP|O3L@Cxxa+YUZoDYpz=X;w0J+nv4CuTWmHATF5zLm95Ie5y93)N1c&%@EdV|Iv z0)Sy-b5vF&eI*n|62Jf^HWk+rsdeEtW4Fuhmn6&@jhx?d-op9X3#{o!mkN11?AqFl#ktZBO&k&I8)d z7sjP3FCgEfC`_0|VLxuYoNImV^dw@zsTK@jahh)`O}1UcL&^%ePfmge!6vff zhpqsc3JOWQNoj59c9;9ixlnnjf@q#!GHp=nd7AH~W2hIklMms$f8!m@ZyuxFSi?(lOs}+-YpZW+8n!+^MbP}o;f-fGwDj#1n-q={Ke`{W% ztKYH5qj3BpNsqbx=?c0iEkU!jw>27{qlYzHJ{5Y(Peb+gj?vWJN=TrR2b`^Mf|@@X z5=x(G2slqp{RkipKEro9D@5OYJvJ#u+C1Jm1(?=f!f0Sj#du?heB|cNvtWvN8A{XP zc;*_VWKv4`cl_Rk4KE<OYq(OMmmnqQHgd+O8B6lHXY2Tlmu0t_TqzVy79}1ijF(g+>N+7xnh_MfqIAP;&BIj9s`@rwxta^yL5Q zGJ)wbPzxYGr&)CZro2L}_L2IP69%8fJ1usuVkdT3P}4pn;w){*FVbA z;c?cl?Yu%tFl*@=sR^;=enXD{2lpvXDeR0DxmF_CRbeELnVe1j+UmI6l<$9I2W)*a z;9i}*n{`p8C-TycGQeCR4y0!s7wVOCuFJ$#Iq{ci4*9uI@h`uRq2j47OH-y#D|tM6 zsS-=@d5SEbKT} zJ~e+v8=59`g&`H1aFz9vooj-#cypBp&+%d!EtNej-5hYip*h$^DvED_r)2uPLqTR& zW(xiS8RC+&PZ@XKV1sHKTYQrDNa+$3agAwRd<5AoYN_5r5-3K5+=9~+N81$Xmw9fT zW?a(sBz+KpGE|pJfD%82MkxIIJI@&U4^~6I%i6H3B7YQXfK2aLdcJpz<}Jc%HL{3u zTB|zFOfdz$^DKlau9Win1qtiFM<&L#_NP+E9D&vTnKa@%NE#WQ49tUS+8QOQuchN0 zuReXNd*`oJd%uJg)o!K`$j>D5_T@F({>HlC|1D{hQ5p(q>n6jCc|Tq;w5FHjoe8K_ zI;4GU4B@+0XW8dSu}HL~u-vAgvE{dzz-EgXm@Nvec+iu@$GAN~UVF~*VZDeizax@7 z%lJp~Opfd9?HfWf8$(RAB0Ul*W;P*R-1XfZSJM)JT-6_#0yaMfa z$Urw&1(up7(ID`>`-DrD$cKMr^zKM~@7-_jSM@A3ZRJ;xRS$o%Nt6z~ywKjpG(-C% z;8UU9FFbC-HkmL&!x{5~J&$(5wdiSE#6b2Rjb&YP7%vPnRcpQ3CEFp%o}LXX`^&dh^@GbwNq^Xf^pdGFbk=58=MxEL9bd!Dp9#cd zN+-1t{Q$3}%)?TAT^=uVYds~Jm)Isj1462=)VtVB)tjRJt_7eohRBK{NkV{wLeN%h4rWia0N3XO1EFp8NUkZDZD0@%Jn|y*V{Za|NWPQcirdl@-L_F zwk3a4vcWy)Qht*tH=V407>{3sDKYdFd!SWUY$3%|Q%a?K7>y5eKJiRL0;m5fI)MyK zkQmrj|6ETg#5BFYoFlC+3W5*X6>s&`l^9pW)$x2^V{QmNn-9WkRZJE+oEG0XrOZkX z$?I9It{23BR3IO-UKdHAr+>pyk$S(OFt4!bb-qIK5vWgq7PK*O2p|7BZTE`MCSljt zf9F1qtf5;aQTAEQ${aK~kF``+*RNzjTVPY}ZADNS)IJZzPHifv>VISMdmfUiN0s7U z&(8JEvR|e_W4jaj?riO+wrEg~#$@3mZBU{8Bcbq>L^o4u>6oWHWh?9bz|TcRS^oiq zQ?v-Id7I_K_2V_Di)!YT^OA@`qacD-2$N58j*gC6yN|r4%};#R8Ejj!ew{o-EOzl?@Nj>#tedY}EPVf9Mg%1mr6H@ zH=gYVe|^XBdXE~KMD{+=49*8CJUxvrw$%p3%y z@e==9h?iyE9}rymPd$YhCS&t&??ZG=o)M-Id(&;*F{VUvZrw^7CB?2PbRw%iiw)hb zv^DDLh}U$V=eOPo5|EhYO>^B`Z&2ukJS^9M`&RNP0=G2CErFbLzU};9qy1X~L6HeL zyKX<0*a+Mvp(mQ2iSy|{BmD|5UFlPOCyzypRPUuA9agQk3+Iz7Y+$N{8;tv0$%=rS zw9Cwv3k?3ebKCZ+?N<8A(}$*U9U@;~2z?_vKNJEb#zoBk8B2H*bFsaHEn%(TzlZxt zm{Y#hK~DPzlX#~4-2Fwyq`-8jO#ejp;^;p-&y$F%JJG=;N%vk6z7~y)9qcyWz@3L# z*p>CQgycxT>jzYxCbjfb#WZ9mWxqzI8b@ytxT#v$bw-tMZaCS`H7^l$$_PR42l34H zD`LDJBcJwzVBqiP#RdEdxnLSM=SMsDqSv>-%{?+A8n}Qs-<5T^=A%^B_~D^JucolG zYuLn!v2E6^M^>ZX%gg=WUe?abTgsuxb2f9QmfZL&j$$O$U1CO4J})F zEiB%uSeov~UsU$V*=t-(z*~5Uq&kl#dd`+oOKce@zG+=)#;-f!x^njx_EJN{Hu@Jm z@MT{=B<@Yv#8;S%%O}mT_el~CZ%2EsrGyM^Z}XKcy)^V(kz&UCCT_3e<9JtJ%;U51 z0$=xScHc|vzEySK7{xc8O7vI>@!GMgz>lcnI&FkkXSA_+yfvrW@K#HO(5}Qp>>F_k z)Hp^5XYpJzsa!BFB5M;RnN%a~edH(#O;1IES}#vd^=>96#Oe$U6}g}ZDZUdCVxM8; z2!DLV4X>D#n^kLkvlY?Y=vlHKH#f?eUTd@jy;r*Q5B-*Zfe zc%=Kv@>e*M+vf9O(RrD)iP`-hr}$(Sg=0PNvBMjri=wMyHhY~m%8BmHv%^qFZD)b= zi)3x%!!6)fgEz}vv(vUkCdqMsGtdsSZBebG)0l&BjeZ zwCh^NSgx1r4Q96p-Nsl*P36_EXoWZN&QvGvq}p?Fw%W+|QC&59p^JG4UL&h{G?9d>wMat=p73 zU0NyftQKmud1OC&32#Gxrwjzx#(i9Mg5l%d?=*?c-4teAY`a@a`L@;Yl0&Y?V4}<9 zv<;qwd9P9~cYiG#@37rGEfDR6vm4%*V&1NEN^}`y7>cNq7+$Ty<92LB!^>S4j!CQ_ zk2>K}nFlY^&E{9Eu8@1}3G5EJR4B=geuisZd)YonvzT!RHySWjXi$?nl zs%%M->U5eJLZI318wtsAjhE4S*Ra zSXj`v&zx7w@TM>|Wg=`;^2YQWe})N?VbLFUa2)nzZCmh*!X$l!Gjzy?`NG?#z1U#; zM^U82?^xSjcaq!Om`%WBnxGXy8fmOw#)iTF3nE1HQ4nmEUU(uq0>j0E=E@^_sE*bo zrX%XQKb)v>3TRMS2`gQ?#F4E#urAYDE5ygoIA&YHdpN&ilSh_+-HEF z8dH83WLB*hUL6&(eooL?e|C5No9})Ue&TCKt$Y6z0Wn`qAR3`-Uuv_l0jeJkePRfo zzJ*Y=EeQx3TjIY-!O0C9)*<+7g^H!k;V5e;MLIvWReZbNYk>gQ*HgB!KD-m}HBzUA zd$*LgRs<3*zRk0^eJ9stei+A5q3+E3nC2iupfXpQXf6RQzeU6^r?pfXWT{F?LgeOZ-5Ga>B05>;A-}i3vZP#3p#~69sfu zjVq+-HVY;Iampx7ub|)Dx)9*S^v(W;@~ej%f%pC3-_e;gTSE8?4eM&pDK<8fQKU!m zDOf(Ly(o7dD-5miXyhMn8&_|iN(g2e)TGUp#NeYbuWgC?|B z0e;rpt+yro08B-iS)~2|Ia89xf4R}(vquO`?6jn7c3(6icJ
BackendTLSPolicySpec: spec
PolicyStatus: status"]] spec[["spec
PolicyTargetReferenceWithSectionName: targetRefs
BackendTLSPolicyValidation: tls"]] status[["status
[ ]PolicyAncestorStatus: ancestors"]] - validation[["tls
LocalObjectReference: caCertificateRefs
wellKnownCACertificatesType: wellKnownCACertificates/
PreciseHostname: hostname"]] + validation[["tls
LocalObjectReference: caCertificateRefs
wellKnownCACertificatesType: wellKnownCACertificates
PreciseHostname: hostname
[]SubjectAltName: subjectAltNames"]] ancestorStatus[["ancestors
AncestorRef: parentReference
GatewayController: controllerName
[]Condition: conditions"]] targetRefs[[targetRefs
]] service["service"] @@ -111,6 +113,34 @@ Also note: - Wildcard hostnames are not allowed. +#### Subject Alternative Names + +??? example "Experimental Channel since v1.2.0" + + This field was added to BackendTLSPolicy in `v1.2.0` +The subjectAltNames field enables basic mutual TLS configuration between Gateways and backends, as well as the optional use of SPIFFE. When subjectAltNames is specified, the certificate served by the backend must have at least one Subject Alternative Name matching one of the specified values. This is particularly useful for SPIFFE implementations where URI-based SANs may not be valid SNIs. +Subject Alternative Names may contain one of either a Hostname or URI field, and must contain a Type specifying whether Hostname or URI is chosen. + +!!! info "Restrictions" + + - IP addresses and wildcard hostnames are not allowed. (see the description for Hostname above for more details). + - Hostname: DNS name format + - URI: URI format (e.g., SPIFFE ID) + +#### TLS Options + +??? example "Experimental Channel since v1.2.0" + + This field was added to BackendTLSPolicy in `v1.2.0` +The options field allows specification of implementation-specific TLS configurations. This can include: + +- Vendor-specific mutual TLS automation configuration +- Minimum supported TLS version restrictions +- Supported cipher suite configurations + +Check your implementation documentation for details. + +### #### Certificates The BackendTLSPolicyValidation must contain a certificate reference of some kind, and contains two ways to configure the @@ -145,4 +175,6 @@ uses `PolicyAncestorStatus` to allow you to know which parentReference set that [wellKnownCACertificates]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.WellKnownCACertificates [hostname]: ../reference/spec.md#gateway.networking.k8s.io/v1.PreciseHostname [rfc-3986]: https://tools.ietf.org/html/rfc3986 -[targetRefs]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha2.PolicyTargetReference +[targetRefs]: ../references/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReference +[subjectAltNames]: ../references/spec/#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation +[options]: ../references/spec/#gateway.networking.k8s.io/v1alpha3.GatewayTLSConfig From b1b50b932712f133e899b3e5ef10fd466fa179b4 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Sep 2025 17:57:15 -0400 Subject: [PATCH 168/224] Define the XMesh API (#4030) * chore(build): Tweak update-protos to not rely on GOPATH being in one's environment Signed-off-by: Flynn * feat(mesh): Define XMesh API and 'make generate' Signed-off-by: Flynn * chore: Review feedback from Mike Morris Co-authored-by: Mike Morris Signed-off-by: Flynn * chore: Review feedback from Mike Morris Co-authored-by: Mike Morris Signed-off-by: Flynn * chore: make generate, sigh... Signed-off-by: Flynn * chore: Make condition naming parallel to Gateway, and correct errors conflating status and condition. Signed-off-by: Flynn * chore: Oops, update the GEP API description to match the Go types. Signed-off-by: Flynn --------- Signed-off-by: Flynn --- apisx/v1alpha1/xmesh_types.go | 183 ++++++++++++ apisx/v1alpha1/zz_generated.deepcopy.go | 112 +++++++ apisx/v1alpha1/zz_generated.register.go | 2 + applyconfiguration/apisx/v1alpha1/meshspec.go | 62 ++++ .../apisx/v1alpha1/meshstatus.go | 63 ++++ applyconfiguration/apisx/v1alpha1/xmesh.go | 279 ++++++++++++++++++ applyconfiguration/internal/internal.go | 53 ++++ applyconfiguration/utils.go | 6 + .../gateway.networking.x-k8s.io_xmeshes.yaml | 248 ++++++++++++++++ geps/gep-3949/index.md | 35 ++- hack/update-protos.sh | 2 +- .../typed/apisx/v1alpha1/apisx_client.go | 5 + .../apisx/v1alpha1/fake/fake_apisx_client.go | 4 + .../typed/apisx/v1alpha1/fake/fake_xmesh.go | 49 +++ .../apisx/v1alpha1/generated_expansion.go | 2 + .../versioned/typed/apisx/v1alpha1/xmesh.go | 74 +++++ .../apisx/v1alpha1/interface.go | 7 + .../externalversions/apisx/v1alpha1/xmesh.go | 101 +++++++ .../informers/externalversions/generic.go | 2 + .../apisx/v1alpha1/expansion_generated.go | 4 + pkg/client/listers/apisx/v1alpha1/xmesh.go | 48 +++ pkg/generated/openapi/zz_generated.openapi.go | 197 +++++++++++++ 22 files changed, 1526 insertions(+), 12 deletions(-) create mode 100644 apisx/v1alpha1/xmesh_types.go create mode 100644 applyconfiguration/apisx/v1alpha1/meshspec.go create mode 100644 applyconfiguration/apisx/v1alpha1/meshstatus.go create mode 100644 applyconfiguration/apisx/v1alpha1/xmesh.go create mode 100644 config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml create mode 100644 pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_xmesh.go create mode 100644 pkg/client/clientset/versioned/typed/apisx/v1alpha1/xmesh.go create mode 100644 pkg/client/informers/externalversions/apisx/v1alpha1/xmesh.go create mode 100644 pkg/client/listers/apisx/v1alpha1/xmesh.go diff --git a/apisx/v1alpha1/xmesh_types.go b/apisx/v1alpha1/xmesh_types.go new file mode 100644 index 0000000000..aa622df5bf --- /dev/null +++ b/apisx/v1alpha1/xmesh_types.go @@ -0,0 +1,183 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,scope=Cluster,shortName=mesh +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// XMesh defines mesh-wide characteristics of a GAMMA-compliant service mesh. +type XMesh struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of XMesh. + // +required + Spec MeshSpec `json:"spec"` + + // Status defines the current state of XMesh. + // + // + // Implementations MUST populate status on all Mesh resources which + // specify their controller name. + // + // + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +optional + Status MeshStatus `json:"status,omitempty"` +} + +// MeshSpec defines the desired state of an XMesh. +type MeshSpec struct { + // ControllerName is the name of a controller that is managing Gateway API + // resources for mesh traffic management. The value of this field MUST be a + // domain prefixed path. + // + // Example: "example.com/awesome-mesh". + // + // This field is not mutable and cannot be empty. + // + // Support: Core + // + // +kubebuilder:validation:XValidation:message="Value is immutable",rule="self == oldSelf" + // +required + ControllerName gatewayapiv1.GatewayController `json:"controllerName"` + + // ParametersRef is an optional reference to a resource that contains + // implementation-specific configuration for this Mesh. If no + // implementation-specific parameters are needed, this field MUST be + // omitted. + // + // ParametersRef can reference a standard Kubernetes resource, i.e. + // ConfigMap, or an implementation-specific custom resource. The resource + // can be cluster-scoped or namespace-scoped. + // + // If the referent cannot be found, refers to an unsupported kind, or when + // the data within that resource is malformed, the Mesh MUST be rejected + // with the "Accepted" status condition set to "False" and an + // "InvalidParameters" reason. + // + // Support: Implementation-specific + // + // +optional + ParametersRef *gatewayapiv1.ParametersReference `json:"parametersRef,omitempty"` + + // Description optionally provides a human-readable description of a Mesh. + // + // +kubebuilder:validation:MaxLength=64 + // +optional + Description *string `json:"description,omitempty"` +} + +// MeshConditionType is the type for status conditions on Mesh resources. +// This type should be used with the MeshStatus.Conditions field. +type MeshConditionType string + +// MeshConditionReason defines the set of reasons that explain why a +// particular Mesh condition type has been raised. +type MeshConditionReason string + +const ( + // The "Accepted" condition indicates whether the Mesh has been accepted + // by the controller requested in the `spec.controllerName` field. + // + // This condition defaults to Unknown, and MUST be set by a controller + // when it sees a Mesh using its controller string. The status of this + // condition MUST be set to True if the controller will accept the Mesh + // resource. Otherwise, this status MUST be set to False. If the status is + // set to False, the controller MUST set a Message and Reason as an + // explanation. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidParameters" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // + // Controllers should prefer to use the values of MeshConditionReason for + // the corresponding Reason, where appropriate. + MeshConditionAccepted MeshConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // true. + MeshReasonAccepted MeshConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the Mesh was not + // accepted because the parametersRef field refers to + // + // * a namespaced resource but the Namespace field is not set, or + // * a cluster-scoped resource but the Namespace field is set, or + // * a nonexistent object, or + // * an unsupported resource or kind, or + // * an existing resource but the data within that resource is malformed. + MeshReasonInvalidParameters MeshConditionReason = "InvalidParameters" + + // This reason is used with the "Accepted" condition when the status is + // "Unknown" and the requested controller has not yet made a decision + // about whether to accept the Mesh. It is the default Reason on a new + // Mesh. + MeshReasonPending MeshConditionReason = "Pending" +) + +// MeshStatus is the current status for the Mesh. +type MeshStatus struct { + // Conditions is the current status from the controller for + // this Mesh. + // + // Controllers should prefer to publish conditions using values + // of MeshConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // SupportedFeatures is the set of features the Mesh support. + // It MUST be sorted in ascending alphabetical order by the Name key. + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + SupportedFeatures []gatewayapiv1.SupportedFeature `json:"supportedFeatures,omitempty"` +} + +// +kubebuilder:object:root=true +type XMeshList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []XMesh `json:"items"` +} diff --git a/apisx/v1alpha1/zz_generated.deepcopy.go b/apisx/v1alpha1/zz_generated.deepcopy.go index 802d371927..d8bc7aa83c 100644 --- a/apisx/v1alpha1/zz_generated.deepcopy.go +++ b/apisx/v1alpha1/zz_generated.deepcopy.go @@ -23,6 +23,7 @@ package v1alpha1 import ( "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -193,6 +194,58 @@ func (in *ListenerSetStatus) DeepCopy() *ListenerSetStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshSpec) DeepCopyInto(out *MeshSpec) { + *out = *in + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(apisv1.ParametersReference) + (*in).DeepCopyInto(*out) + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshSpec. +func (in *MeshSpec) DeepCopy() *MeshSpec { + if in == nil { + return nil + } + out := new(MeshSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshStatus) DeepCopyInto(out *MeshStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SupportedFeatures != nil { + in, out := &in.SupportedFeatures, &out.SupportedFeatures + *out = make([]apisv1.SupportedFeature, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshStatus. +func (in *MeshStatus) DeepCopy() *MeshStatus { + if in == nil { + return nil + } + out := new(MeshStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ParentGatewayReference) DeepCopyInto(out *ParentGatewayReference) { *out = *in @@ -390,3 +443,62 @@ func (in *XListenerSetList) DeepCopyObject() runtime.Object { } return nil } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XMesh) DeepCopyInto(out *XMesh) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XMesh. +func (in *XMesh) DeepCopy() *XMesh { + if in == nil { + return nil + } + out := new(XMesh) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *XMesh) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XMeshList) DeepCopyInto(out *XMeshList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]XMesh, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XMeshList. +func (in *XMeshList) DeepCopy() *XMeshList { + if in == nil { + return nil + } + out := new(XMeshList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *XMeshList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/apisx/v1alpha1/zz_generated.register.go b/apisx/v1alpha1/zz_generated.register.go index fc131e21ff..c3822b2cad 100644 --- a/apisx/v1alpha1/zz_generated.register.go +++ b/apisx/v1alpha1/zz_generated.register.go @@ -65,6 +65,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &XBackendTrafficPolicyList{}, &XListenerSet{}, &XListenerSetList{}, + &XMesh{}, + &XMeshList{}, ) // AddToGroupVersion allows the serialization of client types like ListOptions. v1.AddToGroupVersion(scheme, SchemeGroupVersion) diff --git a/applyconfiguration/apisx/v1alpha1/meshspec.go b/applyconfiguration/apisx/v1alpha1/meshspec.go new file mode 100644 index 0000000000..df9d3ef8b1 --- /dev/null +++ b/applyconfiguration/apisx/v1alpha1/meshspec.go @@ -0,0 +1,62 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "sigs.k8s.io/gateway-api/apis/v1" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" +) + +// MeshSpecApplyConfiguration represents a declarative configuration of the MeshSpec type for use +// with apply. +type MeshSpecApplyConfiguration struct { + ControllerName *v1.GatewayController `json:"controllerName,omitempty"` + ParametersRef *apisv1.ParametersReferenceApplyConfiguration `json:"parametersRef,omitempty"` + Description *string `json:"description,omitempty"` +} + +// MeshSpecApplyConfiguration constructs a declarative configuration of the MeshSpec type for use with +// apply. +func MeshSpec() *MeshSpecApplyConfiguration { + return &MeshSpecApplyConfiguration{} +} + +// WithControllerName sets the ControllerName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ControllerName field is set to the value of the last call. +func (b *MeshSpecApplyConfiguration) WithControllerName(value v1.GatewayController) *MeshSpecApplyConfiguration { + b.ControllerName = &value + return b +} + +// WithParametersRef sets the ParametersRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ParametersRef field is set to the value of the last call. +func (b *MeshSpecApplyConfiguration) WithParametersRef(value *apisv1.ParametersReferenceApplyConfiguration) *MeshSpecApplyConfiguration { + b.ParametersRef = value + return b +} + +// WithDescription sets the Description field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Description field is set to the value of the last call. +func (b *MeshSpecApplyConfiguration) WithDescription(value string) *MeshSpecApplyConfiguration { + b.Description = &value + return b +} diff --git a/applyconfiguration/apisx/v1alpha1/meshstatus.go b/applyconfiguration/apisx/v1alpha1/meshstatus.go new file mode 100644 index 0000000000..fd1f9f9ecc --- /dev/null +++ b/applyconfiguration/apisx/v1alpha1/meshstatus.go @@ -0,0 +1,63 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/client-go/applyconfigurations/meta/v1" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" +) + +// MeshStatusApplyConfiguration represents a declarative configuration of the MeshStatus type for use +// with apply. +type MeshStatusApplyConfiguration struct { + Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"` + SupportedFeatures []apisv1.SupportedFeatureApplyConfiguration `json:"supportedFeatures,omitempty"` +} + +// MeshStatusApplyConfiguration constructs a declarative configuration of the MeshStatus type for use with +// apply. +func MeshStatus() *MeshStatusApplyConfiguration { + return &MeshStatusApplyConfiguration{} +} + +// WithConditions adds the given value to the Conditions field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Conditions field. +func (b *MeshStatusApplyConfiguration) WithConditions(values ...*v1.ConditionApplyConfiguration) *MeshStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithConditions") + } + b.Conditions = append(b.Conditions, *values[i]) + } + return b +} + +// WithSupportedFeatures adds the given value to the SupportedFeatures field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SupportedFeatures field. +func (b *MeshStatusApplyConfiguration) WithSupportedFeatures(values ...*apisv1.SupportedFeatureApplyConfiguration) *MeshStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSupportedFeatures") + } + b.SupportedFeatures = append(b.SupportedFeatures, *values[i]) + } + return b +} diff --git a/applyconfiguration/apisx/v1alpha1/xmesh.go b/applyconfiguration/apisx/v1alpha1/xmesh.go new file mode 100644 index 0000000000..ca4dfe78a9 --- /dev/null +++ b/applyconfiguration/apisx/v1alpha1/xmesh.go @@ -0,0 +1,279 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" + apisxv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" + internal "sigs.k8s.io/gateway-api/applyconfiguration/internal" +) + +// XMeshApplyConfiguration represents a declarative configuration of the XMesh type for use +// with apply. +type XMeshApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *MeshSpecApplyConfiguration `json:"spec,omitempty"` + Status *MeshStatusApplyConfiguration `json:"status,omitempty"` +} + +// XMesh constructs a declarative configuration of the XMesh type for use with +// apply. +func XMesh(name string) *XMeshApplyConfiguration { + b := &XMeshApplyConfiguration{} + b.WithName(name) + b.WithKind("XMesh") + b.WithAPIVersion("gateway.networking.x-k8s.io/v1alpha1") + return b +} + +// ExtractXMesh extracts the applied configuration owned by fieldManager from +// xMesh. If no managedFields are found in xMesh for fieldManager, a +// XMeshApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// xMesh must be a unmodified XMesh API object that was retrieved from the Kubernetes API. +// ExtractXMesh provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractXMesh(xMesh *apisxv1alpha1.XMesh, fieldManager string) (*XMeshApplyConfiguration, error) { + return extractXMesh(xMesh, fieldManager, "") +} + +// ExtractXMeshStatus is the same as ExtractXMesh except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractXMeshStatus(xMesh *apisxv1alpha1.XMesh, fieldManager string) (*XMeshApplyConfiguration, error) { + return extractXMesh(xMesh, fieldManager, "status") +} + +func extractXMesh(xMesh *apisxv1alpha1.XMesh, fieldManager string, subresource string) (*XMeshApplyConfiguration, error) { + b := &XMeshApplyConfiguration{} + err := managedfields.ExtractInto(xMesh, internal.Parser().Type("io.k8s.sigs.gateway-api.apisx.v1alpha1.XMesh"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(xMesh.Name) + + b.WithKind("XMesh") + b.WithAPIVersion("gateway.networking.x-k8s.io/v1alpha1") + return b, nil +} +func (b XMeshApplyConfiguration) IsApplyConfiguration() {} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithKind(value string) *XMeshApplyConfiguration { + b.TypeMetaApplyConfiguration.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithAPIVersion(value string) *XMeshApplyConfiguration { + b.TypeMetaApplyConfiguration.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithName(value string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithGenerateName(value string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithNamespace(value string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithUID(value types.UID) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithResourceVersion(value string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithGeneration(value int64) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithCreationTimestamp(value metav1.Time) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *XMeshApplyConfiguration) WithLabels(entries map[string]string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *XMeshApplyConfiguration) WithAnnotations(entries map[string]string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *XMeshApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *XMeshApplyConfiguration) WithFinalizers(values ...string) *XMeshApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i]) + } + return b +} + +func (b *XMeshApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithSpec(value *MeshSpecApplyConfiguration) *XMeshApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *XMeshApplyConfiguration) WithStatus(value *MeshStatusApplyConfiguration) *XMeshApplyConfiguration { + b.Status = value + return b +} + +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *XMeshApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *XMeshApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *XMeshApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Name +} + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *XMeshApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 131b10d81d..7fa1b6bfb5 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -1961,6 +1961,38 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name +- name: io.k8s.sigs.gateway-api.apisx.v1alpha1.MeshSpec + map: + fields: + - name: controllerName + type: + scalar: string + default: "" + - name: description + type: + scalar: string + - name: parametersRef + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.ParametersReference +- name: io.k8s.sigs.gateway-api.apisx.v1alpha1.MeshStatus + map: + fields: + - name: conditions + type: + list: + elementType: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Condition + elementRelationship: associative + keys: + - type + - name: supportedFeatures + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.SupportedFeature + elementRelationship: associative + keys: + - name - name: io.k8s.sigs.gateway-api.apisx.v1alpha1.ParentGatewayReference map: fields: @@ -2037,6 +2069,27 @@ var schemaYAML = typed.YAMLObject(`types: type: namedType: io.k8s.sigs.gateway-api.apisx.v1alpha1.ListenerSetStatus default: {} +- name: io.k8s.sigs.gateway-api.apisx.v1alpha1.XMesh + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.sigs.gateway-api.apisx.v1alpha1.MeshSpec + default: {} + - name: status + type: + namedType: io.k8s.sigs.gateway-api.apisx.v1alpha1.MeshStatus + default: {} - name: __untyped_atomic_ scalar: untyped list: diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 06ea379351..31bed767a5 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -262,6 +262,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisxv1alpha1.ListenerSetSpecApplyConfiguration{} case v1alpha1.SchemeGroupVersion.WithKind("ListenerSetStatus"): return &apisxv1alpha1.ListenerSetStatusApplyConfiguration{} + case v1alpha1.SchemeGroupVersion.WithKind("MeshSpec"): + return &apisxv1alpha1.MeshSpecApplyConfiguration{} + case v1alpha1.SchemeGroupVersion.WithKind("MeshStatus"): + return &apisxv1alpha1.MeshStatusApplyConfiguration{} case v1alpha1.SchemeGroupVersion.WithKind("ParentGatewayReference"): return &apisxv1alpha1.ParentGatewayReferenceApplyConfiguration{} case v1alpha1.SchemeGroupVersion.WithKind("RequestRate"): @@ -272,6 +276,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisxv1alpha1.XBackendTrafficPolicyApplyConfiguration{} case v1alpha1.SchemeGroupVersion.WithKind("XListenerSet"): return &apisxv1alpha1.XListenerSetApplyConfiguration{} + case v1alpha1.SchemeGroupVersion.WithKind("XMesh"): + return &apisxv1alpha1.XMeshApplyConfiguration{} } return nil diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml new file mode 100644 index 0000000000..ef8e4024ed --- /dev/null +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml @@ -0,0 +1,248 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/channel: experimental + name: xmeshes.gateway.networking.x-k8s.io +spec: + group: gateway.networking.x-k8s.io + names: + categories: + - gateway-api + kind: XMesh + listKind: XMeshList + plural: xmeshes + shortNames: + - mesh + singular: xmesh + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: XMesh defines mesh-wide characteristics of a GAMMA-compliant + service mesh. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of XMesh. + properties: + controllerName: + description: |- + ControllerName is the name of a controller that is managing Gateway API + resources for mesh traffic management. The value of this field MUST be a + domain prefixed path. + + Example: "example.com/awesome-mesh". + + This field is not mutable and cannot be empty. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description optionally provides a human-readable description + of a Mesh. + maxLength: 64 + type: string + parametersRef: + description: |- + ParametersRef is an optional reference to a resource that contains + implementation-specific configuration for this Mesh. If no + implementation-specific parameters are needed, this field MUST be + omitted. + + ParametersRef can reference a standard Kubernetes resource, i.e. + ConfigMap, or an implementation-specific custom resource. The resource + can be cluster-scoped or namespace-scoped. + + If the referent cannot be found, refers to an unsupported kind, or when + the data within that resource is malformed, the Mesh MUST be rejected + with the "Accepted" status condition set to "False" and an + "InvalidParameters" reason. + + Support: Implementation-specific + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. + This field is required when referring to a Namespace-scoped resource and + MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: Status defines the current state of XMesh. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: |- + Conditions is the current status from the controller for + this Mesh. + + Controllers should prefer to publish conditions using values + of MeshConditionType for the type of each Condition. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedFeatures: + description: |- + SupportedFeatures is the set of features the Mesh support. + It MUST be sorted in ascending alphabetical order by the Name key. + items: + properties: + name: + description: |- + FeatureName is used to describe distinct features that are covered by + conformance tests. + type: string + required: + - name + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/geps/gep-3949/index.md b/geps/gep-3949/index.md index 26f5f2056c..eddb161102 100644 --- a/geps/gep-3949/index.md +++ b/geps/gep-3949/index.md @@ -208,8 +208,8 @@ status: ... supportedFeatures: # List of SupportedFeature - - name: MeshHTTPRoute - name: MeshConsumerRoute + - name: MeshHTTPRoute - name: OffClusterGateway ... ``` @@ -358,7 +358,8 @@ without requiring the mesh to be restarted. ### API Type Definitions ```go -// Mesh is a Cluster level resource. +// Mesh defines mesh-wide characteristics of a GAMMA-compliant service mesh. +// It is a cluster-scoped resource. type Mesh struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -406,6 +407,12 @@ type MeshSpec struct { // // +optional ParametersRef *ParametersReference `json:"parametersRef,omitempty"` + + // Description optionally provides a human-readable description of a Mesh. + // + // +kubebuilder:validation:MaxLength=64 + // +optional + Description *string `json:"description,omitempty"` } // MeshConditionType is the type for status conditions on Mesh resources. @@ -417,8 +424,8 @@ type MeshConditionType string type MeshConditionReason string const ( - // This condition indicates whether the Mesh has been accepted by the - // controller requested in the `spec.controller` field. + // The "Accepted" condition indicates whether the Mesh has been accepted + // by the controller requested in the `spec.controllerName` field. // // This condition defaults to Unknown, and MUST be set by a controller // when it sees a Mesh using its controller string. The status of this @@ -435,27 +442,33 @@ const ( // // * "InvalidParameters" // + // Possible reasons for this condition to be Unknown are: + // + // * "Pending" + // // Controllers should prefer to use the values of MeshConditionReason // for the corresponding Reason, where appropriate. - MeshConditionStatusAccepted MeshConditionType = "Accepted" + MeshConditionAccepted MeshConditionType = "Accepted" // This reason is used with the "Accepted" condition when the condition is // true. - MeshConditionReasonAccepted MeshConditionReason = "Accepted" + MeshReasonAccepted MeshConditionReason = "Accepted" // This reason is used with the "Accepted" condition when the Mesh // was not accepted because the parametersRef field refers to + // // * a namespaced resource but the Namespace field is not set, or // * a cluster-scoped resource but the Namespace field is set, or // * a nonexistent object, or // * an unsupported resource or kind, or // * an existing resource but the data within that resource is malformed. - MeshConditionReasonInvalidParameters MeshConditionReason = "InvalidParameters" + MeshReasonInvalidParameters MeshConditionReason = "InvalidParameters" - // This reason is used with the "Accepted" condition when the - // requested controller has not yet made a decision about whether - // to accept the Mesh. It is the default Reason on a new Mesh. - MeshConditionReasonPending MeshConditionReason = "Pending" + // This reason is used with the "Accepted" condition when the status is + // "Unknown" and the requested controller has not yet made a decision + // about whether to accept the Mesh. It is the default Reason on a new + // Mesh. + MeshReasonPending MeshConditionReason = "Pending" ) // MeshStatus is the current status for the Mesh. diff --git a/hack/update-protos.sh b/hack/update-protos.sh index 02828dbe19..51d8348414 100755 --- a/hack/update-protos.sh +++ b/hack/update-protos.sh @@ -87,7 +87,7 @@ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 (cd conformance/echo-basic && \ - export PATH="$PATH:$GOPATH/bin" && \ + export PATH="$PATH:$(go env GOPATH)/bin" && \ "${PROTOC_BINARY}" --go_out=grpcechoserver --go_opt=paths=source_relative \ --go-grpc_out=grpcechoserver --go-grpc_opt=paths=source_relative \ grpcecho.proto diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go index 234356e48e..c17563fe2f 100644 --- a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/apisx_client.go @@ -30,6 +30,7 @@ type ExperimentalV1alpha1Interface interface { RESTClient() rest.Interface XBackendTrafficPoliciesGetter XListenerSetsGetter + XMeshesGetter } // ExperimentalV1alpha1Client is used to interact with features provided by the gateway.networking.x-k8s.io group. @@ -45,6 +46,10 @@ func (c *ExperimentalV1alpha1Client) XListenerSets(namespace string) XListenerSe return newXListenerSets(c, namespace) } +func (c *ExperimentalV1alpha1Client) XMeshes() XMeshInterface { + return newXMeshes(c) +} + // NewForConfig creates a new ExperimentalV1alpha1Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_apisx_client.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_apisx_client.go index 962c5f3e69..0aa7a3c8cd 100644 --- a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_apisx_client.go +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_apisx_client.go @@ -36,6 +36,10 @@ func (c *FakeExperimentalV1alpha1) XListenerSets(namespace string) v1alpha1.XLis return newFakeXListenerSets(c, namespace) } +func (c *FakeExperimentalV1alpha1) XMeshes() v1alpha1.XMeshInterface { + return newFakeXMeshes(c) +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeExperimentalV1alpha1) RESTClient() rest.Interface { diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_xmesh.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_xmesh.go new file mode 100644 index 0000000000..408eb3b017 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/fake/fake_xmesh.go @@ -0,0 +1,49 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + gentype "k8s.io/client-go/gentype" + v1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" + apisxv1alpha1 "sigs.k8s.io/gateway-api/applyconfiguration/apisx/v1alpha1" + typedapisxv1alpha1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apisx/v1alpha1" +) + +// fakeXMeshes implements XMeshInterface +type fakeXMeshes struct { + *gentype.FakeClientWithListAndApply[*v1alpha1.XMesh, *v1alpha1.XMeshList, *apisxv1alpha1.XMeshApplyConfiguration] + Fake *FakeExperimentalV1alpha1 +} + +func newFakeXMeshes(fake *FakeExperimentalV1alpha1) typedapisxv1alpha1.XMeshInterface { + return &fakeXMeshes{ + gentype.NewFakeClientWithListAndApply[*v1alpha1.XMesh, *v1alpha1.XMeshList, *apisxv1alpha1.XMeshApplyConfiguration]( + fake.Fake, + "", + v1alpha1.SchemeGroupVersion.WithResource("xmeshes"), + v1alpha1.SchemeGroupVersion.WithKind("XMesh"), + func() *v1alpha1.XMesh { return &v1alpha1.XMesh{} }, + func() *v1alpha1.XMeshList { return &v1alpha1.XMeshList{} }, + func(dst, src *v1alpha1.XMeshList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha1.XMeshList) []*v1alpha1.XMesh { return gentype.ToPointerSlice(list.Items) }, + func(list *v1alpha1.XMeshList, items []*v1alpha1.XMesh) { list.Items = gentype.FromPointerSlice(items) }, + ), + fake, + } +} diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/generated_expansion.go index bf328780da..9abb54c1d7 100644 --- a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/generated_expansion.go @@ -21,3 +21,5 @@ package v1alpha1 type XBackendTrafficPolicyExpansion interface{} type XListenerSetExpansion interface{} + +type XMeshExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/apisx/v1alpha1/xmesh.go b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/xmesh.go new file mode 100644 index 0000000000..ffb85545d3 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apisx/v1alpha1/xmesh.go @@ -0,0 +1,74 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + apisxv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" + applyconfigurationapisxv1alpha1 "sigs.k8s.io/gateway-api/applyconfiguration/apisx/v1alpha1" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// XMeshesGetter has a method to return a XMeshInterface. +// A group's client should implement this interface. +type XMeshesGetter interface { + XMeshes() XMeshInterface +} + +// XMeshInterface has methods to work with XMesh resources. +type XMeshInterface interface { + Create(ctx context.Context, xMesh *apisxv1alpha1.XMesh, opts v1.CreateOptions) (*apisxv1alpha1.XMesh, error) + Update(ctx context.Context, xMesh *apisxv1alpha1.XMesh, opts v1.UpdateOptions) (*apisxv1alpha1.XMesh, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, xMesh *apisxv1alpha1.XMesh, opts v1.UpdateOptions) (*apisxv1alpha1.XMesh, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*apisxv1alpha1.XMesh, error) + List(ctx context.Context, opts v1.ListOptions) (*apisxv1alpha1.XMeshList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apisxv1alpha1.XMesh, err error) + Apply(ctx context.Context, xMesh *applyconfigurationapisxv1alpha1.XMeshApplyConfiguration, opts v1.ApplyOptions) (result *apisxv1alpha1.XMesh, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, xMesh *applyconfigurationapisxv1alpha1.XMeshApplyConfiguration, opts v1.ApplyOptions) (result *apisxv1alpha1.XMesh, err error) + XMeshExpansion +} + +// xMeshes implements XMeshInterface +type xMeshes struct { + *gentype.ClientWithListAndApply[*apisxv1alpha1.XMesh, *apisxv1alpha1.XMeshList, *applyconfigurationapisxv1alpha1.XMeshApplyConfiguration] +} + +// newXMeshes returns a XMeshes +func newXMeshes(c *ExperimentalV1alpha1Client) *xMeshes { + return &xMeshes{ + gentype.NewClientWithListAndApply[*apisxv1alpha1.XMesh, *apisxv1alpha1.XMeshList, *applyconfigurationapisxv1alpha1.XMeshApplyConfiguration]( + "xmeshes", + c.RESTClient(), + scheme.ParameterCodec, + "", + func() *apisxv1alpha1.XMesh { return &apisxv1alpha1.XMesh{} }, + func() *apisxv1alpha1.XMeshList { return &apisxv1alpha1.XMeshList{} }, + ), + } +} diff --git a/pkg/client/informers/externalversions/apisx/v1alpha1/interface.go b/pkg/client/informers/externalversions/apisx/v1alpha1/interface.go index 9d995d4230..768b081813 100644 --- a/pkg/client/informers/externalversions/apisx/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/apisx/v1alpha1/interface.go @@ -28,6 +28,8 @@ type Interface interface { XBackendTrafficPolicies() XBackendTrafficPolicyInformer // XListenerSets returns a XListenerSetInformer. XListenerSets() XListenerSetInformer + // XMeshes returns a XMeshInformer. + XMeshes() XMeshInformer } type version struct { @@ -50,3 +52,8 @@ func (v *version) XBackendTrafficPolicies() XBackendTrafficPolicyInformer { func (v *version) XListenerSets() XListenerSetInformer { return &xListenerSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// XMeshes returns a XMeshInformer. +func (v *version) XMeshes() XMeshInformer { + return &xMeshInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/apisx/v1alpha1/xmesh.go b/pkg/client/informers/externalversions/apisx/v1alpha1/xmesh.go new file mode 100644 index 0000000000..35d1253afc --- /dev/null +++ b/pkg/client/informers/externalversions/apisx/v1alpha1/xmesh.go @@ -0,0 +1,101 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + gatewayapiapisxv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + apisxv1alpha1 "sigs.k8s.io/gateway-api/pkg/client/listers/apisx/v1alpha1" +) + +// XMeshInformer provides access to a shared informer and lister for +// XMeshes. +type XMeshInformer interface { + Informer() cache.SharedIndexInformer + Lister() apisxv1alpha1.XMeshLister +} + +type xMeshInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewXMeshInformer constructs a new informer for XMesh type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewXMeshInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredXMeshInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredXMeshInformer constructs a new informer for XMesh type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredXMeshInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XMeshes().List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XMeshes().Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XMeshes().List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExperimentalV1alpha1().XMeshes().Watch(ctx, options) + }, + }, + &gatewayapiapisxv1alpha1.XMesh{}, + resyncPeriod, + indexers, + ) +} + +func (f *xMeshInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredXMeshInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *xMeshInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&gatewayapiapisxv1alpha1.XMesh{}, f.defaultInformer) +} + +func (f *xMeshInformer) Lister() apisxv1alpha1.XMeshLister { + return apisxv1alpha1.NewXMeshLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index b777993d4e..e3f00492ba 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -99,6 +99,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Experimental().V1alpha1().XBackendTrafficPolicies().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("xlistenersets"): return &genericInformer{resource: resource.GroupResource(), informer: f.Experimental().V1alpha1().XListenerSets().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("xmeshes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Experimental().V1alpha1().XMeshes().Informer()}, nil } diff --git a/pkg/client/listers/apisx/v1alpha1/expansion_generated.go b/pkg/client/listers/apisx/v1alpha1/expansion_generated.go index c136f6587a..bc7d9e3372 100644 --- a/pkg/client/listers/apisx/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/apisx/v1alpha1/expansion_generated.go @@ -33,3 +33,7 @@ type XListenerSetListerExpansion interface{} // XListenerSetNamespaceListerExpansion allows custom methods to be added to // XListenerSetNamespaceLister. type XListenerSetNamespaceListerExpansion interface{} + +// XMeshListerExpansion allows custom methods to be added to +// XMeshLister. +type XMeshListerExpansion interface{} diff --git a/pkg/client/listers/apisx/v1alpha1/xmesh.go b/pkg/client/listers/apisx/v1alpha1/xmesh.go new file mode 100644 index 0000000000..8ef01deba6 --- /dev/null +++ b/pkg/client/listers/apisx/v1alpha1/xmesh.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" + apisxv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" +) + +// XMeshLister helps list XMeshes. +// All objects returned here must be treated as read-only. +type XMeshLister interface { + // List lists all XMeshes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apisxv1alpha1.XMesh, err error) + // Get retrieves the XMesh from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*apisxv1alpha1.XMesh, error) + XMeshListerExpansion +} + +// xMeshLister implements the XMeshLister interface. +type xMeshLister struct { + listers.ResourceIndexer[*apisxv1alpha1.XMesh] +} + +// NewXMeshLister returns a new XMeshLister. +func NewXMeshLister(indexer cache.Indexer) XMeshLister { + return &xMeshLister{listers.New[*apisxv1alpha1.XMesh](indexer, apisxv1alpha1.Resource("xmesh"))} +} diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index dd27f75ee5..d884aef0c7 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -206,6 +206,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apisx/v1alpha1.ListenerEntryStatus": schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntryStatus(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.ListenerSetSpec": schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerSetSpec(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.ListenerSetStatus": schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerSetStatus(ref), + "sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshSpec": schema_sigsk8sio_gateway_api_apisx_v1alpha1_MeshSpec(ref), + "sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshStatus": schema_sigsk8sio_gateway_api_apisx_v1alpha1_MeshStatus(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.ParentGatewayReference": schema_sigsk8sio_gateway_api_apisx_v1alpha1_ParentGatewayReference(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.RequestRate": schema_sigsk8sio_gateway_api_apisx_v1alpha1_RequestRate(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.RetryConstraint": schema_sigsk8sio_gateway_api_apisx_v1alpha1_RetryConstraint(ref), @@ -213,6 +215,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apisx/v1alpha1.XBackendTrafficPolicyList": schema_sigsk8sio_gateway_api_apisx_v1alpha1_XBackendTrafficPolicyList(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.XListenerSet": schema_sigsk8sio_gateway_api_apisx_v1alpha1_XListenerSet(ref), "sigs.k8s.io/gateway-api/apisx/v1alpha1.XListenerSetList": schema_sigsk8sio_gateway_api_apisx_v1alpha1_XListenerSetList(ref), + "sigs.k8s.io/gateway-api/apisx/v1alpha1.XMesh": schema_sigsk8sio_gateway_api_apisx_v1alpha1_XMesh(ref), + "sigs.k8s.io/gateway-api/apisx/v1alpha1.XMeshList": schema_sigsk8sio_gateway_api_apisx_v1alpha1_XMeshList(ref), } } @@ -8712,6 +8716,101 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerSetStatus(ref common.Re } } +func schema_sigsk8sio_gateway_api_apisx_v1alpha1_MeshSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MeshSpec defines the desired state of an XMesh.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "controllerName": { + SchemaProps: spec.SchemaProps{ + Description: "ControllerName is the name of a controller that is managing Gateway API resources for mesh traffic management. The value of this field MUST be a domain prefixed path.\n\nExample: \"example.com/awesome-mesh\".\n\nThis field is not mutable and cannot be empty.\n\nSupport: Core", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "parametersRef": { + SchemaProps: spec.SchemaProps{ + Description: "ParametersRef is an optional reference to a resource that contains implementation-specific configuration for this Mesh. If no implementation-specific parameters are needed, this field MUST be omitted.\n\nParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped.\n\nIf the referent cannot be found, refers to an unsupported kind, or when the data within that resource is malformed, the Mesh MUST be rejected with the \"Accepted\" status condition set to \"False\" and an \"InvalidParameters\" reason.\n\nSupport: Implementation-specific", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ParametersReference"), + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Description: "Description optionally provides a human-readable description of a Mesh.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"controllerName"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.ParametersReference"}, + } +} + +func schema_sigsk8sio_gateway_api_apisx_v1alpha1_MeshStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MeshStatus is the current status for the Mesh.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "conditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "type", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Conditions is the current status from the controller for this Mesh.\n\nControllers should prefer to publish conditions using values of MeshConditionType for the type of each Condition.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Condition"), + }, + }, + }, + }, + }, + "supportedFeatures": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "name", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "SupportedFeatures is the set of features the Mesh support. It MUST be sorted in ascending alphabetical order by the Name key.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.SupportedFeature"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "sigs.k8s.io/gateway-api/apis/v1.SupportedFeature"}, + } +} + func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ParentGatewayReference(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -9005,3 +9104,101 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XListenerSetList(ref common.Ref "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "sigs.k8s.io/gateway-api/apisx/v1alpha1.XListenerSet"}, } } + +func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XMesh(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "XMesh defines mesh-wide characteristics of a GAMMA-compliant service mesh.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec defines the desired state of XMesh.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status defines the current state of XMesh.\n\n Implementations MUST populate status on all Mesh resources which specify their controller name. ", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshSpec", "sigs.k8s.io/gateway-api/apisx/v1alpha1.MeshStatus"}, + } +} + +func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XMeshList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apisx/v1alpha1.XMesh"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "sigs.k8s.io/gateway-api/apisx/v1alpha1.XMesh"}, + } +} From 54dc773949cfd87362d5fdf4cd9549493a392004 Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Thu, 4 Sep 2025 00:15:15 +0200 Subject: [PATCH 169/224] Add default test timeout to udproute and improve logs (#4027) Signed-off-by: Karol Szwaj --- conformance/tests/udproute-simple.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/conformance/tests/udproute-simple.go b/conformance/tests/udproute-simple.go index 8945d3fead..defc1201ec 100644 --- a/conformance/tests/udproute-simple.go +++ b/conformance/tests/udproute-simple.go @@ -27,6 +27,7 @@ import ( "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/tlog" "sigs.k8s.io/gateway-api/pkg/features" ) @@ -53,15 +54,15 @@ var UDPRouteTest = suite.ConformanceTest{ msg := new(dns.Msg) msg.SetQuestion(domain, dns.TypeA) - - if err := wait.PollUntilContextTimeout(context.TODO(), time.Second, time.Minute, true, + tlog.Logf(t, "performing DNS query %s on %s", domain, gwAddr) + if err := wait.PollUntilContextTimeout(context.TODO(), time.Second, suite.TimeoutConfig.DefaultTestTimeout, true, func(_ context.Context) (done bool, err error) { - t.Logf("performing DNS query %s on %s", domain, gwAddr) - _, err = dns.Exchange(msg, gwAddr) + r, err := dns.Exchange(msg, gwAddr) if err != nil { - t.Logf("failed to perform a UDP query: %v", err) + tlog.Logf(t, "failed to perform a UDP query: %v", err) return false, nil } + tlog.Logf(t, "got DNS response: %s", r.String()) return true, nil }); err != nil { t.Errorf("failed to perform DNS query: %v", err) From aa3208f81966125b032e9ba27bea31234004d8e3 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Thu, 4 Sep 2025 10:53:13 +1000 Subject: [PATCH 170/224] Update gRPC Auth config (#4061) Update gRPC Auth config so that, if no headers are specified in `allowedHeaders`, _all_ headers must be sent rather than a specific list. Signed-off-by: Nick Young --- apis/v1/httproute_types.go | 8 +---- .../gateway.networking.k8s.io_httproutes.yaml | 32 +++---------------- pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 5dad01e00a..3d89af0da7 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1665,13 +1665,7 @@ type GRPCAuthConfig struct { // AllowedRequestHeaders specifies what headers from the client request // will be sent to the authorization server. // - // If this list is empty, then the following headers must be sent: - // - // - `Authorization` - // - `Location` - // - `Proxy-Authenticate` - // - `Set-Cookie` - // - `WWW-Authenticate` + // If this list is empty, then all headers must be sent. // // If the list has entries, only those entries must be sent. // diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 9170ad2aa4..8734186cf9 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -910,13 +910,7 @@ spec: AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server. - If this list is empty, then the following headers must be sent: - - - `Authorization` - - `Location` - - `Proxy-Authenticate` - - `Set-Cookie` - - `WWW-Authenticate` + If this list is empty, then all headers must be sent. If the list has entries, only those entries must be sent. items: @@ -2396,13 +2390,7 @@ spec: AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server. - If this list is empty, then the following headers must be sent: - - - `Authorization` - - `Location` - - `Proxy-Authenticate` - - `Set-Cookie` - - `WWW-Authenticate` + If this list is empty, then all headers must be sent. If the list has entries, only those entries must be sent. items: @@ -5062,13 +5050,7 @@ spec: AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server. - If this list is empty, then the following headers must be sent: - - - `Authorization` - - `Location` - - `Proxy-Authenticate` - - `Set-Cookie` - - `WWW-Authenticate` + If this list is empty, then all headers must be sent. If the list has entries, only those entries must be sent. items: @@ -6548,13 +6530,7 @@ spec: AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server. - If this list is empty, then the following headers must be sent: - - - `Authorization` - - `Location` - - `Proxy-Authenticate` - - `Set-Cookie` - - `WWW-Authenticate` + If this list is empty, then all headers must be sent. If the list has entries, only those entries must be sent. items: diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index d884aef0c7..c21063d36e 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3220,7 +3220,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCAuthConfig(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server.\n\nIf this list is empty, then the following headers must be sent:\n\n- `Authorization` - `Location` - `Proxy-Authenticate` - `Set-Cookie` - `WWW-Authenticate`\n\nIf the list has entries, only those entries must be sent.", + Description: "AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server.\n\nIf this list is empty, then all headers must be sent.\n\nIf the list has entries, only those entries must be sent.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From cb72805823252e04dabbf3b19a80cbaceffa6b8b Mon Sep 17 00:00:00 2001 From: Flynn Date: Tue, 26 Aug 2025 11:00:06 -0400 Subject: [PATCH 171/224] feat(gateway): API for default Gateways Signed-off-by: Flynn --- apis/v1/gateway_types.go | 10 ++++ apis/v1/shared_types.go | 21 +++++++ applyconfiguration/apis/v1/commonroutespec.go | 15 ++++- applyconfiguration/apis/v1/gatewayspec.go | 9 +++ applyconfiguration/apis/v1/grpcroutespec.go | 8 +++ applyconfiguration/apis/v1/httproutespec.go | 8 +++ .../apis/v1alpha2/tcproutespec.go | 9 +++ .../apis/v1alpha2/tlsroutespec.go | 8 +++ .../apis/v1alpha2/udproutespec.go | 9 +++ .../apis/v1alpha3/tlsroutespec.go | 8 +++ applyconfiguration/internal/internal.go | 21 +++++++ .../gateway.networking.k8s.io_gateways.yaml | 16 ++++++ .../gateway.networking.k8s.io_grpcroutes.yaml | 8 +++ .../gateway.networking.k8s.io_httproutes.yaml | 16 ++++++ .../gateway.networking.k8s.io_tcproutes.yaml | 8 +++ .../gateway.networking.k8s.io_tlsroutes.yaml | 16 ++++++ .../gateway.networking.k8s.io_udproutes.yaml | 8 +++ geps/gep-3793/index.md | 29 ++++++++-- pkg/generated/openapi/zz_generated.openapi.go | 56 +++++++++++++++++++ 19 files changed, 276 insertions(+), 7 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 652101ff76..f27fc0a187 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -294,6 +294,16 @@ type GatewaySpec struct { // +optional // TLS *GatewayTLSConfig `json:"tls,omitempty"` + + // DefaultScope defines the default scope for this Gateway. If unset (the + // default), the Gateway will not act as a default Gateway; if set, the + // Gateway will claim any Route with a matching scope set in its + // UseDefaultGateway field, subject to the usual rules about which routes + // the Gateway can attach to. + // + // +optional + // + DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` } // AllowedListeners defines which ListenerSets can be attached to this Gateway. diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 2b38e32cd6..484ce3f27d 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -155,6 +155,17 @@ type ParentReference struct { Port *PortNumber `json:"port,omitempty"` } +// GatewayDefaultScope defines the set of default scopes that a Gateway +// can claim, for use in any Route type. At present the only supported +// scope is "All". +type GatewayDefaultScope string + +const ( + // GatewayDefaultScopeAll indicates that a Gateway can claim absolutely + // any Route asking for a default Gateway. + GatewayDefaultScopeAll GatewayDefaultScope = "All" +) + // CommonRouteSpec defines the common attributes that all Routes MUST include // within their spec. type CommonRouteSpec struct { @@ -229,6 +240,16 @@ type CommonRouteSpec struct { // // ParentRefs []ParentReference `json:"parentRefs,omitempty"` + + // useDefaultGateway indicates the default Gateway scope to use for this + // Route. If unset (the default), the Route will not be attached to any + // default Gateway; if set, it will be attached to any default Gateway + // supporting the named scope, subject to the usual rules about which + // Routes a Gateway is allowed to claim. + // + // +optional + // + UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` } // PortNumber defines a network port. diff --git a/applyconfiguration/apis/v1/commonroutespec.go b/applyconfiguration/apis/v1/commonroutespec.go index 00dcfe71e2..d41edc399c 100644 --- a/applyconfiguration/apis/v1/commonroutespec.go +++ b/applyconfiguration/apis/v1/commonroutespec.go @@ -18,10 +18,15 @@ limitations under the License. package v1 +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + // CommonRouteSpecApplyConfiguration represents a declarative configuration of the CommonRouteSpec type for use // with apply. type CommonRouteSpecApplyConfiguration struct { - ParentRefs []ParentReferenceApplyConfiguration `json:"parentRefs,omitempty"` + ParentRefs []ParentReferenceApplyConfiguration `json:"parentRefs,omitempty"` + UseDefaultGateway *apisv1.GatewayDefaultScope `json:"useDefaultGateway,omitempty"` } // CommonRouteSpecApplyConfiguration constructs a declarative configuration of the CommonRouteSpec type for use with @@ -42,3 +47,11 @@ func (b *CommonRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefe } return b } + +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *CommonRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *CommonRouteSpecApplyConfiguration { + b.UseDefaultGateway = &value + return b +} diff --git a/applyconfiguration/apis/v1/gatewayspec.go b/applyconfiguration/apis/v1/gatewayspec.go index e976dc4827..a2736fb922 100644 --- a/applyconfiguration/apis/v1/gatewayspec.go +++ b/applyconfiguration/apis/v1/gatewayspec.go @@ -31,6 +31,7 @@ type GatewaySpecApplyConfiguration struct { Infrastructure *GatewayInfrastructureApplyConfiguration `json:"infrastructure,omitempty"` AllowedListeners *AllowedListenersApplyConfiguration `json:"allowedListeners,omitempty"` TLS *GatewayTLSConfigApplyConfiguration `json:"tls,omitempty"` + DefaultScope *apisv1.GatewayDefaultScope `json:"defaultScope,omitempty"` } // GatewaySpecApplyConfiguration constructs a declarative configuration of the GatewaySpec type for use with @@ -96,3 +97,11 @@ func (b *GatewaySpecApplyConfiguration) WithTLS(value *GatewayTLSConfigApplyConf b.TLS = value return b } + +// WithDefaultScope sets the DefaultScope field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DefaultScope field is set to the value of the last call. +func (b *GatewaySpecApplyConfiguration) WithDefaultScope(value apisv1.GatewayDefaultScope) *GatewaySpecApplyConfiguration { + b.DefaultScope = &value + return b +} diff --git a/applyconfiguration/apis/v1/grpcroutespec.go b/applyconfiguration/apis/v1/grpcroutespec.go index 00c567e59c..3a8beadfd3 100644 --- a/applyconfiguration/apis/v1/grpcroutespec.go +++ b/applyconfiguration/apis/v1/grpcroutespec.go @@ -49,6 +49,14 @@ func (b *GRPCRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefere return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *GRPCRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *GRPCRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithHostnames adds the given value to the Hostnames field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Hostnames field. diff --git a/applyconfiguration/apis/v1/httproutespec.go b/applyconfiguration/apis/v1/httproutespec.go index 439ddbd9d6..8206d31cbf 100644 --- a/applyconfiguration/apis/v1/httproutespec.go +++ b/applyconfiguration/apis/v1/httproutespec.go @@ -49,6 +49,14 @@ func (b *HTTPRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefere return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *HTTPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *HTTPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithHostnames adds the given value to the Hostnames field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Hostnames field. diff --git a/applyconfiguration/apis/v1alpha2/tcproutespec.go b/applyconfiguration/apis/v1alpha2/tcproutespec.go index 67b40cc776..4e97cf1964 100644 --- a/applyconfiguration/apis/v1alpha2/tcproutespec.go +++ b/applyconfiguration/apis/v1alpha2/tcproutespec.go @@ -19,6 +19,7 @@ limitations under the License. package v1alpha2 import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" ) @@ -48,6 +49,14 @@ func (b *TCPRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *TCPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TCPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithRules adds the given value to the Rules field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Rules field. diff --git a/applyconfiguration/apis/v1alpha2/tlsroutespec.go b/applyconfiguration/apis/v1alpha2/tlsroutespec.go index 7a634a7863..70e5010f63 100644 --- a/applyconfiguration/apis/v1alpha2/tlsroutespec.go +++ b/applyconfiguration/apis/v1alpha2/tlsroutespec.go @@ -50,6 +50,14 @@ func (b *TLSRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithHostnames adds the given value to the Hostnames field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Hostnames field. diff --git a/applyconfiguration/apis/v1alpha2/udproutespec.go b/applyconfiguration/apis/v1alpha2/udproutespec.go index 2f07c51fce..42a8eb7a16 100644 --- a/applyconfiguration/apis/v1alpha2/udproutespec.go +++ b/applyconfiguration/apis/v1alpha2/udproutespec.go @@ -19,6 +19,7 @@ limitations under the License. package v1alpha2 import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" ) @@ -48,6 +49,14 @@ func (b *UDPRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *UDPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *UDPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithRules adds the given value to the Rules field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Rules field. diff --git a/applyconfiguration/apis/v1alpha3/tlsroutespec.go b/applyconfiguration/apis/v1alpha3/tlsroutespec.go index 47c7e06fd6..348abf1d1d 100644 --- a/applyconfiguration/apis/v1alpha3/tlsroutespec.go +++ b/applyconfiguration/apis/v1alpha3/tlsroutespec.go @@ -51,6 +51,14 @@ func (b *TLSRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } +// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UseDefaultGateway field is set to the value of the last call. +func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value + return b +} + // WithHostnames adds the given value to the Hostnames field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Hostnames field. diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 7fa1b6bfb5..9945543600 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -496,6 +496,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.GRPCRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.GRPCRouteStatus map: fields: @@ -613,6 +616,9 @@ var schemaYAML = typed.YAMLObject(`types: - name: allowedListeners type: namedType: io.k8s.sigs.gateway-api.apis.v1.AllowedListeners + - name: defaultScope + type: + scalar: string - name: gatewayClassName type: scalar: string @@ -1045,6 +1051,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.HTTPRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.HTTPRouteStatus map: fields: @@ -1478,6 +1487,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TCPRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.TCPRouteStatus map: fields: @@ -1541,6 +1553,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteStatus map: fields: @@ -1598,6 +1613,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.UDPRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.UDPRouteStatus map: fields: @@ -1723,6 +1741,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteRule elementRelationship: atomic + - name: useDefaultGateway + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1beta1.Gateway map: fields: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 349b14cdfd..42c3a36844 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -214,6 +214,14 @@ spec: x-kubernetes-map-type: atomic type: object type: object + defaultScope: + description: |- + DefaultScope defines the default scope for this Gateway. If unset (the + default), the Gateway will not act as a default Gateway; if set, the + Gateway will claim any Route with a matching scope set in its + UseDefaultGateway field, subject to the usual rules about which routes + the Gateway can attach to. + type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -1766,6 +1774,14 @@ spec: x-kubernetes-map-type: atomic type: object type: object + defaultScope: + description: |- + DefaultScope defines the default scope for this Gateway. If unset (the + default), the Gateway will not act as a default Gateway; if set, the + Gateway will claim any Route with a matching scope set in its + UseDefaultGateway field, subject to the usual rules about which routes + the Gateway can attach to. + type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index e714fd0f51..8d7cfe7fe3 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -1938,6 +1938,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string type: object status: description: Status defines the current state of GRPCRoute. diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 8734186cf9..c83a6ceaa6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3876,6 +3876,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string type: object status: description: Status defines the current state of HTTPRoute. @@ -8016,6 +8024,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string type: object status: description: Status defines the current state of HTTPRoute. diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 35a9e01a86..9b71cf46f5 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -447,6 +447,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string required: - rules type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index d8b177e3e8..9bf351d02f 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -511,6 +511,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string required: - rules type: object @@ -1289,6 +1297,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string required: - hostnames - rules diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 305ddaba13..31ba01fbca 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -447,6 +447,14 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + type: string required: - rules type: object diff --git a/geps/gep-3793/index.md b/geps/gep-3793/index.md index f0cad9a72d..b36737f090 100644 --- a/geps/gep-3793/index.md +++ b/geps/gep-3793/index.md @@ -275,12 +275,13 @@ GEP covers **all** intended changes to Gateway API behavior. Since Ana must be able to choose whether a Route is defaulted or not, marking a Route as defaulted must be an active configuration step she takes, rather than any kind of implicit behavior. To that end, the `CommonRouteSpec` -resource will gain a new field, `useDefaultGateway`, which defines the +resource will gain a new field, `UseDefaultGateway`, which defines the _scope_ for the defaulted Route: ```go // GatewayDefaultScope defines the set of default scopes that a Gateway -// can claim. At present the only supported scope is "All". +// can claim, for use in any Route type. At present the only supported +// scope is "All". type GatewayDefaultScope string const ( @@ -290,8 +291,16 @@ const ( ) type CommonRouteSpec struct { - // ... other fields ... - useDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` + // ... other fields ... + // useDefaultGateway indicates the default Gateway scope to use for this + // Route. If unset (the default), the Route will not be attached to any + // default Gateway; if set, it will be attached to any default Gateway + // supporting the named scope, subject to the usual rules about which + // Routes a Gateway is allowed to claim. + // + // +optional + // + UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` } ``` @@ -418,8 +427,16 @@ behavior. To that end, the Gateway resource will gain a new field, ```go type GatewaySpec struct { - // ... other fields ... - DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` + // ... other fields ... + // DefaultScope defines the default scope for this Gateway. If unset (the + // default), the Gateway will not act as a default Gateway; if set, the + // Gateway will claim any Route with a matching scope set in its + // UseDefaultGateway field, subject to the usual rules about which routes + // the Gateway can attach to. + // + // +optional + // + DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` } ``` diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index c21063d36e..8a41363ca2 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3045,6 +3045,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, @@ -3689,6 +3696,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "hostnames": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -4212,6 +4226,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"), }, }, + "defaultScope": { + SchemaProps: spec.SchemaProps{ + Description: "DefaultScope defines the default scope for this Gateway. If unset (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"gatewayClassName", "listeners"}, }, @@ -5419,6 +5440,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "hostnames": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -6896,6 +6924,13 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "rules": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -7126,6 +7161,13 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "hostnames": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -7376,6 +7418,13 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "rules": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ @@ -7831,6 +7880,13 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, }, }, + "useDefaultGateway": { + SchemaProps: spec.SchemaProps{ + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Type: []string{"string"}, + Format: "", + }, + }, "hostnames": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ From 0ea97210fcb9792f96f03b7d0b243592a36e49a7 Mon Sep 17 00:00:00 2001 From: Flynn Date: Tue, 26 Aug 2025 16:36:31 -0400 Subject: [PATCH 172/224] chore: Review feedback from Mike Morris Signed-off-by: Flynn --- apis/v1/shared_types.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 484ce3f27d..2e89529cfb 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -155,9 +155,9 @@ type ParentReference struct { Port *PortNumber `json:"port,omitempty"` } -// GatewayDefaultScope defines the set of default scopes that a Gateway -// can claim, for use in any Route type. At present the only supported -// scope is "All". +// GatewayDefaultScope defines the set of default scopes that a Gateway can +// claim, for configuring default Gateways and selecting default Gateways in +// any Route type. At present the only supported scope is "All". type GatewayDefaultScope string const ( From d80fa39ca86b739ac1d129ed8bc73a443cf744ef Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 27 Aug 2025 13:51:42 -0400 Subject: [PATCH 173/224] chore: Review feedback from Nick Young Clarify that empty string and unset are equivalent Co-authored-by: Nick Young Signed-off-by: Flynn --- apis/v1/gateway_types.go | 5 ++-- apis/v1/shared_types.go | 10 +++++-- .../gateway.networking.k8s.io_gateways.yaml | 10 ++++--- .../gateway.networking.k8s.io_grpcroutes.yaml | 7 +++++ .../gateway.networking.k8s.io_httproutes.yaml | 14 +++++++++ .../gateway.networking.k8s.io_tcproutes.yaml | 7 +++++ .../gateway.networking.k8s.io_tlsroutes.yaml | 14 +++++++++ .../gateway.networking.k8s.io_udproutes.yaml | 7 +++++ .../gateway.networking.k8s.io_grpcroutes.yaml | 15 ++++++++++ .../gateway.networking.k8s.io_httproutes.yaml | 30 +++++++++++++++++++ pkg/generated/openapi/zz_generated.openapi.go | 16 +++++----- 11 files changed, 119 insertions(+), 16 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index f27fc0a187..a6aced0f54 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -295,8 +295,9 @@ type GatewaySpec struct { // TLS *GatewayTLSConfig `json:"tls,omitempty"` - // DefaultScope defines the default scope for this Gateway. If unset (the - // default), the Gateway will not act as a default Gateway; if set, the + // DefaultScope defines the default scope for this Gateway. If unset or + // set to the empty string `""` (the default), the Gateway will not + // act as a default Gateway; if set, the // Gateway will claim any Route with a matching scope set in its // UseDefaultGateway field, subject to the usual rules about which routes // the Gateway can attach to. diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 2e89529cfb..5c715241d6 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -247,8 +247,14 @@ type CommonRouteSpec struct { // supporting the named scope, subject to the usual rules about which // Routes a Gateway is allowed to claim. // - // +optional - // + // Think carefully before using this functionality! The set of default + // Gateways supporting the requested scope can change over time without + // any notice to the Route author, and in many situations it will not be + // appropriate to request a default Gateway for a given Route -- for + // example, a Route with specific security needs should almost certainly + // not use a default Gateway. + // + // +optional UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` } diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 42c3a36844..0075ef902e 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -216,8 +216,9 @@ spec: type: object defaultScope: description: |- - DefaultScope defines the default scope for this Gateway. If unset (the - default), the Gateway will not act as a default Gateway; if set, the + DefaultScope defines the default scope for this Gateway. If unset or + set to the empty string `""` (the default), the Gateway will not + act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to. @@ -1776,8 +1777,9 @@ spec: type: object defaultScope: description: |- - DefaultScope defines the default scope for this Gateway. If unset (the - default), the Gateway will not act as a default Gateway; if set, the + DefaultScope defines the default scope for this Gateway. If unset or + set to the empty string `""` (the default), the Gateway will not + act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to. diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 8d7cfe7fe3..60461b2c14 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -1945,6 +1945,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string type: object status: diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index c83a6ceaa6..5b3312530c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3883,6 +3883,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string type: object status: @@ -8031,6 +8038,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string type: object status: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 9b71cf46f5..2e60af9aa6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -454,6 +454,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string required: - rules diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 9bf351d02f..e9c24baa95 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -518,6 +518,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string required: - rules @@ -1304,6 +1311,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string required: - hostnames diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 31ba01fbca..76a20a62d7 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -454,6 +454,13 @@ spec: default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. type: string required: - rules diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index b02f9a41d1..841ccdc100 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1799,6 +1799,21 @@ spec: : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128' + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. + type: string type: object status: description: Status defines the current state of GRPCRoute. diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index b57a508f39..13197a2ecf 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2563,6 +2563,21 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. + type: string type: object status: description: Status defines the current state of HTTPRoute. @@ -5372,6 +5387,21 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + useDefaultGateway: + description: |- + useDefaultGateway indicates the default Gateway scope to use for this + Route. If unset (the default), the Route will not be attached to any + default Gateway; if set, it will be attached to any default Gateway + supporting the named scope, subject to the usual rules about which + Routes a Gateway is allowed to claim. + + Think carefully before using this functionality! The set of default + Gateways supporting the requested scope can change over time without + any notice to the Route author, and in many situations it will not be + appropriate to request a default Gateway for a given Route -- for + example, a Route with specific security needs should almost certainly + not use a default Gateway. + type: string type: object status: description: Status defines the current state of HTTPRoute. diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 8a41363ca2..a943309cb2 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3047,7 +3047,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -3698,7 +3698,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope defines the default scope for this Gateway. If unset (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\n", + Description: "DefaultScope defines the default scope for this Gateway. If unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\n", Type: []string{"string"}, Format: "", }, @@ -5442,7 +5442,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -6926,7 +6926,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7163,7 +7163,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7420,7 +7420,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7882,7 +7882,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\n", + Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, From 4acf2f68e97c4c70985229cbc530753ee31d5919 Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 28 Aug 2025 14:24:21 -0400 Subject: [PATCH 174/224] chore: Review feedback from Shane Utt Add security notes on the Gateway side Co-authored-by: Shane Utt Signed-off-by: Flynn --- apis/v1/gateway_types.go | 22 ++++++++++++++++------ apis/v1/shared_types.go | 5 +++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index a6aced0f54..2f5685720d 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -295,12 +295,22 @@ type GatewaySpec struct { // TLS *GatewayTLSConfig `json:"tls,omitempty"` - // DefaultScope defines the default scope for this Gateway. If unset or - // set to the empty string `""` (the default), the Gateway will not - // act as a default Gateway; if set, the - // Gateway will claim any Route with a matching scope set in its - // UseDefaultGateway field, subject to the usual rules about which routes - // the Gateway can attach to. + // DefaultScope when set configures the Gateway as a default Gateway, meaning + // it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached + // to it, according to the scope configured here. + // + // If unset or set to the empty string `""` (the default), the Gateway will not + // act as a default Gateway; if set, the Gateway will claim any Route with a + // matching scope set in its UseDefaultGateway field, subject to the usual + // rules about which routes the Gateway can attach to. + // + // Think carefully before using this functionality! While the normal rules about + // which Route can apply are still enforced, it is simply easier for the wrong + // Route to be accidentally attached to this Gateway in this configuration. If the + // Gateway operator is not also the operator in control of the scope (e.g. + // namespace) with tight controls and checks on what kind of workloads and + // Routes get added in that scope, we strongly recommend not using this just + // because it seems convenient, and instead stick to explicit Route attachment. // // +optional // diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 5c715241d6..4f6b414602 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -241,7 +241,7 @@ type CommonRouteSpec struct { // ParentRefs []ParentReference `json:"parentRefs,omitempty"` - // useDefaultGateway indicates the default Gateway scope to use for this + // UseDefaultGateway indicates the default Gateway scope to use for this // Route. If unset (the default), the Route will not be attached to any // default Gateway; if set, it will be attached to any default Gateway // supporting the named scope, subject to the usual rules about which @@ -251,7 +251,8 @@ type CommonRouteSpec struct { // Gateways supporting the requested scope can change over time without // any notice to the Route author, and in many situations it will not be // appropriate to request a default Gateway for a given Route -- for - // example, a Route with specific security needs should almost certainly + // example, a Route with specific security requirements should almost certainly + // not use a default Gateway. // not use a default Gateway. // // +optional From 548e49b6408f84901d2b1da546f52afd8027e2b3 Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 28 Aug 2025 14:26:57 -0400 Subject: [PATCH 175/224] chore: make generate Signed-off-by: Flynn --- .../gateway.networking.k8s.io_gateways.yaml | 44 ++++++++++++++----- .../gateway.networking.k8s.io_grpcroutes.yaml | 5 ++- .../gateway.networking.k8s.io_httproutes.yaml | 10 +++-- .../gateway.networking.k8s.io_tcproutes.yaml | 5 ++- .../gateway.networking.k8s.io_tlsroutes.yaml | 10 +++-- .../gateway.networking.k8s.io_udproutes.yaml | 5 ++- .../gateway.networking.k8s.io_grpcroutes.yaml | 5 ++- .../gateway.networking.k8s.io_httproutes.yaml | 10 +++-- pkg/generated/openapi/zz_generated.openapi.go | 16 +++---- 9 files changed, 70 insertions(+), 40 deletions(-) diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 0075ef902e..57178dc844 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -216,12 +216,22 @@ spec: type: object defaultScope: description: |- - DefaultScope defines the default scope for this Gateway. If unset or - set to the empty string `""` (the default), the Gateway will not - act as a default Gateway; if set, the - Gateway will claim any Route with a matching scope set in its - UseDefaultGateway field, subject to the usual rules about which routes - the Gateway can attach to. + DefaultScope when set configures the Gateway as a default Gateway, meaning + it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached + to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway will not + act as a default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules about + which Route can apply are still enforced, it is simply easier for the wrong + Route to be accidentally attached to this Gateway in this configuration. If the + Gateway operator is not also the operator in control of the scope (e.g. + namespace) with tight controls and checks on what kind of workloads and + Routes get added in that scope, we strongly recommend not using this just + because it seems convenient, and instead stick to explicit Route attachment. type: string gatewayClassName: description: |- @@ -1777,12 +1787,22 @@ spec: type: object defaultScope: description: |- - DefaultScope defines the default scope for this Gateway. If unset or - set to the empty string `""` (the default), the Gateway will not - act as a default Gateway; if set, the - Gateway will claim any Route with a matching scope set in its - UseDefaultGateway field, subject to the usual rules about which routes - the Gateway can attach to. + DefaultScope when set configures the Gateway as a default Gateway, meaning + it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached + to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway will not + act as a default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules about + which Route can apply are still enforced, it is simply easier for the wrong + Route to be accidentally attached to this Gateway in this configuration. If the + Gateway operator is not also the operator in control of the scope (e.g. + namespace) with tight controls and checks on what kind of workloads and + Routes get added in that scope, we strongly recommend not using this just + because it seems convenient, and instead stick to explicit Route attachment. type: string gatewayClassName: description: |- diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 60461b2c14..468f416b85 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -1940,7 +1940,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -1950,7 +1950,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 5b3312530c..6d37659c34 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3878,7 +3878,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -3888,7 +3888,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object @@ -8033,7 +8034,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -8043,7 +8044,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 2e60af9aa6..8866232617 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -449,7 +449,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -459,7 +459,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string required: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index e9c24baa95..be8fb30607 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -513,7 +513,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -523,7 +523,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string required: @@ -1306,7 +1307,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -1316,7 +1317,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string required: diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 76a20a62d7..f4fb623224 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -449,7 +449,7 @@ spec: && l1.name == l2.name)) useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -459,7 +459,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string required: diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 841ccdc100..3899e22377 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1801,7 +1801,7 @@ spec: : 0) : 0) <= 128' useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -1811,7 +1811,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 13197a2ecf..ab594194eb 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2565,7 +2565,7 @@ spec: : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -2575,7 +2575,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object @@ -5389,7 +5390,7 @@ spec: : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' useDefaultGateway: description: |- - useDefaultGateway indicates the default Gateway scope to use for this + UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which @@ -5399,7 +5400,8 @@ spec: Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security needs should almost certainly + example, a Route with specific security requirements should almost certainly + not use a default Gateway. not use a default Gateway. type: string type: object diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index a943309cb2..b61d0c6769 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3047,7 +3047,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -3698,7 +3698,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope defines the default scope for this Gateway. If unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\n", + Description: "DefaultScope when set configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to explicit Route attachment.\n\n", Type: []string{"string"}, Format: "", }, @@ -5442,7 +5442,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -6926,7 +6926,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7163,7 +7163,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7420,7 +7420,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7882,7 +7882,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "useDefaultGateway": { SchemaProps: spec.SchemaProps{ - Description: "useDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security needs should almost certainly not use a default Gateway.", + Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", Type: []string{"string"}, Format: "", }, From 93b5026d26e9d88c1e9f0e9ea1b00206f3b069bf Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 28 Aug 2025 14:39:00 -0400 Subject: [PATCH 176/224] chore: Rewrap Gateway DefaultScope comments and make generate Signed-off-by: Flynn --- apis/v1/gateway_types.go | 38 +++++------ .../gateway.networking.k8s.io_gateways.yaml | 66 ++++++++++--------- .../gateway.networking.k8s.io_gateways.yaml | 40 +++++++++++ pkg/generated/openapi/zz_generated.openapi.go | 2 +- 4 files changed, 94 insertions(+), 52 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 2f5685720d..77646a0e67 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -295,25 +295,25 @@ type GatewaySpec struct { // TLS *GatewayTLSConfig `json:"tls,omitempty"` - // DefaultScope when set configures the Gateway as a default Gateway, meaning - // it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached - // to it, according to the scope configured here. - // - // If unset or set to the empty string `""` (the default), the Gateway will not - // act as a default Gateway; if set, the Gateway will claim any Route with a - // matching scope set in its UseDefaultGateway field, subject to the usual - // rules about which routes the Gateway can attach to. - // - // Think carefully before using this functionality! While the normal rules about - // which Route can apply are still enforced, it is simply easier for the wrong - // Route to be accidentally attached to this Gateway in this configuration. If the - // Gateway operator is not also the operator in control of the scope (e.g. - // namespace) with tight controls and checks on what kind of workloads and - // Routes get added in that scope, we strongly recommend not using this just - // because it seems convenient, and instead stick to explicit Route attachment. - // - // +optional - // + // DefaultScope, when set, configures the Gateway as a default Gateway, + // meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + // attached to it, according to the scope configured here. + // + // If unset or set to the empty string `""` (the default), the Gateway + // will not act as a default Gateway; if set, the Gateway will claim any + // Route with a matching scope set in its UseDefaultGateway field, subject + // to the usual rules about which routes the Gateway can attach to. + // + // Think carefully before using this functionality! While the normal rules + // about which Route can apply are still enforced, it is simply easier for + // the wrong Route to be accidentally attached to this Gateway in this + // configuration. If the Gateway operator is not also the operator in + // control of the scope (e.g. namespace) with tight controls and checks on + // what kind of workloads and Routes get added in that scope, we strongly + // recommend not using this just because it seems convenient, and instead + // stick to explicit Route attachment. + // + // +optional DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` } diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 57178dc844..2e8479b629 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -216,22 +216,23 @@ spec: type: object defaultScope: description: |- - DefaultScope when set configures the Gateway as a default Gateway, meaning - it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached - to it, according to the scope configured here. - - If unset or set to the empty string `""` (the default), the Gateway will not - act as a default Gateway; if set, the Gateway will claim any Route with a - matching scope set in its UseDefaultGateway field, subject to the usual - rules about which routes the Gateway can attach to. - - Think carefully before using this functionality! While the normal rules about - which Route can apply are still enforced, it is simply easier for the wrong - Route to be accidentally attached to this Gateway in this configuration. If the - Gateway operator is not also the operator in control of the scope (e.g. - namespace) with tight controls and checks on what kind of workloads and - Routes get added in that scope, we strongly recommend not using this just - because it seems convenient, and instead stick to explicit Route attachment. + DefaultScope, when set, configures the Gateway as a default Gateway, + meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + attached to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway + will not act as a default Gateway; if set, the Gateway will claim any + Route with a matching scope set in its UseDefaultGateway field, subject + to the usual rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules + about which Route can apply are still enforced, it is simply easier for + the wrong Route to be accidentally attached to this Gateway in this + configuration. If the Gateway operator is not also the operator in + control of the scope (e.g. namespace) with tight controls and checks on + what kind of workloads and Routes get added in that scope, we strongly + recommend not using this just because it seems convenient, and instead + stick to explicit Route attachment. type: string gatewayClassName: description: |- @@ -1787,22 +1788,23 @@ spec: type: object defaultScope: description: |- - DefaultScope when set configures the Gateway as a default Gateway, meaning - it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached - to it, according to the scope configured here. - - If unset or set to the empty string `""` (the default), the Gateway will not - act as a default Gateway; if set, the Gateway will claim any Route with a - matching scope set in its UseDefaultGateway field, subject to the usual - rules about which routes the Gateway can attach to. - - Think carefully before using this functionality! While the normal rules about - which Route can apply are still enforced, it is simply easier for the wrong - Route to be accidentally attached to this Gateway in this configuration. If the - Gateway operator is not also the operator in control of the scope (e.g. - namespace) with tight controls and checks on what kind of workloads and - Routes get added in that scope, we strongly recommend not using this just - because it seems convenient, and instead stick to explicit Route attachment. + DefaultScope, when set, configures the Gateway as a default Gateway, + meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + attached to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway + will not act as a default Gateway; if set, the Gateway will claim any + Route with a matching scope set in its UseDefaultGateway field, subject + to the usual rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules + about which Route can apply are still enforced, it is simply easier for + the wrong Route to be accidentally attached to this Gateway in this + configuration. If the Gateway operator is not also the operator in + control of the scope (e.g. namespace) with tight controls and checks on + what kind of workloads and Routes get added in that scope, we strongly + recommend not using this just because it seems convenient, and instead + stick to explicit Route attachment. type: string gatewayClassName: description: |- diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 98914347d2..c5baa712b2 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -133,6 +133,26 @@ spec: - message: Hostname values must be unique rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + defaultScope: + description: |- + DefaultScope, when set, configures the Gateway as a default Gateway, + meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + attached to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway + will not act as a default Gateway; if set, the Gateway will claim any + Route with a matching scope set in its UseDefaultGateway field, subject + to the usual rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules + about which Route can apply are still enforced, it is simply easier for + the wrong Route to be accidentally attached to this Gateway in this + configuration. If the Gateway operator is not also the operator in + control of the scope (e.g. namespace) with tight controls and checks on + what kind of workloads and Routes get added in that scope, we strongly + recommend not using this just because it seems convenient, and instead + stick to explicit Route attachment. + type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -1244,6 +1264,26 @@ spec: - message: Hostname values must be unique rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + defaultScope: + description: |- + DefaultScope, when set, configures the Gateway as a default Gateway, + meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + attached to it, according to the scope configured here. + + If unset or set to the empty string `""` (the default), the Gateway + will not act as a default Gateway; if set, the Gateway will claim any + Route with a matching scope set in its UseDefaultGateway field, subject + to the usual rules about which routes the Gateway can attach to. + + Think carefully before using this functionality! While the normal rules + about which Route can apply are still enforced, it is simply easier for + the wrong Route to be accidentally attached to this Gateway in this + configuration. If the Gateway operator is not also the operator in + control of the scope (e.g. namespace) with tight controls and checks on + what kind of workloads and Routes get added in that scope, we strongly + recommend not using this just because it seems convenient, and instead + stick to explicit Route attachment. + type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index b61d0c6769..32eed6cc04 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope when set configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to explicit Route attachment.\n\n", + Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to explicit Route attachment.", Type: []string{"string"}, Format: "", }, From a2bbf1655c60ad70f0f089d53b4e66adf1a6440c Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Sep 2025 13:07:16 -0400 Subject: [PATCH 177/224] Review feedback from Rob Scott These are nits, thanks Rob! Co-authored-by: Rob Scott Signed-off-by: Flynn --- apis/v1/gateway_types.go | 4 ++-- apis/v1/shared_types.go | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 77646a0e67..52b137bc75 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -299,7 +299,7 @@ type GatewaySpec struct { // meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) // attached to it, according to the scope configured here. // - // If unset or set to the empty string `""` (the default), the Gateway + // If unset or set to an empty string `""` (the default), the Gateway // will not act as a default Gateway; if set, the Gateway will claim any // Route with a matching scope set in its UseDefaultGateway field, subject // to the usual rules about which routes the Gateway can attach to. @@ -311,7 +311,7 @@ type GatewaySpec struct { // control of the scope (e.g. namespace) with tight controls and checks on // what kind of workloads and Routes get added in that scope, we strongly // recommend not using this just because it seems convenient, and instead - // stick to explicit Route attachment. + // stick to direct Route attachment. // // +optional DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 4f6b414602..b439eaa128 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -253,7 +253,6 @@ type CommonRouteSpec struct { // appropriate to request a default Gateway for a given Route -- for // example, a Route with specific security requirements should almost certainly // not use a default Gateway. - // not use a default Gateway. // // +optional UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` From 84a8806848ae07dbe3a88338991827b05c705d81 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Sep 2025 13:28:43 -0400 Subject: [PATCH 178/224] chore: useDefaultGateway -> useDefaultGateways (plural), support scope None as explicitly disabling defaulting Signed-off-by: Flynn --- apis/v1/gateway_types.go | 9 +- apis/v1/shared_types.go | 29 ++++--- applyconfiguration/apis/v1/commonroutespec.go | 12 +-- applyconfiguration/apis/v1/grpcroutespec.go | 8 +- applyconfiguration/apis/v1/httproutespec.go | 8 +- .../apis/v1alpha2/tcproutespec.go | 8 +- .../apis/v1alpha2/tlsroutespec.go | 8 +- .../apis/v1alpha2/udproutespec.go | 8 +- .../apis/v1alpha3/tlsroutespec.go | 8 +- applyconfiguration/internal/internal.go | 12 +-- .../gateway.networking.k8s.io_gateways.yaml | 28 +++--- .../gateway.networking.k8s.io_grpcroutes.yaml | 21 +++-- .../gateway.networking.k8s.io_httproutes.yaml | 42 +++++---- .../gateway.networking.k8s.io_tcproutes.yaml | 21 +++-- .../gateway.networking.k8s.io_tlsroutes.yaml | 42 +++++---- .../gateway.networking.k8s.io_udproutes.yaml | 21 +++-- .../gateway.networking.k8s.io_gateways.yaml | 28 +++--- .../gateway.networking.k8s.io_grpcroutes.yaml | 21 +++-- .../gateway.networking.k8s.io_httproutes.yaml | 42 +++++---- geps/gep-3793/index.md | 87 +++++++++++-------- pkg/generated/openapi/zz_generated.openapi.go | 30 +++---- 21 files changed, 280 insertions(+), 213 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 52b137bc75..c566ef40d4 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -299,10 +299,11 @@ type GatewaySpec struct { // meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) // attached to it, according to the scope configured here. // - // If unset or set to an empty string `""` (the default), the Gateway - // will not act as a default Gateway; if set, the Gateway will claim any - // Route with a matching scope set in its UseDefaultGateway field, subject - // to the usual rules about which routes the Gateway can attach to. + // If unset (the default), set to an empty string (`""`), or set to None, + // the Gateway will not act as a default Gateway; if set, the Gateway will + // claim any Route with a matching scope set in its UseDefaultGateway + // field, subject to the usual rules about which routes the Gateway can + // attach to. // // Think carefully before using this functionality! While the normal rules // about which Route can apply are still enforced, it is simply easier for diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index b439eaa128..f7ca95f5a4 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -155,15 +155,21 @@ type ParentReference struct { Port *PortNumber `json:"port,omitempty"` } -// GatewayDefaultScope defines the set of default scopes that a Gateway can -// claim, for configuring default Gateways and selecting default Gateways in -// any Route type. At present the only supported scope is "All". +// GatewayDefaultScope defines the set of default scopes that a Gateway +// can claim, for use in any Route type. At present the only supported +// scopes are "All" and "None". "None" is a special scope which +// explicitly means that the Route MUST NOT be defaulted. +// +kubebuilder:validation:Enum=All;None type GatewayDefaultScope string const ( // GatewayDefaultScopeAll indicates that a Gateway can claim absolutely // any Route asking for a default Gateway. GatewayDefaultScopeAll GatewayDefaultScope = "All" + + // GatewayDefaultScopeNone indicates that a Gateway MUST NOT claim + // any Route asking for a default Gateway. + GatewayDefaultScopeNone GatewayDefaultScope = "None" ) // CommonRouteSpec defines the common attributes that all Routes MUST include @@ -241,21 +247,22 @@ type CommonRouteSpec struct { // ParentRefs []ParentReference `json:"parentRefs,omitempty"` - // UseDefaultGateway indicates the default Gateway scope to use for this - // Route. If unset (the default), the Route will not be attached to any - // default Gateway; if set, it will be attached to any default Gateway - // supporting the named scope, subject to the usual rules about which - // Routes a Gateway is allowed to claim. + // UseDefaultGateways indicates the default Gateway scope to use for this + // Route. If unset (the default), set to an empty string (`""`), or set to + // None, the Route will not be attached to any default Gateway; if set, it + // will be attached to any default Gateway supporting the named scope, + // subject to the usual rules about which Routes a Gateway is allowed to + // claim. // // Think carefully before using this functionality! The set of default // Gateways supporting the requested scope can change over time without // any notice to the Route author, and in many situations it will not be // appropriate to request a default Gateway for a given Route -- for - // example, a Route with specific security requirements should almost certainly - // not use a default Gateway. + // example, a Route with specific security requirements should almost + // certainly not use a default Gateway. // // +optional - UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` + UseDefaultGateways GatewayDefaultScope `json:"useDefaultGateways,omitempty"` } // PortNumber defines a network port. diff --git a/applyconfiguration/apis/v1/commonroutespec.go b/applyconfiguration/apis/v1/commonroutespec.go index d41edc399c..eb6ffdce30 100644 --- a/applyconfiguration/apis/v1/commonroutespec.go +++ b/applyconfiguration/apis/v1/commonroutespec.go @@ -25,8 +25,8 @@ import ( // CommonRouteSpecApplyConfiguration represents a declarative configuration of the CommonRouteSpec type for use // with apply. type CommonRouteSpecApplyConfiguration struct { - ParentRefs []ParentReferenceApplyConfiguration `json:"parentRefs,omitempty"` - UseDefaultGateway *apisv1.GatewayDefaultScope `json:"useDefaultGateway,omitempty"` + ParentRefs []ParentReferenceApplyConfiguration `json:"parentRefs,omitempty"` + UseDefaultGateways *apisv1.GatewayDefaultScope `json:"useDefaultGateways,omitempty"` } // CommonRouteSpecApplyConfiguration constructs a declarative configuration of the CommonRouteSpec type for use with @@ -48,10 +48,10 @@ func (b *CommonRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefe return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *CommonRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *CommonRouteSpecApplyConfiguration { - b.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *CommonRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *CommonRouteSpecApplyConfiguration { + b.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1/grpcroutespec.go b/applyconfiguration/apis/v1/grpcroutespec.go index 3a8beadfd3..bef93cad48 100644 --- a/applyconfiguration/apis/v1/grpcroutespec.go +++ b/applyconfiguration/apis/v1/grpcroutespec.go @@ -49,11 +49,11 @@ func (b *GRPCRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefere return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *GRPCRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *GRPCRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *GRPCRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *GRPCRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1/httproutespec.go b/applyconfiguration/apis/v1/httproutespec.go index 8206d31cbf..15fb8bd929 100644 --- a/applyconfiguration/apis/v1/httproutespec.go +++ b/applyconfiguration/apis/v1/httproutespec.go @@ -49,11 +49,11 @@ func (b *HTTPRouteSpecApplyConfiguration) WithParentRefs(values ...*ParentRefere return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *HTTPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *HTTPRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *HTTPRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *HTTPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1alpha2/tcproutespec.go b/applyconfiguration/apis/v1alpha2/tcproutespec.go index 4e97cf1964..1844749fe1 100644 --- a/applyconfiguration/apis/v1alpha2/tcproutespec.go +++ b/applyconfiguration/apis/v1alpha2/tcproutespec.go @@ -49,11 +49,11 @@ func (b *TCPRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *TCPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TCPRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *TCPRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *TCPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1alpha2/tlsroutespec.go b/applyconfiguration/apis/v1alpha2/tlsroutespec.go index 70e5010f63..a5199e2e20 100644 --- a/applyconfiguration/apis/v1alpha2/tlsroutespec.go +++ b/applyconfiguration/apis/v1alpha2/tlsroutespec.go @@ -50,11 +50,11 @@ func (b *TLSRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1alpha2/udproutespec.go b/applyconfiguration/apis/v1alpha2/udproutespec.go index 42a8eb7a16..e7d0612f16 100644 --- a/applyconfiguration/apis/v1alpha2/udproutespec.go +++ b/applyconfiguration/apis/v1alpha2/udproutespec.go @@ -49,11 +49,11 @@ func (b *UDPRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *UDPRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *UDPRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *UDPRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *UDPRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/apis/v1alpha3/tlsroutespec.go b/applyconfiguration/apis/v1alpha3/tlsroutespec.go index 348abf1d1d..4ca6b385aa 100644 --- a/applyconfiguration/apis/v1alpha3/tlsroutespec.go +++ b/applyconfiguration/apis/v1alpha3/tlsroutespec.go @@ -51,11 +51,11 @@ func (b *TLSRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentRefe return b } -// WithUseDefaultGateway sets the UseDefaultGateway field in the declarative configuration to the given value +// WithUseDefaultGateways sets the UseDefaultGateways field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the UseDefaultGateway field is set to the value of the last call. -func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateway(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { - b.CommonRouteSpecApplyConfiguration.UseDefaultGateway = &value +// If called multiple times, the UseDefaultGateways field is set to the value of the last call. +func (b *TLSRouteSpecApplyConfiguration) WithUseDefaultGateways(value apisv1.GatewayDefaultScope) *TLSRouteSpecApplyConfiguration { + b.CommonRouteSpecApplyConfiguration.UseDefaultGateways = &value return b } diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 9945543600..eb813846ed 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -496,7 +496,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.GRPCRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.GRPCRouteStatus @@ -1051,7 +1051,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.HTTPRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.HTTPRouteStatus @@ -1487,7 +1487,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TCPRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.TCPRouteStatus @@ -1553,7 +1553,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteStatus @@ -1613,7 +1613,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.UDPRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha2.UDPRouteStatus @@ -1741,7 +1741,7 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteRule elementRelationship: atomic - - name: useDefaultGateway + - name: useDefaultGateways type: scalar: string - name: io.k8s.sigs.gateway-api.apis.v1beta1.Gateway diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 2e8479b629..fc6ca9d117 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -220,10 +220,11 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset or set to the empty string `""` (the default), the Gateway - will not act as a default Gateway; if set, the Gateway will claim any - Route with a matching scope set in its UseDefaultGateway field, subject - to the usual rules about which routes the Gateway can attach to. + If unset (the default), set to an empty string (`""`), or set to None, + the Gateway will not act as a default Gateway; if set, the Gateway will + claim any Route with a matching scope set in its UseDefaultGateway + field, subject to the usual rules about which routes the Gateway can + attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -232,7 +233,10 @@ spec: control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead - stick to explicit Route attachment. + stick to direct Route attachment. + enum: + - All + - None type: string gatewayClassName: description: |- @@ -1792,10 +1796,11 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset or set to the empty string `""` (the default), the Gateway - will not act as a default Gateway; if set, the Gateway will claim any - Route with a matching scope set in its UseDefaultGateway field, subject - to the usual rules about which routes the Gateway can attach to. + If unset (the default), set to an empty string (`""`), or set to None, + the Gateway will not act as a default Gateway; if set, the Gateway will + claim any Route with a matching scope set in its UseDefaultGateway + field, subject to the usual rules about which routes the Gateway can + attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -1804,7 +1809,10 @@ spec: control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead - stick to explicit Route attachment. + stick to direct Route attachment. + enum: + - All + - None type: string gatewayClassName: description: |- diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 468f416b85..9d12ec73f7 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -1938,21 +1938,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 6d37659c34..f8591a56f7 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3876,21 +3876,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: @@ -8032,21 +8035,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 8866232617..a2d34a198e 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -447,21 +447,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string required: - rules diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index be8fb30607..4dfadbfdb5 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -511,21 +511,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string required: - rules @@ -1305,21 +1308,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string required: - hostnames diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index f4fb623224..f610603648 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -447,21 +447,24 @@ spec: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string required: - rules diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index c5baa712b2..cd71c1bf02 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -139,10 +139,11 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset or set to the empty string `""` (the default), the Gateway - will not act as a default Gateway; if set, the Gateway will claim any - Route with a matching scope set in its UseDefaultGateway field, subject - to the usual rules about which routes the Gateway can attach to. + If unset (the default), set to an empty string (`""`), or set to None, + the Gateway will not act as a default Gateway; if set, the Gateway will + claim any Route with a matching scope set in its UseDefaultGateway + field, subject to the usual rules about which routes the Gateway can + attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -151,7 +152,10 @@ spec: control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead - stick to explicit Route attachment. + stick to direct Route attachment. + enum: + - All + - None type: string gatewayClassName: description: |- @@ -1270,10 +1274,11 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset or set to the empty string `""` (the default), the Gateway - will not act as a default Gateway; if set, the Gateway will claim any - Route with a matching scope set in its UseDefaultGateway field, subject - to the usual rules about which routes the Gateway can attach to. + If unset (the default), set to an empty string (`""`), or set to None, + the Gateway will not act as a default Gateway; if set, the Gateway will + claim any Route with a matching scope set in its UseDefaultGateway + field, subject to the usual rules about which routes the Gateway can + attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -1282,7 +1287,10 @@ spec: control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead - stick to explicit Route attachment. + stick to direct Route attachment. + enum: + - All + - None type: string gatewayClassName: description: |- diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 3899e22377..9c99efd467 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1799,21 +1799,24 @@ spec: : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128' - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index ab594194eb..80f75e9b1b 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2563,21 +2563,24 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: @@ -5388,21 +5391,24 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' - useDefaultGateway: + useDefaultGateways: description: |- - UseDefaultGateway indicates the default Gateway scope to use for this - Route. If unset (the default), the Route will not be attached to any - default Gateway; if set, it will be attached to any default Gateway - supporting the named scope, subject to the usual rules about which - Routes a Gateway is allowed to claim. + UseDefaultGateways indicates the default Gateway scope to use for this + Route. If unset (the default), set to an empty string (`""`), or set to + None, the Route will not be attached to any default Gateway; if set, it + will be attached to any default Gateway supporting the named scope, + subject to the usual rules about which Routes a Gateway is allowed to + claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost certainly - not use a default Gateway. - not use a default Gateway. + example, a Route with specific security requirements should almost + certainly not use a default Gateway. + enum: + - All + - None type: string type: object status: diff --git a/geps/gep-3793/index.md b/geps/gep-3793/index.md index b36737f090..052419fff1 100644 --- a/geps/gep-3793/index.md +++ b/geps/gep-3793/index.md @@ -281,43 +281,50 @@ _scope_ for the defaulted Route: ```go // GatewayDefaultScope defines the set of default scopes that a Gateway // can claim, for use in any Route type. At present the only supported -// scope is "All". +// scopes are "All" and "None". "None" is a special scope which +// explicitly means that the Route MUST NOT be defaulted. type GatewayDefaultScope string const ( // GatewayDefaultScopeAll indicates that a Gateway can claim absolutely // any Route asking for a default Gateway. GatewayDefaultScopeAll GatewayDefaultScope = "All" + + // GatewayDefaultScopeNone indicates that a Gateway MUST NOT claim + // any Route asking for a default Gateway. + GatewayDefaultScopeNone GatewayDefaultScope = "None" ) type CommonRouteSpec struct { // ... other fields ... - // useDefaultGateway indicates the default Gateway scope to use for this - // Route. If unset (the default), the Route will not be attached to any - // default Gateway; if set, it will be attached to any default Gateway - // supporting the named scope, subject to the usual rules about which - // Routes a Gateway is allowed to claim. + // UseDefaultGateways indicates the default Gateway scope to use for this + // Route. If unset (the default), set to an empty string (`""`), or set to + // None, the Route will not be attached to any default Gateway; if set, it + // will be attached to any default Gateway supporting the named scope, + // subject to the usual rules about which Routes a Gateway is allowed to + // claim. // // +optional // - UseDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` + // +kubebuilder:validation:Enum=All;None + UseDefaultGateways GatewayDefaultScope `json:"useDefaultGateways,omitempty"` } ``` For Ana to indicate that a Route should use a default Gateway, she MUST set -the Route's `spec.useDefaultGateway` to the desired scope: +the Route's `spec.useDefaultGateways` to the desired scope: ```yaml ... spec: - useDefaultGateway: All + useDefaultGateways: All ``` A defaulted Route MUST be accepted only by Gateways that have been configured -with a matching `spec.useDefaultGateway` scope. +with a matching `spec.useDefaultGateways` scope. A Route MAY include explicit `parentRefs` in addition to setting -`spec.useDefaultGateway`. In this case, the Route will be a candidate for +`spec.useDefaultGateways`. In this case, the Route will be a candidate for being bound to default Gateways, but it will also be bound to its explicitly-specified `parentRefs`. This allows Ana to create a single Route that handles N/S traffic via the default Gateways and also handles E/W traffic @@ -337,7 +344,7 @@ kind: HTTPRoute metadata: name: my-route spec: - useDefaultGateway: All + useDefaultGateways: All rules: - backendRefs: - name: my-service @@ -355,7 +362,7 @@ kind: HTTPRoute metadata: name: ns-ew-route spec: - useDefaultGateway: All + useDefaultGateways: All parentRefs: - kind: Service name: face @@ -366,7 +373,7 @@ spec: port: 80 ``` -**Multiple Gateways**: A defaulted Route MAY both set `useDefaultGateway` and +**Multiple Gateways**: A defaulted Route MAY both set `useDefaultGateways` and name other Gateways in `parentRefs`, although this is not expected to be common in practice: @@ -376,7 +383,7 @@ kind: HTTPRoute metadata: name: multi-gateway-route spec: - useDefaultGateway: All + useDefaultGateways: All parentRefs: - kind: Gateway name: my-gateway @@ -412,10 +419,10 @@ indicate that the Route has been claimed by a default Gateway. This becomes important if the set of default Gateways changes, or (in some situations) if GitOps tools are in play. -If there are no default Gateways in the cluster, `spec.useDefaultGateway` MUST -be treated as if it were set to `false` in all Routes, parallel to the -situation where a Route specifies a Gateway by name, but no Gateway of that -name exists in the cluster. +If there are no default Gateways in the cluster, `spec.useDefaultGateways` +MUST be treated as if it were unset in all Routes, parallel to the situation +where a Route specifies a Gateway by name, but no Gateway of that name exists +in the cluster. #### 2. Controlling which Gateways accept Defaulted Routes @@ -428,11 +435,15 @@ behavior. To that end, the Gateway resource will gain a new field, ```go type GatewaySpec struct { // ... other fields ... - // DefaultScope defines the default scope for this Gateway. If unset (the - // default), the Gateway will not act as a default Gateway; if set, the - // Gateway will claim any Route with a matching scope set in its - // UseDefaultGateway field, subject to the usual rules about which routes - // the Gateway can attach to. + // DefaultScope, when set, configures the Gateway as a default Gateway, + // meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) + // attached to it, according to the scope configured here. + // + // If unset (the default), set to an empty string (`""`), or set to None, + // the Gateway will not act as a default Gateway; if set, the Gateway will + // claim any Route with a matching scope set in its UseDefaultGateway + // field, subject to the usual rules about which routes the Gateway can + // attach to. // // +optional // @@ -440,13 +451,14 @@ type GatewaySpec struct { } ``` -Again, the only currently-defined scope is `All`. +Again, the only currently-defined scopes are `All` and `None`, with `None` +explicitly disabling default-Gateway functionality. If `spec.defaultScope` is set, the Gateway MUST claim Routes that have set -`spec.useDefaultGateway` to a matching value (subject to the usual Gateway API -rules about which Routes may be bound to a Gateway), and it MUST update its -own `status` with a `condition` of type `DefaultGateway` and `status` true to -indicate that it is a default Gateway and what its scope is, for example: +`spec.useDefaultGateways` to a matching value (subject to the usual Gateway +API rules about which Routes may be bound to a Gateway), and it MUST update +its own `status` with a `condition` of type `DefaultGateway` and `status` true +to indicate that it is a default Gateway and what its scope is, for example: ```yaml status: @@ -472,7 +484,8 @@ from its own namespace. ##### Behavior with No Default Gateway If no Gateway has `spec.defaultScope` set, then all Gateways MUST ignore -`spec.useDefaultGateway` in all Routes. A Route will be bound to only those Gateways that it specifically names in `parentRefs` entries. +`spec.useDefaultGateways` in all Routes. A Route will be bound to only those +Gateways that it specifically names in `parentRefs` entries. ##### Deleting a Default Gateway @@ -496,7 +509,7 @@ options here. 1. Don't bother with any enforcement logic. - In this case, a Route that sets `spec.useDefaultGateway` would be bound to + In this case, a Route that sets `spec.useDefaultGateways` would be bound to _all_ Gateways that have `spec.defaultScope` set a matching scope. Since Gateway API already allows a Route to be bound to multiple Gateways, and the Route `status` is already designed for it, this should function @@ -512,7 +525,7 @@ options here. In this case, every Gateway with `spec.defaultScope` set would ignore it, with the final effect being the same as if no Gateway had `spec.defaultScope` set: all Gateways would ignore - `spec.useDefaultGateway` in all Routes, and each Gateway would only accept + `spec.useDefaultGateways` in all Routes, and each Gateway would only accept Routes that explicitly named it in `parentRefs`. Each Gateway with `spec.defaultScope` set would also update its `status` @@ -532,9 +545,9 @@ options here. In this case, the oldest Gateway with `spec.defaultScope` set would be considered the only default Gateway. That oldest Gateway would be the only - one that honors `spec.useDefaultGateway` in Routes, and all other Gateways - with `spec.defaultScope` set would ignore `spec.useDefaultGateway` in - every Route. + one that honors `spec.useDefaultGateways` in Routes, and all other + Gateways with `spec.defaultScope` set would ignore + `spec.useDefaultGateways` in every Route. The oldest default Gateway would update its `status` to reflect that it the default Gateway; all other Gateways with `spec.defaultScope` set to @@ -601,7 +614,7 @@ merged with other Gateways. #### 4. Enumerating Routes Bound to Default Gateways To enumerate Routes bound to the default Gateways, any of Ana, Chihiro, or Ian -can look for Routes that set `spec.useDefaultGateway` to `true`, and then +can look for Routes that set `spec.useDefaultGateways` to `true`, and then check the `status.parents` of those Routes to see if the Route has been claimed. Since this will also show _which_ Gateways have claimed a given defaulted Route, it neatly solves the problem of allowing Ana to determine @@ -622,7 +635,7 @@ Mesh traffic is defined by using a Service as a `parentRef` rather than a Gateway. As such, there is no case where a default Gateway would be used for mesh traffic. -As noted above, a Route MAY both set `spec.useDefaultGateway` _and_ include a +As noted above, a Route MAY both set `spec.useDefaultGateways` _and_ include a `Service` `parentRef` entry, allowing a single Route to handle both N/S and E/W traffic. In this case, the Route will be bound to both the default Gateway and the mesh, and the `status` will show both parents. diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 32eed6cc04..492299449e 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3045,9 +3045,9 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -3696,9 +3696,9 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset or set to the empty string `\"\"` (the default), the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to explicit Route attachment.", + Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset (the default), set to an empty string (`\"\"`), or set to None, the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to direct Route attachment.", Type: []string{"string"}, Format: "", }, @@ -5440,9 +5440,9 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -6924,9 +6924,9 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7161,9 +7161,9 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7418,9 +7418,9 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7880,9 +7880,9 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, }, }, - "useDefaultGateway": { + "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateway indicates the default Gateway scope to use for this Route. If unset (the default), the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway. not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, From d86675029baf0acfe379b8c327c0a346d682f235 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Sep 2025 13:49:06 -0400 Subject: [PATCH 179/224] chore: Review feedback: Drop empty string from doc comments Signed-off-by: Flynn --- apis/v1/gateway_types.go | 9 ++++----- apis/v1/shared_types.go | 9 ++++----- .../gateway.networking.k8s.io_gateways.yaml | 18 ++++++++---------- .../gateway.networking.k8s.io_grpcroutes.yaml | 9 ++++----- .../gateway.networking.k8s.io_httproutes.yaml | 18 ++++++++---------- .../gateway.networking.k8s.io_tcproutes.yaml | 9 ++++----- .../gateway.networking.k8s.io_tlsroutes.yaml | 18 ++++++++---------- .../gateway.networking.k8s.io_udproutes.yaml | 9 ++++----- .../gateway.networking.k8s.io_gateways.yaml | 18 ++++++++---------- .../gateway.networking.k8s.io_grpcroutes.yaml | 9 ++++----- .../gateway.networking.k8s.io_httproutes.yaml | 18 ++++++++---------- pkg/generated/openapi/zz_generated.openapi.go | 16 ++++++++-------- 12 files changed, 72 insertions(+), 88 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index c566ef40d4..82bdd76749 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -299,11 +299,10 @@ type GatewaySpec struct { // meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) // attached to it, according to the scope configured here. // - // If unset (the default), set to an empty string (`""`), or set to None, - // the Gateway will not act as a default Gateway; if set, the Gateway will - // claim any Route with a matching scope set in its UseDefaultGateway - // field, subject to the usual rules about which routes the Gateway can - // attach to. + // If unset (the default) or set to None, the Gateway will not act as a + // default Gateway; if set, the Gateway will claim any Route with a + // matching scope set in its UseDefaultGateway field, subject to the usual + // rules about which routes the Gateway can attach to. // // Think carefully before using this functionality! While the normal rules // about which Route can apply are still enforced, it is simply easier for diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index f7ca95f5a4..5c29aa4f00 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -248,11 +248,10 @@ type CommonRouteSpec struct { ParentRefs []ParentReference `json:"parentRefs,omitempty"` // UseDefaultGateways indicates the default Gateway scope to use for this - // Route. If unset (the default), set to an empty string (`""`), or set to - // None, the Route will not be attached to any default Gateway; if set, it - // will be attached to any default Gateway supporting the named scope, - // subject to the usual rules about which Routes a Gateway is allowed to - // claim. + // Route. If unset (the default) or set to None, the Route will not be + // attached to any default Gateway; if set, it will be attached to any + // default Gateway supporting the named scope, subject to the usual rules + // about which Routes a Gateway is allowed to claim. // // Think carefully before using this functionality! The set of default // Gateways supporting the requested scope can change over time without diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index fc6ca9d117..563669ba35 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -220,11 +220,10 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset (the default), set to an empty string (`""`), or set to None, - the Gateway will not act as a default Gateway; if set, the Gateway will - claim any Route with a matching scope set in its UseDefaultGateway - field, subject to the usual rules about which routes the Gateway can - attach to. + If unset (the default) or set to None, the Gateway will not act as a + default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -1796,11 +1795,10 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset (the default), set to an empty string (`""`), or set to None, - the Gateway will not act as a default Gateway; if set, the Gateway will - claim any Route with a matching scope set in its UseDefaultGateway - field, subject to the usual rules about which routes the Gateway can - attach to. + If unset (the default) or set to None, the Gateway will not act as a + default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 9d12ec73f7..d10b0530d6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -1941,11 +1941,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index f8591a56f7..e3538d5991 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3879,11 +3879,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without @@ -8038,11 +8037,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index a2d34a198e..159d6a73d8 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -450,11 +450,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 4dfadbfdb5..2961ddd945 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -514,11 +514,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without @@ -1311,11 +1310,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index f610603648..12faf4df0a 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -450,11 +450,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index cd71c1bf02..83f92493ba 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -139,11 +139,10 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset (the default), set to an empty string (`""`), or set to None, - the Gateway will not act as a default Gateway; if set, the Gateway will - claim any Route with a matching scope set in its UseDefaultGateway - field, subject to the usual rules about which routes the Gateway can - attach to. + If unset (the default) or set to None, the Gateway will not act as a + default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for @@ -1274,11 +1273,10 @@ spec: meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here. - If unset (the default), set to an empty string (`""`), or set to None, - the Gateway will not act as a default Gateway; if set, the Gateway will - claim any Route with a matching scope set in its UseDefaultGateway - field, subject to the usual rules about which routes the Gateway can - attach to. + If unset (the default) or set to None, the Gateway will not act as a + default Gateway; if set, the Gateway will claim any Route with a + matching scope set in its UseDefaultGateway field, subject to the usual + rules about which routes the Gateway can attach to. Think carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 9c99efd467..2580392a81 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1802,11 +1802,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 80f75e9b1b..d63aab6844 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2566,11 +2566,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without @@ -5394,11 +5393,10 @@ spec: useDefaultGateways: description: |- UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default), set to an empty string (`""`), or set to - None, the Route will not be attached to any default Gateway; if set, it - will be attached to any default Gateway supporting the named scope, - subject to the usual rules about which Routes a Gateway is allowed to - claim. + Route. If unset (the default) or set to None, the Route will not be + attached to any default Gateway; if set, it will be attached to any + default Gateway supporting the named scope, subject to the usual rules + about which Routes a Gateway is allowed to claim. Think carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 492299449e..ddab62145b 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3047,7 +3047,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -3698,7 +3698,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset (the default), set to an empty string (`\"\"`), or set to None, the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to direct Route attachment.", + Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset (the default) or set to None, the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to direct Route attachment.", Type: []string{"string"}, Format: "", }, @@ -5442,7 +5442,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -6926,7 +6926,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7163,7 +7163,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7420,7 +7420,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, @@ -7882,7 +7882,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default), set to an empty string (`\"\"`), or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", Type: []string{"string"}, Format: "", }, From 0a48c44a3d52211b6ccf762cd1de5eb9f1e3a51c Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Sep 2025 18:31:27 -0400 Subject: [PATCH 180/224] chore: Address more review feedback Signed-off-by: Flynn --- apis/v1/gateway_types.go | 3 +- apis/v1/shared_types.go | 7 ++- .../gateway.networking.k8s.io_gateways.yaml | 46 ------------------- .../gateway.networking.k8s.io_grpcroutes.yaml | 18 -------- .../gateway.networking.k8s.io_httproutes.yaml | 36 --------------- pkg/generated/openapi/zz_generated.openapi.go | 16 +++---- 6 files changed, 15 insertions(+), 111 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 82bdd76749..10eb5bee06 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -313,7 +313,8 @@ type GatewaySpec struct { // recommend not using this just because it seems convenient, and instead // stick to direct Route attachment. // - // +optional + // +optional + // DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` } diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 5c29aa4f00..eb8806837f 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -158,7 +158,9 @@ type ParentReference struct { // GatewayDefaultScope defines the set of default scopes that a Gateway // can claim, for use in any Route type. At present the only supported // scopes are "All" and "None". "None" is a special scope which -// explicitly means that the Route MUST NOT be defaulted. +// explicitly means that the Route MUST NOT attached to any default +// Gateway. +// // +kubebuilder:validation:Enum=All;None type GatewayDefaultScope string @@ -260,7 +262,8 @@ type CommonRouteSpec struct { // example, a Route with specific security requirements should almost // certainly not use a default Gateway. // - // +optional + // +optional + // UseDefaultGateways GatewayDefaultScope `json:"useDefaultGateways,omitempty"` } diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 83f92493ba..98914347d2 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -133,29 +133,6 @@ spec: - message: Hostname values must be unique rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' - defaultScope: - description: |- - DefaultScope, when set, configures the Gateway as a default Gateway, - meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) - attached to it, according to the scope configured here. - - If unset (the default) or set to None, the Gateway will not act as a - default Gateway; if set, the Gateway will claim any Route with a - matching scope set in its UseDefaultGateway field, subject to the usual - rules about which routes the Gateway can attach to. - - Think carefully before using this functionality! While the normal rules - about which Route can apply are still enforced, it is simply easier for - the wrong Route to be accidentally attached to this Gateway in this - configuration. If the Gateway operator is not also the operator in - control of the scope (e.g. namespace) with tight controls and checks on - what kind of workloads and Routes get added in that scope, we strongly - recommend not using this just because it seems convenient, and instead - stick to direct Route attachment. - enum: - - All - - None - type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -1267,29 +1244,6 @@ spec: - message: Hostname values must be unique rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' - defaultScope: - description: |- - DefaultScope, when set, configures the Gateway as a default Gateway, - meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) - attached to it, according to the scope configured here. - - If unset (the default) or set to None, the Gateway will not act as a - default Gateway; if set, the Gateway will claim any Route with a - matching scope set in its UseDefaultGateway field, subject to the usual - rules about which routes the Gateway can attach to. - - Think carefully before using this functionality! While the normal rules - about which Route can apply are still enforced, it is simply easier for - the wrong Route to be accidentally attached to this Gateway in this - configuration. If the Gateway operator is not also the operator in - control of the scope (e.g. namespace) with tight controls and checks on - what kind of workloads and Routes get added in that scope, we strongly - recommend not using this just because it seems convenient, and instead - stick to direct Route attachment. - enum: - - All - - None - type: string gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 2580392a81..b02f9a41d1 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1799,24 +1799,6 @@ spec: : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128' - useDefaultGateways: - description: |- - UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default) or set to None, the Route will not be - attached to any default Gateway; if set, it will be attached to any - default Gateway supporting the named scope, subject to the usual rules - about which Routes a Gateway is allowed to claim. - - Think carefully before using this functionality! The set of default - Gateways supporting the requested scope can change over time without - any notice to the Route author, and in many situations it will not be - appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost - certainly not use a default Gateway. - enum: - - All - - None - type: string type: object status: description: Status defines the current state of GRPCRoute. diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index d63aab6844..b57a508f39 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2563,24 +2563,6 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' - useDefaultGateways: - description: |- - UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default) or set to None, the Route will not be - attached to any default Gateway; if set, it will be attached to any - default Gateway supporting the named scope, subject to the usual rules - about which Routes a Gateway is allowed to claim. - - Think carefully before using this functionality! The set of default - Gateways supporting the requested scope can change over time without - any notice to the Route author, and in many situations it will not be - appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost - certainly not use a default Gateway. - enum: - - All - - None - type: string type: object status: description: Status defines the current state of HTTPRoute. @@ -5390,24 +5372,6 @@ spec: : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' - useDefaultGateways: - description: |- - UseDefaultGateways indicates the default Gateway scope to use for this - Route. If unset (the default) or set to None, the Route will not be - attached to any default Gateway; if set, it will be attached to any - default Gateway supporting the named scope, subject to the usual rules - about which Routes a Gateway is allowed to claim. - - Think carefully before using this functionality! The set of default - Gateways supporting the requested scope can change over time without - any notice to the Route author, and in many situations it will not be - appropriate to request a default Gateway for a given Route -- for - example, a Route with specific security requirements should almost - certainly not use a default Gateway. - enum: - - All - - None - type: string type: object status: description: Status defines the current state of HTTPRoute. diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index ddab62145b..bfa005bef0 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3047,7 +3047,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -3698,7 +3698,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -4228,7 +4228,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "defaultScope": { SchemaProps: spec.SchemaProps{ - Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset (the default) or set to None, the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to direct Route attachment.", + Description: "DefaultScope, when set, configures the Gateway as a default Gateway, meaning it will dynamically and implicitly have Routes (e.g. HTTPRoute) attached to it, according to the scope configured here.\n\nIf unset (the default) or set to None, the Gateway will not act as a default Gateway; if set, the Gateway will claim any Route with a matching scope set in its UseDefaultGateway field, subject to the usual rules about which routes the Gateway can attach to.\n\nThink carefully before using this functionality! While the normal rules about which Route can apply are still enforced, it is simply easier for the wrong Route to be accidentally attached to this Gateway in this configuration. If the Gateway operator is not also the operator in control of the scope (e.g. namespace) with tight controls and checks on what kind of workloads and Routes get added in that scope, we strongly recommend not using this just because it seems convenient, and instead stick to direct Route attachment.\n\n", Type: []string{"string"}, Format: "", }, @@ -5442,7 +5442,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -6926,7 +6926,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -7163,7 +7163,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -7420,7 +7420,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, @@ -7882,7 +7882,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "useDefaultGateways": { SchemaProps: spec.SchemaProps{ - Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.", + Description: "UseDefaultGateways indicates the default Gateway scope to use for this Route. If unset (the default) or set to None, the Route will not be attached to any default Gateway; if set, it will be attached to any default Gateway supporting the named scope, subject to the usual rules about which Routes a Gateway is allowed to claim.\n\nThink carefully before using this functionality! The set of default Gateways supporting the requested scope can change over time without any notice to the Route author, and in many situations it will not be appropriate to request a default Gateway for a given Route -- for example, a Route with specific security requirements should almost certainly not use a default Gateway.\n\n", Type: []string{"string"}, Format: "", }, From 368d492fffe6dc503312003f65c228e294f7947e Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Thu, 4 Sep 2025 20:27:15 -0300 Subject: [PATCH 181/224] Improve some ListenetSet gep descriptions (#3978) * Improve some ListenetSet gep descriptions * Add examples of conflicting ListenerSets * Fix some review findings * Fix some comments on GEP * Make the behavior on route attachement explicit * Fix some reviews * Use XListenerSet on example kinds * Final fix on listenerset gep * Fix some more reviews * Add clarification on ListenerSet attachment --- geps/gep-1713/index.md | 372 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 353 insertions(+), 19 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index c720b35794..db9f765159 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -49,6 +49,9 @@ The feature will be part of the experimental channel, which implementations can This proposal introduces a new `ListenerSet` resource that has the ability to attach a set of listeners to multiple parent `Gateways`. +**Note**: While this API is experimental, its `Kind` will be `XListenerSet` and +once the API is gratuated to stable it will be renamed to `ListenerSet`. + ### Go ```go @@ -59,7 +62,7 @@ type GatewaySpec struct { } type AllowedListeners struct { - // +kubebuilder:default={from:Same} + // +kubebuilder:default={from: None} Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` } @@ -69,7 +72,7 @@ type ListenerNamespaces struct { // values are: // // * Same: Only ListenerSets in the same namespace may be attached to this Gateway. - // * Selector: ListenerSets in namespaces selected by the selector may be attached to this Gateway.:w + // * Selector: ListenerSets in namespaces selected by the selector may be attached to this Gateway. // * All: ListenerSets in all namespaces may be attached to this Gateway. // * None: Only listeners defined in the Gateway's spec are allowed // @@ -109,12 +112,24 @@ type ListenerSetSpec struct { // Listeners in a `Gateway` and their attached `ListenerSets` are concatenated // as a list when programming the underlying infrastructure. // + // // Listeners should be merged using the following precedence: // // 1. "parent" Gateway // 2. ListenerSet ordered by creation time (oldest first) // 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. // + // Regarding Conflict Management, Listeners in a ListenerSet follow the same + // rules of Listeners on a Gateway resource. + // + // Listener validation should happen within all of the ListenerSets attached to a + // Gateway, and the precedence of "parent Gateway" -> "oldest first" -> + // "alphabetically ordered" should be respected. + // + // ListenerSets containing conflicting Listeners MUST set the Conflicted + // Condition to true and clearly indicate which Listeners are conflicted. + // + // // +listType=map // +listMapKey=name // +kubebuilder:validation:MinItems=1 @@ -330,7 +345,8 @@ type ParentGatewayReference struct { ### YAML -The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. +The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. +Only `ListenerSets` from the same namespace of the `Gateway` will be accepted: ```yaml apiVersion: gateway.networking.k8s.io/v1 @@ -339,6 +355,9 @@ metadata: name: parent-gateway spec: gatewayClassName: example + allowedListeners: + namespaces: + from: Same listeners: - name: foo hostname: foo.com @@ -346,7 +365,7 @@ spec: port: 80 --- apiVersion: gateway.networking.x-k8s.io/v1alpha1 -kind: ListenerSet +kind: XListenerSet metadata: name: first-workload-listeners spec: @@ -367,7 +386,7 @@ spec: name: first-workload-cert # Provisioned via HTTP01 challenge --- apiVersion: gateway.networking.x-k8s.io/v1alpha1 -kind: ListenerSet +kind: XListenerSet metadata: name: second-workload-listeners spec: @@ -397,6 +416,22 @@ spec: ## Semantics +### Summary of attachments + +Nick Young did a great summarization of how a handshake and route attachment should behave. This is copied as/is as it is a great summary: + +* Routes attach to all **relevant** Listeners in their **direct Parent** object. +* If a Route has a parentRef that is a ListenerSet, then the ListenerSet is the **direct Parent**. +* If a Route has a parentRef that is a Gateway, then the Gateway is the **direct Parent**. +* If the Route is using Gateway defaulting, then the default Gateway is the **direct Parent**. +* If `sectionName` is not set, then all Listeners in the direct Parent object are **relevant**, and the Route must attach to all of them (subject to any `allowedRoutes` criteria.) +* If `sectionName` is set, then only the Listener in the direct Parent object with the `name` field set to the same value as `sectionname` is **relevant**, and the Route must attach only to that Listener (subject to any `allowedRoutes` criteria). +* If there are no relevant Listeners (because, for example, a sectionName is specified that does not exist on the direct Parent), then the Route has nowhere to attach to and MUST be have `Accepted` set to `false` for that `parentRef`. + +Route status is per-`parentRef`, so if a new parentRef is added, that attachment is independent of any existing parentRefs. A Route can be Accepted by one parentRef and not another, that's fine. + +If you have a Route that has a Gateway `parentRef` with a sectionName, that is Accepted already, and you add another parentRef that points to a `ListenerSet` with a `sectionName`, and the `ListenerSet` does not include a Listener with a name matching the sectionName, then the `ListenerSet parentRef` must be `Accepted status: false`. That does not affect the Gateway parentRef. + ### Gateway Changes An initial experimental release of `ListenerSets` _will have no modifications_ to listener list on the `Gateway` resource. Using `ListenerSets` will require a dummy listener to be configured. @@ -417,15 +452,14 @@ metadata: name: parent-gateway spec: allowedListeners: - - from: Same + namespaces: + from: Same ``` ### Route Attachment Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners in the `ListenerSet`. -Routes MUST be able to attach to a `ListenerSet` and it's parent `Gateway` by having multiple `parentRefs` eg: - ```yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute @@ -434,11 +468,11 @@ metadata: spec: parentRefs: - name: second-workload-listeners - kind: ListenerSet + kind: XListenerSet sectionName: second ``` -For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status `Accepted` condition should be set to `False` +To attach a Route to a `XListenerSet` and its parent `Gateway`, it MUST have multiple `parentRefs` eg: ```yaml apiVersion: gateway.networking.k8s.io/v1 @@ -447,30 +481,132 @@ metadata: name: httproute-example spec: parentRefs: - - name: some-workload-listeners - kind: ListenerSet + - name: second-workload-listeners + kind: XListenerSet + sectionName: second + - name: parent-gateway + kind: Gateway sectionName: foo ``` -To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`: +For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`, which exists on a `ListenerSet` but not on a `Gateway`. +This is not valid and the route's status `Accepted` condition should be set to `False` + ```yaml apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + allowedListeners: + namespaces: + from: Same + listeners: + - name: notfoo + hostname: foo.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + name: first-workload-listeners +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: foo + hostname: first.foo.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-example spec: parentRefs: - - name: second-workload-listeners - kind: ListenerSet - sectionName: second - name: parent-gateway kind: Gateway sectionName: foo ``` -#### Optional Section Name +#### Gateway parents and sectionName + +If a `sectionName` in a Route's `parentRef` is not set then the Route MUST attach to only the listeners in the referenced parent. As an example given a `Gateway` and it's child `ListenerSets` a route attaching to the `Gateway` with an empty `sectionName` shall only attach to the listeners in the `Gateways` immediate `spec.listeners` list. + +In other words, the Route MUST attach just to the Gateway listeners specified on `.spec.listeners` and MUST NOT not attach to any listeners in the child `ListenerSets` +of the `Gateway`. + +This is necessary because, for UX reasons, the `name` field does not have to be unique across all Listeners merged into a Gateway (see the section below for details). -If a `sectionName` in a Route's `parentRef` is not set then the Route MUST attach to only the listeners in the referenced parent. As an example given a `Gateway` and it's child `ListenerSets` a route attaching to the `Gateway` with an empty `sectionName` shall only attach to the listeners in the `Gateways` immediate `spec.listeners` list. In other words, the Route will not attach to any listeners in the `ListenerSets`. This is necessary because, for UX reasons, the `name` field does not have to be unique across all Listeners merged into a Gateway (see the section below for details). +The following manifest exemplifies this situation: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + allowedListeners: + namespaces: + from: Same + listeners: + - name: foo2 + hostname: foo.com + protocol: HTTP + port: 80 + - name: foo3 + hostname: foo1.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + name: first-workload-listeners +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: foo + hostname: first.foo.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + # No SectionName is set on this parentRef + - name: some-workload-listeners + kind: Gateway +``` + +The example above SHOULD be attached only to the following listeners: +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +..... +spec: + listeners: + - name: foo2 + hostname: foo.com + protocol: HTTP + port: 80 + - name: foo3 + hostname: foo1.com + protocol: HTTP + port: 80 +``` ### Policy Attachment @@ -545,7 +681,203 @@ Listeners should be merged using the following precedence: 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. -Conflicts are covered in the section 'ListenerConditions within a ListenerSet' +Conflicts are covered in the section [Listener and ListenerSet conflicts](#listener-and-listenerset-conflicts) + +### Listener and ListenerSet conflicts + +ListenerSet conflicts should be managed similarly to [Gateway resource conflict](https://github.com/kubernetes-sigs/gateway-api/blob/372a5b06624cff12117f41dcd26c08cb1def22e7/apis/v1/gateway_types.go#L76) +management. + +With ListenerSet this validation should happen within the same ListenerSet resource, +but MUST be validated also within a Gateway scope and all of the attached Listeners/ListenerSets. +The SectionName field is an exception for this validation, and while it should +not conflict within the same ListenerSet, it can be duplicated between different ListenerSets. + +This means that the validation should happen now between distinct ListenerSets +attached to the same Gateway, and in case of a conflict, the [Listener Precedence](#listener-precedence) +should be respected, so the first Listener on the precedence list MUST be accepted, +and should not have a `Conflicted` condition, while the conflicting listeners +MUST have a `Conflicted` condition set to True and with an explicit reason on its message. + +Following are some examples of a conflict situation: + +#### Conflict between ListenerSet and parent Gateway + +Given the following resource definitions: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway + namespace: infra +spec: + allowedListeners: + namespaces: + from: All + listeners: + - name: foo + hostname: www.something.tld + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: default-cert +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + name: user-listenerset + namespace: user01 +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: app-cert +``` + +The ListenerSet `user-listenerset` should be marked as Conflicted, as the `parent-gateway` +has a listener definition called `foo` that conflicts with the ListenetSet definition +called `myapp`. The conflict happens because hostname is the same on both `ListenerSet` +but they use different termination TLS certificates: + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + name: user-listenerset + namespace: user01 +.... +status: + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + conditions: + - message: ListenerSet has conflicts with Gateway 'infra/parent-gateway' + reason: ParentNotAccepted + status: "False" + type: Accepted + - message: ListenerSet has conflicts with Gateway 'infra/parent-gateway' + reason: ListenerConflict + status: "True" + type: Conflicted +``` + +#### Conflict between two ListenerSets + +The following example represents a conflict between two ListenerSets on distinct +namespaces. The controller should avoid setting any Condition that exposes information +from other users, but still provide meaningful information of why a ListenerSet +was not accepted + + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + creationTimestamp: "2025-08-11T15:44:05Z" + name: listenerset1 + namespace: user01 +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: app-cert +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + creationTimestamp: "2025-08-11T13:44:05Z" + name: listenerset2 + namespace: user02 +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: other-app-cert +``` + +In this case, there's a conflict as both users are setting the same hostname and +port on distinct Listeners. In this case, because the ListenerSet `user02/listenerset2` +is older, it will be accepted while `user01/listenerset1` should not be accepted, +and receive a `Conflicted=True` condition. + +The status of ListenerSets can be defined as the following: + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + creationTimestamp: "2025-08-11T15:44:05Z" + name: listenerset1 + namespace: user01 +status: + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + conditions: + - message: ListenerSet has conflicts with other listeners attached to the same Gateway + reason: ListenerConflict + status: "True" + type: Conflicted +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XListenerSet +metadata: + creationTimestamp: "2025-08-11T13:44:05Z" + name: listenerset2 + namespace: user02 +status: + listeners: + - name: myapp + hostname: www.something.tld + protocol: HTTPS + port: 443 + conditions: + - reason: Accepted + status: "True" + type: Accepted +``` ### Gateway Conditions @@ -588,6 +920,8 @@ If a listener has a conflict, this should be reported in the `ListenerEntryStatu Implementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc. +Conflicts are covered in the section [Listener and ListenerSet conflicts](#listener-and-listenerset-conflicts) + ## Alternatives ### Re-using Gateway Resource From 17422d48c9e14172b39ec86fb99fb81c0e17eadf Mon Sep 17 00:00:00 2001 From: Romain Date: Sun, 7 Sep 2025 19:05:27 +0200 Subject: [PATCH 182/224] Add conformance report for Traefik Proxy (#4062) --- .../reports/v1.3.0/traefik-traefik/README.md | 29 ++++++++ .../experimental-v3.5.0-default-report.yaml | 69 +++++++++++++++++++ site-src/implementations.md | 4 +- 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 conformance/reports/v1.3.0/traefik-traefik/README.md create mode 100644 conformance/reports/v1.3.0/traefik-traefik/experimental-v3.5.0-default-report.yaml diff --git a/conformance/reports/v1.3.0/traefik-traefik/README.md b/conformance/reports/v1.3.0/traefik-traefik/README.md new file mode 100644 index 0000000000..121b2bd6cd --- /dev/null +++ b/conformance/reports/v1.3.0/traefik-traefik/README.md @@ -0,0 +1,29 @@ +# Traefik Proxy + +## Table of Contents + +| API channel | Implementation version | Mode | Report | +|--------------|------------------------------------------------------------------|---------|------------------------------------------------------------| +| experimental | [v3.5.0](https://github.com/traefik/traefik/releases/tag/v3.5.0) | default | [v3.5.0 report](./experimental-v3.5.0-default-report.yaml) | + +## Reproduce + +To reproduce the results, clone the Traefik Proxy repository: + +```shell +git clone https://github.com/traefik/traefik.git && cd traefik +``` + +Check out the desired version: + +```shell +git checkout vX.Y +``` + +Run the conformance tests with: + +```shell +make test-gateway-api-conformance +``` + +Check the produced report in the `./integration/conformance-reports` folder. diff --git a/conformance/reports/v1.3.0/traefik-traefik/experimental-v3.5.0-default-report.yaml b/conformance/reports/v1.3.0/traefik-traefik/experimental-v3.5.0-default-report.yaml new file mode 100644 index 0000000000..5f11a8bf1b --- /dev/null +++ b/conformance/reports/v1.3.0/traefik-traefik/experimental-v3.5.0-default-report.yaml @@ -0,0 +1,69 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: '-' +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - '@traefik/maintainers' + organization: traefik + project: traefik + url: https://traefik.io/ + version: v3.5 +kind: ConformanceReport +mode: default +profiles: + - core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + name: GATEWAY-GRPC + summary: Core tests succeeded. + - core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 13 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteParentRefPort + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. + - core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + name: GATEWAY-TLS + summary: Core tests succeeded. diff --git a/site-src/implementations.md b/site-src/implementations.md index dc12477c22..aab49663ff 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -600,11 +600,11 @@ STUNner currently supports version `v1alpha2` of the Gateway API specification. ### Traefik Proxy -[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Traefik Proxy-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/traefik-traefik) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Traefik Proxy-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/traefik-traefik) [Traefik Proxy][traefik-proxy] is an open source cloud-native application proxy. -Traefik Proxy currently supports version `v1.2.1` of the Gateway API specification, check the [Kubernetes Gateway Provider Documentation][traefik-proxy-gateway-api-doc] for more information on how to deploy and use it. +Traefik Proxy currently supports version `v1.3.0` of the Gateway API specification, check the [Kubernetes Gateway Provider Documentation][traefik-proxy-gateway-api-doc] for more information on how to deploy and use it. Traefik Proxy's implementation passes all HTTP core and some extended conformance tests, like GRPCRoute, but also supports TCPRoute and TLSRoute features from the Experimental channel. For help and support with Traefik Proxy, [create an issue][traefik-proxy-issue-new] or ask for help in the [Traefik Labs Community Forum][traefiklabs-community-forum]. From d43c0f4060f42d2419f151fe8a4c077043933577 Mon Sep 17 00:00:00 2001 From: Antonio Ojea Date: Mon, 8 Sep 2025 01:53:26 +0200 Subject: [PATCH 183/224] submit report for cloud provider kind (#4067) --- .../v1.3.0/cloud-provider-kind/README.md | 30 +++++++++++++++++++ ...tandard-v0.8.0-alpha.1-default-report.yaml | 22 ++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 conformance/reports/v1.3.0/cloud-provider-kind/README.md create mode 100644 conformance/reports/v1.3.0/cloud-provider-kind/standard-v0.8.0-alpha.1-default-report.yaml diff --git a/conformance/reports/v1.3.0/cloud-provider-kind/README.md b/conformance/reports/v1.3.0/cloud-provider-kind/README.md new file mode 100644 index 0000000000..78ef0af3a5 --- /dev/null +++ b/conformance/reports/v1.3.0/cloud-provider-kind/README.md @@ -0,0 +1,30 @@ +# Cloud Provider KIND + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|standard|[v0.8.0-alpha.1]|default|[report](./standard-v0.8.0-alpha.1-default-report.yaml)| + +## Reproduce + +1. `[Install `cloud-provider-kind`](https://github.com/kubernetes-sigs/cloud-provider-kind/tree/v0.8.0-alpha.1?tab=readme-ov-file#install) + +2. [Run a `KIND` cluster](https://kind.sigs.k8s.io/docs/user/quick-start/) + +3. [Start the `cloud-provider-kind`](https://github.com/kubernetes-sigs/cloud-provider-kind/tree/v0.8.0-alpha.1?tab=readme-ov-file#gateway-api-support-alpha) + +4. Run the conformance tests: + +```sh +go test ./conformance -run TestConformance \ + --report-output /tmp/report.yaml \ + --organization=sigs.k8s.io \ + --project=cloud-provider-kind \ + --url=https://github.com/kubernetes-sigs/cloud-provider-kind \ + --version=v0.8.0-alpha.1 \ + --contact=https://github.com/kubernetes-sigs/cloud-provider-kind/issues/new \ + --gateway-class=cloud-provider-kind \ + --conformance-profiles=GATEWAY-HTTP \ + --supported-features=Gateway,HTTPRoute,ReferenceGrant +``` \ No newline at end of file diff --git a/conformance/reports/v1.3.0/cloud-provider-kind/standard-v0.8.0-alpha.1-default-report.yaml b/conformance/reports/v1.3.0/cloud-provider-kind/standard-v0.8.0-alpha.1-default-report.yaml new file mode 100644 index 0000000000..a9709d2fbd --- /dev/null +++ b/conformance/reports/v1.3.0/cloud-provider-kind/standard-v0.8.0-alpha.1-default-report.yaml @@ -0,0 +1,22 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-09-07T12:44:41Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/kubernetes-sigs/cloud-provider-kind/issues/new + organization: sigs.k8s.io + project: cloud-provider-kind + url: https://github.com/kubernetes-sigs/cloud-provider-kind + version: v0.8.0-alpha.1 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + name: GATEWAY-HTTP + summary: Core tests succeeded. From 78f48a1f856f8980cca2547831ac4ce64c90e90d Mon Sep 17 00:00:00 2001 From: Aaron Wood Date: Mon, 8 Sep 2025 13:23:29 -0700 Subject: [PATCH 184/224] Allow preprepared CoreDNS image to be used (#3906) * Switch to registry.k8s.io/coredns/coredns, only pull if not present * Properly support multiple embedded manifests --- conformance/base/manifests.yaml | 3 ++- conformance/utils/kubernetes/apply.go | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/conformance/base/manifests.yaml b/conformance/base/manifests.yaml index 9380223ea0..63efb5375a 100644 --- a/conformance/base/manifests.yaml +++ b/conformance/base/manifests.yaml @@ -704,7 +704,8 @@ spec: - args: - -conf - /root/Corefile - image: coredns/coredns + image: registry.k8s.io/coredns/coredns:v1.12.2 + imagePullPolicy: IfNotPresent name: coredns securityContext: allowPrivilegeEscalation: false diff --git a/conformance/utils/kubernetes/apply.go b/conformance/utils/kubernetes/apply.go index 1b3b01d5aa..3f31b308d7 100644 --- a/conformance/utils/kubernetes/apply.go +++ b/conformance/utils/kubernetes/apply.go @@ -340,18 +340,21 @@ func getContentsFromPathOrURL(manifestFS []fs.FS, location string, timeoutConfig } return manifests, nil } - var err error - var buf []byte + + var buffer bytes.Buffer for _, mfs := range manifestFS { - buf, err = fs.ReadFile(mfs, location) + buf, err := fs.ReadFile(mfs, location) if err != nil && errors.Is(err, fs.ErrNotExist) { continue } else if err != nil { return nil, err } - return bytes.NewBuffer(buf), nil + _, err = buffer.Write(buf) + if err != nil { + return nil, err + } } - return nil, err + return &buffer, nil } // convertGatewayAddrsToPrimitives converts a slice of Gateway addresses From 58c1466f361b664fafdc39ae54588d904e02a04b Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Wed, 10 Sep 2025 18:37:58 +0200 Subject: [PATCH 185/224] Update index.md field after moving BackendTLS struct (#4041) --- geps/gep-3155/index.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/geps/gep-3155/index.md b/geps/gep-3155/index.md index 06324f6811..0ced93ae9b 100644 --- a/geps/gep-3155/index.md +++ b/geps/gep-3155/index.md @@ -43,20 +43,24 @@ Specifying credentials at the gateway level is the default operation mode, where backends will be presented with a single gateway certificate. Per-service overrides are subject for consideration as the future work. -**1. Add a new `BackendValidation` field at TLSConfig struct located in GatewayTLSConfig.Default field** +**1. Add a new `Backend` field at GatewayTLSConfig struct located in Gateway** ```go -// TLSConfig describes TLS configuration that can apply to multiple Listeners -// within this Gateway. -type TLSConfig struct { - ... - // GatewayBackendTLS describes TLS configuration for gateway when connecting +// GatewayTLSConfig specifies frontend and backend tls configuration for gateway. +type GatewayTLSConfig struct { + // Backend describes TLS configuration for gateway when connecting // to backends. + // + // Note that this contains only details for the Gateway as a TLS client, + // and does _not_ imply behavior about how to choose which backend should + // get a TLS connection. That is determined by the presence of a BackendTLSPolicy. + // // Support: Core // // +optional // - BackendValidation *GatewayBackendTLS `json:"backendValidation,omitempty"` + Backend *GatewayBackendTLS `json:"backend,omitempty"` + ... } type GatewayBackendTLS struct { // ClientCertificateRef is a reference to an object that contains a Client From 03e088610c703380f865e4d6610f054f7f416540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Dudfield?= Date: Fri, 12 Sep 2025 20:24:08 +0200 Subject: [PATCH 186/224] concepts/tooling.md: Add Headlamp tool (#4083) --- site-src/concepts/tooling.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/site-src/concepts/tooling.md b/site-src/concepts/tooling.md index c8e6a240ba..5f4e853b96 100644 --- a/site-src/concepts/tooling.md +++ b/site-src/concepts/tooling.md @@ -14,6 +14,12 @@ A command line tool for managing your Gateway API resources. Explore your polici Get started with [kubernetes-sigs/gwctl: installation](https://github.com/kubernetes-sigs/gwctl?tab=readme-ov-file#installation)! +## `Headlamp` + +A UI for Kubernetes which has Gateway API support built in. View Gateway API resources in a map view, or in data tables. Updated in real time, with links between Kubernetes resources to make it easier to see relationships. + +Get started with [kubernetes-sigs/headlamp: installation](https://github.com/kubernetes-sigs/headlamp?tab=readme-ov-file#quickstart)! + ## Third-Party Tooling ### `policy-machinery` From 5cad7cc473bb34a57672f381541891da3e30c44d Mon Sep 17 00:00:00 2001 From: Candace Holman Date: Mon, 15 Sep 2025 19:50:10 -0400 Subject: [PATCH 187/224] Issue 3940: Move BackendTLSPolicy to standard (#4074) Copy: apis/v1alpha3/backendtlspolicy_types.go -> apis/v1/backendtlspolicy_types.go apis/v1alpha2/policy_types.go -> apis/v1/policy_types.go Update: apis/v1alpha2/policy_types.go apis/v1alpha3/backendtlspolicy_types.go config/crd/kustomization.yaml conformance/tests/backendtlspolicy-conflict-resolution.go conformance/tests/backendtlspolicy-conflict-resolution.yaml conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml conformance/tests/backendtlspolicy-invalid-kind.go conformance/tests/backendtlspolicy-invalid-kind.yaml conformance/tests/backendtlspolicy-observed-generation-bump.go conformance/tests/backendtlspolicy-observed-generation-bump.yaml conformance/tests/backendtlspolicy-san.go conformance/tests/backendtlspolicy-san.yaml conformance/tests/backendtlspolicy.go conformance/tests/backendtlspolicy.yaml conformance/utils/kubernetes/helpers.go examples/standard/backendtlspolicy/backendtlspolicy-ca-certs.yaml examples/standard/backendtlspolicy/backendtlspolicy-system-certs.yaml pkg/features/backendtlspolicy.go pkg/generator/main.go pkg/test/cel/backendtlspolicy_test.go site-src/guides/tls.md Delete: examples/experimental/v1alpha3/backendtlspolicy-ca-certs.yaml examples/experimental/v1alpha3/backendtlspolicy-system-certs.yaml Regenerate the remaining files: rm -rf pkg/client make generate hack/../hack/verify-golint.sh (if needed) --- apis/v1/backendtlspolicy_types.go | 318 ++++ apis/v1/policy_types.go | 279 ++++ apis/v1/zz_generated.deepcopy.go | 235 +++ apis/v1/zz_generated.register.go | 2 + apis/v1alpha2/policy_types.go | 262 +--- apis/v1alpha2/zz_generated.deepcopy.go | 13 +- apis/v1alpha3/backendtlspolicy_types.go | 292 +--- apis/v1alpha3/zz_generated.deepcopy.go | 76 - apisx/v1alpha1/shared_types.go | 5 +- apisx/v1alpha1/zz_generated.deepcopy.go | 4 +- .../apis/v1/backendtlspolicy.go | 281 ++++ .../apis/v1/backendtlspolicyspec.go | 72 + .../apis/v1/backendtlspolicyvalidation.go | 80 + .../apis/v1/localpolicytargetreference.go | 61 + ...calpolicytargetreferencewithsectionname.go | 68 + .../apis/v1/policyancestorstatus.go | 67 + applyconfiguration/apis/v1/policystatus.go | 44 + applyconfiguration/apis/v1/subjectaltname.go | 61 + .../apis/v1alpha2/policystatus.go | 8 +- .../apis/v1alpha3/backendtlspolicy.go | 10 +- .../v1alpha3/backendtlspolicyvalidation.go | 5 +- .../apis/v1alpha3/subjectaltname.go | 9 +- .../v1alpha1/backendtrafficpolicyspec.go | 9 +- .../apisx/v1alpha1/xbackendtrafficpolicy.go | 6 +- applyconfiguration/internal/internal.go | 257 ++-- applyconfiguration/utils.go | 30 +- ....networking.k8s.io_backendtlspolicies.yaml | 663 ++++++++- config/crd/kustomization.yaml | 1 + ....networking.k8s.io_backendtlspolicies.yaml | 1318 +++++++++++++++++ .../backendtlspolicy-conflict-resolution.go | 9 +- .../backendtlspolicy-conflict-resolution.yaml | 10 +- ...endtlspolicy-invalid-ca-certificate-ref.go | 10 +- ...dtlspolicy-invalid-ca-certificate-ref.yaml | 4 +- .../tests/backendtlspolicy-invalid-kind.go | 10 +- .../tests/backendtlspolicy-invalid-kind.yaml | 2 +- ...ckendtlspolicy-observed-generation-bump.go | 11 +- ...endtlspolicy-observed-generation-bump.yaml | 2 +- conformance/tests/backendtlspolicy-san.go | 5 +- conformance/tests/backendtlspolicy-san.yaml | 12 +- conformance/tests/backendtlspolicy.go | 12 +- conformance/tests/backendtlspolicy.yaml | 6 +- conformance/utils/kubernetes/helpers.go | 5 +- .../backendtlspolicy-ca-certs.yaml | 2 +- .../backendtlspolicy-system-certs.yaml | 2 +- .../versioned/typed/apis/v1/apis_client.go | 5 + .../typed/apis/v1/backendtlspolicy.go | 74 + .../typed/apis/v1/fake/fake_apis_client.go | 4 + .../apis/v1/fake/fake_backendtlspolicy.go | 51 + .../typed/apis/v1/generated_expansion.go | 2 + .../apis/v1/backendtlspolicy.go | 102 ++ .../externalversions/apis/v1/interface.go | 7 + .../informers/externalversions/generic.go | 2 + .../listers/apis/v1/backendtlspolicy.go | 70 + .../listers/apis/v1/expansion_generated.go | 8 + pkg/features/backendtlspolicy.go | 2 +- pkg/generated/openapi/zz_generated.openapi.go | 751 +++++++--- pkg/generator/main.go | 11 +- pkg/test/cel/backendtlspolicy_test.go | 273 ++-- site-src/guides/tls.md | 4 +- 59 files changed, 4797 insertions(+), 1207 deletions(-) create mode 100644 apis/v1/backendtlspolicy_types.go create mode 100644 apis/v1/policy_types.go create mode 100644 applyconfiguration/apis/v1/backendtlspolicy.go create mode 100644 applyconfiguration/apis/v1/backendtlspolicyspec.go create mode 100644 applyconfiguration/apis/v1/backendtlspolicyvalidation.go create mode 100644 applyconfiguration/apis/v1/localpolicytargetreference.go create mode 100644 applyconfiguration/apis/v1/localpolicytargetreferencewithsectionname.go create mode 100644 applyconfiguration/apis/v1/policyancestorstatus.go create mode 100644 applyconfiguration/apis/v1/policystatus.go create mode 100644 applyconfiguration/apis/v1/subjectaltname.go create mode 100644 config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml rename examples/{experimental/v1alpha3 => standard/backendtlspolicy}/backendtlspolicy-ca-certs.yaml (86%) rename examples/{experimental/v1alpha3 => standard/backendtlspolicy}/backendtlspolicy-system-certs.yaml (84%) create mode 100644 pkg/client/clientset/versioned/typed/apis/v1/backendtlspolicy.go create mode 100644 pkg/client/clientset/versioned/typed/apis/v1/fake/fake_backendtlspolicy.go create mode 100644 pkg/client/informers/externalversions/apis/v1/backendtlspolicy.go create mode 100644 pkg/client/listers/apis/v1/backendtlspolicy.go diff --git a/apis/v1/backendtlspolicy_types.go b/apis/v1/backendtlspolicy_types.go new file mode 100644 index 0000000000..5a755eb1ba --- /dev/null +++ b/apis/v1/backendtlspolicy_types.go @@ -0,0 +1,318 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:categories=gateway-api,shortName=btlspolicy +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +// BackendTLSPolicy is a Direct Attached Policy. +// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=Direct" + +// BackendTLSPolicy provides a way to configure how a Gateway +// connects to a Backend via TLS. +type BackendTLSPolicy struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of BackendTLSPolicy. + // +required + Spec BackendTLSPolicySpec `json:"spec"` + + // Status defines the current state of BackendTLSPolicy. + // +optional + Status PolicyStatus `json:"status,omitempty"` +} + +// BackendTLSPolicyList contains a list of BackendTLSPolicies +// +kubebuilder:object:root=true +type BackendTLSPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BackendTLSPolicy `json:"items"` +} + +// BackendTLSPolicySpec defines the desired state of BackendTLSPolicy. +// +// Support: Extended +type BackendTLSPolicySpec struct { + // TargetRefs identifies an API object to apply the policy to. + // Only Services have Extended support. Implementations MAY support + // additional objects, with Implementation Specific support. + // Note that this config applies to the entire referenced resource + // by default, but this default may change in the future to provide + // a more granular application of the policy. + // + // TargetRefs must be _distinct_. This means either that: + // + // * They select different targets. If this is the case, then targetRef + // entries are distinct. In terms of fields, this means that the + // multi-part key defined by `group`, `kind`, and `name` must + // be unique across all targetRef entries in the BackendTLSPolicy. + // * They select different sectionNames in the same target. + // + // + // When more than one BackendTLSPolicy selects the same target and + // sectionName, implementations MUST determine precedence using the + // following criteria, continuing on ties: + // + // * The older policy by creation timestamp takes precedence. For + // example, a policy with a creation timestamp of "2021-07-15 + // 01:02:03" MUST be given precedence over a policy with a + // creation timestamp of "2021-07-15 01:02:04". + // * The policy appearing first in alphabetical order by {name}. + // For example, a policy named `bar` is given precedence over a + // policy named `baz`. + // + // For any BackendTLSPolicy that does not take precedence, the + // implementation MUST ensure the `Accepted` Condition is set to + // `status: False`, with Reason `Conflicted`. + // + // Support: Extended for Kubernetes Service + // + // Support: Implementation-specific for any other resource + // + // +required + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="sectionName must be specified when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" + // +kubebuilder:validation:XValidation:message="sectionName must be unique when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName))))" + TargetRefs []LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"` + + // Validation contains backend TLS validation configuration. + // +required + Validation BackendTLSPolicyValidation `json:"validation"` + + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} + +// BackendTLSPolicyValidation contains backend TLS validation configuration. +// +kubebuilder:validation:XValidation:message="must not contain both CACertificateRefs and WellKnownCACertificates",rule="!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" +// +kubebuilder:validation:XValidation:message="must specify either CACertificateRefs or WellKnownCACertificates",rule="(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" +type BackendTLSPolicyValidation struct { + // CACertificateRefs contains one or more references to Kubernetes objects that + // contain a PEM-encoded TLS CA certificate bundle, which is used to + // validate a TLS handshake between the Gateway and backend Pod. + // + // If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + // specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + // not both. If CACertificateRefs is empty or unspecified, the configuration for + // WellKnownCACertificates MUST be honored instead if supported by the implementation. + // + // A CACertificateRef is invalid if: + // + // * It refers to a resource that cannot be resolved (e.g., the referenced resource + // does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + // named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + // and the Message of the Condition must indicate which reference is invalid and why. + // + // * It refers to an unknown or unsupported kind of resource. In this case, the Reason + // must be set to `InvalidKind` and the Message of the Condition must explain which + // kind of resource is unknown or unsupported. + // + // * It refers to a resource in another namespace. This may change in future + // spec updates. + // + // Implementations MAY choose to perform further validation of the certificate + // content (e.g., checking expiry or enforcing specific formats). In such cases, + // an implementation-specific Reason and Message must be set for the invalid reference. + // + // In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + // the BackendTLSPolicy is set to `status: False`, with a Reason and Message + // that indicate the cause of the error. Connections using an invalid + // CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + // response. If ALL CACertificateRefs are invalid, the implementation MUST also + // ensure the `Accepted` Condition on the BackendTLSPolicy is set to + // `status: False`, with a Reason `NoValidCACertificate`. + // + // + // A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a backend, but this behavior is implementation-specific. + // + // Support: Core - An optional single reference to a Kubernetes ConfigMap, + // with the CA certificate in a key named `ca.crt`. + // + // Support: Implementation-specific - More than one reference, other kinds + // of resources, or a single reference that includes multiple certificates. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MaxItems=8 + CACertificateRefs []LocalObjectReference `json:"caCertificateRefs,omitempty"` + + // WellKnownCACertificates specifies whether system CA certificates may be used in + // the TLS handshake between the gateway and backend pod. + // + // If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + // must be specified with at least one entry for a valid configuration. Only one of + // CACertificateRefs or WellKnownCACertificates may be specified, not both. + // If an implementation does not support the WellKnownCACertificates field, or + // the supplied value is not recognized, the implementation MUST ensure the + // `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + // a Reason `Invalid`. + // + // Support: Implementation-specific + // + // +optional + // +listType=atomic + WellKnownCACertificates *WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` + + // Hostname is used for two purposes in the connection between Gateways and + // backends: + // + // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + // 2. Hostname MUST be used for authentication and MUST match the certificate + // served by the matching backend, unless SubjectAltNames is specified. + // 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + // but MUST NOT be used for authentication. If you want to use the value + // of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. + // + // Support: Core + // + // +required + Hostname PreciseHostname `json:"hostname"` + + // SubjectAltNames contains one or more Subject Alternative Names. + // When specified the certificate served from the backend MUST + // have at least one Subject Alternate Name matching one of the specified SubjectAltNames. + // + // Support: Extended + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MaxItems=5 + SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` +} + +// SubjectAltName represents Subject Alternative Name. +// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain Hostname, if Type is set to Hostname",rule="!(self.type == \"Hostname\" && (!has(self.hostname) || self.hostname == \"\"))" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain Hostname, if Type is not set to Hostname",rule="!(self.type != \"Hostname\" && has(self.hostname) && self.hostname != \"\")" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain URI, if Type is set to URI",rule="!(self.type == \"URI\" && (!has(self.uri) || self.uri == \"\"))" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain URI, if Type is not set to URI",rule="!(self.type != \"URI\" && has(self.uri) && self.uri != \"\")" +type SubjectAltName struct { + // Type determines the format of the Subject Alternative Name. Always required. + // + // Support: Core + // + // +required + Type SubjectAltNameType `json:"type"` + + // Hostname contains Subject Alternative Name specified in DNS name format. + // Required when Type is set to Hostname, ignored otherwise. + // + // Support: Core + // + // +optional + Hostname Hostname `json:"hostname,omitempty"` + + // URI contains Subject Alternative Name specified in a full URI format. + // It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + // Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + // Required when Type is set to URI, ignored otherwise. + // + // Support: Core + // + // +optional + URI AbsoluteURI `json:"uri,omitempty"` +} + +// WellKnownCACertificatesType is the type of CA certificate that will be used +// when the caCertificateRefs field is unspecified. +// +kubebuilder:validation:Enum=System +type WellKnownCACertificatesType string + +const ( + // WellKnownCACertificatesSystem indicates that well known system CA certificates should be used. + WellKnownCACertificatesSystem WellKnownCACertificatesType = "System" +) + +// SubjectAltNameType is the type of the Subject Alternative Name. +// +kubebuilder:validation:Enum=Hostname;URI +type SubjectAltNameType string + +const ( + // HostnameSubjectAltNameType specifies hostname-based SAN. + // + // Support: Core + HostnameSubjectAltNameType SubjectAltNameType = "Hostname" + + // URISubjectAltNameType specifies URI-based SAN, e.g. SPIFFE id. + // + // Support: Core + URISubjectAltNameType SubjectAltNameType = "URI" +) + +const ( + // This reason is used with the "Accepted" condition when it is + // set to false because all CACertificateRefs of the + // BackendTLSPolicy are invalid. + BackendTLSPolicyReasonNoValidCACertificate PolicyConditionReason = "NoValidCACertificate" +) + +const ( + // This condition indicates whether the controller was able to resolve all + // object references for the BackendTLSPolicy. + // + // Possible reasons for this condition to be True are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCACertificateRef" + // * "InvalidKind" + // + // Controllers may raise this condition with other reasons, but should + // prefer to use the reasons listed above to improve interoperability. + BackendTLSPolicyConditionResolvedRefs PolicyConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + BackendTLSPolicyReasonResolvedRefs PolicyConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs is invalid. + // A CACertificateRef is considered invalid when it refers to a nonexistent + // resource or when the data within that resource is malformed. + BackendTLSPolicyReasonInvalidCACertificateRef PolicyConditionReason = "InvalidCACertificateRef" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs references an unknown or unsupported + // Group and/or Kind. + BackendTLSPolicyReasonInvalidKind PolicyConditionReason = "InvalidKind" +) diff --git a/apis/v1/policy_types.go b/apis/v1/policy_types.go new file mode 100644 index 0000000000..552db9bf7a --- /dev/null +++ b/apis/v1/policy_types.go @@ -0,0 +1,279 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +const ( + // PolicyLabelKey is the label whose presence identifies a CRD that the + // Gateway API Policy attachment model. The value of the label SHOULD be one + // of the following: + // - A label value of "Inherited" indicates that this Policy is inheritable. + // An example of inheritable policy is one which if applied at the Gateway + // level would affect all attached HTTPRoutes and their respective + // Backends. + // - A label value of "Direct" indicates that the policy only affects the + // resource to which it is attached and does not affect it's sub resources. + PolicyLabelKey = "gateway.networking.k8s.io/policy" +) + +// LocalPolicyTargetReference identifies an API object to apply a direct or +// inherited policy to. This should be used as part of Policy resources +// that can target Gateway API resources. For more information on how this +// policy attachment model works, and a sample Policy resource, refer to +// the policy attachment documentation for Gateway API. +type LocalPolicyTargetReference struct { + // Group is the group of the target resource. + // +required + Group Group `json:"group"` + + // Kind is kind of the target resource. + // +required + Kind Kind `json:"kind"` + + // Name is the name of the target resource. + // +required + Name ObjectName `json:"name"` +} + +// NamespacedPolicyTargetReference identifies an API object to apply a direct or +// inherited policy to, potentially in a different namespace. This should only +// be used as part of Policy resources that need to be able to target resources +// in different namespaces. For more information on how this policy attachment +// model works, and a sample Policy resource, refer to the policy attachment +// documentation for Gateway API. +type NamespacedPolicyTargetReference struct { + // Group is the group of the target resource. + // +required + Group Group `json:"group"` + + // Kind is kind of the target resource. + // +required + Kind Kind `json:"kind"` + + // Name is the name of the target resource. + // +required + Name ObjectName `json:"name"` + + // Namespace is the namespace of the referent. When unspecified, the local + // namespace is inferred. Even when policy targets a resource in a different + // namespace, it MUST only apply to traffic originating from the same + // namespace as the policy. + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a +// direct policy to. This should be used as part of Policy resources that can +// target single resources. For more information on how this policy attachment +// mode works, and a sample Policy resource, refer to the policy attachment +// documentation for Gateway API. +// +// Note: This should only be used for direct policy attachment when references +// to SectionName are actually needed. In all other cases, +// LocalPolicyTargetReference should be used. +type LocalPolicyTargetReferenceWithSectionName struct { + LocalPolicyTargetReference `json:",inline"` + + // SectionName is the name of a section within the target resource. When + // unspecified, this targetRef targets the entire resource. In the following + // resources, SectionName is interpreted as the following: + // + // * Gateway: Listener name + // * HTTPRoute: HTTPRouteRule name + // * Service: Port name + // + // If a SectionName is specified, but does not exist on the targeted object, + // the Policy must fail to attach, and the policy implementation should record + // a `ResolvedRefs` or similar Condition in the Policy's status. + // + // +optional + SectionName *SectionName `json:"sectionName,omitempty"` +} + +// PolicyConditionType is a type of condition for a policy. This type should be +// used with a Policy resource Status.Conditions field. +type PolicyConditionType string + +// PolicyConditionReason is a reason for a policy condition. +type PolicyConditionReason string + +const ( + // PolicyConditionAccepted indicates whether the policy has been accepted or + // rejected by a targeted resource, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Conflicted" + // * "Invalid" + // * "TargetNotFound" + // + PolicyConditionAccepted PolicyConditionType = "Accepted" + + // PolicyReasonAccepted is used with the "Accepted" condition when the policy + // has been accepted by the targeted resource. + PolicyReasonAccepted PolicyConditionReason = "Accepted" + + // PolicyReasonConflicted is used with the "Accepted" condition when the + // policy has not been accepted by a targeted resource because there is + // another policy that targets the same resource and a merge is not possible. + PolicyReasonConflicted PolicyConditionReason = "Conflicted" + + // PolicyReasonInvalid is used with the "Accepted" condition when the policy + // is syntactically or semantically invalid. + PolicyReasonInvalid PolicyConditionReason = "Invalid" + + // PolicyReasonTargetNotFound is used with the "Accepted" condition when the + // policy is attached to an invalid target resource. + PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" +) + +// PolicyAncestorStatus describes the status of a route with respect to an +// associated Ancestor. +// +// Ancestors refer to objects that are either the Target of a policy or above it +// in terms of object hierarchy. For example, if a policy targets a Service, the +// Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and +// the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most +// useful object to place Policy status on, so we recommend that implementations +// SHOULD use Gateway as the PolicyAncestorStatus object unless the designers +// have a _very_ good reason otherwise. +// +// In the context of policy attachment, the Ancestor is used to distinguish which +// resource results in a distinct application of this policy. For example, if a policy +// targets a Service, it may have a distinct result per attached Gateway. +// +// Policies targeting the same resource may have different effects depending on the +// ancestors of those resources. For example, different Gateways targeting the same +// Service may have different capabilities, especially if they have different underlying +// implementations. +// +// For example, in BackendTLSPolicy, the Policy attaches to a Service that is +// used as a backend in a HTTPRoute that is itself attached to a Gateway. +// In this case, the relevant object for status is the Gateway, and that is the +// ancestor object referred to in this status. +// +// Note that a parent is also an ancestor, so for objects where the parent is the +// relevant object for status, this struct SHOULD still be used. +// +// This struct is intended to be used in a slice that's effectively a map, +// with a composite key made up of the AncestorRef and the ControllerName. +type PolicyAncestorStatus struct { + // AncestorRef corresponds with a ParentRef in the spec that this + // PolicyAncestorStatus struct describes the status of. + // +required + AncestorRef ParentReference `json:"ancestorRef"` + + // ControllerName is a domain/path string that indicates the name of the + // controller that wrote this status. This corresponds with the + // controllerName field on GatewayClass. + // + // Example: "example.net/gateway-controller". + // + // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + // valid Kubernetes names + // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + // +required + ControllerName GatewayController `json:"controllerName"` + + // Conditions describes the status of the Policy with respect to the given Ancestor. + // + // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // + // + // +required + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// PolicyStatus defines the common attributes that all Policies should include within +// their status. +type PolicyStatus struct { + // Ancestors is a list of ancestor resources (usually Gateways) that are + // associated with the policy, and the status of the policy with respect to + // each ancestor. When this policy attaches to a parent, the controller that + // manages the parent and the ancestors MUST add an entry to this list when + // the controller first sees the policy and SHOULD update the entry as + // appropriate when the relevant ancestor is modified. + // + // Note that choosing the relevant ancestor is left to the Policy designers; + // an important part of Policy design is designing the right object level at + // which to namespace this status. + // + // Note also that implementations MUST ONLY populate ancestor status for + // the Ancestor resources they are responsible for. Implementations MUST + // use the ControllerName field to uniquely identify the entries in this list + // that they are responsible for. + // + // Note that to achieve this, the list of PolicyAncestorStatus structs + // MUST be treated as a map with a composite key, made up of the AncestorRef + // and ControllerName fields combined. + // + // A maximum of 16 ancestors will be represented in this list. An empty list + // means the Policy is not relevant for any ancestors. + // + // If this slice is full, implementations MUST NOT add further entries. + // Instead they MUST consider the policy unimplementable and signal that + // on any related resources such as the ancestor that would be referenced + // here. For example, if this list was full on BackendTLSPolicy, no + // additional Gateways would be able to reference the Service targeted by + // the BackendTLSPolicy. + // + // +required + // +listType=atomic + // +kubebuilder:validation:MaxItems=16 + Ancestors []PolicyAncestorStatus `json:"ancestors"` +} diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index be8e2485c2..174c292702 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -128,6 +128,125 @@ func (in *BackendRef) DeepCopy() *BackendRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicy) DeepCopyInto(out *BackendTLSPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicy. +func (in *BackendTLSPolicy) DeepCopy() *BackendTLSPolicy { + if in == nil { + return nil + } + out := new(BackendTLSPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackendTLSPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicyList) DeepCopyInto(out *BackendTLSPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BackendTLSPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicyList. +func (in *BackendTLSPolicyList) DeepCopy() *BackendTLSPolicyList { + if in == nil { + return nil + } + out := new(BackendTLSPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackendTLSPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicySpec) DeepCopyInto(out *BackendTLSPolicySpec) { + *out = *in + if in.TargetRefs != nil { + in, out := &in.TargetRefs, &out.TargetRefs + *out = make([]LocalPolicyTargetReferenceWithSectionName, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Validation.DeepCopyInto(&out.Validation) + if in.Options != nil { + in, out := &in.Options, &out.Options + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicySpec. +func (in *BackendTLSPolicySpec) DeepCopy() *BackendTLSPolicySpec { + if in == nil { + return nil + } + out := new(BackendTLSPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSPolicyValidation) DeepCopyInto(out *BackendTLSPolicyValidation) { + *out = *in + if in.CACertificateRefs != nil { + in, out := &in.CACertificateRefs, &out.CACertificateRefs + *out = make([]LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.WellKnownCACertificates != nil { + in, out := &in.WellKnownCACertificates, &out.WellKnownCACertificates + *out = new(WellKnownCACertificatesType) + **out = **in + } + if in.SubjectAltNames != nil { + in, out := &in.SubjectAltNames, &out.SubjectAltNames + *out = make([]SubjectAltName, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicyValidation. +func (in *BackendTLSPolicyValidation) DeepCopy() *BackendTLSPolicyValidation { + if in == nil { + return nil + } + out := new(BackendTLSPolicyValidation) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CommonRouteSpec) DeepCopyInto(out *CommonRouteSpec) { *out = *in @@ -1724,6 +1843,62 @@ func (in *LocalParametersReference) DeepCopy() *LocalParametersReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalPolicyTargetReference) DeepCopyInto(out *LocalPolicyTargetReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalPolicyTargetReference. +func (in *LocalPolicyTargetReference) DeepCopy() *LocalPolicyTargetReference { + if in == nil { + return nil + } + out := new(LocalPolicyTargetReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalPolicyTargetReferenceWithSectionName) DeepCopyInto(out *LocalPolicyTargetReferenceWithSectionName) { + *out = *in + out.LocalPolicyTargetReference = in.LocalPolicyTargetReference + if in.SectionName != nil { + in, out := &in.SectionName, &out.SectionName + *out = new(SectionName) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalPolicyTargetReferenceWithSectionName. +func (in *LocalPolicyTargetReferenceWithSectionName) DeepCopy() *LocalPolicyTargetReferenceWithSectionName { + if in == nil { + return nil + } + out := new(LocalPolicyTargetReferenceWithSectionName) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacedPolicyTargetReference) DeepCopyInto(out *NamespacedPolicyTargetReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacedPolicyTargetReference. +func (in *NamespacedPolicyTargetReference) DeepCopy() *NamespacedPolicyTargetReference { + if in == nil { + return nil + } + out := new(NamespacedPolicyTargetReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in @@ -1804,6 +1979,51 @@ func (in *ParentReference) DeepCopy() *ParentReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyAncestorStatus) DeepCopyInto(out *PolicyAncestorStatus) { + *out = *in + in.AncestorRef.DeepCopyInto(&out.AncestorRef) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyAncestorStatus. +func (in *PolicyAncestorStatus) DeepCopy() *PolicyAncestorStatus { + if in == nil { + return nil + } + out := new(PolicyAncestorStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) { + *out = *in + if in.Ancestors != nil { + in, out := &in.Ancestors, &out.Ancestors + *out = make([]PolicyAncestorStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyStatus. +func (in *PolicyStatus) DeepCopy() *PolicyStatus { + if in == nil { + return nil + } + out := new(PolicyStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteGroupKind) DeepCopyInto(out *RouteGroupKind) { *out = *in @@ -1964,6 +2184,21 @@ func (in *SessionPersistence) DeepCopy() *SessionPersistence { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubjectAltName) DeepCopyInto(out *SubjectAltName) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubjectAltName. +func (in *SubjectAltName) DeepCopy() *SubjectAltName { + if in == nil { + return nil + } + out := new(SubjectAltName) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SupportedFeature) DeepCopyInto(out *SupportedFeature) { *out = *in diff --git a/apis/v1/zz_generated.register.go b/apis/v1/zz_generated.register.go index 115de0a1cd..1f390588e4 100644 --- a/apis/v1/zz_generated.register.go +++ b/apis/v1/zz_generated.register.go @@ -61,6 +61,8 @@ func init() { // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, + &BackendTLSPolicy{}, + &BackendTLSPolicyList{}, &GRPCRoute{}, &GRPCRouteList{}, &Gateway{}, diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index d24bb2ee74..8b8181a323 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -16,264 +16,18 @@ limitations under the License. package v1alpha2 -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import v1 "sigs.k8s.io/gateway-api/apis/v1" -const ( - // PolicyLabelKey is the label whose presence identifies a CRD that the - // Gateway API Policy attachment model. The value of the label SHOULD be one - // of the following: - // - A label value of "Inherited" indicates that this Policy is inheritable. - // An example of inheritable policy is one which if applied at the Gateway - // level would affect all attached HTTPRoutes and their respective - // Backends. - // - A label value of "Direct" indicates that the policy only affects the - // resource to which it is attached and does not affect it's sub resources. - PolicyLabelKey = "gateway.networking.k8s.io/policy" -) +type LocalPolicyTargetReference v1.LocalPolicyTargetReference -// LocalPolicyTargetReference identifies an API object to apply a direct or -// inherited policy to. This should be used as part of Policy resources -// that can target Gateway API resources. For more information on how this -// policy attachment model works, and a sample Policy resource, refer to -// the policy attachment documentation for Gateway API. -type LocalPolicyTargetReference struct { - // Group is the group of the target resource. - // +required - Group Group `json:"group"` +type NamespacedPolicyTargetReference v1.NamespacedPolicyTargetReference - // Kind is kind of the target resource. - // +required - Kind Kind `json:"kind"` +type LocalPolicyTargetReferenceWithSectionName v1.LocalPolicyTargetReferenceWithSectionName - // Name is the name of the target resource. - // +required - Name ObjectName `json:"name"` -} +type PolicyConditionType v1.PolicyConditionType -// NamespacedPolicyTargetReference identifies an API object to apply a direct or -// inherited policy to, potentially in a different namespace. This should only -// be used as part of Policy resources that need to be able to target resources -// in different namespaces. For more information on how this policy attachment -// model works, and a sample Policy resource, refer to the policy attachment -// documentation for Gateway API. -type NamespacedPolicyTargetReference struct { - // Group is the group of the target resource. - // +required - Group Group `json:"group"` +type PolicyConditionReason v1.PolicyConditionReason - // Kind is kind of the target resource. - // +required - Kind Kind `json:"kind"` +type PolicyAncestorStatus v1.PolicyAncestorStatus - // Name is the name of the target resource. - // +required - Name ObjectName `json:"name"` - - // Namespace is the namespace of the referent. When unspecified, the local - // namespace is inferred. Even when policy targets a resource in a different - // namespace, it MUST only apply to traffic originating from the same - // namespace as the policy. - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` -} - -// LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a -// direct policy to. This should be used as part of Policy resources that can -// target single resources. For more information on how this policy attachment -// mode works, and a sample Policy resource, refer to the policy attachment -// documentation for Gateway API. -// -// Note: This should only be used for direct policy attachment when references -// to SectionName are actually needed. In all other cases, -// LocalPolicyTargetReference should be used. -type LocalPolicyTargetReferenceWithSectionName struct { - LocalPolicyTargetReference `json:",inline"` - - // SectionName is the name of a section within the target resource. When - // unspecified, this targetRef targets the entire resource. In the following - // resources, SectionName is interpreted as the following: - // - // * Gateway: Listener name - // * HTTPRoute: HTTPRouteRule name - // * Service: Port name - // - // If a SectionName is specified, but does not exist on the targeted object, - // the Policy must fail to attach, and the policy implementation should record - // a `ResolvedRefs` or similar Condition in the Policy's status. - // - // +optional - SectionName *SectionName `json:"sectionName,omitempty"` -} - -// PolicyConditionType is a type of condition for a policy. This type should be -// used with a Policy resource Status.Conditions field. -type PolicyConditionType string - -// PolicyConditionReason is a reason for a policy condition. -type PolicyConditionReason string - -const ( - // PolicyConditionAccepted indicates whether the policy has been accepted or - // rejected by a targeted resource, and why. - // - // Possible reasons for this condition to be True are: - // - // * "Accepted" - // - // Possible reasons for this condition to be False are: - // - // * "Conflicted" - // * "Invalid" - // * "TargetNotFound" - // - PolicyConditionAccepted PolicyConditionType = "Accepted" - - // PolicyReasonAccepted is used with the "Accepted" condition when the policy - // has been accepted by the targeted resource. - PolicyReasonAccepted PolicyConditionReason = "Accepted" - - // PolicyReasonConflicted is used with the "Accepted" condition when the - // policy has not been accepted by a targeted resource because there is - // another policy that targets the same resource and a merge is not possible. - PolicyReasonConflicted PolicyConditionReason = "Conflicted" - - // PolicyReasonInvalid is used with the "Accepted" condition when the policy - // is syntactically or semantically invalid. - PolicyReasonInvalid PolicyConditionReason = "Invalid" - - // PolicyReasonTargetNotFound is used with the "Accepted" condition when the - // policy is attached to an invalid target resource. - PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" -) - -// PolicyAncestorStatus describes the status of a route with respect to an -// associated Ancestor. -// -// Ancestors refer to objects that are either the Target of a policy or above it -// in terms of object hierarchy. For example, if a policy targets a Service, the -// Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and -// the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most -// useful object to place Policy status on, so we recommend that implementations -// SHOULD use Gateway as the PolicyAncestorStatus object unless the designers -// have a _very_ good reason otherwise. -// -// In the context of policy attachment, the Ancestor is used to distinguish which -// resource results in a distinct application of this policy. For example, if a policy -// targets a Service, it may have a distinct result per attached Gateway. -// -// Policies targeting the same resource may have different effects depending on the -// ancestors of those resources. For example, different Gateways targeting the same -// Service may have different capabilities, especially if they have different underlying -// implementations. -// -// For example, in BackendTLSPolicy, the Policy attaches to a Service that is -// used as a backend in a HTTPRoute that is itself attached to a Gateway. -// In this case, the relevant object for status is the Gateway, and that is the -// ancestor object referred to in this status. -// -// Note that a parent is also an ancestor, so for objects where the parent is the -// relevant object for status, this struct SHOULD still be used. -// -// This struct is intended to be used in a slice that's effectively a map, -// with a composite key made up of the AncestorRef and the ControllerName. -type PolicyAncestorStatus struct { - // AncestorRef corresponds with a ParentRef in the spec that this - // PolicyAncestorStatus struct describes the status of. - // +required - AncestorRef ParentReference `json:"ancestorRef"` - - // ControllerName is a domain/path string that indicates the name of the - // controller that wrote this status. This corresponds with the - // controllerName field on GatewayClass. - // - // Example: "example.net/gateway-controller". - // - // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are - // valid Kubernetes names - // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). - // - // Controllers MUST populate this field when writing status. Controllers should ensure that - // entries to status populated with their ControllerName are cleaned up when they are no - // longer necessary. - // +required - ControllerName GatewayController `json:"controllerName"` - - // Conditions describes the status of the Policy with respect to the given Ancestor. - // - // - // - // Notes for implementors: - // - // Conditions are a listType `map`, which means that they function like a - // map with a key of the `type` field _in the k8s apiserver_. - // - // This means that implementations must obey some rules when updating this - // section. - // - // * Implementations MUST perform a read-modify-write cycle on this field - // before modifying it. That is, when modifying this field, implementations - // must be confident they have fetched the most recent version of this field, - // and ensure that changes they make are on that recent version. - // * Implementations MUST NOT remove or reorder Conditions that they are not - // directly responsible for. For example, if an implementation sees a Condition - // with type `special.io/SomeField`, it MUST NOT remove, change or update that - // Condition. - // * Implementations MUST always _merge_ changes into Conditions of the same Type, - // rather than creating more than one Condition of the same Type. - // * Implementations MUST always update the `observedGeneration` field of the - // Condition to the `metadata.generation` of the Gateway at the time of update creation. - // * If the `observedGeneration` of a Condition is _greater than_ the value the - // implementation knows about, then it MUST NOT perform the update on that Condition, - // but must wait for a future reconciliation and status update. (The assumption is that - // the implementation's copy of the object is stale and an update will be re-triggered - // if relevant.) - // - // - // - // +required - // +listType=map - // +listMapKey=type - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=8 - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - -// PolicyStatus defines the common attributes that all Policies should include within -// their status. -type PolicyStatus struct { - // Ancestors is a list of ancestor resources (usually Gateways) that are - // associated with the policy, and the status of the policy with respect to - // each ancestor. When this policy attaches to a parent, the controller that - // manages the parent and the ancestors MUST add an entry to this list when - // the controller first sees the policy and SHOULD update the entry as - // appropriate when the relevant ancestor is modified. - // - // Note that choosing the relevant ancestor is left to the Policy designers; - // an important part of Policy design is designing the right object level at - // which to namespace this status. - // - // Note also that implementations MUST ONLY populate ancestor status for - // the Ancestor resources they are responsible for. Implementations MUST - // use the ControllerName field to uniquely identify the entries in this list - // that they are responsible for. - // - // Note that to achieve this, the list of PolicyAncestorStatus structs - // MUST be treated as a map with a composite key, made up of the AncestorRef - // and ControllerName fields combined. - // - // A maximum of 16 ancestors will be represented in this list. An empty list - // means the Policy is not relevant for any ancestors. - // - // If this slice is full, implementations MUST NOT add further entries. - // Instead they MUST consider the policy unimplementable and signal that - // on any related resources such as the ancestor that would be referenced - // here. For example, if this list was full on BackendTLSPolicy, no - // additional Gateways would be able to reference the Service targeted by - // the BackendTLSPolicy. - // - // +required - // +listType=atomic - // +kubebuilder:validation:MaxItems=16 - Ancestors []PolicyAncestorStatus `json:"ancestors"` -} +type PolicyStatus v1.PolicyStatus diff --git a/apis/v1alpha2/zz_generated.deepcopy.go b/apis/v1alpha2/zz_generated.deepcopy.go index 8b09c2d70d..486af9f079 100644 --- a/apis/v1alpha2/zz_generated.deepcopy.go +++ b/apis/v1alpha2/zz_generated.deepcopy.go @@ -21,8 +21,9 @@ limitations under the License. package v1alpha2 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/gateway-api/apis/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -102,10 +103,10 @@ func (in *LocalPolicyTargetReference) DeepCopy() *LocalPolicyTargetReference { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalPolicyTargetReferenceWithSectionName) DeepCopyInto(out *LocalPolicyTargetReferenceWithSectionName) { *out = *in - in.LocalPolicyTargetReference.DeepCopyInto(&out.LocalPolicyTargetReference) + out.LocalPolicyTargetReference = in.LocalPolicyTargetReference if in.SectionName != nil { in, out := &in.SectionName, &out.SectionName - *out = new(SectionName) + *out = new(v1.SectionName) **out = **in } } @@ -125,7 +126,7 @@ func (in *NamespacedPolicyTargetReference) DeepCopyInto(out *NamespacedPolicyTar *out = *in if in.Namespace != nil { in, out := &in.Namespace, &out.Namespace - *out = new(Namespace) + *out = new(v1.Namespace) **out = **in } } @@ -146,7 +147,7 @@ func (in *PolicyAncestorStatus) DeepCopyInto(out *PolicyAncestorStatus) { in.AncestorRef.DeepCopyInto(&out.AncestorRef) if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -168,7 +169,7 @@ func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) { *out = *in if in.Ancestors != nil { in, out := &in.Ancestors, &out.Ancestors - *out = make([]PolicyAncestorStatus, len(*in)) + *out = make([]v1.PolicyAncestorStatus, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index cbd2c46410..4917063b12 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -20,304 +20,16 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" ) // +genclient // +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:storageversion -// +kubebuilder:resource:categories=gateway-api,shortName=btlspolicy -// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` -// -// BackendTLSPolicy is a Direct Attached Policy. -// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=Direct" +// +kubebuilder:deprecatedversion:warning="The v1alpha3 version of BackendTLSPolicy has been deprecated and will be removed in a future release of the API. Please upgrade to v1." +type BackendTLSPolicy v1.BackendTLSPolicy -// BackendTLSPolicy provides a way to configure how a Gateway -// connects to a Backend via TLS. -type BackendTLSPolicy struct { - metav1.TypeMeta `json:",inline"` - // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` - - // Spec defines the desired state of BackendTLSPolicy. - // +required - Spec BackendTLSPolicySpec `json:"spec"` - - // Status defines the current state of BackendTLSPolicy. - // +optional - Status v1alpha2.PolicyStatus `json:"status,omitempty"` -} - -// BackendTLSPolicyList contains a list of BackendTLSPolicies // +kubebuilder:object:root=true type BackendTLSPolicyList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []BackendTLSPolicy `json:"items"` } - -// BackendTLSPolicySpec defines the desired state of BackendTLSPolicy. -// -// Support: Extended -type BackendTLSPolicySpec struct { - // TargetRefs identifies an API object to apply the policy to. - // Only Services have Extended support. Implementations MAY support - // additional objects, with Implementation Specific support. - // Note that this config applies to the entire referenced resource - // by default, but this default may change in the future to provide - // a more granular application of the policy. - // - // TargetRefs must be _distinct_. This means either that: - // - // * They select different targets. If this is the case, then targetRef - // entries are distinct. In terms of fields, this means that the - // multi-part key defined by `group`, `kind`, and `name` must - // be unique across all targetRef entries in the BackendTLSPolicy. - // * They select different sectionNames in the same target. - // - // - // When more than one BackendTLSPolicy selects the same target and - // sectionName, implementations MUST determine precedence using the - // following criteria, continuing on ties: - // - // * The older policy by creation timestamp takes precedence. For - // example, a policy with a creation timestamp of "2021-07-15 - // 01:02:03" MUST be given precedence over a policy with a - // creation timestamp of "2021-07-15 01:02:04". - // * The policy appearing first in alphabetical order by {name}. - // For example, a policy named `bar` is given precedence over a - // policy named `baz`. - // - // For any BackendTLSPolicy that does not take precedence, the - // implementation MUST ensure the `Accepted` Condition is set to - // `status: False`, with Reason `Conflicted`. - // - // Support: Extended for Kubernetes Service - // - // Support: Implementation-specific for any other resource - // - // +required - // +listType=atomic - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:validation:XValidation:message="sectionName must be specified when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - // +kubebuilder:validation:XValidation:message="sectionName must be unique when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName))))" - TargetRefs []v1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"` - - // Validation contains backend TLS validation configuration. - // +required - Validation BackendTLSPolicyValidation `json:"validation"` - - // Options are a list of key/value pairs to enable extended TLS - // configuration for each implementation. For example, configuring the - // minimum TLS version or supported cipher suites. - // - // A set of common keys MAY be defined by the API in the future. To avoid - // any ambiguity, implementation-specific definitions MUST use - // domain-prefixed names, such as `example.com/my-custom-option`. - // Un-prefixed names are reserved for key names defined by Gateway API. - // - // Support: Implementation-specific - // - // +optional - // +kubebuilder:validation:MaxProperties=16 - Options map[v1.AnnotationKey]v1.AnnotationValue `json:"options,omitempty"` -} - -// BackendTLSPolicyValidation contains backend TLS validation configuration. -// +kubebuilder:validation:XValidation:message="must not contain both CACertificateRefs and WellKnownCACertificates",rule="!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" -// +kubebuilder:validation:XValidation:message="must specify either CACertificateRefs or WellKnownCACertificates",rule="(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" -type BackendTLSPolicyValidation struct { - // CACertificateRefs contains one or more references to Kubernetes objects that - // contain a PEM-encoded TLS CA certificate bundle, which is used to - // validate a TLS handshake between the Gateway and backend Pod. - // - // If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be - // specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, - // not both. If CACertificateRefs is empty or unspecified, the configuration for - // WellKnownCACertificates MUST be honored instead if supported by the implementation. - // - // A CACertificateRef is invalid if: - // - // * It refers to a resource that cannot be resolved (e.g., the referenced resource - // does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key - // named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` - // and the Message of the Condition must indicate which reference is invalid and why. - // - // * It refers to an unknown or unsupported kind of resource. In this case, the Reason - // must be set to `InvalidKind` and the Message of the Condition must explain which - // kind of resource is unknown or unsupported. - // - // * It refers to a resource in another namespace. This may change in future - // spec updates. - // - // Implementations MAY choose to perform further validation of the certificate - // content (e.g., checking expiry or enforcing specific formats). In such cases, - // an implementation-specific Reason and Message must be set for the invalid reference. - // - // In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on - // the BackendTLSPolicy is set to `status: False`, with a Reason and Message - // that indicate the cause of the error. Connections using an invalid - // CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error - // response. If ALL CACertificateRefs are invalid, the implementation MUST also - // ensure the `Accepted` Condition on the BackendTLSPolicy is set to - // `status: False`, with a Reason `NoValidCACertificate`. - // - // - // A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. - // Implementations MAY choose to support attaching multiple certificates to - // a backend, but this behavior is implementation-specific. - // - // Support: Core - An optional single reference to a Kubernetes ConfigMap, - // with the CA certificate in a key named `ca.crt`. - // - // Support: Implementation-specific - More than one reference, other kinds - // of resources, or a single reference that includes multiple certificates. - // - // +optional - // +listType=atomic - // +kubebuilder:validation:MaxItems=8 - CACertificateRefs []v1.LocalObjectReference `json:"caCertificateRefs,omitempty"` - - // WellKnownCACertificates specifies whether system CA certificates may be used in - // the TLS handshake between the gateway and backend pod. - // - // If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs - // must be specified with at least one entry for a valid configuration. Only one of - // CACertificateRefs or WellKnownCACertificates may be specified, not both. - // If an implementation does not support the WellKnownCACertificates field, or - // the supplied value is not recognized, the implementation MUST ensure the - // `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with - // a Reason `Invalid`. - // - // Support: Implementation-specific - // - // +optional - // +listType=atomic - WellKnownCACertificates *WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` - - // Hostname is used for two purposes in the connection between Gateways and - // backends: - // - // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). - // 2. Hostname MUST be used for authentication and MUST match the certificate - // served by the matching backend, unless SubjectAltNames is specified. - // 3. If SubjectAltNames are specified, Hostname can be used for certificate selection - // but MUST NOT be used for authentication. If you want to use the value - // of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. - // - // Support: Core - // - // +required - Hostname v1.PreciseHostname `json:"hostname"` - - // SubjectAltNames contains one or more Subject Alternative Names. - // When specified the certificate served from the backend MUST - // have at least one Subject Alternate Name matching one of the specified SubjectAltNames. - // - // Support: Extended - // - // +optional - // +listType=atomic - // +kubebuilder:validation:MaxItems=5 - SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` -} - -// SubjectAltName represents Subject Alternative Name. -// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain Hostname, if Type is set to Hostname",rule="!(self.type == \"Hostname\" && (!has(self.hostname) || self.hostname == \"\"))" -// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain Hostname, if Type is not set to Hostname",rule="!(self.type != \"Hostname\" && has(self.hostname) && self.hostname != \"\")" -// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain URI, if Type is set to URI",rule="!(self.type == \"URI\" && (!has(self.uri) || self.uri == \"\"))" -// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain URI, if Type is not set to URI",rule="!(self.type != \"URI\" && has(self.uri) && self.uri != \"\")" -type SubjectAltName struct { - // Type determines the format of the Subject Alternative Name. Always required. - // - // Support: Core - // - // +required - Type SubjectAltNameType `json:"type"` - - // Hostname contains Subject Alternative Name specified in DNS name format. - // Required when Type is set to Hostname, ignored otherwise. - // - // Support: Core - // - // +optional - Hostname v1.Hostname `json:"hostname,omitempty"` - - // URI contains Subject Alternative Name specified in a full URI format. - // It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. - // Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". - // Required when Type is set to URI, ignored otherwise. - // - // Support: Core - // - // +optional - URI v1.AbsoluteURI `json:"uri,omitempty"` -} - -// WellKnownCACertificatesType is the type of CA certificate that will be used -// when the caCertificateRefs field is unspecified. -// +kubebuilder:validation:Enum=System -type WellKnownCACertificatesType string - -const ( - // WellKnownCACertificatesSystem indicates that well known system CA certificates should be used. - WellKnownCACertificatesSystem WellKnownCACertificatesType = "System" -) - -// SubjectAltNameType is the type of the Subject Alternative Name. -// +kubebuilder:validation:Enum=Hostname;URI -type SubjectAltNameType string - -const ( - // HostnameSubjectAltNameType specifies hostname-based SAN. - // - // Support: Core - HostnameSubjectAltNameType SubjectAltNameType = "Hostname" - - // URISubjectAltNameType specifies URI-based SAN, e.g. SPIFFE id. - // - // Support: Core - URISubjectAltNameType SubjectAltNameType = "URI" -) - -const ( - // This reason is used with the "Accepted" condition when it is - // set to false because all CACertificateRefs of the - // BackendTLSPolicy are invalid. - BackendTLSPolicyReasonNoValidCACertificate v1alpha2.PolicyConditionReason = "NoValidCACertificate" -) - -const ( - // This condition indicates whether the controller was able to resolve all - // object references for the BackendTLSPolicy. - // - // Possible reasons for this condition to be True are: - // - // * "ResolvedRefs" - // - // Possible reasons for this condition to be False are: - // - // * "InvalidCACertificateRef" - // * "InvalidKind" - // - // Controllers may raise this condition with other reasons, but should - // prefer to use the reasons listed above to improve interoperability. - BackendTLSPolicyConditionResolvedRefs v1alpha2.PolicyConditionType = "ResolvedRefs" - - // This reason is used with the "ResolvedRefs" condition when the condition - // is true. - BackendTLSPolicyReasonResolvedRefs v1alpha2.PolicyConditionReason = "ResolvedRefs" - - // This reason is used with the "ResolvedRefs" condition when one of the - // BackendTLSPolicy's CACertificateRefs is invalid. - // A CACertificateRef is considered invalid when it refers to a nonexistent - // resource or when the data within that resource is malformed. - BackendTLSPolicyReasonInvalidCACertificateRef v1alpha2.PolicyConditionReason = "InvalidCACertificateRef" - - // This reason is used with the "ResolvedRefs" condition when one of the - // BackendTLSPolicy's CACertificateRefs references an unknown or unsupported - // Group and/or Kind. - BackendTLSPolicyReasonInvalidKind v1alpha2.PolicyConditionReason = "InvalidKind" -) diff --git a/apis/v1alpha3/zz_generated.deepcopy.go b/apis/v1alpha3/zz_generated.deepcopy.go index 9b659eadab..479672b66a 100644 --- a/apis/v1alpha3/zz_generated.deepcopy.go +++ b/apis/v1alpha3/zz_generated.deepcopy.go @@ -22,7 +22,6 @@ package v1alpha3 import ( runtime "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" ) @@ -85,81 +84,6 @@ func (in *BackendTLSPolicyList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackendTLSPolicySpec) DeepCopyInto(out *BackendTLSPolicySpec) { - *out = *in - if in.TargetRefs != nil { - in, out := &in.TargetRefs, &out.TargetRefs - *out = make([]v1alpha2.LocalPolicyTargetReferenceWithSectionName, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.Validation.DeepCopyInto(&out.Validation) - if in.Options != nil { - in, out := &in.Options, &out.Options - *out = make(map[v1.AnnotationKey]v1.AnnotationValue, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicySpec. -func (in *BackendTLSPolicySpec) DeepCopy() *BackendTLSPolicySpec { - if in == nil { - return nil - } - out := new(BackendTLSPolicySpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackendTLSPolicyValidation) DeepCopyInto(out *BackendTLSPolicyValidation) { - *out = *in - if in.CACertificateRefs != nil { - in, out := &in.CACertificateRefs, &out.CACertificateRefs - *out = make([]v1.LocalObjectReference, len(*in)) - copy(*out, *in) - } - if in.WellKnownCACertificates != nil { - in, out := &in.WellKnownCACertificates, &out.WellKnownCACertificates - *out = new(WellKnownCACertificatesType) - **out = **in - } - if in.SubjectAltNames != nil { - in, out := &in.SubjectAltNames, &out.SubjectAltNames - *out = make([]SubjectAltName, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSPolicyValidation. -func (in *BackendTLSPolicyValidation) DeepCopy() *BackendTLSPolicyValidation { - if in == nil { - return nil - } - out := new(BackendTLSPolicyValidation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SubjectAltName) DeepCopyInto(out *SubjectAltName) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubjectAltName. -func (in *SubjectAltName) DeepCopy() *SubjectAltName { - if in == nil { - return nil - } - out := new(SubjectAltName) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSRoute) DeepCopyInto(out *TLSRoute) { *out = *in diff --git a/apisx/v1alpha1/shared_types.go b/apisx/v1alpha1/shared_types.go index 01331bf8cd..94851df261 100644 --- a/apisx/v1alpha1/shared_types.go +++ b/apisx/v1alpha1/shared_types.go @@ -18,7 +18,6 @@ package v1alpha1 import ( v1 "sigs.k8s.io/gateway-api/apis/v1" - v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) type ( @@ -34,8 +33,8 @@ type ( SectionName = v1.SectionName Namespace = v1.Namespace Duration = v1.Duration - PolicyStatus = v1alpha2.PolicyStatus - LocalPolicyTargetReference = v1alpha2.LocalPolicyTargetReference + PolicyStatus = v1.PolicyStatus + LocalPolicyTargetReference = v1.LocalPolicyTargetReference SessionPersistence = v1.SessionPersistence ) diff --git a/apisx/v1alpha1/zz_generated.deepcopy.go b/apisx/v1alpha1/zz_generated.deepcopy.go index d8bc7aa83c..9e93ad9e88 100644 --- a/apisx/v1alpha1/zz_generated.deepcopy.go +++ b/apisx/v1alpha1/zz_generated.deepcopy.go @@ -32,9 +32,7 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) if in.TargetRefs != nil { in, out := &in.TargetRefs, &out.TargetRefs *out = make([]LocalPolicyTargetReference, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + copy(*out, *in) } if in.RetryConstraint != nil { in, out := &in.RetryConstraint, &out.RetryConstraint diff --git a/applyconfiguration/apis/v1/backendtlspolicy.go b/applyconfiguration/apis/v1/backendtlspolicy.go new file mode 100644 index 0000000000..4b33502db0 --- /dev/null +++ b/applyconfiguration/apis/v1/backendtlspolicy.go @@ -0,0 +1,281 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apismetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + metav1 "k8s.io/client-go/applyconfigurations/meta/v1" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + internal "sigs.k8s.io/gateway-api/applyconfiguration/internal" +) + +// BackendTLSPolicyApplyConfiguration represents a declarative configuration of the BackendTLSPolicy type for use +// with apply. +type BackendTLSPolicyApplyConfiguration struct { + metav1.TypeMetaApplyConfiguration `json:",inline"` + *metav1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *BackendTLSPolicySpecApplyConfiguration `json:"spec,omitempty"` + Status *PolicyStatusApplyConfiguration `json:"status,omitempty"` +} + +// BackendTLSPolicy constructs a declarative configuration of the BackendTLSPolicy type for use with +// apply. +func BackendTLSPolicy(name, namespace string) *BackendTLSPolicyApplyConfiguration { + b := &BackendTLSPolicyApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("BackendTLSPolicy") + b.WithAPIVersion("gateway.networking.k8s.io/v1") + return b +} + +// ExtractBackendTLSPolicy extracts the applied configuration owned by fieldManager from +// backendTLSPolicy. If no managedFields are found in backendTLSPolicy for fieldManager, a +// BackendTLSPolicyApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// backendTLSPolicy must be a unmodified BackendTLSPolicy API object that was retrieved from the Kubernetes API. +// ExtractBackendTLSPolicy provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractBackendTLSPolicy(backendTLSPolicy *apisv1.BackendTLSPolicy, fieldManager string) (*BackendTLSPolicyApplyConfiguration, error) { + return extractBackendTLSPolicy(backendTLSPolicy, fieldManager, "") +} + +// ExtractBackendTLSPolicyStatus is the same as ExtractBackendTLSPolicy except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractBackendTLSPolicyStatus(backendTLSPolicy *apisv1.BackendTLSPolicy, fieldManager string) (*BackendTLSPolicyApplyConfiguration, error) { + return extractBackendTLSPolicy(backendTLSPolicy, fieldManager, "status") +} + +func extractBackendTLSPolicy(backendTLSPolicy *apisv1.BackendTLSPolicy, fieldManager string, subresource string) (*BackendTLSPolicyApplyConfiguration, error) { + b := &BackendTLSPolicyApplyConfiguration{} + err := managedfields.ExtractInto(backendTLSPolicy, internal.Parser().Type("io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicy"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(backendTLSPolicy.Name) + b.WithNamespace(backendTLSPolicy.Namespace) + + b.WithKind("BackendTLSPolicy") + b.WithAPIVersion("gateway.networking.k8s.io/v1") + return b, nil +} +func (b BackendTLSPolicyApplyConfiguration) IsApplyConfiguration() {} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithKind(value string) *BackendTLSPolicyApplyConfiguration { + b.TypeMetaApplyConfiguration.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithAPIVersion(value string) *BackendTLSPolicyApplyConfiguration { + b.TypeMetaApplyConfiguration.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithName(value string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithGenerateName(value string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithNamespace(value string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithUID(value types.UID) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithResourceVersion(value string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithGeneration(value int64) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithCreationTimestamp(value apismetav1.Time) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithDeletionTimestamp(value apismetav1.Time) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *BackendTLSPolicyApplyConfiguration) WithLabels(entries map[string]string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *BackendTLSPolicyApplyConfiguration) WithAnnotations(entries map[string]string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *BackendTLSPolicyApplyConfiguration) WithOwnerReferences(values ...*metav1.OwnerReferenceApplyConfiguration) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *BackendTLSPolicyApplyConfiguration) WithFinalizers(values ...string) *BackendTLSPolicyApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i]) + } + return b +} + +func (b *BackendTLSPolicyApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &metav1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithSpec(value *BackendTLSPolicySpecApplyConfiguration) *BackendTLSPolicyApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *BackendTLSPolicyApplyConfiguration) WithStatus(value *PolicyStatusApplyConfiguration) *BackendTLSPolicyApplyConfiguration { + b.Status = value + return b +} + +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Name +} + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1/backendtlspolicyspec.go b/applyconfiguration/apis/v1/backendtlspolicyspec.go new file mode 100644 index 0000000000..b6d8d9727b --- /dev/null +++ b/applyconfiguration/apis/v1/backendtlspolicyspec.go @@ -0,0 +1,72 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// BackendTLSPolicySpecApplyConfiguration represents a declarative configuration of the BackendTLSPolicySpec type for use +// with apply. +type BackendTLSPolicySpecApplyConfiguration struct { + TargetRefs []LocalPolicyTargetReferenceWithSectionNameApplyConfiguration `json:"targetRefs,omitempty"` + Validation *BackendTLSPolicyValidationApplyConfiguration `json:"validation,omitempty"` + Options map[apisv1.AnnotationKey]apisv1.AnnotationValue `json:"options,omitempty"` +} + +// BackendTLSPolicySpecApplyConfiguration constructs a declarative configuration of the BackendTLSPolicySpec type for use with +// apply. +func BackendTLSPolicySpec() *BackendTLSPolicySpecApplyConfiguration { + return &BackendTLSPolicySpecApplyConfiguration{} +} + +// WithTargetRefs adds the given value to the TargetRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the TargetRefs field. +func (b *BackendTLSPolicySpecApplyConfiguration) WithTargetRefs(values ...*LocalPolicyTargetReferenceWithSectionNameApplyConfiguration) *BackendTLSPolicySpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithTargetRefs") + } + b.TargetRefs = append(b.TargetRefs, *values[i]) + } + return b +} + +// WithValidation sets the Validation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Validation field is set to the value of the last call. +func (b *BackendTLSPolicySpecApplyConfiguration) WithValidation(value *BackendTLSPolicyValidationApplyConfiguration) *BackendTLSPolicySpecApplyConfiguration { + b.Validation = value + return b +} + +// WithOptions puts the entries into the Options field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Options field, +// overwriting an existing map entries in Options field with the same key. +func (b *BackendTLSPolicySpecApplyConfiguration) WithOptions(entries map[apisv1.AnnotationKey]apisv1.AnnotationValue) *BackendTLSPolicySpecApplyConfiguration { + if b.Options == nil && len(entries) > 0 { + b.Options = make(map[apisv1.AnnotationKey]apisv1.AnnotationValue, len(entries)) + } + for k, v := range entries { + b.Options[k] = v + } + return b +} diff --git a/applyconfiguration/apis/v1/backendtlspolicyvalidation.go b/applyconfiguration/apis/v1/backendtlspolicyvalidation.go new file mode 100644 index 0000000000..db18fc4ed7 --- /dev/null +++ b/applyconfiguration/apis/v1/backendtlspolicyvalidation.go @@ -0,0 +1,80 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// BackendTLSPolicyValidationApplyConfiguration represents a declarative configuration of the BackendTLSPolicyValidation type for use +// with apply. +type BackendTLSPolicyValidationApplyConfiguration struct { + CACertificateRefs []LocalObjectReferenceApplyConfiguration `json:"caCertificateRefs,omitempty"` + WellKnownCACertificates *apisv1.WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` + Hostname *apisv1.PreciseHostname `json:"hostname,omitempty"` + SubjectAltNames []SubjectAltNameApplyConfiguration `json:"subjectAltNames,omitempty"` +} + +// BackendTLSPolicyValidationApplyConfiguration constructs a declarative configuration of the BackendTLSPolicyValidation type for use with +// apply. +func BackendTLSPolicyValidation() *BackendTLSPolicyValidationApplyConfiguration { + return &BackendTLSPolicyValidationApplyConfiguration{} +} + +// WithCACertificateRefs adds the given value to the CACertificateRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the CACertificateRefs field. +func (b *BackendTLSPolicyValidationApplyConfiguration) WithCACertificateRefs(values ...*LocalObjectReferenceApplyConfiguration) *BackendTLSPolicyValidationApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithCACertificateRefs") + } + b.CACertificateRefs = append(b.CACertificateRefs, *values[i]) + } + return b +} + +// WithWellKnownCACertificates sets the WellKnownCACertificates field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the WellKnownCACertificates field is set to the value of the last call. +func (b *BackendTLSPolicyValidationApplyConfiguration) WithWellKnownCACertificates(value apisv1.WellKnownCACertificatesType) *BackendTLSPolicyValidationApplyConfiguration { + b.WellKnownCACertificates = &value + return b +} + +// WithHostname sets the Hostname field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Hostname field is set to the value of the last call. +func (b *BackendTLSPolicyValidationApplyConfiguration) WithHostname(value apisv1.PreciseHostname) *BackendTLSPolicyValidationApplyConfiguration { + b.Hostname = &value + return b +} + +// WithSubjectAltNames adds the given value to the SubjectAltNames field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SubjectAltNames field. +func (b *BackendTLSPolicyValidationApplyConfiguration) WithSubjectAltNames(values ...*SubjectAltNameApplyConfiguration) *BackendTLSPolicyValidationApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSubjectAltNames") + } + b.SubjectAltNames = append(b.SubjectAltNames, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/localpolicytargetreference.go b/applyconfiguration/apis/v1/localpolicytargetreference.go new file mode 100644 index 0000000000..2265b31873 --- /dev/null +++ b/applyconfiguration/apis/v1/localpolicytargetreference.go @@ -0,0 +1,61 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// LocalPolicyTargetReferenceApplyConfiguration represents a declarative configuration of the LocalPolicyTargetReference type for use +// with apply. +type LocalPolicyTargetReferenceApplyConfiguration struct { + Group *apisv1.Group `json:"group,omitempty"` + Kind *apisv1.Kind `json:"kind,omitempty"` + Name *apisv1.ObjectName `json:"name,omitempty"` +} + +// LocalPolicyTargetReferenceApplyConfiguration constructs a declarative configuration of the LocalPolicyTargetReference type for use with +// apply. +func LocalPolicyTargetReference() *LocalPolicyTargetReferenceApplyConfiguration { + return &LocalPolicyTargetReferenceApplyConfiguration{} +} + +// WithGroup sets the Group field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Group field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceApplyConfiguration) WithGroup(value apisv1.Group) *LocalPolicyTargetReferenceApplyConfiguration { + b.Group = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceApplyConfiguration) WithKind(value apisv1.Kind) *LocalPolicyTargetReferenceApplyConfiguration { + b.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceApplyConfiguration) WithName(value apisv1.ObjectName) *LocalPolicyTargetReferenceApplyConfiguration { + b.Name = &value + return b +} diff --git a/applyconfiguration/apis/v1/localpolicytargetreferencewithsectionname.go b/applyconfiguration/apis/v1/localpolicytargetreferencewithsectionname.go new file mode 100644 index 0000000000..a46cb5c953 --- /dev/null +++ b/applyconfiguration/apis/v1/localpolicytargetreferencewithsectionname.go @@ -0,0 +1,68 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// LocalPolicyTargetReferenceWithSectionNameApplyConfiguration represents a declarative configuration of the LocalPolicyTargetReferenceWithSectionName type for use +// with apply. +type LocalPolicyTargetReferenceWithSectionNameApplyConfiguration struct { + LocalPolicyTargetReferenceApplyConfiguration `json:",inline"` + SectionName *apisv1.SectionName `json:"sectionName,omitempty"` +} + +// LocalPolicyTargetReferenceWithSectionNameApplyConfiguration constructs a declarative configuration of the LocalPolicyTargetReferenceWithSectionName type for use with +// apply. +func LocalPolicyTargetReferenceWithSectionName() *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration { + return &LocalPolicyTargetReferenceWithSectionNameApplyConfiguration{} +} + +// WithGroup sets the Group field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Group field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration) WithGroup(value apisv1.Group) *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration { + b.LocalPolicyTargetReferenceApplyConfiguration.Group = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration) WithKind(value apisv1.Kind) *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration { + b.LocalPolicyTargetReferenceApplyConfiguration.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration) WithName(value apisv1.ObjectName) *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration { + b.LocalPolicyTargetReferenceApplyConfiguration.Name = &value + return b +} + +// WithSectionName sets the SectionName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SectionName field is set to the value of the last call. +func (b *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration) WithSectionName(value apisv1.SectionName) *LocalPolicyTargetReferenceWithSectionNameApplyConfiguration { + b.SectionName = &value + return b +} diff --git a/applyconfiguration/apis/v1/policyancestorstatus.go b/applyconfiguration/apis/v1/policyancestorstatus.go new file mode 100644 index 0000000000..7eb9953f07 --- /dev/null +++ b/applyconfiguration/apis/v1/policyancestorstatus.go @@ -0,0 +1,67 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/client-go/applyconfigurations/meta/v1" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// PolicyAncestorStatusApplyConfiguration represents a declarative configuration of the PolicyAncestorStatus type for use +// with apply. +type PolicyAncestorStatusApplyConfiguration struct { + AncestorRef *ParentReferenceApplyConfiguration `json:"ancestorRef,omitempty"` + ControllerName *apisv1.GatewayController `json:"controllerName,omitempty"` + Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` +} + +// PolicyAncestorStatusApplyConfiguration constructs a declarative configuration of the PolicyAncestorStatus type for use with +// apply. +func PolicyAncestorStatus() *PolicyAncestorStatusApplyConfiguration { + return &PolicyAncestorStatusApplyConfiguration{} +} + +// WithAncestorRef sets the AncestorRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AncestorRef field is set to the value of the last call. +func (b *PolicyAncestorStatusApplyConfiguration) WithAncestorRef(value *ParentReferenceApplyConfiguration) *PolicyAncestorStatusApplyConfiguration { + b.AncestorRef = value + return b +} + +// WithControllerName sets the ControllerName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ControllerName field is set to the value of the last call. +func (b *PolicyAncestorStatusApplyConfiguration) WithControllerName(value apisv1.GatewayController) *PolicyAncestorStatusApplyConfiguration { + b.ControllerName = &value + return b +} + +// WithConditions adds the given value to the Conditions field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Conditions field. +func (b *PolicyAncestorStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *PolicyAncestorStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithConditions") + } + b.Conditions = append(b.Conditions, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/policystatus.go b/applyconfiguration/apis/v1/policystatus.go new file mode 100644 index 0000000000..64de9b413e --- /dev/null +++ b/applyconfiguration/apis/v1/policystatus.go @@ -0,0 +1,44 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// PolicyStatusApplyConfiguration represents a declarative configuration of the PolicyStatus type for use +// with apply. +type PolicyStatusApplyConfiguration struct { + Ancestors []PolicyAncestorStatusApplyConfiguration `json:"ancestors,omitempty"` +} + +// PolicyStatusApplyConfiguration constructs a declarative configuration of the PolicyStatus type for use with +// apply. +func PolicyStatus() *PolicyStatusApplyConfiguration { + return &PolicyStatusApplyConfiguration{} +} + +// WithAncestors adds the given value to the Ancestors field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Ancestors field. +func (b *PolicyStatusApplyConfiguration) WithAncestors(values ...*PolicyAncestorStatusApplyConfiguration) *PolicyStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithAncestors") + } + b.Ancestors = append(b.Ancestors, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/subjectaltname.go b/applyconfiguration/apis/v1/subjectaltname.go new file mode 100644 index 0000000000..52278686ee --- /dev/null +++ b/applyconfiguration/apis/v1/subjectaltname.go @@ -0,0 +1,61 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// SubjectAltNameApplyConfiguration represents a declarative configuration of the SubjectAltName type for use +// with apply. +type SubjectAltNameApplyConfiguration struct { + Type *apisv1.SubjectAltNameType `json:"type,omitempty"` + Hostname *apisv1.Hostname `json:"hostname,omitempty"` + URI *apisv1.AbsoluteURI `json:"uri,omitempty"` +} + +// SubjectAltNameApplyConfiguration constructs a declarative configuration of the SubjectAltName type for use with +// apply. +func SubjectAltName() *SubjectAltNameApplyConfiguration { + return &SubjectAltNameApplyConfiguration{} +} + +// WithType sets the Type field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Type field is set to the value of the last call. +func (b *SubjectAltNameApplyConfiguration) WithType(value apisv1.SubjectAltNameType) *SubjectAltNameApplyConfiguration { + b.Type = &value + return b +} + +// WithHostname sets the Hostname field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Hostname field is set to the value of the last call. +func (b *SubjectAltNameApplyConfiguration) WithHostname(value apisv1.Hostname) *SubjectAltNameApplyConfiguration { + b.Hostname = &value + return b +} + +// WithURI sets the URI field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the URI field is set to the value of the last call. +func (b *SubjectAltNameApplyConfiguration) WithURI(value apisv1.AbsoluteURI) *SubjectAltNameApplyConfiguration { + b.URI = &value + return b +} diff --git a/applyconfiguration/apis/v1alpha2/policystatus.go b/applyconfiguration/apis/v1alpha2/policystatus.go index b7b158b29a..c2df85f61a 100644 --- a/applyconfiguration/apis/v1alpha2/policystatus.go +++ b/applyconfiguration/apis/v1alpha2/policystatus.go @@ -18,10 +18,14 @@ limitations under the License. package v1alpha2 +import ( + v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" +) + // PolicyStatusApplyConfiguration represents a declarative configuration of the PolicyStatus type for use // with apply. type PolicyStatusApplyConfiguration struct { - Ancestors []PolicyAncestorStatusApplyConfiguration `json:"ancestors,omitempty"` + Ancestors []v1.PolicyAncestorStatusApplyConfiguration `json:"ancestors,omitempty"` } // PolicyStatusApplyConfiguration constructs a declarative configuration of the PolicyStatus type for use with @@ -33,7 +37,7 @@ func PolicyStatus() *PolicyStatusApplyConfiguration { // WithAncestors adds the given value to the Ancestors field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Ancestors field. -func (b *PolicyStatusApplyConfiguration) WithAncestors(values ...*PolicyAncestorStatusApplyConfiguration) *PolicyStatusApplyConfiguration { +func (b *PolicyStatusApplyConfiguration) WithAncestors(values ...*v1.PolicyAncestorStatusApplyConfiguration) *PolicyStatusApplyConfiguration { for i := range values { if values[i] == nil { panic("nil value passed to WithAncestors") diff --git a/applyconfiguration/apis/v1alpha3/backendtlspolicy.go b/applyconfiguration/apis/v1alpha3/backendtlspolicy.go index dc5180214d..9a8f8721de 100644 --- a/applyconfiguration/apis/v1alpha3/backendtlspolicy.go +++ b/applyconfiguration/apis/v1alpha3/backendtlspolicy.go @@ -24,7 +24,7 @@ import ( managedfields "k8s.io/apimachinery/pkg/util/managedfields" v1 "k8s.io/client-go/applyconfigurations/meta/v1" apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" - v1alpha2 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha2" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" internal "sigs.k8s.io/gateway-api/applyconfiguration/internal" ) @@ -33,8 +33,8 @@ import ( type BackendTLSPolicyApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` - Spec *BackendTLSPolicySpecApplyConfiguration `json:"spec,omitempty"` - Status *v1alpha2.PolicyStatusApplyConfiguration `json:"status,omitempty"` + Spec *apisv1.BackendTLSPolicySpecApplyConfiguration `json:"spec,omitempty"` + Status *apisv1.PolicyStatusApplyConfiguration `json:"status,omitempty"` } // BackendTLSPolicy constructs a declarative configuration of the BackendTLSPolicy type for use with @@ -246,7 +246,7 @@ func (b *BackendTLSPolicyApplyConfiguration) ensureObjectMetaApplyConfigurationE // WithSpec sets the Spec field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Spec field is set to the value of the last call. -func (b *BackendTLSPolicyApplyConfiguration) WithSpec(value *BackendTLSPolicySpecApplyConfiguration) *BackendTLSPolicyApplyConfiguration { +func (b *BackendTLSPolicyApplyConfiguration) WithSpec(value *apisv1.BackendTLSPolicySpecApplyConfiguration) *BackendTLSPolicyApplyConfiguration { b.Spec = value return b } @@ -254,7 +254,7 @@ func (b *BackendTLSPolicyApplyConfiguration) WithSpec(value *BackendTLSPolicySpe // WithStatus sets the Status field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Status field is set to the value of the last call. -func (b *BackendTLSPolicyApplyConfiguration) WithStatus(value *v1alpha2.PolicyStatusApplyConfiguration) *BackendTLSPolicyApplyConfiguration { +func (b *BackendTLSPolicyApplyConfiguration) WithStatus(value *apisv1.PolicyStatusApplyConfiguration) *BackendTLSPolicyApplyConfiguration { b.Status = value return b } diff --git a/applyconfiguration/apis/v1alpha3/backendtlspolicyvalidation.go b/applyconfiguration/apis/v1alpha3/backendtlspolicyvalidation.go index b0cf5bfa88..50cd59b9ff 100644 --- a/applyconfiguration/apis/v1alpha3/backendtlspolicyvalidation.go +++ b/applyconfiguration/apis/v1alpha3/backendtlspolicyvalidation.go @@ -20,7 +20,6 @@ package v1alpha3 import ( apisv1 "sigs.k8s.io/gateway-api/apis/v1" - apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" ) @@ -28,7 +27,7 @@ import ( // with apply. type BackendTLSPolicyValidationApplyConfiguration struct { CACertificateRefs []v1.LocalObjectReferenceApplyConfiguration `json:"caCertificateRefs,omitempty"` - WellKnownCACertificates *apisv1alpha3.WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` + WellKnownCACertificates *apisv1.WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` Hostname *apisv1.PreciseHostname `json:"hostname,omitempty"` SubjectAltNames []SubjectAltNameApplyConfiguration `json:"subjectAltNames,omitempty"` } @@ -55,7 +54,7 @@ func (b *BackendTLSPolicyValidationApplyConfiguration) WithCACertificateRefs(val // WithWellKnownCACertificates sets the WellKnownCACertificates field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the WellKnownCACertificates field is set to the value of the last call. -func (b *BackendTLSPolicyValidationApplyConfiguration) WithWellKnownCACertificates(value apisv1alpha3.WellKnownCACertificatesType) *BackendTLSPolicyValidationApplyConfiguration { +func (b *BackendTLSPolicyValidationApplyConfiguration) WithWellKnownCACertificates(value apisv1.WellKnownCACertificatesType) *BackendTLSPolicyValidationApplyConfiguration { b.WellKnownCACertificates = &value return b } diff --git a/applyconfiguration/apis/v1alpha3/subjectaltname.go b/applyconfiguration/apis/v1alpha3/subjectaltname.go index 42823831b8..a024a62ebe 100644 --- a/applyconfiguration/apis/v1alpha3/subjectaltname.go +++ b/applyconfiguration/apis/v1alpha3/subjectaltname.go @@ -20,15 +20,14 @@ package v1alpha3 import ( v1 "sigs.k8s.io/gateway-api/apis/v1" - apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" ) // SubjectAltNameApplyConfiguration represents a declarative configuration of the SubjectAltName type for use // with apply. type SubjectAltNameApplyConfiguration struct { - Type *apisv1alpha3.SubjectAltNameType `json:"type,omitempty"` - Hostname *v1.Hostname `json:"hostname,omitempty"` - URI *v1.AbsoluteURI `json:"uri,omitempty"` + Type *v1.SubjectAltNameType `json:"type,omitempty"` + Hostname *v1.Hostname `json:"hostname,omitempty"` + URI *v1.AbsoluteURI `json:"uri,omitempty"` } // SubjectAltNameApplyConfiguration constructs a declarative configuration of the SubjectAltName type for use with @@ -40,7 +39,7 @@ func SubjectAltName() *SubjectAltNameApplyConfiguration { // WithType sets the Type field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Type field is set to the value of the last call. -func (b *SubjectAltNameApplyConfiguration) WithType(value apisv1alpha3.SubjectAltNameType) *SubjectAltNameApplyConfiguration { +func (b *SubjectAltNameApplyConfiguration) WithType(value v1.SubjectAltNameType) *SubjectAltNameApplyConfiguration { b.Type = &value return b } diff --git a/applyconfiguration/apisx/v1alpha1/backendtrafficpolicyspec.go b/applyconfiguration/apisx/v1alpha1/backendtrafficpolicyspec.go index 205609b882..ec7a76b009 100644 --- a/applyconfiguration/apisx/v1alpha1/backendtrafficpolicyspec.go +++ b/applyconfiguration/apisx/v1alpha1/backendtrafficpolicyspec.go @@ -20,15 +20,14 @@ package v1alpha1 import ( v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" - v1alpha2 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha2" ) // BackendTrafficPolicySpecApplyConfiguration represents a declarative configuration of the BackendTrafficPolicySpec type for use // with apply. type BackendTrafficPolicySpecApplyConfiguration struct { - TargetRefs []v1alpha2.LocalPolicyTargetReferenceApplyConfiguration `json:"targetRefs,omitempty"` - RetryConstraint *RetryConstraintApplyConfiguration `json:"retryConstraint,omitempty"` - SessionPersistence *v1.SessionPersistenceApplyConfiguration `json:"sessionPersistence,omitempty"` + TargetRefs []v1.LocalPolicyTargetReferenceApplyConfiguration `json:"targetRefs,omitempty"` + RetryConstraint *RetryConstraintApplyConfiguration `json:"retryConstraint,omitempty"` + SessionPersistence *v1.SessionPersistenceApplyConfiguration `json:"sessionPersistence,omitempty"` } // BackendTrafficPolicySpecApplyConfiguration constructs a declarative configuration of the BackendTrafficPolicySpec type for use with @@ -40,7 +39,7 @@ func BackendTrafficPolicySpec() *BackendTrafficPolicySpecApplyConfiguration { // WithTargetRefs adds the given value to the TargetRefs field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the TargetRefs field. -func (b *BackendTrafficPolicySpecApplyConfiguration) WithTargetRefs(values ...*v1alpha2.LocalPolicyTargetReferenceApplyConfiguration) *BackendTrafficPolicySpecApplyConfiguration { +func (b *BackendTrafficPolicySpecApplyConfiguration) WithTargetRefs(values ...*v1.LocalPolicyTargetReferenceApplyConfiguration) *BackendTrafficPolicySpecApplyConfiguration { for i := range values { if values[i] == nil { panic("nil value passed to WithTargetRefs") diff --git a/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go b/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go index 99a39f03a7..6e9de039b5 100644 --- a/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go +++ b/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go @@ -24,7 +24,7 @@ import ( managedfields "k8s.io/apimachinery/pkg/util/managedfields" v1 "k8s.io/client-go/applyconfigurations/meta/v1" apisxv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" - v1alpha2 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha2" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" internal "sigs.k8s.io/gateway-api/applyconfiguration/internal" ) @@ -34,7 +34,7 @@ type XBackendTrafficPolicyApplyConfiguration struct { v1.TypeMetaApplyConfiguration `json:",inline"` *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` Spec *BackendTrafficPolicySpecApplyConfiguration `json:"spec,omitempty"` - Status *v1alpha2.PolicyStatusApplyConfiguration `json:"status,omitempty"` + Status *apisv1.PolicyStatusApplyConfiguration `json:"status,omitempty"` } // XBackendTrafficPolicy constructs a declarative configuration of the XBackendTrafficPolicy type for use with @@ -254,7 +254,7 @@ func (b *XBackendTrafficPolicyApplyConfiguration) WithSpec(value *BackendTraffic // WithStatus sets the Status field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Status field is set to the value of the last call. -func (b *XBackendTrafficPolicyApplyConfiguration) WithStatus(value *v1alpha2.PolicyStatusApplyConfiguration) *XBackendTrafficPolicyApplyConfiguration { +func (b *XBackendTrafficPolicyApplyConfiguration) WithStatus(value *apisv1.PolicyStatusApplyConfiguration) *XBackendTrafficPolicyApplyConfiguration { b.Status = value return b } diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index eb813846ed..5fa65d155a 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -282,6 +282,67 @@ var schemaYAML = typed.YAMLObject(`types: - name: weight type: scalar: numeric +- name: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicy + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicySpec + default: {} + - name: status + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.PolicyStatus + default: {} +- name: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicySpec + map: + fields: + - name: options + type: + map: + elementType: + scalar: string + - name: targetRefs + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.LocalPolicyTargetReferenceWithSectionName + elementRelationship: atomic + - name: validation + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicyValidation + default: {} +- name: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicyValidation + map: + fields: + - name: caCertificateRefs + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.LocalObjectReference + elementRelationship: atomic + - name: hostname + type: + scalar: string + default: "" + - name: subjectAltNames + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.SubjectAltName + elementRelationship: atomic + - name: wellKnownCACertificates + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.CookieConfig map: fields: @@ -1186,6 +1247,39 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: string default: "" +- name: io.k8s.sigs.gateway-api.apis.v1.LocalPolicyTargetReference + map: + fields: + - name: group + type: + scalar: string + default: "" + - name: kind + type: + scalar: string + default: "" + - name: name + type: + scalar: string + default: "" +- name: io.k8s.sigs.gateway-api.apis.v1.LocalPolicyTargetReferenceWithSectionName + map: + fields: + - name: group + type: + scalar: string + default: "" + - name: kind + type: + scalar: string + default: "" + - name: name + type: + scalar: string + default: "" + - name: sectionName + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.ObjectReference map: fields: @@ -1244,6 +1338,34 @@ var schemaYAML = typed.YAMLObject(`types: - name: sectionName type: scalar: string +- name: io.k8s.sigs.gateway-api.apis.v1.PolicyAncestorStatus + map: + fields: + - name: ancestorRef + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.ParentReference + default: {} + - name: conditions + type: + list: + elementType: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Condition + elementRelationship: associative + keys: + - type + - name: controllerName + type: + scalar: string + default: "" +- name: io.k8s.sigs.gateway-api.apis.v1.PolicyStatus + map: + fields: + - name: ancestors + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.PolicyAncestorStatus + elementRelationship: atomic - name: io.k8s.sigs.gateway-api.apis.v1.RouteGroupKind map: fields: @@ -1316,6 +1438,19 @@ var schemaYAML = typed.YAMLObject(`types: - name: type type: scalar: string +- name: io.k8s.sigs.gateway-api.apis.v1.SubjectAltName + map: + fields: + - name: hostname + type: + scalar: string + - name: type + type: + scalar: string + default: "" + - name: uri + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.SupportedFeature map: fields: @@ -1361,67 +1496,6 @@ var schemaYAML = typed.YAMLObject(`types: type: namedType: io.k8s.sigs.gateway-api.apis.v1.GRPCRouteStatus default: {} -- name: io.k8s.sigs.gateway-api.apis.v1alpha2.LocalPolicyTargetReference - map: - fields: - - name: group - type: - scalar: string - default: "" - - name: kind - type: - scalar: string - default: "" - - name: name - type: - scalar: string - default: "" -- name: io.k8s.sigs.gateway-api.apis.v1alpha2.LocalPolicyTargetReferenceWithSectionName - map: - fields: - - name: group - type: - scalar: string - default: "" - - name: kind - type: - scalar: string - default: "" - - name: name - type: - scalar: string - default: "" - - name: sectionName - type: - scalar: string -- name: io.k8s.sigs.gateway-api.apis.v1alpha2.PolicyAncestorStatus - map: - fields: - - name: ancestorRef - type: - namedType: io.k8s.sigs.gateway-api.apis.v1.ParentReference - default: {} - - name: conditions - type: - list: - elementType: - namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Condition - elementRelationship: associative - keys: - - type - - name: controllerName - type: - scalar: string - default: "" -- name: io.k8s.sigs.gateway-api.apis.v1alpha2.PolicyStatus - map: - fields: - - name: ancestors - type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.PolicyAncestorStatus - elementRelationship: atomic - name: io.k8s.sigs.gateway-api.apis.v1alpha2.ReferenceGrant map: fields: @@ -1640,65 +1714,12 @@ var schemaYAML = typed.YAMLObject(`types: default: {} - name: spec type: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha3.BackendTLSPolicySpec + namedType: io.k8s.sigs.gateway-api.apis.v1.BackendTLSPolicySpec default: {} - name: status type: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.PolicyStatus - default: {} -- name: io.k8s.sigs.gateway-api.apis.v1alpha3.BackendTLSPolicySpec - map: - fields: - - name: options - type: - map: - elementType: - scalar: string - - name: targetRefs - type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.LocalPolicyTargetReferenceWithSectionName - elementRelationship: atomic - - name: validation - type: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha3.BackendTLSPolicyValidation + namedType: io.k8s.sigs.gateway-api.apis.v1.PolicyStatus default: {} -- name: io.k8s.sigs.gateway-api.apis.v1alpha3.BackendTLSPolicyValidation - map: - fields: - - name: caCertificateRefs - type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1.LocalObjectReference - elementRelationship: atomic - - name: hostname - type: - scalar: string - default: "" - - name: subjectAltNames - type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha3.SubjectAltName - elementRelationship: atomic - - name: wellKnownCACertificates - type: - scalar: string -- name: io.k8s.sigs.gateway-api.apis.v1alpha3.SubjectAltName - map: - fields: - - name: hostname - type: - scalar: string - - name: type - type: - scalar: string - default: "" - - name: uri - type: - scalar: string - name: io.k8s.sigs.gateway-api.apis.v1alpha3.TLSRoute map: fields: @@ -1881,7 +1902,7 @@ var schemaYAML = typed.YAMLObject(`types: type: list: elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.LocalPolicyTargetReference + namedType: io.k8s.sigs.gateway-api.apis.v1.LocalPolicyTargetReference elementRelationship: associative keys: - group @@ -2067,7 +2088,7 @@ var schemaYAML = typed.YAMLObject(`types: default: {} - name: status type: - namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.PolicyStatus + namedType: io.k8s.sigs.gateway-api.apis.v1.PolicyStatus default: {} - name: io.k8s.sigs.gateway-api.apisx.v1alpha1.XListenerSet map: diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 31bed767a5..23a89a009c 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -48,6 +48,12 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.BackendObjectReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("BackendRef"): return &apisv1.BackendRefApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("BackendTLSPolicy"): + return &apisv1.BackendTLSPolicyApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("BackendTLSPolicySpec"): + return &apisv1.BackendTLSPolicySpecApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("BackendTLSPolicyValidation"): + return &apisv1.BackendTLSPolicyValidationApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("CommonRouteSpec"): return &apisv1.CommonRouteSpecApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("CookieConfig"): @@ -156,12 +162,20 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.LocalObjectReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("LocalParametersReference"): return &apisv1.LocalParametersReferenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("LocalPolicyTargetReference"): + return &apisv1.LocalPolicyTargetReferenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("LocalPolicyTargetReferenceWithSectionName"): + return &apisv1.LocalPolicyTargetReferenceWithSectionNameApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ObjectReference"): return &apisv1.ObjectReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ParametersReference"): return &apisv1.ParametersReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ParentReference"): return &apisv1.ParentReferenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("PolicyAncestorStatus"): + return &apisv1.PolicyAncestorStatusApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("PolicyStatus"): + return &apisv1.PolicyStatusApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("RouteGroupKind"): return &apisv1.RouteGroupKindApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("RouteNamespaces"): @@ -174,6 +188,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.SecretObjectReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("SessionPersistence"): return &apisv1.SessionPersistenceApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("SubjectAltName"): + return &apisv1.SubjectAltNameApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("SupportedFeature"): return &apisv1.SupportedFeatureApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("TLSConfig"): @@ -184,14 +200,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} { // Group=gateway.networking.k8s.io, Version=v1alpha2 case v1alpha2.SchemeGroupVersion.WithKind("GRPCRoute"): return &apisv1alpha2.GRPCRouteApplyConfiguration{} - case v1alpha2.SchemeGroupVersion.WithKind("LocalPolicyTargetReference"): - return &apisv1alpha2.LocalPolicyTargetReferenceApplyConfiguration{} - case v1alpha2.SchemeGroupVersion.WithKind("LocalPolicyTargetReferenceWithSectionName"): - return &apisv1alpha2.LocalPolicyTargetReferenceWithSectionNameApplyConfiguration{} - case v1alpha2.SchemeGroupVersion.WithKind("PolicyAncestorStatus"): - return &apisv1alpha2.PolicyAncestorStatusApplyConfiguration{} - case v1alpha2.SchemeGroupVersion.WithKind("PolicyStatus"): - return &apisv1alpha2.PolicyStatusApplyConfiguration{} case v1alpha2.SchemeGroupVersion.WithKind("ReferenceGrant"): return &apisv1alpha2.ReferenceGrantApplyConfiguration{} case v1alpha2.SchemeGroupVersion.WithKind("TCPRoute"): @@ -222,12 +230,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} { // Group=gateway.networking.k8s.io, Version=v1alpha3 case v1alpha3.SchemeGroupVersion.WithKind("BackendTLSPolicy"): return &apisv1alpha3.BackendTLSPolicyApplyConfiguration{} - case v1alpha3.SchemeGroupVersion.WithKind("BackendTLSPolicySpec"): - return &apisv1alpha3.BackendTLSPolicySpecApplyConfiguration{} - case v1alpha3.SchemeGroupVersion.WithKind("BackendTLSPolicyValidation"): - return &apisv1alpha3.BackendTLSPolicyValidationApplyConfiguration{} - case v1alpha3.SchemeGroupVersion.WithKind("SubjectAltName"): - return &apisv1alpha3.SubjectAltNameApplyConfiguration{} case v1alpha3.SchemeGroupVersion.WithKind("TLSRoute"): return &apisv1alpha3.TLSRouteApplyConfiguration{} case v1alpha3.SchemeGroupVersion.WithKind("TLSRouteSpec"): diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index b110a95a73..4cf0053506 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -25,7 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha3 + name: v1 schema: openAPIV3Schema: description: |- @@ -685,6 +685,667 @@ spec: storage: true subresources: status: {} + - deprecated: true + deprecationWarning: The v1alpha3 version of BackendTLSPolicy has been deprecated + and will be removed in a future release of the API. Please upgrade to v1. + name: v1alpha3 + schema: + openAPIV3Schema: + description: |- + BackendTLSPolicy provides a way to configure how a Gateway + connects to a Backend via TLS. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + targetRefs: + description: |- + TargetRefs identifies an API object to apply the policy to. + Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. + Note that this config applies to the entire referenced resource + by default, but this default may change in the future to provide + a more granular application of the policy. + + TargetRefs must be _distinct_. This means either that: + + * They select different targets. If this is the case, then targetRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, and `name` must + be unique across all targetRef entries in the BackendTLSPolicy. + * They select different sectionNames in the same target. + + When more than one BackendTLSPolicy selects the same target and + sectionName, implementations MUST determine precedence using the + following criteria, continuing on ties: + + * The older policy by creation timestamp takes precedence. For + example, a policy with a creation timestamp of "2021-07-15 + 01:02:03" MUST be given precedence over a policy with a + creation timestamp of "2021-07-15 01:02:04". + * The policy appearing first in alphabetical order by {name}. + For example, a policy named `bar` is given precedence over a + policy named `baz`. + + For any BackendTLSPolicy that does not take precedence, the + implementation MUST ensure the `Accepted` Condition is set to + `status: False`, with Reason `Conflicted`. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + items: + description: |- + LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a + direct policy to. This should be used as part of Policy resources that can + target single resources. For more information on how this policy attachment + mode works, and a sample Policy resource, refer to the policy attachment + documentation for Gateway API. + + Note: This should only be used for direct policy attachment when references + to SectionName are actually needed. In all other cases, + LocalPolicyTargetReference should be used. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + sectionName: + description: |- + SectionName is the name of a section within the target resource. When + unspecified, this targetRef targets the entire resource. In the following + resources, SectionName is interpreted as the following: + + * Gateway: Listener name + * HTTPRoute: HTTPRouteRule name + * Service: Port name + + If a SectionName is specified, but does not exist on the targeted object, + the Policy must fail to attach, and the policy implementation should record + a `ResolvedRefs` or similar Condition in the Policy's status. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: sectionName must be specified when targetRefs includes + 2 or more references to the same target + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName + == '''') == (!has(p2.sectionName) || p2.sectionName == '''')) + : true))' + - message: sectionName must be unique when targetRefs includes 2 or + more references to the same target + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || + p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + validation: + description: Validation contains backend TLS validation configuration. + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to Kubernetes objects that + contain a PEM-encoded TLS CA certificate bundle, which is used to + validate a TLS handshake between the Gateway and backend Pod. + + If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + not both. If CACertificateRefs is empty or unspecified, the configuration for + WellKnownCACertificates MUST be honored instead if supported by the implementation. + + A CACertificateRef is invalid if: + + * It refers to a resource that cannot be resolved (e.g., the referenced resource + does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + and the Message of the Condition must indicate which reference is invalid and why. + + * It refers to an unknown or unsupported kind of resource. In this case, the Reason + must be set to `InvalidKind` and the Message of the Condition must explain which + kind of resource is unknown or unsupported. + + * It refers to a resource in another namespace. This may change in future + spec updates. + + Implementations MAY choose to perform further validation of the certificate + content (e.g., checking expiry or enforcing specific formats). In such cases, + an implementation-specific Reason and Message must be set for the invalid reference. + + In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + the BackendTLSPolicy is set to `status: False`, with a Reason and Message + that indicate the cause of the error. Connections using an invalid + CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + response. If ALL CACertificateRefs are invalid, the implementation MUST also + ensure the `Accepted` Condition on the BackendTLSPolicy is set to + `status: False`, with a Reason `NoValidCACertificate`. + + A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a backend, but this behavior is implementation-specific. + + Support: Core - An optional single reference to a Kubernetes ConfigMap, + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific - More than one reference, other kinds + of resources, or a single reference that includes multiple certificates. + items: + description: |- + LocalObjectReference identifies an API object within the namespace of the + referrer. + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" + or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + x-kubernetes-list-type: atomic + hostname: + description: |- + Hostname is used for two purposes in the connection between Gateways and + backends: + + 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + 2. Hostname MUST be used for authentication and MUST match the certificate + served by the matching backend, unless SubjectAltNames is specified. + 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + but MUST NOT be used for authentication. If you want to use the value + of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + subjectAltNames: + description: |- + SubjectAltNames contains one or more Subject Alternative Names. + When specified the certificate served from the backend MUST + have at least one Subject Alternate Name matching one of the specified SubjectAltNames. + + Support: Extended + items: + description: SubjectAltName represents Subject Alternative Name. + properties: + hostname: + description: |- + Hostname contains Subject Alternative Name specified in DNS name format. + Required when Type is set to Hostname, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: + description: |- + Type determines the format of the Subject Alternative Name. Always required. + + Support: Core + enum: + - Hostname + - URI + type: string + uri: + description: |- + URI contains Subject Alternative Name specified in a full URI format. + It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + Required when Type is set to URI, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: SubjectAltName element must contain Hostname, if + Type is set to Hostname + rule: '!(self.type == "Hostname" && (!has(self.hostname) || + self.hostname == ""))' + - message: SubjectAltName element must not contain Hostname, + if Type is not set to Hostname + rule: '!(self.type != "Hostname" && has(self.hostname) && + self.hostname != "")' + - message: SubjectAltName element must contain URI, if Type + is set to URI + rule: '!(self.type == "URI" && (!has(self.uri) || self.uri + == ""))' + - message: SubjectAltName element must not contain URI, if Type + is not set to URI + rule: '!(self.type != "URI" && has(self.uri) && self.uri != + "")' + maxItems: 5 + type: array + x-kubernetes-list-type: atomic + wellKnownCACertificates: + description: |- + WellKnownCACertificates specifies whether system CA certificates may be used in + the TLS handshake between the gateway and backend pod. + + If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + must be specified with at least one entry for a valid configuration. Only one of + CACertificateRefs or WellKnownCACertificates may be specified, not both. + If an implementation does not support the WellKnownCACertificates field, or + the supplied value is not recognized, the implementation MUST ensure the + `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + a Reason `Invalid`. + + Support: Implementation-specific + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertificateRefs and WellKnownCACertificates + rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "")' + - message: must specify either CACertificateRefs or WellKnownCACertificates + rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "") + required: + - targetRefs + - validation + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: |- + Ancestors is a list of ancestor resources (usually Gateways) that are + associated with the policy, and the status of the policy with respect to + each ancestor. When this policy attaches to a parent, the controller that + manages the parent and the ancestors MUST add an entry to this list when + the controller first sees the policy and SHOULD update the entry as + appropriate when the relevant ancestor is modified. + + Note that choosing the relevant ancestor is left to the Policy designers; + an important part of Policy design is designing the right object level at + which to namespace this status. + + Note also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations MUST + use the ControllerName field to uniquely identify the entries in this list + that they are responsible for. + + Note that to achieve this, the list of PolicyAncestorStatus structs + MUST be treated as a map with a composite key, made up of the AncestorRef + and ControllerName fields combined. + + A maximum of 16 ancestors will be represented in this list. An empty list + means the Policy is not relevant for any ancestors. + + If this slice is full, implementations MUST NOT add further entries. + Instead they MUST consider the policy unimplementable and signal that + on any related resources such as the ancestor that would be referenced + here. For example, if this list was full on BackendTLSPolicy, no + additional Gateways would be able to reference the Service targeted by + the BackendTLSPolicy. + items: + description: |- + PolicyAncestorStatus describes the status of a route with respect to an + associated Ancestor. + + Ancestors refer to objects that are either the Target of a policy or above it + in terms of object hierarchy. For example, if a policy targets a Service, the + Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and + the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most + useful object to place Policy status on, so we recommend that implementations + SHOULD use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. + + In the context of policy attachment, the Ancestor is used to distinguish which + resource results in a distinct application of this policy. For example, if a policy + targets a Service, it may have a distinct result per attached Gateway. + + Policies targeting the same resource may have different effects depending on the + ancestors of those resources. For example, different Gateways targeting the same + Service may have different capabilities, especially if they have different underlying + implementations. + + For example, in BackendTLSPolicy, the Policy attaches to a Service that is + used as a backend in a HTTPRoute that is itself attached to a Gateway. + In this case, the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. + + Note that a parent is also an ancestor, so for objects where the parent is the + relevant object for status, this struct SHOULD still be used. + + This struct is intended to be used in a slice that's effectively a map, + with a composite key made up of the AncestorRef and the ControllerName. + properties: + ancestorRef: + description: |- + AncestorRef corresponds with a ParentRef in the spec that this + PolicyAncestorStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - conditions + - controllerName + type: object + maxItems: 16 + type: array + x-kubernetes-list-type: atomic + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: false status: acceptedNames: kind: "" diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 3f0cb0daa9..c21d60cb74 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -4,3 +4,4 @@ resources: - standard/gateway.networking.k8s.io_grpcroutes.yaml - standard/gateway.networking.k8s.io_httproutes.yaml - standard/gateway.networking.k8s.io_referencegrants.yaml +- standard/gateway.networking.k8s.io_backendtlspolicies.yaml diff --git a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml new file mode 100644 index 0000000000..f218dbd0e9 --- /dev/null +++ b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -0,0 +1,1318 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 + gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/channel: standard + labels: + gateway.networking.k8s.io/policy: Direct + name: backendtlspolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendTLSPolicy + listKind: BackendTLSPolicyList + plural: backendtlspolicies + shortNames: + - btlspolicy + singular: backendtlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + BackendTLSPolicy provides a way to configure how a Gateway + connects to a Backend via TLS. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + targetRefs: + description: |- + TargetRefs identifies an API object to apply the policy to. + Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. + Note that this config applies to the entire referenced resource + by default, but this default may change in the future to provide + a more granular application of the policy. + + TargetRefs must be _distinct_. This means either that: + + * They select different targets. If this is the case, then targetRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, and `name` must + be unique across all targetRef entries in the BackendTLSPolicy. + * They select different sectionNames in the same target. + + When more than one BackendTLSPolicy selects the same target and + sectionName, implementations MUST determine precedence using the + following criteria, continuing on ties: + + * The older policy by creation timestamp takes precedence. For + example, a policy with a creation timestamp of "2021-07-15 + 01:02:03" MUST be given precedence over a policy with a + creation timestamp of "2021-07-15 01:02:04". + * The policy appearing first in alphabetical order by {name}. + For example, a policy named `bar` is given precedence over a + policy named `baz`. + + For any BackendTLSPolicy that does not take precedence, the + implementation MUST ensure the `Accepted` Condition is set to + `status: False`, with Reason `Conflicted`. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + items: + description: |- + LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a + direct policy to. This should be used as part of Policy resources that can + target single resources. For more information on how this policy attachment + mode works, and a sample Policy resource, refer to the policy attachment + documentation for Gateway API. + + Note: This should only be used for direct policy attachment when references + to SectionName are actually needed. In all other cases, + LocalPolicyTargetReference should be used. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + sectionName: + description: |- + SectionName is the name of a section within the target resource. When + unspecified, this targetRef targets the entire resource. In the following + resources, SectionName is interpreted as the following: + + * Gateway: Listener name + * HTTPRoute: HTTPRouteRule name + * Service: Port name + + If a SectionName is specified, but does not exist on the targeted object, + the Policy must fail to attach, and the policy implementation should record + a `ResolvedRefs` or similar Condition in the Policy's status. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: sectionName must be specified when targetRefs includes + 2 or more references to the same target + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName + == '''') == (!has(p2.sectionName) || p2.sectionName == '''')) + : true))' + - message: sectionName must be unique when targetRefs includes 2 or + more references to the same target + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || + p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + validation: + description: Validation contains backend TLS validation configuration. + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to Kubernetes objects that + contain a PEM-encoded TLS CA certificate bundle, which is used to + validate a TLS handshake between the Gateway and backend Pod. + + If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + not both. If CACertificateRefs is empty or unspecified, the configuration for + WellKnownCACertificates MUST be honored instead if supported by the implementation. + + A CACertificateRef is invalid if: + + * It refers to a resource that cannot be resolved (e.g., the referenced resource + does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + and the Message of the Condition must indicate which reference is invalid and why. + + * It refers to an unknown or unsupported kind of resource. In this case, the Reason + must be set to `InvalidKind` and the Message of the Condition must explain which + kind of resource is unknown or unsupported. + + * It refers to a resource in another namespace. This may change in future + spec updates. + + Implementations MAY choose to perform further validation of the certificate + content (e.g., checking expiry or enforcing specific formats). In such cases, + an implementation-specific Reason and Message must be set for the invalid reference. + + In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + the BackendTLSPolicy is set to `status: False`, with a Reason and Message + that indicate the cause of the error. Connections using an invalid + CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + response. If ALL CACertificateRefs are invalid, the implementation MUST also + ensure the `Accepted` Condition on the BackendTLSPolicy is set to + `status: False`, with a Reason `NoValidCACertificate`. + + A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a backend, but this behavior is implementation-specific. + + Support: Core - An optional single reference to a Kubernetes ConfigMap, + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific - More than one reference, other kinds + of resources, or a single reference that includes multiple certificates. + items: + description: |- + LocalObjectReference identifies an API object within the namespace of the + referrer. + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" + or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + x-kubernetes-list-type: atomic + hostname: + description: |- + Hostname is used for two purposes in the connection between Gateways and + backends: + + 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + 2. Hostname MUST be used for authentication and MUST match the certificate + served by the matching backend, unless SubjectAltNames is specified. + 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + but MUST NOT be used for authentication. If you want to use the value + of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + subjectAltNames: + description: |- + SubjectAltNames contains one or more Subject Alternative Names. + When specified the certificate served from the backend MUST + have at least one Subject Alternate Name matching one of the specified SubjectAltNames. + + Support: Extended + items: + description: SubjectAltName represents Subject Alternative Name. + properties: + hostname: + description: |- + Hostname contains Subject Alternative Name specified in DNS name format. + Required when Type is set to Hostname, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: + description: |- + Type determines the format of the Subject Alternative Name. Always required. + + Support: Core + enum: + - Hostname + - URI + type: string + uri: + description: |- + URI contains Subject Alternative Name specified in a full URI format. + It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + Required when Type is set to URI, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: SubjectAltName element must contain Hostname, if + Type is set to Hostname + rule: '!(self.type == "Hostname" && (!has(self.hostname) || + self.hostname == ""))' + - message: SubjectAltName element must not contain Hostname, + if Type is not set to Hostname + rule: '!(self.type != "Hostname" && has(self.hostname) && + self.hostname != "")' + - message: SubjectAltName element must contain URI, if Type + is set to URI + rule: '!(self.type == "URI" && (!has(self.uri) || self.uri + == ""))' + - message: SubjectAltName element must not contain URI, if Type + is not set to URI + rule: '!(self.type != "URI" && has(self.uri) && self.uri != + "")' + maxItems: 5 + type: array + x-kubernetes-list-type: atomic + wellKnownCACertificates: + description: |- + WellKnownCACertificates specifies whether system CA certificates may be used in + the TLS handshake between the gateway and backend pod. + + If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + must be specified with at least one entry for a valid configuration. Only one of + CACertificateRefs or WellKnownCACertificates may be specified, not both. + If an implementation does not support the WellKnownCACertificates field, or + the supplied value is not recognized, the implementation MUST ensure the + `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + a Reason `Invalid`. + + Support: Implementation-specific + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertificateRefs and WellKnownCACertificates + rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "")' + - message: must specify either CACertificateRefs or WellKnownCACertificates + rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "") + required: + - targetRefs + - validation + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: |- + Ancestors is a list of ancestor resources (usually Gateways) that are + associated with the policy, and the status of the policy with respect to + each ancestor. When this policy attaches to a parent, the controller that + manages the parent and the ancestors MUST add an entry to this list when + the controller first sees the policy and SHOULD update the entry as + appropriate when the relevant ancestor is modified. + + Note that choosing the relevant ancestor is left to the Policy designers; + an important part of Policy design is designing the right object level at + which to namespace this status. + + Note also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations MUST + use the ControllerName field to uniquely identify the entries in this list + that they are responsible for. + + Note that to achieve this, the list of PolicyAncestorStatus structs + MUST be treated as a map with a composite key, made up of the AncestorRef + and ControllerName fields combined. + + A maximum of 16 ancestors will be represented in this list. An empty list + means the Policy is not relevant for any ancestors. + + If this slice is full, implementations MUST NOT add further entries. + Instead they MUST consider the policy unimplementable and signal that + on any related resources such as the ancestor that would be referenced + here. For example, if this list was full on BackendTLSPolicy, no + additional Gateways would be able to reference the Service targeted by + the BackendTLSPolicy. + items: + description: |- + PolicyAncestorStatus describes the status of a route with respect to an + associated Ancestor. + + Ancestors refer to objects that are either the Target of a policy or above it + in terms of object hierarchy. For example, if a policy targets a Service, the + Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and + the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most + useful object to place Policy status on, so we recommend that implementations + SHOULD use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. + + In the context of policy attachment, the Ancestor is used to distinguish which + resource results in a distinct application of this policy. For example, if a policy + targets a Service, it may have a distinct result per attached Gateway. + + Policies targeting the same resource may have different effects depending on the + ancestors of those resources. For example, different Gateways targeting the same + Service may have different capabilities, especially if they have different underlying + implementations. + + For example, in BackendTLSPolicy, the Policy attaches to a Service that is + used as a backend in a HTTPRoute that is itself attached to a Gateway. + In this case, the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. + + Note that a parent is also an ancestor, so for objects where the parent is the + relevant object for status, this struct SHOULD still be used. + + This struct is intended to be used in a slice that's effectively a map, + with a composite key made up of the AncestorRef and the ControllerName. + properties: + ancestorRef: + description: |- + AncestorRef corresponds with a ParentRef in the spec that this + PolicyAncestorStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - conditions + - controllerName + type: object + maxItems: 16 + type: array + x-kubernetes-list-type: atomic + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - deprecated: true + deprecationWarning: The v1alpha3 version of BackendTLSPolicy has been deprecated + and will be removed in a future release of the API. Please upgrade to v1. + name: v1alpha3 + schema: + openAPIV3Schema: + description: |- + BackendTLSPolicy provides a way to configure how a Gateway + connects to a Backend via TLS. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + options: + additionalProperties: + description: |- + AnnotationValue is the value of an annotation in Gateway API. This is used + for validation of maps such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation in that case is based + on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: |- + Options are a list of key/value pairs to enable extended TLS + configuration for each implementation. For example, configuring the + minimum TLS version or supported cipher suites. + + A set of common keys MAY be defined by the API in the future. To avoid + any ambiguity, implementation-specific definitions MUST use + domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by Gateway API. + + Support: Implementation-specific + maxProperties: 16 + type: object + targetRefs: + description: |- + TargetRefs identifies an API object to apply the policy to. + Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. + Note that this config applies to the entire referenced resource + by default, but this default may change in the future to provide + a more granular application of the policy. + + TargetRefs must be _distinct_. This means either that: + + * They select different targets. If this is the case, then targetRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, and `name` must + be unique across all targetRef entries in the BackendTLSPolicy. + * They select different sectionNames in the same target. + + When more than one BackendTLSPolicy selects the same target and + sectionName, implementations MUST determine precedence using the + following criteria, continuing on ties: + + * The older policy by creation timestamp takes precedence. For + example, a policy with a creation timestamp of "2021-07-15 + 01:02:03" MUST be given precedence over a policy with a + creation timestamp of "2021-07-15 01:02:04". + * The policy appearing first in alphabetical order by {name}. + For example, a policy named `bar` is given precedence over a + policy named `baz`. + + For any BackendTLSPolicy that does not take precedence, the + implementation MUST ensure the `Accepted` Condition is set to + `status: False`, with Reason `Conflicted`. + + Support: Extended for Kubernetes Service + + Support: Implementation-specific for any other resource + items: + description: |- + LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a + direct policy to. This should be used as part of Policy resources that can + target single resources. For more information on how this policy attachment + mode works, and a sample Policy resource, refer to the policy attachment + documentation for Gateway API. + + Note: This should only be used for direct policy attachment when references + to SectionName are actually needed. In all other cases, + LocalPolicyTargetReference should be used. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + sectionName: + description: |- + SectionName is the name of a section within the target resource. When + unspecified, this targetRef targets the entire resource. In the following + resources, SectionName is interpreted as the following: + + * Gateway: Listener name + * HTTPRoute: HTTPRouteRule name + * Service: Port name + + If a SectionName is specified, but does not exist on the targeted object, + the Policy must fail to attach, and the policy implementation should record + a `ResolvedRefs` or similar Condition in the Policy's status. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: sectionName must be specified when targetRefs includes + 2 or more references to the same target + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName + == '''') == (!has(p2.sectionName) || p2.sectionName == '''')) + : true))' + - message: sectionName must be unique when targetRefs includes 2 or + more references to the same target + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || + p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)))) + validation: + description: Validation contains backend TLS validation configuration. + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to Kubernetes objects that + contain a PEM-encoded TLS CA certificate bundle, which is used to + validate a TLS handshake between the Gateway and backend Pod. + + If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + not both. If CACertificateRefs is empty or unspecified, the configuration for + WellKnownCACertificates MUST be honored instead if supported by the implementation. + + A CACertificateRef is invalid if: + + * It refers to a resource that cannot be resolved (e.g., the referenced resource + does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + and the Message of the Condition must indicate which reference is invalid and why. + + * It refers to an unknown or unsupported kind of resource. In this case, the Reason + must be set to `InvalidKind` and the Message of the Condition must explain which + kind of resource is unknown or unsupported. + + * It refers to a resource in another namespace. This may change in future + spec updates. + + Implementations MAY choose to perform further validation of the certificate + content (e.g., checking expiry or enforcing specific formats). In such cases, + an implementation-specific Reason and Message must be set for the invalid reference. + + In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + the BackendTLSPolicy is set to `status: False`, with a Reason and Message + that indicate the cause of the error. Connections using an invalid + CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + response. If ALL CACertificateRefs are invalid, the implementation MUST also + ensure the `Accepted` Condition on the BackendTLSPolicy is set to + `status: False`, with a Reason `NoValidCACertificate`. + + A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + Implementations MAY choose to support attaching multiple certificates to + a backend, but this behavior is implementation-specific. + + Support: Core - An optional single reference to a Kubernetes ConfigMap, + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific - More than one reference, other kinds + of resources, or a single reference that includes multiple certificates. + items: + description: |- + LocalObjectReference identifies an API object within the namespace of the + referrer. + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" + or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + x-kubernetes-list-type: atomic + hostname: + description: |- + Hostname is used for two purposes in the connection between Gateways and + backends: + + 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + 2. Hostname MUST be used for authentication and MUST match the certificate + served by the matching backend, unless SubjectAltNames is specified. + 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + but MUST NOT be used for authentication. If you want to use the value + of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + subjectAltNames: + description: |- + SubjectAltNames contains one or more Subject Alternative Names. + When specified the certificate served from the backend MUST + have at least one Subject Alternate Name matching one of the specified SubjectAltNames. + + Support: Extended + items: + description: SubjectAltName represents Subject Alternative Name. + properties: + hostname: + description: |- + Hostname contains Subject Alternative Name specified in DNS name format. + Required when Type is set to Hostname, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: + description: |- + Type determines the format of the Subject Alternative Name. Always required. + + Support: Core + enum: + - Hostname + - URI + type: string + uri: + description: |- + URI contains Subject Alternative Name specified in a full URI format. + It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + Required when Type is set to URI, ignored otherwise. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: SubjectAltName element must contain Hostname, if + Type is set to Hostname + rule: '!(self.type == "Hostname" && (!has(self.hostname) || + self.hostname == ""))' + - message: SubjectAltName element must not contain Hostname, + if Type is not set to Hostname + rule: '!(self.type != "Hostname" && has(self.hostname) && + self.hostname != "")' + - message: SubjectAltName element must contain URI, if Type + is set to URI + rule: '!(self.type == "URI" && (!has(self.uri) || self.uri + == ""))' + - message: SubjectAltName element must not contain URI, if Type + is not set to URI + rule: '!(self.type != "URI" && has(self.uri) && self.uri != + "")' + maxItems: 5 + type: array + x-kubernetes-list-type: atomic + wellKnownCACertificates: + description: |- + WellKnownCACertificates specifies whether system CA certificates may be used in + the TLS handshake between the gateway and backend pod. + + If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + must be specified with at least one entry for a valid configuration. Only one of + CACertificateRefs or WellKnownCACertificates may be specified, not both. + If an implementation does not support the WellKnownCACertificates field, or + the supplied value is not recognized, the implementation MUST ensure the + `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + a Reason `Invalid`. + + Support: Implementation-specific + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertificateRefs and WellKnownCACertificates + rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "")' + - message: must specify either CACertificateRefs or WellKnownCACertificates + rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) + > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates + != "") + required: + - targetRefs + - validation + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: |- + Ancestors is a list of ancestor resources (usually Gateways) that are + associated with the policy, and the status of the policy with respect to + each ancestor. When this policy attaches to a parent, the controller that + manages the parent and the ancestors MUST add an entry to this list when + the controller first sees the policy and SHOULD update the entry as + appropriate when the relevant ancestor is modified. + + Note that choosing the relevant ancestor is left to the Policy designers; + an important part of Policy design is designing the right object level at + which to namespace this status. + + Note also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations MUST + use the ControllerName field to uniquely identify the entries in this list + that they are responsible for. + + Note that to achieve this, the list of PolicyAncestorStatus structs + MUST be treated as a map with a composite key, made up of the AncestorRef + and ControllerName fields combined. + + A maximum of 16 ancestors will be represented in this list. An empty list + means the Policy is not relevant for any ancestors. + + If this slice is full, implementations MUST NOT add further entries. + Instead they MUST consider the policy unimplementable and signal that + on any related resources such as the ancestor that would be referenced + here. For example, if this list was full on BackendTLSPolicy, no + additional Gateways would be able to reference the Service targeted by + the BackendTLSPolicy. + items: + description: |- + PolicyAncestorStatus describes the status of a route with respect to an + associated Ancestor. + + Ancestors refer to objects that are either the Target of a policy or above it + in terms of object hierarchy. For example, if a policy targets a Service, the + Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and + the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most + useful object to place Policy status on, so we recommend that implementations + SHOULD use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. + + In the context of policy attachment, the Ancestor is used to distinguish which + resource results in a distinct application of this policy. For example, if a policy + targets a Service, it may have a distinct result per attached Gateway. + + Policies targeting the same resource may have different effects depending on the + ancestors of those resources. For example, different Gateways targeting the same + Service may have different capabilities, especially if they have different underlying + implementations. + + For example, in BackendTLSPolicy, the Policy attaches to a Service that is + used as a backend in a HTTPRoute that is itself attached to a Gateway. + In this case, the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. + + Note that a parent is also an ancestor, so for objects where the parent is the + relevant object for status, this struct SHOULD still be used. + + This struct is intended to be used in a slice that's effectively a map, + with a composite key made up of the AncestorRef and the ControllerName. + properties: + ancestorRef: + description: |- + AncestorRef corresponds with a ParentRef in the spec that this + PolicyAncestorStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - conditions + - controllerName + type: object + maxItems: 16 + type: array + x-kubernetes-list-type: atomic + required: + - ancestors + type: object + required: + - spec + type: object + served: false + storage: false +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/conformance/tests/backendtlspolicy-conflict-resolution.go b/conformance/tests/backendtlspolicy-conflict-resolution.go index 6aac39c9df..906d60c680 100644 --- a/conformance/tests/backendtlspolicy-conflict-resolution.go +++ b/conformance/tests/backendtlspolicy-conflict-resolution.go @@ -23,7 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -53,14 +52,14 @@ var BackendTLSPolicyConflictResolution = suite.ConformanceTest{ kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) acceptedCond := metav1.Condition{ - Type: string(v1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1alpha2.PolicyReasonAccepted), + Reason: string(gatewayv1.PolicyReasonAccepted), } conflictedCond := metav1.Condition{ - Type: string(v1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(v1alpha2.PolicyReasonConflicted), + Reason: string(gatewayv1.PolicyReasonConflicted), } t.Run("Conflicting BackendTLSPolicies targeting the same Service without a section name", func(t *testing.T) { diff --git a/conformance/tests/backendtlspolicy-conflict-resolution.yaml b/conformance/tests/backendtlspolicy-conflict-resolution.yaml index 5d5e6583f9..b5817f62dd 100644 --- a/conformance/tests/backendtlspolicy-conflict-resolution.yaml +++ b/conformance/tests/backendtlspolicy-conflict-resolution.yaml @@ -115,7 +115,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "other.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: conflicted-without-section-name-2 @@ -134,7 +134,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: conflicted-with-section-name-1 @@ -154,7 +154,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "other.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: conflicted-with-section-name-2 @@ -174,7 +174,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: not-conflicted-with-section-name @@ -194,7 +194,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "other.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: not-conflicted-without-section-name diff --git a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go index 824d8dd199..54908a2341 100644 --- a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go +++ b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go @@ -23,8 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -61,9 +59,9 @@ var BackendTLSPolicyInvalidCACertificateRef = suite.ConformanceTest{ t.Run("BackendTLSPolicy_"+policyNN.Name, func(t *testing.T) { t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a Accepted Condition with status False and Reason NoValidCACertificate", func(t *testing.T) { acceptedCond := metav1.Condition{ - Type: string(gatewayv1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonNoValidCACertificate), + Reason: string(gatewayv1.BackendTLSPolicyReasonNoValidCACertificate), } kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) @@ -71,9 +69,9 @@ var BackendTLSPolicyInvalidCACertificateRef = suite.ConformanceTest{ t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a ResolvedRefs Condition with status False and Reason InvalidCACertificateRef", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(gatewayv1alpha3.BackendTLSPolicyConditionResolvedRefs), + Type: string(gatewayv1.BackendTLSPolicyConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonInvalidCACertificateRef), + Reason: string(gatewayv1.BackendTLSPolicyReasonInvalidCACertificateRef), } kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml index 138812fddb..fbb08c30d1 100644 --- a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml +++ b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml @@ -55,7 +55,7 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: nonexistent-ca-certificate-ref @@ -72,7 +72,7 @@ spec: name: "nonexistent-ca-certificate" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: malformed-ca-certificate-ref diff --git a/conformance/tests/backendtlspolicy-invalid-kind.go b/conformance/tests/backendtlspolicy-invalid-kind.go index 5a3bba597e..35f30fd268 100644 --- a/conformance/tests/backendtlspolicy-invalid-kind.go +++ b/conformance/tests/backendtlspolicy-invalid-kind.go @@ -23,8 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -58,9 +56,9 @@ var BackendTLSPolicyInvalidKind = suite.ConformanceTest{ t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a Accepted Condition with status False and Reason NoValidCACertificate", func(t *testing.T) { acceptedCond := metav1.Condition{ - Type: string(gatewayv1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionFalse, - Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonNoValidCACertificate), + Reason: string(gatewayv1.BackendTLSPolicyReasonNoValidCACertificate), } kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) @@ -68,9 +66,9 @@ var BackendTLSPolicyInvalidKind = suite.ConformanceTest{ t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a ResolvedRefs Condition with status False and Reason InvalidKind", func(t *testing.T) { resolvedRefsCond := metav1.Condition{ - Type: string(gatewayv1alpha3.BackendTLSPolicyConditionResolvedRefs), + Type: string(gatewayv1.BackendTLSPolicyConditionResolvedRefs), Status: metav1.ConditionFalse, - Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonInvalidKind), + Reason: string(gatewayv1.BackendTLSPolicyReasonInvalidKind), } kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, resolvedRefsCond) diff --git a/conformance/tests/backendtlspolicy-invalid-kind.yaml b/conformance/tests/backendtlspolicy-invalid-kind.yaml index a7eaeb5d5c..858856c64e 100644 --- a/conformance/tests/backendtlspolicy-invalid-kind.yaml +++ b/conformance/tests/backendtlspolicy-invalid-kind.yaml @@ -33,7 +33,7 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: invalid-kind diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.go b/conformance/tests/backendtlspolicy-observed-generation-bump.go index a3cd4000bd..83c12378fb 100644 --- a/conformance/tests/backendtlspolicy-observed-generation-bump.go +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.go @@ -21,12 +21,13 @@ import ( "testing" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1alpha3" + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" "sigs.k8s.io/gateway-api/pkg/features" @@ -57,7 +58,7 @@ var BackendTLSPolicyObservedGenerationBump = suite.ConformanceTest{ namespaces := []string{"gateway-conformance-infra"} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, namespaces) - original := &v1alpha3.BackendTLSPolicy{} + original := &gatewayv1.BackendTLSPolicy{} err := suite.Client.Get(ctx, policyNN, original) require.NoError(t, err, "error getting HTTPRoute") @@ -70,12 +71,12 @@ var BackendTLSPolicyObservedGenerationBump = suite.ConformanceTest{ require.NoError(t, err, "error patching the BackendTLSPolicy") kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, metav1.Condition{ - Type: string(v1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionTrue, Reason: "", // any reason }) - updated := &v1alpha3.BackendTLSPolicy{} + updated := &gatewayv1.BackendTLSPolicy{} err = suite.Client.Get(ctx, policyNN, updated) require.NoError(t, err, "error getting BackendTLSPolicy") diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.yaml b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml index c21bd45bbc..e7d4d40cae 100644 --- a/conformance/tests/backendtlspolicy-observed-generation-bump.yaml +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml @@ -25,7 +25,7 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: observed-generation-bump diff --git a/conformance/tests/backendtlspolicy-san.go b/conformance/tests/backendtlspolicy-san.go index bbcb334d1b..2bc91acc26 100644 --- a/conformance/tests/backendtlspolicy-san.go +++ b/conformance/tests/backendtlspolicy-san.go @@ -23,7 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -54,9 +53,9 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) policyCond := metav1.Condition{ - Type: string(v1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1alpha2.PolicyReasonAccepted), + Reason: string(gatewayv1.PolicyReasonAccepted), } serverStr := "abc.example.com" diff --git a/conformance/tests/backendtlspolicy-san.yaml b/conformance/tests/backendtlspolicy-san.yaml index 7bf7a26dfd..6bab519db0 100644 --- a/conformance/tests/backendtlspolicy-san.yaml +++ b/conformance/tests/backendtlspolicy-san.yaml @@ -154,7 +154,7 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: san-dns @@ -177,7 +177,7 @@ spec: - type: "Hostname" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: san-dns-mismatch @@ -200,7 +200,7 @@ spec: - type: "Hostname" hostname: "dce.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: san-uri @@ -223,7 +223,7 @@ spec: - type: "URI" uri: "spiffe://abc.example.com/test-identity" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: san-uri-mismatch @@ -246,7 +246,7 @@ spec: - type: "URI" uri: "spiffe://def.example.com/test-identity" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: multiple-sans @@ -271,7 +271,7 @@ spec: - type: "Hostname" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: multiple-mismatch-sans diff --git a/conformance/tests/backendtlspolicy.go b/conformance/tests/backendtlspolicy.go index 203f3f8948..f4552d6926 100644 --- a/conformance/tests/backendtlspolicy.go +++ b/conformance/tests/backendtlspolicy.go @@ -23,8 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1alpha3" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -49,14 +47,14 @@ var BackendTLSPolicy = suite.ConformanceTest{ ns := "gateway-conformance-infra" acceptedCond := metav1.Condition{ - Type: string(v1alpha2.PolicyConditionAccepted), + Type: string(gatewayv1.PolicyConditionAccepted), Status: metav1.ConditionTrue, - Reason: string(v1alpha2.PolicyReasonAccepted), + Reason: string(gatewayv1.PolicyReasonAccepted), } resolvedRefsCond := metav1.Condition{ - Type: string(v1alpha3.BackendTLSPolicyConditionResolvedRefs), + Type: string(gatewayv1.BackendTLSPolicyConditionResolvedRefs), Status: metav1.ConditionTrue, - Reason: string(v1alpha3.BackendTLSPolicyReasonResolvedRefs), + Reason: string(gatewayv1.BackendTLSPolicyReasonResolvedRefs), } t.Run("Re-encrypt HTTPS request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { @@ -138,7 +136,7 @@ var BackendTLSPolicy = suite.ConformanceTest{ }) }) - // Verify that request sent to Service targeted by BackendTLSPolicy with mismatched cert should failed. + // Verify that request sent to Service targeted by BackendTLSPolicy with mismatched cert should fail. t.Run("HTTP request send to Service targeted by BackendTLSPolicy with mismatched cert should return HTTP error", func(t *testing.T) { invalidCertPolicyNN := types.NamespacedName{Name: "cert-mismatch", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, acceptedCond) diff --git a/conformance/tests/backendtlspolicy.yaml b/conformance/tests/backendtlspolicy.yaml index db9a017c39..80f634dfb5 100644 --- a/conformance/tests/backendtlspolicy.yaml +++ b/conformance/tests/backendtlspolicy.yaml @@ -104,7 +104,7 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: normative-test @@ -124,7 +124,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "abc.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: host-mismatch @@ -144,7 +144,7 @@ spec: name: "tls-checks-ca-certificate" hostname: "mismatch.example.com" --- -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: cert-mismatch diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 3309c8f29b..d37d16affa 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -37,7 +37,6 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1alpha3" "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/tlog" ) @@ -1000,7 +999,7 @@ func findPodConditionInList(t *testing.T, conditions []v1.PodCondition, condName func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, policyNN, gwNN types.NamespacedName, condition metav1.Condition) { t.Helper() waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.HTTPRouteMustHaveCondition, true, func(ctx context.Context) (bool, error) { - policy := &v1alpha3.BackendTLSPolicy{} + policy := &gatewayv1.BackendTLSPolicy{} err := client.Get(ctx, policyNN, policy) if err != nil { return false, fmt.Errorf("error fetching BackendTLSPolicy %v err: %w", policyNN, err) @@ -1029,7 +1028,7 @@ func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeo // BackendTLSPolicyMustHaveLatestConditions will fail the test if there are // conditions that were not updated -func BackendTLSPolicyMustHaveLatestConditions(t *testing.T, r *v1alpha3.BackendTLSPolicy) { +func BackendTLSPolicyMustHaveLatestConditions(t *testing.T, r *gatewayv1.BackendTLSPolicy) { t.Helper() for _, ancestor := range r.Status.Ancestors { diff --git a/examples/experimental/v1alpha3/backendtlspolicy-ca-certs.yaml b/examples/standard/backendtlspolicy/backendtlspolicy-ca-certs.yaml similarity index 86% rename from examples/experimental/v1alpha3/backendtlspolicy-ca-certs.yaml rename to examples/standard/backendtlspolicy/backendtlspolicy-ca-certs.yaml index 574ac5a83e..3cac8646b7 100644 --- a/examples/experimental/v1alpha3/backendtlspolicy-ca-certs.yaml +++ b/examples/standard/backendtlspolicy/backendtlspolicy-ca-certs.yaml @@ -1,6 +1,6 @@ #$ Used in: #$ - site-src/guides/tls.md -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: tls-upstream-auth diff --git a/examples/experimental/v1alpha3/backendtlspolicy-system-certs.yaml b/examples/standard/backendtlspolicy/backendtlspolicy-system-certs.yaml similarity index 84% rename from examples/experimental/v1alpha3/backendtlspolicy-system-certs.yaml rename to examples/standard/backendtlspolicy/backendtlspolicy-system-certs.yaml index 82dd500647..b5bf80b1a5 100644 --- a/examples/experimental/v1alpha3/backendtlspolicy-system-certs.yaml +++ b/examples/standard/backendtlspolicy/backendtlspolicy-system-certs.yaml @@ -1,6 +1,6 @@ #$ Used in: #$ - site-src/guides/tls.md -apiVersion: gateway.networking.k8s.io/v1alpha3 +apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: tls-upstream-dev diff --git a/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go index 7ed0bc4d55..c3a8ce111a 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1/apis_client.go @@ -28,6 +28,7 @@ import ( type GatewayV1Interface interface { RESTClient() rest.Interface + BackendTLSPoliciesGetter GRPCRoutesGetter GatewaysGetter GatewayClassesGetter @@ -39,6 +40,10 @@ type GatewayV1Client struct { restClient rest.Interface } +func (c *GatewayV1Client) BackendTLSPolicies(namespace string) BackendTLSPolicyInterface { + return newBackendTLSPolicies(c, namespace) +} + func (c *GatewayV1Client) GRPCRoutes(namespace string) GRPCRouteInterface { return newGRPCRoutes(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/apis/v1/backendtlspolicy.go b/pkg/client/clientset/versioned/typed/apis/v1/backendtlspolicy.go new file mode 100644 index 0000000000..8e5b27386f --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/backendtlspolicy.go @@ -0,0 +1,74 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + context "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + applyconfigurationapisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// BackendTLSPoliciesGetter has a method to return a BackendTLSPolicyInterface. +// A group's client should implement this interface. +type BackendTLSPoliciesGetter interface { + BackendTLSPolicies(namespace string) BackendTLSPolicyInterface +} + +// BackendTLSPolicyInterface has methods to work with BackendTLSPolicy resources. +type BackendTLSPolicyInterface interface { + Create(ctx context.Context, backendTLSPolicy *apisv1.BackendTLSPolicy, opts metav1.CreateOptions) (*apisv1.BackendTLSPolicy, error) + Update(ctx context.Context, backendTLSPolicy *apisv1.BackendTLSPolicy, opts metav1.UpdateOptions) (*apisv1.BackendTLSPolicy, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, backendTLSPolicy *apisv1.BackendTLSPolicy, opts metav1.UpdateOptions) (*apisv1.BackendTLSPolicy, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*apisv1.BackendTLSPolicy, error) + List(ctx context.Context, opts metav1.ListOptions) (*apisv1.BackendTLSPolicyList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *apisv1.BackendTLSPolicy, err error) + Apply(ctx context.Context, backendTLSPolicy *applyconfigurationapisv1.BackendTLSPolicyApplyConfiguration, opts metav1.ApplyOptions) (result *apisv1.BackendTLSPolicy, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, backendTLSPolicy *applyconfigurationapisv1.BackendTLSPolicyApplyConfiguration, opts metav1.ApplyOptions) (result *apisv1.BackendTLSPolicy, err error) + BackendTLSPolicyExpansion +} + +// backendTLSPolicies implements BackendTLSPolicyInterface +type backendTLSPolicies struct { + *gentype.ClientWithListAndApply[*apisv1.BackendTLSPolicy, *apisv1.BackendTLSPolicyList, *applyconfigurationapisv1.BackendTLSPolicyApplyConfiguration] +} + +// newBackendTLSPolicies returns a BackendTLSPolicies +func newBackendTLSPolicies(c *GatewayV1Client, namespace string) *backendTLSPolicies { + return &backendTLSPolicies{ + gentype.NewClientWithListAndApply[*apisv1.BackendTLSPolicy, *apisv1.BackendTLSPolicyList, *applyconfigurationapisv1.BackendTLSPolicyApplyConfiguration]( + "backendtlspolicies", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *apisv1.BackendTLSPolicy { return &apisv1.BackendTLSPolicy{} }, + func() *apisv1.BackendTLSPolicyList { return &apisv1.BackendTLSPolicyList{} }, + ), + } +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go index 0b68bad3c8..b4acb44170 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_apis_client.go @@ -28,6 +28,10 @@ type FakeGatewayV1 struct { *testing.Fake } +func (c *FakeGatewayV1) BackendTLSPolicies(namespace string) v1.BackendTLSPolicyInterface { + return newFakeBackendTLSPolicies(c, namespace) +} + func (c *FakeGatewayV1) GRPCRoutes(namespace string) v1.GRPCRouteInterface { return newFakeGRPCRoutes(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_backendtlspolicy.go b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_backendtlspolicy.go new file mode 100644 index 0000000000..986ba4849b --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1/fake/fake_backendtlspolicy.go @@ -0,0 +1,51 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + gentype "k8s.io/client-go/gentype" + v1 "sigs.k8s.io/gateway-api/apis/v1" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" + typedapisv1 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1" +) + +// fakeBackendTLSPolicies implements BackendTLSPolicyInterface +type fakeBackendTLSPolicies struct { + *gentype.FakeClientWithListAndApply[*v1.BackendTLSPolicy, *v1.BackendTLSPolicyList, *apisv1.BackendTLSPolicyApplyConfiguration] + Fake *FakeGatewayV1 +} + +func newFakeBackendTLSPolicies(fake *FakeGatewayV1, namespace string) typedapisv1.BackendTLSPolicyInterface { + return &fakeBackendTLSPolicies{ + gentype.NewFakeClientWithListAndApply[*v1.BackendTLSPolicy, *v1.BackendTLSPolicyList, *apisv1.BackendTLSPolicyApplyConfiguration]( + fake.Fake, + namespace, + v1.SchemeGroupVersion.WithResource("backendtlspolicies"), + v1.SchemeGroupVersion.WithKind("BackendTLSPolicy"), + func() *v1.BackendTLSPolicy { return &v1.BackendTLSPolicy{} }, + func() *v1.BackendTLSPolicyList { return &v1.BackendTLSPolicyList{} }, + func(dst, src *v1.BackendTLSPolicyList) { dst.ListMeta = src.ListMeta }, + func(list *v1.BackendTLSPolicyList) []*v1.BackendTLSPolicy { return gentype.ToPointerSlice(list.Items) }, + func(list *v1.BackendTLSPolicyList, items []*v1.BackendTLSPolicy) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go b/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go index 69d7f1f91e..0ed9e12b3f 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apis/v1/generated_expansion.go @@ -18,6 +18,8 @@ limitations under the License. package v1 +type BackendTLSPolicyExpansion interface{} + type GRPCRouteExpansion interface{} type GatewayExpansion interface{} diff --git a/pkg/client/informers/externalversions/apis/v1/backendtlspolicy.go b/pkg/client/informers/externalversions/apis/v1/backendtlspolicy.go new file mode 100644 index 0000000000..281489e466 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1/backendtlspolicy.go @@ -0,0 +1,102 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + context "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + gatewayapiapisv1 "sigs.k8s.io/gateway-api/apis/v1" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + apisv1 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1" +) + +// BackendTLSPolicyInformer provides access to a shared informer and lister for +// BackendTLSPolicies. +type BackendTLSPolicyInformer interface { + Informer() cache.SharedIndexInformer + Lister() apisv1.BackendTLSPolicyLister +} + +type backendTLSPolicyInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewBackendTLSPolicyInformer constructs a new informer for BackendTLSPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewBackendTLSPolicyInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredBackendTLSPolicyInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredBackendTLSPolicyInformer constructs a new informer for BackendTLSPolicy type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredBackendTLSPolicyInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().BackendTLSPolicies(namespace).List(context.Background(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().BackendTLSPolicies(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().BackendTLSPolicies(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1().BackendTLSPolicies(namespace).Watch(ctx, options) + }, + }, + &gatewayapiapisv1.BackendTLSPolicy{}, + resyncPeriod, + indexers, + ) +} + +func (f *backendTLSPolicyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredBackendTLSPolicyInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *backendTLSPolicyInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&gatewayapiapisv1.BackendTLSPolicy{}, f.defaultInformer) +} + +func (f *backendTLSPolicyInformer) Lister() apisv1.BackendTLSPolicyLister { + return apisv1.NewBackendTLSPolicyLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/apis/v1/interface.go b/pkg/client/informers/externalversions/apis/v1/interface.go index 18666f971a..d0fd01c92c 100644 --- a/pkg/client/informers/externalversions/apis/v1/interface.go +++ b/pkg/client/informers/externalversions/apis/v1/interface.go @@ -24,6 +24,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // BackendTLSPolicies returns a BackendTLSPolicyInformer. + BackendTLSPolicies() BackendTLSPolicyInformer // GRPCRoutes returns a GRPCRouteInformer. GRPCRoutes() GRPCRouteInformer // Gateways returns a GatewayInformer. @@ -45,6 +47,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// BackendTLSPolicies returns a BackendTLSPolicyInformer. +func (v *version) BackendTLSPolicies() BackendTLSPolicyInformer { + return &backendTLSPolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // GRPCRoutes returns a GRPCRouteInformer. func (v *version) GRPCRoutes() GRPCRouteInformer { return &gRPCRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index e3f00492ba..2f690b8fa2 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -57,6 +57,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=gateway.networking.k8s.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("backendtlspolicies"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1().BackendTLSPolicies().Informer()}, nil case v1.SchemeGroupVersion.WithResource("grpcroutes"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1().GRPCRoutes().Informer()}, nil case v1.SchemeGroupVersion.WithResource("gateways"): diff --git a/pkg/client/listers/apis/v1/backendtlspolicy.go b/pkg/client/listers/apis/v1/backendtlspolicy.go new file mode 100644 index 0000000000..a5dda65561 --- /dev/null +++ b/pkg/client/listers/apis/v1/backendtlspolicy.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// BackendTLSPolicyLister helps list BackendTLSPolicies. +// All objects returned here must be treated as read-only. +type BackendTLSPolicyLister interface { + // List lists all BackendTLSPolicies in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apisv1.BackendTLSPolicy, err error) + // BackendTLSPolicies returns an object that can list and get BackendTLSPolicies. + BackendTLSPolicies(namespace string) BackendTLSPolicyNamespaceLister + BackendTLSPolicyListerExpansion +} + +// backendTLSPolicyLister implements the BackendTLSPolicyLister interface. +type backendTLSPolicyLister struct { + listers.ResourceIndexer[*apisv1.BackendTLSPolicy] +} + +// NewBackendTLSPolicyLister returns a new BackendTLSPolicyLister. +func NewBackendTLSPolicyLister(indexer cache.Indexer) BackendTLSPolicyLister { + return &backendTLSPolicyLister{listers.New[*apisv1.BackendTLSPolicy](indexer, apisv1.Resource("backendtlspolicy"))} +} + +// BackendTLSPolicies returns an object that can list and get BackendTLSPolicies. +func (s *backendTLSPolicyLister) BackendTLSPolicies(namespace string) BackendTLSPolicyNamespaceLister { + return backendTLSPolicyNamespaceLister{listers.NewNamespaced[*apisv1.BackendTLSPolicy](s.ResourceIndexer, namespace)} +} + +// BackendTLSPolicyNamespaceLister helps list and get BackendTLSPolicies. +// All objects returned here must be treated as read-only. +type BackendTLSPolicyNamespaceLister interface { + // List lists all BackendTLSPolicies in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apisv1.BackendTLSPolicy, err error) + // Get retrieves the BackendTLSPolicy from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*apisv1.BackendTLSPolicy, error) + BackendTLSPolicyNamespaceListerExpansion +} + +// backendTLSPolicyNamespaceLister implements the BackendTLSPolicyNamespaceLister +// interface. +type backendTLSPolicyNamespaceLister struct { + listers.ResourceIndexer[*apisv1.BackendTLSPolicy] +} diff --git a/pkg/client/listers/apis/v1/expansion_generated.go b/pkg/client/listers/apis/v1/expansion_generated.go index 4324e25514..1627fa33b7 100644 --- a/pkg/client/listers/apis/v1/expansion_generated.go +++ b/pkg/client/listers/apis/v1/expansion_generated.go @@ -18,6 +18,14 @@ limitations under the License. package v1 +// BackendTLSPolicyListerExpansion allows custom methods to be added to +// BackendTLSPolicyLister. +type BackendTLSPolicyListerExpansion interface{} + +// BackendTLSPolicyNamespaceListerExpansion allows custom methods to be added to +// BackendTLSPolicyNamespaceLister. +type BackendTLSPolicyNamespaceListerExpansion interface{} + // GRPCRouteListerExpansion allows custom methods to be added to // GRPCRouteLister. type GRPCRouteListerExpansion interface{} diff --git a/pkg/features/backendtlspolicy.go b/pkg/features/backendtlspolicy.go index 12c6a24ccc..391e29c99e 100644 --- a/pkg/features/backendtlspolicy.go +++ b/pkg/features/backendtlspolicy.go @@ -33,7 +33,7 @@ const ( // TLSRouteFeature contains metadata for the TLSRoute feature. var BackendTLSPolicyFeature = Feature{ Name: SupportBackendTLSPolicy, - Channel: FeatureChannelExperimental, + Channel: FeatureChannelStandard, } // BackendTLSPolicySanValidationFeature contains metadata for the BackendTLSPolicy diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index bfa005bef0..f6dab0757c 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -86,6 +86,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.AllowedRoutes": schema_sigsk8sio_gateway_api_apis_v1_AllowedRoutes(ref), "sigs.k8s.io/gateway-api/apis/v1.BackendObjectReference": schema_sigsk8sio_gateway_api_apis_v1_BackendObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.BackendRef": schema_sigsk8sio_gateway_api_apis_v1_BackendRef(ref), + "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicy": schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicy(ref), + "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicyList": schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicyList(ref), + "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicySpec": schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicySpec(ref), + "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicyValidation": schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicyValidation(ref), "sigs.k8s.io/gateway-api/apis/v1.CommonRouteSpec": schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref), "sigs.k8s.io/gateway-api/apis/v1.CookieConfig": schema_sigsk8sio_gateway_api_apis_v1_CookieConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.ForwardBodyConfig": schema_sigsk8sio_gateway_api_apis_v1_ForwardBodyConfig(ref), @@ -144,15 +148,21 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig": schema_sigsk8sio_gateway_api_apis_v1_ListenerTLSConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference": schema_sigsk8sio_gateway_api_apis_v1_LocalObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.LocalParametersReference": schema_sigsk8sio_gateway_api_apis_v1_LocalParametersReference(ref), + "sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReference": schema_sigsk8sio_gateway_api_apis_v1_LocalPolicyTargetReference(ref), + "sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReferenceWithSectionName": schema_sigsk8sio_gateway_api_apis_v1_LocalPolicyTargetReferenceWithSectionName(ref), + "sigs.k8s.io/gateway-api/apis/v1.NamespacedPolicyTargetReference": schema_sigsk8sio_gateway_api_apis_v1_NamespacedPolicyTargetReference(ref), "sigs.k8s.io/gateway-api/apis/v1.ObjectReference": schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.ParametersReference": schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref), "sigs.k8s.io/gateway-api/apis/v1.ParentReference": schema_sigsk8sio_gateway_api_apis_v1_ParentReference(ref), + "sigs.k8s.io/gateway-api/apis/v1.PolicyAncestorStatus": schema_sigsk8sio_gateway_api_apis_v1_PolicyAncestorStatus(ref), + "sigs.k8s.io/gateway-api/apis/v1.PolicyStatus": schema_sigsk8sio_gateway_api_apis_v1_PolicyStatus(ref), "sigs.k8s.io/gateway-api/apis/v1.RouteGroupKind": schema_sigsk8sio_gateway_api_apis_v1_RouteGroupKind(ref), "sigs.k8s.io/gateway-api/apis/v1.RouteNamespaces": schema_sigsk8sio_gateway_api_apis_v1_RouteNamespaces(ref), "sigs.k8s.io/gateway-api/apis/v1.RouteParentStatus": schema_sigsk8sio_gateway_api_apis_v1_RouteParentStatus(ref), "sigs.k8s.io/gateway-api/apis/v1.RouteStatus": schema_sigsk8sio_gateway_api_apis_v1_RouteStatus(ref), "sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference": schema_sigsk8sio_gateway_api_apis_v1_SecretObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.SessionPersistence": schema_sigsk8sio_gateway_api_apis_v1_SessionPersistence(ref), + "sigs.k8s.io/gateway-api/apis/v1.SubjectAltName": schema_sigsk8sio_gateway_api_apis_v1_SubjectAltName(ref), "sigs.k8s.io/gateway-api/apis/v1.SupportedFeature": schema_sigsk8sio_gateway_api_apis_v1_SupportedFeature(ref), "sigs.k8s.io/gateway-api/apis/v1.TLSConfig": schema_sigsk8sio_gateway_api_apis_v1_TLSConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig": schema_sigsk8sio_gateway_api_apis_v1_TLSPortConfig(ref), @@ -183,9 +193,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1alpha2.UDPRouteStatus": schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteStatus(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicy": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicy(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicyList": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyList(ref), - "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicySpec": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicySpec(ref), - "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicyValidation": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref), - "sigs.k8s.io/gateway-api/apis/v1alpha3.SubjectAltName": schema_sigsk8sio_gateway_api_apis_v1alpha3_SubjectAltName(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRoute": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRoute(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteList": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteList(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteSpec": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref), @@ -3019,6 +3026,237 @@ func schema_sigsk8sio_gateway_api_apis_v1_BackendRef(ref common.ReferenceCallbac } } +func schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BackendTLSPolicy provides a way to configure how a Gateway connects to a Backend via TLS.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec defines the desired state of BackendTLSPolicy.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicySpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status defines the current state of BackendTLSPolicy.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.PolicyStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicySpec", "sigs.k8s.io/gateway-api/apis/v1.PolicyStatus"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicyList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BackendTLSPolicyList contains a list of BackendTLSPolicies", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicy"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicy"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicySpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BackendTLSPolicySpec defines the desired state of BackendTLSPolicy.\n\nSupport: Extended", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "targetRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy.\n\nTargetRefs must be _distinct_. This means either that:\n\n* They select different targets. If this is the case, then targetRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, and `name` must\n be unique across all targetRef entries in the BackendTLSPolicy.\n* They select different sectionNames in the same target.\n\nWhen more than one BackendTLSPolicy selects the same target and sectionName, implementations MUST determine precedence using the following criteria, continuing on ties:\n\n* The older policy by creation timestamp takes precedence. For\n example, a policy with a creation timestamp of \"2021-07-15\n 01:02:03\" MUST be given precedence over a policy with a\n creation timestamp of \"2021-07-15 01:02:04\".\n* The policy appearing first in alphabetical order by {name}.\n For example, a policy named `bar` is given precedence over a\n policy named `baz`.\n\nFor any BackendTLSPolicy that does not take precedence, the implementation MUST ensure the `Accepted` Condition is set to `status: False`, with Reason `Conflicted`.\n\nSupport: Extended for Kubernetes Service\n\nSupport: Implementation-specific for any other resource", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReferenceWithSectionName"), + }, + }, + }, + }, + }, + "validation": { + SchemaProps: spec.SchemaProps{ + Description: "Validation contains backend TLS validation configuration.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicyValidation"), + }, + }, + "options": { + SchemaProps: spec.SchemaProps{ + Description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites.\n\nA set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API.\n\nSupport: Implementation-specific", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + Required: []string{"targetRefs", "validation"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicyValidation", "sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReferenceWithSectionName"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_BackendTLSPolicyValidation(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "BackendTLSPolicyValidation contains backend TLS validation configuration.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "caCertificateRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod.\n\nIf CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation.\n\nA CACertificateRef is invalid if:\n\n* It refers to a resource that cannot be resolved (e.g., the referenced resource\n does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key\n named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef`\n and the Message of the Condition must indicate which reference is invalid and why.\n\n* It refers to an unknown or unsupported kind of resource. In this case, the Reason\n must be set to `InvalidKind` and the Message of the Condition must explain which\n kind of resource is unknown or unsupported.\n\n* It refers to a resource in another namespace. This may change in future\n spec updates.\n\nImplementations MAY choose to perform further validation of the certificate content (e.g., checking expiry or enforcing specific formats). In such cases, an implementation-specific Reason and Message must be set for the invalid reference.\n\nIn all cases, the implementation MUST ensure the `ResolvedRefs` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason and Message that indicate the cause of the error. Connections using an invalid CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. If ALL CACertificateRefs are invalid, the implementation MUST also ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `NoValidCACertificate`.\n\nA single CACertificateRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific.\n\nSupport: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific - More than one reference, other kinds of resources, or a single reference that includes multiple certificates.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference"), + }, + }, + }, + }, + }, + "wellKnownCACertificates": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod.\n\nIf WellKnownCACertificates is unspecified or empty (\"\"), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field, or the supplied value is not recognized, the implementation MUST ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `Invalid`.\n\nSupport: Implementation-specific", + Type: []string{"string"}, + Format: "", + }, + }, + "hostname": { + SchemaProps: spec.SchemaProps{ + Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate\n served by the matching backend, unless SubjectAltNames is specified.\n3. If SubjectAltNames are specified, Hostname can be used for certificate selection\n but MUST NOT be used for authentication. If you want to use the value\n of the Hostname field for authentication, you MUST add it to the SubjectAltNames list.\n\nSupport: Core", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "subjectAltNames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "SubjectAltNames contains one or more Subject Alternative Names. When specified the certificate served from the backend MUST have at least one Subject Alternate Name matching one of the specified SubjectAltNames.\n\nSupport: Extended", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.SubjectAltName"), + }, + }, + }, + }, + }, + }, + Required: []string{"hostname"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference", "sigs.k8s.io/gateway-api/apis/v1.SubjectAltName"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -5877,16 +6115,16 @@ func schema_sigsk8sio_gateway_api_apis_v1_LocalParametersReference(ref common.Re } } -func schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_sigsk8sio_gateway_api_apis_v1_LocalPolicyTargetReference(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ObjectReference identifies an API object including its namespace.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.\n\nReferences to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object.", + Description: "LocalPolicyTargetReference identifies an API object to apply a direct or inherited policy to. This should be used as part of Policy resources that can target Gateway API resources. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ - Description: "Group is the group of the referent. For example, \"gateway.networking.k8s.io\". When set to the empty string, core API group is inferred.", + Description: "Group is the group of the target resource.", Default: "", Type: []string{"string"}, Format: "", @@ -5894,7 +6132,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref common.ReferenceCa }, "kind": { SchemaProps: spec.SchemaProps{ - Description: "Kind is kind of the referent. For example \"ConfigMap\" or \"Service\".", + Description: "Kind is kind of the target resource.", Default: "", Type: []string{"string"}, Format: "", @@ -5902,19 +6140,12 @@ func schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref common.ReferenceCa }, "name": { SchemaProps: spec.SchemaProps{ - Description: "Name is the name of the referent.", + Description: "Name is the name of the target resource.", Default: "", Type: []string{"string"}, Format: "", }, }, - "namespace": { - SchemaProps: spec.SchemaProps{ - Description: "Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred.\n\nNote that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.\n\nSupport: Core", - Type: []string{"string"}, - Format: "", - }, - }, }, Required: []string{"group", "kind", "name"}, }, @@ -5922,16 +6153,16 @@ func schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref common.ReferenceCa } } -func schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_sigsk8sio_gateway_api_apis_v1_LocalPolicyTargetReferenceWithSectionName(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ParametersReference identifies an API object containing controller-specific configuration resource within the cluster.", + Description: "LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a direct policy to. This should be used as part of Policy resources that can target single resources. For more information on how this policy attachment mode works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.\n\nNote: This should only be used for direct policy attachment when references to SectionName are actually needed. In all other cases, LocalPolicyTargetReference should be used.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ - Description: "Group is the group of the referent.", + Description: "Group is the group of the target resource.", Default: "", Type: []string{"string"}, Format: "", @@ -5939,7 +6170,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref common.Referen }, "kind": { SchemaProps: spec.SchemaProps{ - Description: "Kind is kind of the referent.", + Description: "Kind is kind of the target resource.", Default: "", Type: []string{"string"}, Format: "", @@ -5947,15 +6178,15 @@ func schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref common.Referen }, "name": { SchemaProps: spec.SchemaProps{ - Description: "Name is the name of the referent.", + Description: "Name is the name of the target resource.", Default: "", Type: []string{"string"}, Format: "", }, }, - "namespace": { + "sectionName": { SchemaProps: spec.SchemaProps{ - Description: "Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource.", + Description: "SectionName is the name of a section within the target resource. When unspecified, this targetRef targets the entire resource. In the following resources, SectionName is interpreted as the following:\n\n* Gateway: Listener name * HTTPRoute: HTTPRouteRule name * Service: Port name\n\nIf a SectionName is specified, but does not exist on the targeted object, the Policy must fail to attach, and the policy implementation should record a `ResolvedRefs` or similar Condition in the Policy's status.", Type: []string{"string"}, Format: "", }, @@ -5967,28 +6198,163 @@ func schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref common.Referen } } -func schema_sigsk8sio_gateway_api_apis_v1_ParentReference(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_sigsk8sio_gateway_api_apis_v1_NamespacedPolicyTargetReference(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.", + Description: "NamespacedPolicyTargetReference identifies an API object to apply a direct or inherited policy to, potentially in a different namespace. This should only be used as part of Policy resources that need to be able to target resources in different namespaces. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ - Description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string).\n\nSupport: Core", + Description: "Group is the group of the target resource.", + Default: "", Type: []string{"string"}, Format: "", }, }, "kind": { SchemaProps: spec.SchemaProps{ - Description: "Kind is kind of the referent.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nSupport for other resources is Implementation-Specific.", + Description: "Kind is kind of the target resource.", + Default: "", Type: []string{"string"}, Format: "", }, }, - "namespace": { + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of the target resource.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace is the namespace of the referent. When unspecified, the local namespace is inferred. Even when policy targets a resource in a different namespace, it MUST only apply to traffic originating from the same namespace as the policy.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "kind", "name"}, + }, + }, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ObjectReference identifies an API object including its namespace.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.\n\nReferences to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Description: "Group is the group of the referent. For example, \"gateway.networking.k8s.io\". When set to the empty string, core API group is inferred.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is kind of the referent. For example \"ConfigMap\" or \"Service\".", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of the referent.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred.\n\nNote that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "kind", "name"}, + }, + }, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_ParametersReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ParametersReference identifies an API object containing controller-specific configuration resource within the cluster.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Description: "Group is the group of the referent.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is kind of the referent.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of the referent.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { + SchemaProps: spec.SchemaProps{ + Description: "Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"group", "kind", "name"}, + }, + }, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_ParentReference(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "group": { + SchemaProps: spec.SchemaProps{ + Description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string).\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is kind of the referent.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nSupport for other resources is Implementation-Specific.", + Type: []string{"string"}, + Format: "", + }, + }, + "namespace": { SchemaProps: spec.SchemaProps{ Description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route.\n\nNote that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\nSupport: Core", Type: []string{"string"}, @@ -6024,6 +6390,94 @@ func schema_sigsk8sio_gateway_api_apis_v1_ParentReference(ref common.ReferenceCa } } +func schema_sigsk8sio_gateway_api_apis_v1_PolicyAncestorStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PolicyAncestorStatus describes the status of a route with respect to an associated Ancestor.\n\nAncestors refer to objects that are either the Target of a policy or above it in terms of object hierarchy. For example, if a policy targets a Service, the Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most useful object to place Policy status on, so we recommend that implementations SHOULD use Gateway as the PolicyAncestorStatus object unless the designers have a _very_ good reason otherwise.\n\nIn the context of policy attachment, the Ancestor is used to distinguish which resource results in a distinct application of this policy. For example, if a policy targets a Service, it may have a distinct result per attached Gateway.\n\nPolicies targeting the same resource may have different effects depending on the ancestors of those resources. For example, different Gateways targeting the same Service may have different capabilities, especially if they have different underlying implementations.\n\nFor example, in BackendTLSPolicy, the Policy attaches to a Service that is used as a backend in a HTTPRoute that is itself attached to a Gateway. In this case, the relevant object for status is the Gateway, and that is the ancestor object referred to in this status.\n\nNote that a parent is also an ancestor, so for objects where the parent is the relevant object for status, this struct SHOULD still be used.\n\nThis struct is intended to be used in a slice that's effectively a map, with a composite key made up of the AncestorRef and the ControllerName.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "ancestorRef": { + SchemaProps: spec.SchemaProps{ + Description: "AncestorRef corresponds with a ParentRef in the spec that this PolicyAncestorStatus struct describes the status of.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ParentReference"), + }, + }, + "controllerName": { + SchemaProps: spec.SchemaProps{ + Description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass.\n\nExample: \"example.net/gateway-controller\".\n\nThe format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).\n\nControllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "conditions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "type", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Conditions describes the status of the Policy with respect to the given Ancestor.\n\n\n\nNotes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n\n", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Condition"), + }, + }, + }, + }, + }, + }, + Required: []string{"ancestorRef", "controllerName", "conditions"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Condition", "sigs.k8s.io/gateway-api/apis/v1.ParentReference"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_PolicyStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PolicyStatus defines the common attributes that all Policies should include within their status.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "ancestors": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "Ancestors is a list of ancestor resources (usually Gateways) that are associated with the policy, and the status of the policy with respect to each ancestor. When this policy attaches to a parent, the controller that manages the parent and the ancestors MUST add an entry to this list when the controller first sees the policy and SHOULD update the entry as appropriate when the relevant ancestor is modified.\n\nNote that choosing the relevant ancestor is left to the Policy designers; an important part of Policy design is designing the right object level at which to namespace this status.\n\nNote also that implementations MUST ONLY populate ancestor status for the Ancestor resources they are responsible for. Implementations MUST use the ControllerName field to uniquely identify the entries in this list that they are responsible for.\n\nNote that to achieve this, the list of PolicyAncestorStatus structs MUST be treated as a map with a composite key, made up of the AncestorRef and ControllerName fields combined.\n\nA maximum of 16 ancestors will be represented in this list. An empty list means the Policy is not relevant for any ancestors.\n\nIf this slice is full, implementations MUST NOT add further entries. Instead they MUST consider the policy unimplementable and signal that on any related resources such as the ancestor that would be referenced here. For example, if this list was full on BackendTLSPolicy, no additional Gateways would be able to reference the Service targeted by the BackendTLSPolicy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.PolicyAncestorStatus"), + }, + }, + }, + }, + }, + }, + Required: []string{"ancestors"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.PolicyAncestorStatus"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_RouteGroupKind(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6261,6 +6715,42 @@ func schema_sigsk8sio_gateway_api_apis_v1_SessionPersistence(ref common.Referenc } } +func schema_sigsk8sio_gateway_api_apis_v1_SubjectAltName(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "SubjectAltName represents Subject Alternative Name.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type determines the format of the Subject Alternative Name. Always required.\n\nSupport: Core", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "hostname": { + SchemaProps: spec.SchemaProps{ + Description: "Hostname contains Subject Alternative Name specified in DNS name format. Required when Type is set to Hostname, ignored otherwise.\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, + "uri": { + SchemaProps: spec.SchemaProps{ + Description: "URI contains Subject Alternative Name specified in a full URI format. It MUST include both a scheme (e.g., \"http\" or \"ftp\") and a scheme-specific-part. Common values include SPIFFE IDs like \"spiffe://mycluster.example.com/ns/myns/sa/svc1sa\". Required when Type is set to URI, ignored otherwise.\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type"}, + }, + }, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_SupportedFeature(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6454,8 +6944,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_LocalPolicyTargetReference(ref c return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "LocalPolicyTargetReference identifies an API object to apply a direct or inherited policy to. This should be used as part of Policy resources that can target Gateway API resources. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ @@ -6492,8 +6981,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_LocalPolicyTargetReferenceWithSe return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a direct policy to. This should be used as part of Policy resources that can target single resources. For more information on how this policy attachment mode works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.\n\nNote: This should only be used for direct policy attachment when references to SectionName are actually needed. In all other cases, LocalPolicyTargetReference should be used.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ @@ -6537,8 +7025,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_NamespacedPolicyTargetReference( return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "NamespacedPolicyTargetReference identifies an API object to apply a direct or inherited policy to, potentially in a different namespace. This should only be used as part of Policy resources that need to be able to target resources in different namespaces. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ @@ -6582,8 +7069,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyAncestorStatus(ref common. return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "PolicyAncestorStatus describes the status of a route with respect to an associated Ancestor.\n\nAncestors refer to objects that are either the Target of a policy or above it in terms of object hierarchy. For example, if a policy targets a Service, the Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most useful object to place Policy status on, so we recommend that implementations SHOULD use Gateway as the PolicyAncestorStatus object unless the designers have a _very_ good reason otherwise.\n\nIn the context of policy attachment, the Ancestor is used to distinguish which resource results in a distinct application of this policy. For example, if a policy targets a Service, it may have a distinct result per attached Gateway.\n\nPolicies targeting the same resource may have different effects depending on the ancestors of those resources. For example, different Gateways targeting the same Service may have different capabilities, especially if they have different underlying implementations.\n\nFor example, in BackendTLSPolicy, the Policy attaches to a Service that is used as a backend in a HTTPRoute that is itself attached to a Gateway. In this case, the relevant object for status is the Gateway, and that is the ancestor object referred to in this status.\n\nNote that a parent is also an ancestor, so for objects where the parent is the relevant object for status, this struct SHOULD still be used.\n\nThis struct is intended to be used in a slice that's effectively a map, with a composite key made up of the AncestorRef and the ControllerName.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "ancestorRef": { SchemaProps: spec.SchemaProps{ @@ -6635,8 +7121,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyStatus(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "PolicyStatus defines the common attributes that all Policies should include within their status.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "ancestors": { VendorExtensible: spec.VendorExtensible{ @@ -6651,7 +7136,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyStatus(ref common.Referenc Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyAncestorStatus"), + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.PolicyAncestorStatus"), }, }, }, @@ -6662,7 +7147,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyStatus(ref common.Referenc }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyAncestorStatus"}, + "sigs.k8s.io/gateway-api/apis/v1.PolicyAncestorStatus"}, } } @@ -7492,8 +7977,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicy(ref common.Refe return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "BackendTLSPolicy provides a way to configure how a Gateway connects to a Backend via TLS.", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ @@ -7519,14 +8003,14 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicy(ref common.Refe SchemaProps: spec.SchemaProps{ Description: "Spec defines the desired state of BackendTLSPolicy.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicySpec"), + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicySpec"), }, }, "status": { SchemaProps: spec.SchemaProps{ Description: "Status defines the current state of BackendTLSPolicy.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus"), + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.PolicyStatus"), }, }, }, @@ -7534,7 +8018,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicy(ref common.Refe }, }, Dependencies: []string{ - "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus", "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicySpec"}, + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1.BackendTLSPolicySpec", "sigs.k8s.io/gateway-api/apis/v1.PolicyStatus"}, } } @@ -7542,8 +8026,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyList(ref common. return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "BackendTLSPolicyList contains a list of BackendTLSPolicies", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ @@ -7587,174 +8070,6 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyList(ref common. } } -func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicySpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "BackendTLSPolicySpec defines the desired state of BackendTLSPolicy.\n\nSupport: Extended", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "targetRefs": { - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-list-type": "atomic", - }, - }, - SchemaProps: spec.SchemaProps{ - Description: "TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy.\n\nTargetRefs must be _distinct_. This means either that:\n\n* They select different targets. If this is the case, then targetRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, and `name` must\n be unique across all targetRef entries in the BackendTLSPolicy.\n* They select different sectionNames in the same target.\n\nWhen more than one BackendTLSPolicy selects the same target and sectionName, implementations MUST determine precedence using the following criteria, continuing on ties:\n\n* The older policy by creation timestamp takes precedence. For\n example, a policy with a creation timestamp of \"2021-07-15\n 01:02:03\" MUST be given precedence over a policy with a\n creation timestamp of \"2021-07-15 01:02:04\".\n* The policy appearing first in alphabetical order by {name}.\n For example, a policy named `bar` is given precedence over a\n policy named `baz`.\n\nFor any BackendTLSPolicy that does not take precedence, the implementation MUST ensure the `Accepted` Condition is set to `status: False`, with Reason `Conflicted`.\n\nSupport: Extended for Kubernetes Service\n\nSupport: Implementation-specific for any other resource", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReferenceWithSectionName"), - }, - }, - }, - }, - }, - "validation": { - SchemaProps: spec.SchemaProps{ - Description: "Validation contains backend TLS validation configuration.", - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicyValidation"), - }, - }, - "options": { - SchemaProps: spec.SchemaProps{ - Description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites.\n\nA set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API.\n\nSupport: Implementation-specific", - Type: []string{"object"}, - AdditionalProperties: &spec.SchemaOrBool{ - Allows: true, - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - }, - Required: []string{"targetRefs", "validation"}, - }, - }, - Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReferenceWithSectionName", "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicyValidation"}, - } -} - -func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "BackendTLSPolicyValidation contains backend TLS validation configuration.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "caCertificateRefs": { - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-list-type": "atomic", - }, - }, - SchemaProps: spec.SchemaProps{ - Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod.\n\nIf CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation.\n\nA CACertificateRef is invalid if:\n\n* It refers to a resource that cannot be resolved (e.g., the referenced resource\n does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key\n named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef`\n and the Message of the Condition must indicate which reference is invalid and why.\n\n* It refers to an unknown or unsupported kind of resource. In this case, the Reason\n must be set to `InvalidKind` and the Message of the Condition must explain which\n kind of resource is unknown or unsupported.\n\n* It refers to a resource in another namespace. This may change in future\n spec updates.\n\nImplementations MAY choose to perform further validation of the certificate content (e.g., checking expiry or enforcing specific formats). In such cases, an implementation-specific Reason and Message must be set for the invalid reference.\n\nIn all cases, the implementation MUST ensure the `ResolvedRefs` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason and Message that indicate the cause of the error. Connections using an invalid CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. If ALL CACertificateRefs are invalid, the implementation MUST also ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `NoValidCACertificate`.\n\nA single CACertificateRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific.\n\nSupport: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific - More than one reference, other kinds of resources, or a single reference that includes multiple certificates.", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference"), - }, - }, - }, - }, - }, - "wellKnownCACertificates": { - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-list-type": "atomic", - }, - }, - SchemaProps: spec.SchemaProps{ - Description: "WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod.\n\nIf WellKnownCACertificates is unspecified or empty (\"\"), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field, or the supplied value is not recognized, the implementation MUST ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `Invalid`.\n\nSupport: Implementation-specific", - Type: []string{"string"}, - Format: "", - }, - }, - "hostname": { - SchemaProps: spec.SchemaProps{ - Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate\n served by the matching backend, unless SubjectAltNames is specified.\n3. If SubjectAltNames are specified, Hostname can be used for certificate selection\n but MUST NOT be used for authentication. If you want to use the value\n of the Hostname field for authentication, you MUST add it to the SubjectAltNames list.\n\nSupport: Core", - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "subjectAltNames": { - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-list-type": "atomic", - }, - }, - SchemaProps: spec.SchemaProps{ - Description: "SubjectAltNames contains one or more Subject Alternative Names. When specified the certificate served from the backend MUST have at least one Subject Alternate Name matching one of the specified SubjectAltNames.\n\nSupport: Extended", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha3.SubjectAltName"), - }, - }, - }, - }, - }, - }, - Required: []string{"hostname"}, - }, - }, - Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference", "sigs.k8s.io/gateway-api/apis/v1alpha3.SubjectAltName"}, - } -} - -func schema_sigsk8sio_gateway_api_apis_v1alpha3_SubjectAltName(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "SubjectAltName represents Subject Alternative Name.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "type": { - SchemaProps: spec.SchemaProps{ - Description: "Type determines the format of the Subject Alternative Name. Always required.\n\nSupport: Core", - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "hostname": { - SchemaProps: spec.SchemaProps{ - Description: "Hostname contains Subject Alternative Name specified in DNS name format. Required when Type is set to Hostname, ignored otherwise.\n\nSupport: Core", - Type: []string{"string"}, - Format: "", - }, - }, - "uri": { - SchemaProps: spec.SchemaProps{ - Description: "URI contains Subject Alternative Name specified in a full URI format. It MUST include both a scheme (e.g., \"http\" or \"ftp\") and a scheme-specific-part. Common values include SPIFFE IDs like \"spiffe://mycluster.example.com/ns/myns/sa/svc1sa\". Required when Type is set to URI, ignored otherwise.\n\nSupport: Core", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"type"}, - }, - }, - } -} - func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRoute(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -8477,7 +8792,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_BackendTrafficPolicySpec(ref co Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference"), + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReference"), }, }, }, @@ -8500,7 +8815,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_BackendTrafficPolicySpec(ref co }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.SessionPersistence", "sigs.k8s.io/gateway-api/apis/v1alpha2.LocalPolicyTargetReference", "sigs.k8s.io/gateway-api/apisx/v1alpha1.RetryConstraint"}, + "sigs.k8s.io/gateway-api/apis/v1.LocalPolicyTargetReference", "sigs.k8s.io/gateway-api/apis/v1.SessionPersistence", "sigs.k8s.io/gateway-api/apisx/v1alpha1.RetryConstraint"}, } } @@ -9002,7 +9317,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XBackendTrafficPolicy(ref commo SchemaProps: spec.SchemaProps{ Description: "Status defines the current state of BackendTrafficPolicy.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus"), + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.PolicyStatus"), }, }, }, @@ -9010,7 +9325,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_XBackendTrafficPolicy(ref commo }, }, Dependencies: []string{ - "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1alpha2.PolicyStatus", "sigs.k8s.io/gateway-api/apisx/v1alpha1.BackendTrafficPolicySpec"}, + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1.PolicyStatus", "sigs.k8s.io/gateway-api/apisx/v1alpha1.BackendTrafficPolicySpec"}, } } diff --git a/pkg/generator/main.go b/pkg/generator/main.go index 1149e1a902..0916864b93 100644 --- a/pkg/generator/main.go +++ b/pkg/generator/main.go @@ -33,11 +33,12 @@ import ( ) var standardKinds = map[string]bool{ - "GatewayClass": true, - "Gateway": true, - "GRPCRoute": true, - "HTTPRoute": true, - "ReferenceGrant": true, + "GatewayClass": true, + "Gateway": true, + "GRPCRoute": true, + "HTTPRoute": true, + "ReferenceGrant": true, + "BackendTLSPolicy": true, } // This generation code is largely copied from diff --git a/pkg/test/cel/backendtlspolicy_test.go b/pkg/test/cel/backendtlspolicy_test.go index d035ef6f00..2be7fa5b8f 100644 --- a/pkg/test/cel/backendtlspolicy_test.go +++ b/pkg/test/cel/backendtlspolicy_test.go @@ -1,6 +1,3 @@ -//go:build experimental -// +build experimental - /* Copyright 2023 The Kubernetes Authors. @@ -26,31 +23,31 @@ import ( "time" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - gatewayv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1a3 "sigs.k8s.io/gateway-api/apis/v1alpha3" - v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" ) func TestBackendTLSPolicyTargetRefs(t *testing.T) { tests := []struct { name string wantErrors []string - targetRefs []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName + targetRefs []gatewayv1.LocalPolicyTargetReferenceWithSectionName }{ { name: "invalid because duplicate target refs without section name", wantErrors: []string{"sectionName must be unique when targetRefs includes 2 or more references to the same target"}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, }}, @@ -58,60 +55,60 @@ func TestBackendTLSPolicyTargetRefs(t *testing.T) { { name: "invalid because duplicate target refs with only one section name", wantErrors: []string{"sectionName must be specified when targetRefs includes 2 or more references to the same target"}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example2", }, }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "invalid because duplicate target refs with duplicate section names", wantErrors: []string{"sectionName must be unique when targetRefs includes 2 or more references to the same target"}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("bar")), + SectionName: ptrTo(gatewayv1.SectionName("bar")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid single targetRef without sectionName", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, }}, @@ -119,117 +116,117 @@ func TestBackendTLSPolicyTargetRefs(t *testing.T) { { name: "valid single targetRef with sectionName", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because duplicate target refs with different section names", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("bar")), + SectionName: ptrTo(gatewayv1.SectionName("bar")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("jin")), + SectionName: ptrTo(gatewayv1.SectionName("jin")), }}, }, { name: "valid because duplicate target refs with different names", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example2", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example3", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because duplicate target refs with different kinds", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("NotService"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("NotService"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, { name: "valid because duplicate target refs with different groups", wantErrors: []string{}, - targetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{{ - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group(corev1.GroupName), - Kind: gatewayv1a2.Kind("Service"), + targetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group(corev1.GroupName), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }, { - LocalPolicyTargetReference: gatewayv1a2.LocalPolicyTargetReference{ - Group: gatewayv1a2.Group("svc.other.io"), - Kind: gatewayv1a2.Kind("Service"), + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ + Group: gatewayv1.Group("svc.other.io"), + Kind: gatewayv1.Kind("Service"), Name: "example", }, - SectionName: ptrTo(gatewayv1a2.SectionName("foo")), + SectionName: ptrTo(gatewayv1.SectionName("foo")), }}, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - policy := &gatewayv1a3.BackendTLSPolicy{ + policy := &gatewayv1.BackendTLSPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1a3.BackendTLSPolicySpec{ + Spec: gatewayv1.BackendTLSPolicySpec{ TargetRefs: tc.targetRefs, - Validation: gatewayv1a3.BackendTLSPolicyValidation{ - WellKnownCACertificates: ptrTo(gatewayv1a3.WellKnownCACertificatesType("System")), + Validation: gatewayv1.BackendTLSPolicyValidation{ + WellKnownCACertificates: ptrTo(gatewayv1.WellKnownCACertificatesType("System")), Hostname: "foo.example.com", }, }, @@ -243,20 +240,20 @@ func TestBackendTLSPolicyValidation(t *testing.T) { tests := []struct { name string wantErrors []string - policyValidation gatewayv1a3.BackendTLSPolicyValidation + policyValidation gatewayv1.BackendTLSPolicyValidation }{ { name: "valid BackendTLSPolicyValidation with WellKnownCACertificates", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - WellKnownCACertificates: ptrTo(gatewayv1a3.WellKnownCACertificatesType("System")), + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + WellKnownCACertificates: ptrTo(gatewayv1.WellKnownCACertificatesType("System")), Hostname: "foo.example.com", }, wantErrors: []string{}, }, { name: "valid BackendTLSPolicyValidation with CACertificateRefs", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -269,20 +266,20 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with missing fields", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{}, + policyValidation: gatewayv1.BackendTLSPolicyValidation{}, wantErrors: []string{"spec.validation.hostname in body should be at least 1 chars long", "must specify either CACertificateRefs or WellKnownCACertificates"}, }, { name: "invalid BackendTLSPolicyValidation with both CACertificateRefs and WellKnownCACertificates", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", Name: "name", }, }, - WellKnownCACertificates: ptrTo(gatewayv1a3.WellKnownCACertificatesType("System")), + WellKnownCACertificates: ptrTo(gatewayv1.WellKnownCACertificatesType("System")), Hostname: "foo.example.com", }, @@ -290,16 +287,16 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with Unsupported value for WellKnownCACertificates", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - WellKnownCACertificates: ptrTo(gatewayv1a3.WellKnownCACertificatesType("bar")), + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + WellKnownCACertificates: ptrTo(gatewayv1.WellKnownCACertificatesType("bar")), Hostname: "foo.example.com", }, wantErrors: []string{"supported values: \"System\""}, }, { name: "invalid BackendTLSPolicyValidation with empty Hostname field", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -312,8 +309,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "valid BackendTLSPolicyValidation with SubjectAltName type Hostname", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -321,7 +318,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "Hostname", Hostname: "foo.example.com", @@ -332,8 +329,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "valid BackendTLSPolicyValidation with SubjectAltName type URI", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -341,7 +338,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "URI", URI: "spiffe://mycluster.example", @@ -352,8 +349,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with SubjectAltName type Hostname and empty Hostname field", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -361,7 +358,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "Hostname", Hostname: "", @@ -372,8 +369,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with SubjectAltName type URI and non-empty Hostname field", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -381,7 +378,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "URI", Hostname: "foo.example.com", @@ -392,8 +389,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with SubjectAltName type URI and empty URI field", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -401,7 +398,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "URI", URI: "", @@ -412,8 +409,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with SubjectAltName type Hostname and non-empty URI field", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -421,7 +418,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "Hostname", URI: "test", @@ -432,8 +429,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation with SubjectAltName type Hostname and both Hostname and URI specified", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -441,7 +438,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "Hostname", Hostname: "foo.example.com", @@ -453,8 +450,8 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, { name: "invalid BackendTLSPolicyValidation incorrect URI SAN", - policyValidation: gatewayv1a3.BackendTLSPolicyValidation{ - CACertificateRefs: []v1beta1.LocalObjectReference{ + policyValidation: gatewayv1.BackendTLSPolicyValidation{ + CACertificateRefs: []gatewayv1.LocalObjectReference{ { Group: "group", Kind: "kind", @@ -462,7 +459,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { }, }, Hostname: "foo.example.com", - SubjectAltNames: []gatewayv1a3.SubjectAltName{ + SubjectAltNames: []gatewayv1.SubjectAltName{ { Type: "URI", URI: "foo.example.com", @@ -475,21 +472,21 @@ func TestBackendTLSPolicyValidation(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - policy := &gatewayv1a3.BackendTLSPolicy{ + policy := &gatewayv1.BackendTLSPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), Namespace: metav1.NamespaceDefault, }, - Spec: gatewayv1a3.BackendTLSPolicySpec{ - TargetRefs: []gatewayv1a2.LocalPolicyTargetReferenceWithSectionName{ + Spec: gatewayv1.BackendTLSPolicySpec{ + TargetRefs: []gatewayv1.LocalPolicyTargetReferenceWithSectionName{ { - gatewayv1a2.LocalPolicyTargetReference{ + LocalPolicyTargetReference: gatewayv1.LocalPolicyTargetReference{ Group: "group", Kind: "kind", Name: "name", }, // SectionName cannot contain capital letters. - ptrTo(gatewayv1a2.SectionName("section")), + SectionName: ptrTo(gatewayv1.SectionName("section")), }, }, Validation: tc.policyValidation, @@ -500,7 +497,7 @@ func TestBackendTLSPolicyValidation(t *testing.T) { } } -func validateBackendTLSPolicy(t *testing.T, policy *gatewayv1a3.BackendTLSPolicy, wantErrors []string) { +func validateBackendTLSPolicy(t *testing.T, policy *gatewayv1.BackendTLSPolicy, wantErrors []string) { t.Helper() ctx := context.Background() diff --git a/site-src/guides/tls.md b/site-src/guides/tls.md index be3281ee8a..4741171ac2 100644 --- a/site-src/guides/tls.md +++ b/site-src/guides/tls.md @@ -145,7 +145,7 @@ TLS-encrypted upstream connection where Pods backing the `dev` Service are expec certificate for `dev.example.com`. ```yaml -{% include 'experimental/v1alpha3/backendtlspolicy-system-certs.yaml' %} +{% include 'standard/v1/backendtlspolicy-system-certs.yaml' %} ``` #### Using Explicit CA Certificates @@ -155,7 +155,7 @@ map `auth-cert` to connect with a TLS-encrypted upstream connection where Pods b are expected to serve a valid certificate for `auth.example.com`. ```yaml -{% include 'experimental/v1alpha3/backendtlspolicy-ca-certs.yaml' %} +{% include 'standard/v1/backendtlspolicy-ca-certs.yaml' %} ``` ## Extensions From 7c6e71ba5f7a36bc4f1ea16cb04b1cbe3f33b2e1 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Tue, 16 Sep 2025 20:12:11 +0200 Subject: [PATCH 188/224] Add allowOrigins configuration to CORSAllowCredentialsBehavior and perform cleanup (#4094) Signed-off-by: Norwin Schnyder --- ...proute-cors-allow-credentials-behavior.go} | 26 +++++++++++++++---- ...oute-cors-allow-credentials-behavior.yaml} | 4 +++ 2 files changed, 25 insertions(+), 5 deletions(-) rename conformance/tests/{cors-allow-credentials-behavior.go => httproute-cors-allow-credentials-behavior.go} (76%) rename conformance/tests/{cors-allow-credentials-behavior.yaml => httproute-cors-allow-credentials-behavior.yaml} (86%) diff --git a/conformance/tests/cors-allow-credentials-behavior.go b/conformance/tests/httproute-cors-allow-credentials-behavior.go similarity index 76% rename from conformance/tests/cors-allow-credentials-behavior.go rename to conformance/tests/httproute-cors-allow-credentials-behavior.go index 391b3cee80..c550dc0b7b 100644 --- a/conformance/tests/cors-allow-credentials-behavior.go +++ b/conformance/tests/httproute-cors-allow-credentials-behavior.go @@ -28,13 +28,13 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, CORSAllowCredentialsBehavior) + ConformanceTests = append(ConformanceTests, HTTPRouteCORSAllowCredentialsBehavior) } -var CORSAllowCredentialsBehavior = suite.ConformanceTest{ - ShortName: "CORSAllowCredentialsBehavior", - Description: "Validate ACA-Credentials responses", - Manifests: []string{"tests/cors-allow-credentials-behavior.yaml"}, +var HTTPRouteCORSAllowCredentialsBehavior = suite.ConformanceTest{ + ShortName: "HTTPRouteCORSAllowCredentialsBehavior", + Description: "An HTTPRoute with CORS includes Access-Control-Allow-Credentials only when configured as 'true', and then only alongside a matching Access-Control-Allow-Origin.", + Manifests: []string{"tests/httproute-cors-allow-credentials-behavior.yaml"}, Features: []features.FeatureName{ features.SupportGateway, features.SupportHTTPRoute, @@ -66,6 +66,22 @@ var CORSAllowCredentialsBehavior = suite.ConformanceTest{ }, Namespace: ns, }, + { + Request: http.Request{ + Method: "GET", + Path: "/cors-behavior-creds-true", + Headers: map[string]string{ + "Origin": "http://not-app.example", + "Cookie": "sid=abc123", + "Authorization": "Bearer test", + }, + }, + Response: http.Response{ + StatusCode: 200, + AbsentHeaders: []string{"Access-Control-Allow-Credentials"}, + }, + Namespace: ns, + }, { Request: http.Request{ Method: "GET", diff --git a/conformance/tests/cors-allow-credentials-behavior.yaml b/conformance/tests/httproute-cors-allow-credentials-behavior.yaml similarity index 86% rename from conformance/tests/cors-allow-credentials-behavior.yaml rename to conformance/tests/httproute-cors-allow-credentials-behavior.yaml index 13992e28f4..e4b5a39008 100644 --- a/conformance/tests/cors-allow-credentials-behavior.yaml +++ b/conformance/tests/httproute-cors-allow-credentials-behavior.yaml @@ -16,6 +16,8 @@ spec: port: 8080 filters: - cors: + allowOrigins: + - https://app.example allowCredentials: false type: CORS - matches: @@ -27,6 +29,8 @@ spec: port: 8080 filters: - cors: + allowOrigins: + - https://app.example allowCredentials: true type: CORS From 6ef015207f37e81c9095d7f5adecf36a3f0f8fb2 Mon Sep 17 00:00:00 2001 From: bjee19 <139261241+bjee19@users.noreply.github.com> Date: Tue, 16 Sep 2025 15:50:10 -0700 Subject: [PATCH 189/224] Fix CEL validation on gateway spec addresses (#4084) --- apis/v1/gateway_types.go | 8 ++-- .../gateway.networking.k8s.io_gateways.yaml | 36 +++++++------- .../gateway.networking.k8s.io_gateways.yaml | 36 +++++++------- conformance/tests/gateway-static-addresses.go | 4 +- pkg/generated/openapi/zz_generated.openapi.go | 2 +- pkg/test/cel/gateway_test.go | 48 +++++++++++++++++++ 6 files changed, 95 insertions(+), 39 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 10eb5bee06..58d9751866 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -246,7 +246,7 @@ type GatewaySpec struct { // Addresses requested for this Gateway. This is optional and behavior can // depend on the implementation. If a value is set in the spec and the // requested address is invalid or unavailable, the implementation MUST - // indicate this in the associated entry in GatewayStatus.Addresses. + // indicate this in an associated entry in GatewayStatus.Conditions. // // The Addresses field represents a request for the address(es) on the // "outside of the Gateway", that traffic bound for this Gateway will use. @@ -268,8 +268,8 @@ type GatewaySpec struct { // +listType=atomic // // +kubebuilder:validation:MaxItems=16 - // +kubebuilder:validation:XValidation:message="IPAddress values must be unique",rule="self.all(a1, a1.type == 'IPAddress' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" - // +kubebuilder:validation:XValidation:message="Hostname values must be unique",rule="self.all(a1, a1.type == 'Hostname' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" + // +kubebuilder:validation:XValidation:message="IPAddress values must be unique",rule="self.all(a1, a1.type == 'IPAddress' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" + // +kubebuilder:validation:XValidation:message="Hostname values must be unique",rule="self.all(a1, a1.type == 'Hostname' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" Addresses []GatewaySpecAddress `json:"addresses,omitempty"` // Infrastructure defines infrastructure level attributes about this Gateway instance. @@ -884,7 +884,7 @@ type RouteGroupKind struct { // GatewaySpecAddress describes an address that can be bound to a Gateway. // -// +kubebuilder:validation:XValidation:message="Hostname value must only contain valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\"): true" +// +kubebuilder:validation:XValidation:message="Hostname value must be empty or contain only valid characters (matching ^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)",rule="self.type == 'Hostname' ? (!has(self.value) || self.value.matches(r\"\"\"^(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"\"\")): true" type GatewaySpecAddress struct { // Type of the address. // diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 563669ba35..dc78ec615e 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -64,7 +64,7 @@ spec: Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST - indicate this in the associated entry in GatewayStatus.Addresses. + indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. @@ -119,20 +119,22 @@ spec: type: string type: object x-kubernetes-validations: - - message: Hostname value must only contain valid characters (matching - ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) - rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + - message: Hostname value must be empty or contain only valid characters + (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique - rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''IPAddress'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' - message: Hostname values must be unique - rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''Hostname'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' allowedListeners: description: |- AllowedListeners defines which ListenerSets can be attached to this Gateway. @@ -1639,7 +1641,7 @@ spec: Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST - indicate this in the associated entry in GatewayStatus.Addresses. + indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. @@ -1694,20 +1696,22 @@ spec: type: string type: object x-kubernetes-validations: - - message: Hostname value must only contain valid characters (matching - ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) - rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + - message: Hostname value must be empty or contain only valid characters + (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique - rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''IPAddress'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' - message: Hostname values must be unique - rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''Hostname'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' allowedListeners: description: |- AllowedListeners defines which ListenerSets can be attached to this Gateway. diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 98914347d2..43ab793f8a 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -64,7 +64,7 @@ spec: Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST - indicate this in the associated entry in GatewayStatus.Addresses. + indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. @@ -119,20 +119,22 @@ spec: type: string type: object x-kubernetes-validations: - - message: Hostname value must only contain valid characters (matching - ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) - rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + - message: Hostname value must be empty or contain only valid characters + (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique - rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''IPAddress'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' - message: Hostname values must be unique - rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''Hostname'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -1175,7 +1177,7 @@ spec: Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST - indicate this in the associated entry in GatewayStatus.Addresses. + indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. @@ -1230,20 +1232,22 @@ spec: type: string type: object x-kubernetes-validations: - - message: Hostname value must only contain valid characters (matching - ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) - rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + - message: Hostname value must be empty or contain only valid characters + (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique - rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''IPAddress'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' - message: Hostname values must be unique - rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, - a2.type == a1.type && a2.value == a1.value) : true )' + rule: 'self.all(a1, a1.type == ''Hostname'' && has(a1.value) ? + self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value + == a1.value) : true )' gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a diff --git a/conformance/tests/gateway-static-addresses.go b/conformance/tests/gateway-static-addresses.go index fcee1b3f99..89654c9ed8 100644 --- a/conformance/tests/gateway-static-addresses.go +++ b/conformance/tests/gateway-static-addresses.go @@ -135,8 +135,8 @@ var GatewayStaticAddresses = suite.ConformanceTest{ kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, finalExpectedListenerState) require.Len(t, currentGW.Spec.Addresses, 1, "expected only 1 address left specified on Gateway") statusAddresses := extractStatusAddresses(currentGW.Status.Addresses) - require.NotContains(t, statusAddresses, unusableAddress.Value, "should contain the unusable address") - require.NotContains(t, statusAddresses, invalidAddress.Value, "should contain the invalid address") + require.NotContains(t, statusAddresses, unusableAddress.Value, "should not contain the unusable address") + require.NotContains(t, statusAddresses, invalidAddress.Value, "should not contain the invalid address") require.Contains(t, statusAddresses, usableAddress.Value, "should contain the usable address") for _, addr := range currentGW.Status.Addresses { if usableAddress.Value != addr.Value { diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index f6dab0757c..b11d00af1b 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -4434,7 +4434,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, }, SchemaProps: spec.SchemaProps{ - Description: "Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in the associated entry in GatewayStatus.Addresses.\n\nThe Addresses field represents a request for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to.\n\nIf no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses.\n\nThe implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses.\n\nSupport: Extended\n\n", + Description: "Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in an associated entry in GatewayStatus.Conditions.\n\nThe Addresses field represents a request for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to.\n\nIf no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses.\n\nThe implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses.\n\nSupport: Extended\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/pkg/test/cel/gateway_test.go b/pkg/test/cel/gateway_test.go index ba85b50f2e..0bff6093b6 100644 --- a/pkg/test/cel/gateway_test.go +++ b/pkg/test/cel/gateway_test.go @@ -584,6 +584,54 @@ func TestValidateGateway(t *testing.T) { }, wantErrors: []string{"IPAddress values must be unique", "Hostname values must be unique"}, }, + { + desc: "optional ip address or hostname values", + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewaySpecAddress{ + { + Type: ptrTo(gatewayv1.IPAddressType), + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + }, + } + }, + }, + { + desc: "multiple optional ip address or hostname values alongside defined values", + mutate: func(gw *gatewayv1.Gateway) { + gw.Spec.Addresses = []gatewayv1.GatewaySpecAddress{ + { + Type: ptrTo(gatewayv1.HostnameAddressType), + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "1.2.3.4", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "foo.bar", + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + }, + { + Type: ptrTo(gatewayv1.IPAddressType), + Value: "2.3.4.5", + }, + { + Type: ptrTo(gatewayv1.HostnameAddressType), + Value: "bar.bar", + }, + } + }, + }, } for _, tc := range testCases { From f21f75378b9c751089d7d027cc53c3be9e0252d8 Mon Sep 17 00:00:00 2001 From: Shinya Murakami Date: Wed, 17 Sep 2025 16:24:13 +0900 Subject: [PATCH 190/224] fix including yaml filepath (#4091) --- site-src/guides/tls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site-src/guides/tls.md b/site-src/guides/tls.md index 4741171ac2..4d703dce9d 100644 --- a/site-src/guides/tls.md +++ b/site-src/guides/tls.md @@ -145,7 +145,7 @@ TLS-encrypted upstream connection where Pods backing the `dev` Service are expec certificate for `dev.example.com`. ```yaml -{% include 'standard/v1/backendtlspolicy-system-certs.yaml' %} +{% include 'standard/backendtlspolicy/backendtlspolicy-system-certs.yaml' %} ``` #### Using Explicit CA Certificates @@ -155,7 +155,7 @@ map `auth-cert` to connect with a TLS-encrypted upstream connection where Pods b are expected to serve a valid certificate for `auth.example.com`. ```yaml -{% include 'standard/v1/backendtlspolicy-ca-certs.yaml' %} +{% include 'standard/backendtlspolicy/backendtlspolicy-ca-certs.yaml' %} ``` ## Extensions From bb5b2770c67a1f4b106d8379c06a7a0044d66816 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 17 Sep 2025 03:24:20 -0400 Subject: [PATCH 191/224] Update OWNERS_ALIASES for gateway-api teams (#4093) Removed mlavacca from gateway-api-maintainers and added to gateway-api-mesh-leads. --- OWNERS_ALIASES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 207dd1d776..510384849d 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -11,7 +11,6 @@ aliases: # Reference: https://github.com/kubernetes/org/blob/main/config/kubernetes-sigs/sig-network/teams.yaml gateway-api-maintainers: - - mlavacca - robscott - shaneutt - youngnick @@ -21,6 +20,7 @@ aliases: - danehans - hbagdi - jpeach + - mlavacca gateway-api-mesh-leads: - howardjohn From 5c450a39356b1ecb2ae64672bea42eebed4a8e68 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Wed, 17 Sep 2025 11:42:13 -0300 Subject: [PATCH 192/224] Automate GEP TOC generation and validate (#4075) * Fix GEP API and geps metadata The GEP API is using a wrong structure/tag name for some fields, so this PR fixes the markers. Additionally the metadata.yaml files from some GEPs are fixed to reflect the right GEP API structure * Implement automatic NAV generation This change makes the navigation section of GW API website to be generated. The modification adds a new Go program that is able to transverse the GEP directory and generate a navigation section correctly from the existing GEPs. Additionally, some scripts and Makefiles are added to verify if the generated nav.yml file reflects the current state of GEPs, a Github Action that fails in case nav.yml is outdated * Add the new generated nav file --- .github/workflows/mkdocs-nav-validation.yml | 25 +++ .yamllint.yaml | 1 + Makefile | 8 + cmd/gepstoc/main.go | 174 ++++++++++++++++++++ geps/gep-1494/metadata.yaml | 2 +- geps/gep-1731/metadata.yaml | 8 +- geps/gep-3388/metadata.yaml | 12 +- geps/gep-3567/metadata.yaml | 14 +- geps/gep-3779/metadata.yaml | 6 +- geps/gep-3792/metadata.yaml | 16 +- geps/gep-3793/metadata.yaml | 16 +- geps/gep-3798/metadata.yaml | 14 +- geps/gep-3949/metadata.yaml | 16 +- geps/gep-696/metadata.yaml | 16 +- hack/mkdocs/image/entrypoint.sh | 4 +- hack/update-mkdocs-nav.sh | 28 ++++ hack/verify-all.sh | 2 +- hack/verify-mkdocs-nav.sh | 51 ++++++ mkdocs.yml | 125 +------------- nav.yml | 115 +++++++++++++ nav.yml.tmpl | 80 +++++++++ pkg/gep/gepdetail.go | 4 +- 22 files changed, 548 insertions(+), 189 deletions(-) create mode 100644 .github/workflows/mkdocs-nav-validation.yml create mode 100644 cmd/gepstoc/main.go create mode 100755 hack/update-mkdocs-nav.sh create mode 100755 hack/verify-mkdocs-nav.sh create mode 100644 nav.yml create mode 100644 nav.yml.tmpl diff --git a/.github/workflows/mkdocs-nav-validation.yml b/.github/workflows/mkdocs-nav-validation.yml new file mode 100644 index 0000000000..b7d32c0399 --- /dev/null +++ b/.github/workflows/mkdocs-nav-validation.yml @@ -0,0 +1,25 @@ +name: Website Table of Content Validation + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +# Remove all permissions from GITHUB_TOKEN except metadata. +permissions: {} + +jobs: + gep-validation: + name: Verify if nav is updated + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + with: + persist-credentials: false + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 + - name: Run MKDocs nav Validation + run: | + make verify-mkdocs-nav diff --git a/.yamllint.yaml b/.yamllint.yaml index 19fdcf471b..718c7763ae 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -4,6 +4,7 @@ ignore: | .github/ .golangci.yml mkdocs.yml + nav.yml cloudbuild.yaml config/crd diff --git a/Makefile b/Makefile index 3f2fee4146..3b8c45e0b9 100644 --- a/Makefile +++ b/Makefile @@ -182,6 +182,14 @@ live-docs: docker build -t gw/mkdocs hack/mkdocs/image docker run --rm -it -p 3000:3000 -v ${PWD}:/docs gw/mkdocs +.PHONY: verify-mkdocs-nav +verify-mkdocs-nav: + hack/verify-mkdocs-nav.sh + +.PHONY: update-mkdocs-nav +update-mkdocs-nav: + hack/update-mkdocs-nav.sh + .PHONY: api-ref-docs api-ref-docs: crd-ref-docs \ diff --git a/cmd/gepstoc/main.go b/cmd/gepstoc/main.go new file mode 100644 index 0000000000..7a186bde39 --- /dev/null +++ b/cmd/gepstoc/main.go @@ -0,0 +1,174 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "bytes" + "flag" + "fmt" + "html/template" + "io/fs" + "log" + "os" + "path/filepath" + "slices" + "sort" + "strconv" + "strings" + + "sigs.k8s.io/yaml" + + gep "sigs.k8s.io/gateway-api/pkg/gep" +) + +var ( + GEPSDir string + MKDocsTemplate string + SkipGEPNumber string +) + +// Those are the GEPs that will be included in the final navigation bar +// The order established below will be the order that the statuses will be shown +var includeGEPStatus = []gep.GEPStatus{ + gep.GEPStatusImplementable, + gep.GEPStatusExperimental, + gep.GEPStatusStandard, + gep.GEPStatusMemorandum, +} + +type GEPArray []GEPList + +type GEPList struct { + GepType string + Geps []uint +} + +type TemplateData struct { + GEPData GEPArray +} + +const kindDetails = "GEPDetails" + +func main() { + flag.StringVar(&GEPSDir, "g", "", "Defines the absolute path of the directory containing the GEPs") + flag.StringVar(&MKDocsTemplate, "t", "", "Defines the absolute path of mkdocs.yaml file") + flag.StringVar(&SkipGEPNumber, "s", "696", "Defines GEPs number to be skipped, should be comma-separated") + flag.Parse() + + if GEPSDir == "" || MKDocsTemplate == "" { + log.Fatal("-g and -c are mandatory arguments") + } + + if strings.Contains(SkipGEPNumber, " ") { + log.Fatal("-s flag should not contain spaces") + } + + skipGep := strings.Split(SkipGEPNumber, ",") + + geps, err := walkGEPs(GEPSDir, skipGep) + if err != nil { + panic(err) + } + + tmpl, err := template.ParseFiles(MKDocsTemplate) + if err != nil { + log.Fatalf("error reading mkdocs template: %s", err) + } + + tmplData := TemplateData{ + GEPData: geps, + } + + buf := &bytes.Buffer{} + + if err := tmpl.Execute(buf, tmplData); err != nil { + panic(err) + } + fmt.Print(buf.String()) +} + +func walkGEPs(dir string, skipGEPs []string) (GEPArray, error) { + gepArray := make(GEPArray, 0) + tmpMap := make(map[gep.GEPStatus]GEPList) + + err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("error accessing %s: %w", path, err) + } + if d.IsDir() || d.Name() != "metadata.yaml" { + return nil + } + + content, err := os.ReadFile(path) + if err != nil { + return err + } + + gepDetail := &gep.GEPDetail{} + log.Printf("checking %s", path) + if err := yaml.Unmarshal(content, gepDetail); err != nil { + return err + } + + if gepDetail.Kind != kindDetails { + return nil + } + + // Skip the GEPs types we don't care + if !slices.Contains(includeGEPStatus, gepDetail.Status) { + return nil + } + + // Skip the GEPs numbers we don't care + if slices.Contains(skipGEPs, strconv.FormatUint(uint64(gepDetail.Number), 10)) { + return nil + } + + // Add the GEP to a map indexed by GEP types, so we can provide the sorted array + // easily later + _, ok := tmpMap[gepDetail.Status] + if !ok { + tmpMap[gepDetail.Status] = GEPList{ + GepType: string(gepDetail.Status), + Geps: make([]uint, 0), + } + } + + item := tmpMap[gepDetail.Status] + item.Geps = append(item.Geps, gepDetail.Number) + tmpMap[gepDetail.Status] = item + return nil + }) + if err != nil { + return nil, err + } + + // Include the GEPs toc on the desired order + for _, v := range includeGEPStatus { + if geps, ok := tmpMap[v]; ok { + gepArray = append(gepArray, geps) + } + } + + for i := range gepArray { + sort.SliceStable(gepArray[i].Geps, func(x, y int) bool { + return gepArray[i].Geps[x] < gepArray[i].Geps[y] + }) + } + + return gepArray, nil +} diff --git a/geps/gep-1494/metadata.yaml b/geps/gep-1494/metadata.yaml index 600aed9a6a..1e27264076 100644 --- a/geps/gep-1494/metadata.yaml +++ b/geps/gep-1494/metadata.yaml @@ -10,7 +10,7 @@ authors: - jgao1025 # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. featureNames: diff --git a/geps/gep-1731/metadata.yaml b/geps/gep-1731/metadata.yaml index c85ccbcb0c..1a1f8daa66 100644 --- a/geps/gep-1731/metadata.yaml +++ b/geps/gep-1731/metadata.yaml @@ -11,12 +11,12 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} + extends: [] extendedBy: - number: 3388 name: Retry Budgets @@ -44,4 +44,4 @@ featureNames: - SupportHTTPRouteRetryConnectionError # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3388/metadata.yaml b/geps/gep-3388/metadata.yaml index 53b9ef127a..1571692b0c 100644 --- a/geps/gep-3388/metadata.yaml +++ b/geps/gep-3388/metadata.yaml @@ -12,18 +12,18 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. extends: - number: 1731 name: HTTPRoute Retries - extendedBy: {} + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. references: @@ -34,7 +34,7 @@ references: - https://github.com/kubernetes-sigs/gateway-api/pull/3695 # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3567/metadata.yaml b/geps/gep-3567/metadata.yaml index be9f0fd374..d613089157 100644 --- a/geps/gep-3567/metadata.yaml +++ b/geps/gep-3567/metadata.yaml @@ -11,23 +11,23 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. featureNames: - GatewayReturn421 # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3779/metadata.yaml b/geps/gep-3779/metadata.yaml index 3c5b9af7d2..a02025772f 100644 --- a/geps/gep-3779/metadata.yaml +++ b/geps/gep-3779/metadata.yaml @@ -10,10 +10,10 @@ authors: - aryan16 # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3792/metadata.yaml b/geps/gep-3792/metadata.yaml index 4478b32b1e..fd3dfafd5e 100644 --- a/geps/gep-3792/metadata.yaml +++ b/geps/gep-3792/metadata.yaml @@ -11,23 +11,23 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. # This is the value added to supportedFeatures and the conformance tests, in string form. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3793/metadata.yaml b/geps/gep-3793/metadata.yaml index db611f5988..ccaf298f56 100644 --- a/geps/gep-3793/metadata.yaml +++ b/geps/gep-3793/metadata.yaml @@ -11,23 +11,23 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. # This is the value added to supportedFeatures and the conformance tests, in string form. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3798/metadata.yaml b/geps/gep-3798/metadata.yaml index 85a47289c0..9d1408c609 100644 --- a/geps/gep-3798/metadata.yaml +++ b/geps/gep-3798/metadata.yaml @@ -11,13 +11,13 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. seeAlso: @@ -27,11 +27,11 @@ relationships: # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. # This is the value added to supportedFeatures and the conformance tests, in string form. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-3949/metadata.yaml b/geps/gep-3949/metadata.yaml index de9c3639e7..09b4cb3e7f 100644 --- a/geps/gep-3949/metadata.yaml +++ b/geps/gep-3949/metadata.yaml @@ -12,23 +12,23 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. # This is the value added to supportedFeatures and the conformance tests, in string form. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/geps/gep-696/metadata.yaml b/geps/gep-696/metadata.yaml index cc3c2ce20f..035546b291 100644 --- a/geps/gep-696/metadata.yaml +++ b/geps/gep-696/metadata.yaml @@ -15,23 +15,23 @@ relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field # set back to this GEP, and MUST be moved to Declined. - obsoletes: {} - obsoletedBy: {} + obsoletes: [] + obsoletedBy: [] # extends indicates that a GEP extends the linked GEP, adding more detail # or additional implementation. The extended GEP MUST have its extendedBy # field set back to this GEP. - extends: {} - extendedBy: {} + extends: [] + extendedBy: [] # seeAlso indicates other GEPs that are relevant in some way without being # covered by an existing relationship. - seeAlso: {} + seeAlso: [] # references is a list of hyperlinks to relevant external references. # It's intended to be used for storing GitHub discussions, Google docs, etc. -references: {} +references: [] # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. # This is the value added to supportedFeatures and the conformance tests, in string form. -featureNames: {} +featureNames: [] # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: [] diff --git a/hack/mkdocs/image/entrypoint.sh b/hack/mkdocs/image/entrypoint.sh index 6b3fd33866..067102dc29 100755 --- a/hack/mkdocs/image/entrypoint.sh +++ b/hack/mkdocs/image/entrypoint.sh @@ -18,10 +18,10 @@ set -o errexit CMD=$1 -if [ "$CMD" == "build" ]; +if [ "$CMD" = "build" ]; then mkdocs build exit 0; fi -mkdocs serve --dev-addr=0.0.0.0:3000 --livereload \ No newline at end of file +mkdocs serve --dev-addr=0.0.0.0:3000 --livereload diff --git a/hack/update-mkdocs-nav.sh b/hack/update-mkdocs-nav.sh new file mode 100755 index 0000000000..16c6c611ce --- /dev/null +++ b/hack/update-mkdocs-nav.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright 2025 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. + +GEPS_TOC_SKIP="${GEPS_TOC_SKIP:-696}" +NAV_CONF="${NAV_CONF:-${SCRIPT_ROOT}/nav.yml}" +NAV_TEMPLATE="${NAV_TEMPLATE:-${NAV_CONF}.tmpl}" +GEPS_TOC_DIR=${GEPS_TOC_DIR:-${SCRIPT_ROOT}/geps} + +go run cmd/gepstoc/main.go -g "${GEPS_TOC_DIR}/" -t "${NAV_TEMPLATE}" -s "${GEPS_TOC_SKIP}" > "${NAV_CONF}" diff --git a/hack/verify-all.sh b/hack/verify-all.sh index 540302291f..eb7e7f68a0 100755 --- a/hack/verify-all.sh +++ b/hack/verify-all.sh @@ -52,7 +52,7 @@ if $SILENT ; then echo "Running in the silent mode, run with -v if you want to see script logs." fi -EXCLUDE="verify-all.sh" +EXCLUDE="verify-all.sh verify-mkdocs-nav.sh" SCRIPTS=$(find "${SCRIPT_ROOT}"/hack -name "verify-*.sh") diff --git a/hack/verify-mkdocs-nav.sh b/hack/verify-mkdocs-nav.sh new file mode 100755 index 0000000000..c0261b1c16 --- /dev/null +++ b/hack/verify-mkdocs-nav.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2025 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. + +TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp" +TMP_FILE="${TMP_DIFFROOT}/nav.yml" + +GEPS_TOC_SKIP="${GEPS_TOC_SKIP:-696}" +NAV_CONF="${NAV_CONF:-${SCRIPT_ROOT}/nav.yml}" +NAV_TEMPLATE="${NAV_TEMPLATE:-${NAV_CONF}.tmpl}" +GEPS_TOC_DIR=${GEPS_TOC_DIR:-${SCRIPT_ROOT}/geps} + +cleanup() { + rm -rf "${TMP_DIFFROOT}" +} +trap "cleanup" EXIT SIGINT + +cleanup + +mkdir -p "${TMP_DIFFROOT}" + +go run cmd/gepstoc/main.go -g "${GEPS_TOC_DIR}/" -t "${NAV_TEMPLATE}" -s "${GEPS_TOC_SKIP}" > "${TMP_FILE}" + +echo "diffing ${NAV_CONF} against freshly generated configuration" +ret=0 +diff -Naupr --no-dereference "${NAV_CONF}" "${TMP_FILE}" || ret=1 + +if [[ $ret -eq 0 ]]; then + echo "${NAV_CONF} up to date." +else + echo "${NAV_CONF} is out of date. Please run hack/update-mkdocs-nav.sh" + exit 1 +fi diff --git a/mkdocs.yml b/mkdocs.yml index 1052a44512..bb14f5ba3e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,3 +1,4 @@ +INHERIT: ./nav.yml site_name: Kubernetes Gateway API repo_url: https://github.com/kubernetes-sigs/gateway-api repo_name: kubernetes-sigs/gateway-api @@ -76,127 +77,3 @@ markdown_extensions: - toc: permalink: true - tables -nav: - - Overview: - - Introduction: index.md - - Concepts: - - API Overview: concepts/api-overview.md - - Conformance: concepts/conformance.md - - Roles and Personas: concepts/roles-and-personas.md - - Security Model: concepts/security-model.md - - Tools: concepts/tooling.md - - Use Cases: concepts/use-cases.md - - Versioning: concepts/versioning.md - - Service Mesh: - - Overview: mesh/index.md - - GAMMA Initiative: mesh/gamma.md - - Service Facets: mesh/service-facets.md - - Implementations: - - List: implementations.md - - Comparisons: - - v1.3: implementations/v1.3.md - - v1.2: implementations/v1.2.md - - v1.1: implementations/v1.1.md - - v1.0: implementations/v1.0.md - - FAQ: faq.md - - Glossary: concepts/glossary.md - - Guides: - - User Guides: - - Getting started: guides/index.md - - Simple Gateway: guides/simple-gateway.md - - HTTP routing: guides/http-routing.md - - HTTP redirects and rewrites: guides/http-redirect-rewrite.md - - HTTP header modifier: guides/http-header-modifier.md - - HTTP traffic splitting: guides/traffic-splitting.md - - HTTP request mirroring: guides/http-request-mirroring.md - - Cross-Namespace routing: guides/multiple-ns.md - - TLS: guides/tls.md - - TCP routing: guides/tcp.md - - gRPC Routing: guides/grpc-routing.md - - Migrating from Ingress: guides/migrating-from-ingress.md - - Backend Protocol Selection: guides/backend-protocol.md - - Infrastructure attributes: guides/infrastructure.md - - API Design: guides/api-design.md - - CRD Management: guides/crd-management.md - - Implementer's Guide: guides/implementers.md - - Reference: - - API Types: - - Gateway: api-types/gateway.md - - GatewayClass: api-types/gatewayclass.md - - GRPCRoute: api-types/grpcroute.md - - HTTPRoute: api-types/httproute.md - - Policy: - - BackendTLSPolicy: api-types/backendtlspolicy.md - - BackendTrafficPolicy: api-types/backendtrafficpolicy.md - - ReferenceGrant: api-types/referencegrant.md - - API specification: - - Standard: reference/spec.md - - Experimental: reference/specx.md - - Policy Attachment: reference/policy-attachment.md - - Enhancements: - - Overview: geps/overview.md - - Provisional: - - geps/gep-1494/index.md - - geps/gep-1651/index.md - - geps/gep-2648/index.md - - geps/gep-3779/index.md - - geps/gep-3792/index.md - - Implementable: - - geps/gep-91/index.md - - geps/gep-3567/index.md - - geps/gep-3949/index.md - - Experimental: - - geps/gep-1619/index.md - - geps/gep-1713/index.md - - geps/gep-1731/index.md - - geps/gep-1748/index.md - - geps/gep-1767/index.md - - geps/gep-1897/index.md - - geps/gep-2162/index.md - - geps/gep-2649/index.md - - geps/gep-3155/index.md - - geps/gep-3388/index.md - - geps/gep-3567/index.md - - Standard: - - geps/gep-709/index.md - - geps/gep-718/index.md - - geps/gep-724/index.md - - geps/gep-726/index.md - - geps/gep-746/index.md - - geps/gep-820/index.md - - geps/gep-851/index.md - - geps/gep-957/index.md - - geps/gep-995/index.md - - geps/gep-1016/index.md - - geps/gep-1294/index.md - - geps/gep-1323/index.md - - geps/gep-1364/index.md - - geps/gep-1686/index.md - - geps/gep-1709/index.md - - geps/gep-1742/index.md - - geps/gep-1762/index.md - - geps/gep-1867/index.md - - geps/gep-1911/index.md - - geps/gep-2257/index.md - - geps/gep-3171/index.md - - Memorandum: - - geps/gep-713/index.md - - geps/gep-917/index.md - - geps/gep-922/index.md - - geps/gep-1324/index.md - - geps/gep-2659/index.md - - geps/gep-2722/index.md - - geps/gep-2907/index.md - - Declined: - - geps/gep-735/index.md - - geps/gep-1282/index.md - - Contributing: - - How to Get Involved: contributing/index.md - - Developer Guide: contributing/devguide.md - - Documentation Style Guide: contributing/style-guide.md - - Enhancement Requests: contributing/enhancement-requests.md - - Release Cycle: contributing/release-cycle.md - - Contributor Ladder: contributing/contributor-ladder.md -not_in_nav: | - /blog/* - /geps/gep-696/* diff --git a/nav.yml b/nav.yml new file mode 100644 index 0000000000..dd16ff3274 --- /dev/null +++ b/nav.yml @@ -0,0 +1,115 @@ +# WARNING: nav.yml file is generated from nav.yml.tmpl file +# If you are changing nav.yml directly you SHOULDN'T, please +# modify nav.yml.tmpl and run the script "hack/update-mkdocs-nav.sh" +nav: + - Overview: + - Introduction: index.md + - Concepts: + - API Overview: concepts/api-overview.md + - Conformance: concepts/conformance.md + - Roles and Personas: concepts/roles-and-personas.md + - Security Model: concepts/security-model.md + - Tools: concepts/tooling.md + - Use Cases: concepts/use-cases.md + - Versioning: concepts/versioning.md + - Service Mesh: + - Overview: mesh/index.md + - GAMMA Initiative: mesh/gamma.md + - Service Facets: mesh/service-facets.md + - Implementations: + - List: implementations.md + - Comparisons: + - v1.3: implementations/v1.3.md + - v1.2: implementations/v1.2.md + - v1.1: implementations/v1.1.md + - v1.0: implementations/v1.0.md + - FAQ: faq.md + - Glossary: concepts/glossary.md + - Guides: + - User Guides: + - Getting started: guides/index.md + - Simple Gateway: guides/simple-gateway.md + - HTTP routing: guides/http-routing.md + - HTTP redirects and rewrites: guides/http-redirect-rewrite.md + - HTTP header modifier: guides/http-header-modifier.md + - HTTP traffic splitting: guides/traffic-splitting.md + - HTTP request mirroring: guides/http-request-mirroring.md + - Cross-Namespace routing: guides/multiple-ns.md + - TLS: guides/tls.md + - TCP routing: guides/tcp.md + - gRPC Routing: guides/grpc-routing.md + - Migrating from Ingress: guides/migrating-from-ingress.md + - Backend Protocol Selection: guides/backend-protocol.md + - Infrastructure attributes: guides/infrastructure.md + - API Design: guides/api-design.md + - CRD Management: guides/crd-management.md + - Implementer's Guide: guides/implementers.md + - Reference: + - API Types: + - Gateway: api-types/gateway.md + - GatewayClass: api-types/gatewayclass.md + - GRPCRoute: api-types/grpcroute.md + - HTTPRoute: api-types/httproute.md + - Policy: + - BackendTLSPolicy: api-types/backendtlspolicy.md + - BackendTrafficPolicy: api-types/backendtrafficpolicy.md + - ReferenceGrant: api-types/referencegrant.md + - API specification: + - Standard: reference/spec.md + - Experimental: reference/specx.md + - Policy Attachment: reference/policy-attachment.md + - Enhancements: + - Overview: geps/overview.md + - Implementable: + - geps/gep-1494/index.md + - geps/gep-3388/index.md + - geps/gep-3567/index.md + - geps/gep-3793/index.md + - geps/gep-3949/index.md + - Experimental: + - geps/gep-1016/index.md + - geps/gep-1713/index.md + - geps/gep-1731/index.md + - geps/gep-1748/index.md + - geps/gep-1767/index.md + - geps/gep-1897/index.md + - geps/gep-2162/index.md + - geps/gep-3155/index.md + - Standard: + - geps/gep-709/index.md + - geps/gep-718/index.md + - geps/gep-724/index.md + - geps/gep-726/index.md + - geps/gep-746/index.md + - geps/gep-820/index.md + - geps/gep-851/index.md + - geps/gep-957/index.md + - geps/gep-995/index.md + - geps/gep-1294/index.md + - geps/gep-1323/index.md + - geps/gep-1364/index.md + - geps/gep-1686/index.md + - geps/gep-1709/index.md + - geps/gep-1742/index.md + - geps/gep-1762/index.md + - geps/gep-1867/index.md + - geps/gep-1911/index.md + - geps/gep-2257/index.md + - geps/gep-3171/index.md + - Memorandum: + - geps/gep-713/index.md + - geps/gep-917/index.md + - geps/gep-922/index.md + - geps/gep-1324/index.md + - geps/gep-2722/index.md + - geps/gep-2907/index.md + - Contributing: + - How to Get Involved: contributing/index.md + - Developer Guide: contributing/devguide.md + - Documentation Style Guide: contributing/style-guide.md + - Enhancement Requests: contributing/enhancement-requests.md + - Release Cycle: contributing/release-cycle.md + - Contributor Ladder: contributing/contributor-ladder.md +not_in_nav: | + /blog/* + /geps/gep-696/* diff --git a/nav.yml.tmpl b/nav.yml.tmpl new file mode 100644 index 0000000000..94e9a0aa1d --- /dev/null +++ b/nav.yml.tmpl @@ -0,0 +1,80 @@ +# WARNING: nav.yml file is generated from nav.yml.tmpl file +# If you are changing nav.yml directly you SHOULDN'T, please +# modify nav.yml.tmpl and run the script "hack/update-mkdocs-nav.sh" +nav: + - Overview: + - Introduction: index.md + - Concepts: + - API Overview: concepts/api-overview.md + - Conformance: concepts/conformance.md + - Roles and Personas: concepts/roles-and-personas.md + - Security Model: concepts/security-model.md + - Tools: concepts/tooling.md + - Use Cases: concepts/use-cases.md + - Versioning: concepts/versioning.md + - Service Mesh: + - Overview: mesh/index.md + - GAMMA Initiative: mesh/gamma.md + - Service Facets: mesh/service-facets.md + - Implementations: + - List: implementations.md + - Comparisons: + - v1.3: implementations/v1.3.md + - v1.2: implementations/v1.2.md + - v1.1: implementations/v1.1.md + - v1.0: implementations/v1.0.md + - FAQ: faq.md + - Glossary: concepts/glossary.md + - Guides: + - User Guides: + - Getting started: guides/index.md + - Simple Gateway: guides/simple-gateway.md + - HTTP routing: guides/http-routing.md + - HTTP redirects and rewrites: guides/http-redirect-rewrite.md + - HTTP header modifier: guides/http-header-modifier.md + - HTTP traffic splitting: guides/traffic-splitting.md + - HTTP request mirroring: guides/http-request-mirroring.md + - Cross-Namespace routing: guides/multiple-ns.md + - TLS: guides/tls.md + - TCP routing: guides/tcp.md + - gRPC Routing: guides/grpc-routing.md + - Migrating from Ingress: guides/migrating-from-ingress.md + - Backend Protocol Selection: guides/backend-protocol.md + - Infrastructure attributes: guides/infrastructure.md + - API Design: guides/api-design.md + - CRD Management: guides/crd-management.md + - Implementer's Guide: guides/implementers.md + - Reference: + - API Types: + - Gateway: api-types/gateway.md + - GatewayClass: api-types/gatewayclass.md + - GRPCRoute: api-types/grpcroute.md + - HTTPRoute: api-types/httproute.md + - Policy: + - BackendTLSPolicy: api-types/backendtlspolicy.md + - BackendTrafficPolicy: api-types/backendtrafficpolicy.md + - ReferenceGrant: api-types/referencegrant.md + - API specification: + - Standard: reference/spec.md + - Experimental: reference/specx.md + - Policy Attachment: reference/policy-attachment.md + - Enhancements: + - Overview: geps/overview.md + {{- with .GEPData }} + {{- range . }} + - {{ .GepType }}: + {{- range .Geps }} + - geps/gep-{{ . }}/index.md + {{- end }} + {{- end }} + {{- end }} + - Contributing: + - How to Get Involved: contributing/index.md + - Developer Guide: contributing/devguide.md + - Documentation Style Guide: contributing/style-guide.md + - Enhancement Requests: contributing/enhancement-requests.md + - Release Cycle: contributing/release-cycle.md + - Contributor Ladder: contributing/contributor-ladder.md +not_in_nav: | + /blog/* + /geps/gep-696/* diff --git a/pkg/gep/gepdetail.go b/pkg/gep/gepdetail.go index a8c2d1c714..7d903ed362 100644 --- a/pkg/gep/gepdetail.go +++ b/pkg/gep/gepdetail.go @@ -84,9 +84,9 @@ type GEPRelationships struct { // The GEP is Obsoleted by the listed GEPs. ObsoletedBy []GEPRelationship `json:"obsoletedBy,omitempty"` // The GEP Updates the listed GEPs. - Extends []GEPRelationship `json:"updates,omitempty"` + Extends []GEPRelationship `json:"extends,omitempty"` // The GEP is Updated by the listed GEPs. - ExtendedBy []GEPRelationship `json:"updatedBy,omitempty"` + ExtendedBy []GEPRelationship `json:"extendedBy,omitempty"` // The listed GEPs are relevant for some other reason. SeeAlso []GEPRelationship `json:"seeAlso,omitempty"` } From 682d60e6a93eb19937113e18e0debc8cf1e2cf6a Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Mon, 15 Sep 2025 13:17:17 -0400 Subject: [PATCH 193/224] docs: add the v1.4 CHANGELOG Signed-off-by: Shane Utt --- CHANGELOG/1.4-CHANGELOG.md | 223 +++++++++++++++++++++++++++++++++++++ CHANGELOG/1.4-TEAM.md | 39 +++++++ 2 files changed, 262 insertions(+) create mode 100644 CHANGELOG/1.4-CHANGELOG.md create mode 100644 CHANGELOG/1.4-TEAM.md diff --git a/CHANGELOG/1.4-CHANGELOG.md b/CHANGELOG/1.4-CHANGELOG.md new file mode 100644 index 0000000000..65c00e5aa3 --- /dev/null +++ b/CHANGELOG/1.4-CHANGELOG.md @@ -0,0 +1,223 @@ +# v1.4 Changelog + +## Table of Contents + +- [v1.4.0-rc.1](#v140-rc1) + +# v1.4.0-rc.1 + +## Major Changes since v1.3.0 + +### Breaking Changes + +#### Experimental CORS Support in HTTPRoute - Breaking Change for AllowCredentials Field + +Users of the `Experimental` CORS `AllowCredentials` field can now specify false. +The underlying API specification type has changed from a enum of type boolean to +just a boolean, so users deploying `HTTPRoutes` via libraries and evaluating the +experimental CORS support will need to adjust for the change in types. Please +see #3895 for more details. + +#### Standard GRPCRoute - Spec Field Required (Technicality) + +This PR makes `grpcroute.spec` a required field. This is _technically_ a +backward-incompatible change, as previously the field was unintentionally +treated as optional because we erroneously used `omitempty` on `.spec` (unlike +other APIs). Since the codebase didn't yet enforce explicit required markers, +that `omitempty` allowed a missing `.spec`. + +Because `.spec` contains essential route configuration, omitting it renders a +`GRPCRoute` unusable and causes route implementation to fail, so we expect this +change will not have adverse effects, but wanted to call it out all the same. +Please see #3937 for more details. + +### GEPs + +#### New Features + +In this release, the following major features are moving to the `Standard` +channel and are now considered generally available: + +* [GEP-1897 BackendTLSPolicy] - Configuration of TLS from the Gateway to Backends +* [GEP-3164 SupportedFeatures] - Status information about the features that an implementation supports. + +In this release, we introduced the following new features are moving to the +`Experimental` channel, for implementations to evaluate: + +* [GEP-3949 Mesh Resource] - Mesh-wide configuration and supported features. +* [GEP-3793 Default Gateways] - Allowing `Gateways` to program some routes by default. +* [GEP-1494 HTTP External Auth] - Enabling External Auth for `HTTPRoute`. + +[GEP-1897 BackendTLSPolicy]:https://github.com/kubernetes-sigs/gateway-api/issues/1897 +[GEP-3164 SupportedFeatures]:https://github.com/kubernetes-sigs/gateway-api/issues/3164 +[GEP-3949 Mesh Resource]:https://github.com/kubernetes-sigs/gateway-api/issues/3949 +[GEP-3793 Default Gateways]:https://github.com/kubernetes-sigs/gateway-api/issues/3793 +[GEP-1494 HTTP External Auth]:https://github.com/kubernetes-sigs/gateway-api/pull/4001 + +#### Other Iterations + +* GEP-1897: standardizing behavior for invalid BackendTLSPolicy by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/3909 +* GEP-1897: describe TargetRefs conflict-resolution rules in BackendTLSPolicy by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4048 +* GEP-2627: DNS Configuration - Initial Provisional PR by @maleck13 in https://github.com/kubernetes-sigs/gateway-api/pull/2712 +* GEP-1713: Revisions by @dprotaso in https://github.com/kubernetes-sigs/gateway-api/pull/3744 +* GEP 91: Update Goals and Prior Art by @arkodg in https://github.com/kubernetes-sigs/gateway-api/pull/3838 +* GEP-91: Address connection coalescing security issue - API updates by @kl52752 in #3960 and #3942 +* GEP-1494: Update gRPC Auth config by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/4061 +* GEP 3779: East/West Identity-Based Authorization by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3822 +* GEP-3792: Off-Cluster Gateways by @kflynn in https://github.com/kubernetes-sigs/gateway-api/pull/3851 +* GEP-3798: Adding initial Provisional GEP for client ip based session persistence by @arihantg in https://github.com/kubernetes-sigs/gateway-api/pull/3844 +* GEP-696: Update the possible states by @mlavacca in https://github.com/kubernetes-sigs/gateway-api/pull/3901 +* TLSRoute: Require hostnames and bump version to v1alpha3 by @rostislavbobo in https://github.com/kubernetes-sigs/gateway-api/pull/3872 +* TLSRoute: Require hostnames via +required by @rostislavbobo in https://github.com/kubernetes-sigs/gateway-api/pull/3918 +* TLSRoute: Set MaxItems=1 for rules[] in v1alpha3 by @rostislavbobo in https://github.com/kubernetes-sigs/gateway-api/pull/3971 +* Update Auth GEP with Implementable details by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/3884 +* add GRPCRouteExtendedFeatures to AllFeatures list by @skriss in https://github.com/kubernetes-sigs/gateway-api/pull/4046 +* Allow preprepared CoreDNS image to be used by @aaronjwood in https://github.com/kubernetes-sigs/gateway-api/pull/3906 +* Specify SAN validation precedence over Hostname validation by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/4039 +* docs: move GEP-3798 to Deferred for now by @shaneutt in https://github.com/kubernetes-sigs/gateway-api/pull/3947 + +## Bug or Regression + +* The boolean "TrueField" introduced for CORS can cause generator issues by @shaneutt in https://github.com/kubernetes-sigs/gateway-api/issues/3895 +* Mark grpcroutes spec as required by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3937 + +## Administrative + +* chore: remove inactive reviewers by @shaneutt in https://github.com/kubernetes-sigs/gateway-api/pull/3829 +* Adding Lior to Mesh Leads by @robscott in https://github.com/kubernetes-sigs/gateway-api/pull/3877 + +## Changes by Kind + +### API + +#### HTTPRoute + +In the `Standard` channel, we've [now added] a `Name` field to `HTTPRouteRule` +and `HTTPRouteMatch`. + +[now added]:https://github.com/kubernetes-sigs/gateway-api/issues/995 + +### Documentation + +* Enable dark mode switch on docs by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3977 +* docs: Add v1.3 conformance report table by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/3810 +* docs: Update HTTPRoute status example by @jonstacks in https://github.com/kubernetes-sigs/gateway-api/pull/3784 +* Add time extensions to release management doc by @shaneutt in https://github.com/kubernetes-sigs/gateway-api/pull/3943 +* Update implementations.md with removal policy by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/3863 +* TLSRoute: Hostnames godoc by @rostislavbobo in https://github.com/kubernetes-sigs/gateway-api/pull/3925 +* Make feature name required for Experimental by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/3859 +* Support comparison of response protocol by @zirain in https://github.com/kubernetes-sigs/gateway-api/pull/3986 +* docs: note about expectations when a gep misses a release timeline by @shaneutt in https://github.com/kubernetes-sigs/gateway-api/pull/3866 + +## CI & Testing + +* Enable Kubernetes API Linter by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3917 +* Use envtest for CRD validation tests by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3948 + +## Conformance Tests + +* Add mesh conformance tests structure and a first test by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3729 +* Add mesh conformance tests for httproute redirect(s) by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3777 +* Improve feature name readability in conformance reports by @08volt in https://github.com/kubernetes-sigs/gateway-api/pull/3564 +* conformance: add Hook in ConformanceTestSuite by @zirain in https://github.com/kubernetes-sigs/gateway-api/pull/3786 +* add mesh conformance for request header modifier by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3812 +* add httproute weight based routing mesh conformance tests by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3827 +* Add mesh core conformance tests for httproute same-namespace attachment by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3833 +* add httproute matching conformance mesh by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3831 +* add mesh conformance for httproute-queryparmas-match by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3834 +* fix meshredirectport and schemeredirect mesh conformance features by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/3847 +* Add body to http.Request and roundTripper.request to extend conformance testutil ability to send request with body. by @zetxqx in https://github.com/kubernetes-sigs/gateway-api/pull/3853 +* Infer SupportedFeatures in Conformance Tests (GEP-2162) [#3759] by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/3848 +* Improve distribution tests in conformance for MeshHTTPRouteWeight by @carsontham in https://github.com/kubernetes-sigs/gateway-api/pull/3855 +* feat(conformance): validate implementation flags by @mlavacca in https://github.com/kubernetes-sigs/gateway-api/pull/3715 +* Issue 3138 - Conformance Tests for BackendTLSPolicy - normative by @candita in https://github.com/kubernetes-sigs/gateway-api/pull/3212 +* Fix(conformance report) Add Skip test count in Conformance Report if RunTest is configured. by @zetxqx in https://github.com/kubernetes-sigs/gateway-api/pull/3966 +* Add Conformance test for Invalid BackendTLSPolicy TLS settings by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/3930 +* Improve distribution tests in conformance for HTTPRouteWeight by @carsontham in https://github.com/kubernetes-sigs/gateway-api/pull/3880 +* BackendTLSPolicy conformance tests for observedGeneration bump by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/3997 +* conformance: add test for optional address value by @EyalPazz in https://github.com/kubernetes-sigs/gateway-api/pull/3689 +* BackendTLSPolicy conformance tests for ResolvedRefs status condition by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4010 +* conformance: add test to check for proper cors allow-credentials behvior by @EyalPazz in https://github.com/kubernetes-sigs/gateway-api/pull/3990 +* Add Conformance tests for BackendTLSPolicy validating SANs with Type dsnName by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/3983 +* fix conformance test HTTPRouteWeight by @fabian4 in https://github.com/kubernetes-sigs/gateway-api/pull/4038 +* BackendTLSPolicy conformance tests for conflict resolution by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4043 +* Updated a new field on supported features inference from boolean to enum and remove from report. by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/3885 +* Add GRPCRoute weighted backendRefs test by @sarthyparty in https://github.com/kubernetes-sigs/gateway-api/pull/3962 + +## Cleanup + +* Remove unused dependabot config for Github actions by @FelipeYepez in https://github.com/kubernetes-sigs/gateway-api/pull/3816 +* rm duplicate explanation by @naruse666 in https://github.com/kubernetes-sigs/gateway-api/pull/3780 +* fix: remove misleading description by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/3778 +* Fix typo for the file name case type in GEP-2162 doc. by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/3807 +* fix(gep-1911): remove duplicated header in table by @davinkevin in https://github.com/kubernetes-sigs/gateway-api/pull/3818 +* Fix godoc comment for GatewaySpecAddress by @syw14 in https://github.com/kubernetes-sigs/gateway-api/pull/3845 +* Updated index.md to reflect changes in GEP-2162 by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/3898 +* GEP-3792 and GEP-3793 title fixes :man_facepalming: by @kflynn in https://github.com/kubernetes-sigs/gateway-api/pull/3870 +* docs: fix typo and add contents about "ngrok Kubernetes Operator" by @Seo-yul in https://github.com/kubernetes-sigs/gateway-api/pull/3874 +* docs: Fix links to nonexistent anchors by @blake in https://github.com/kubernetes-sigs/gateway-api/pull/3862 +* kubecon talk link updated. by @kundan2707 in https://github.com/kubernetes-sigs/gateway-api/pull/3660 +* Fix Godoc for BackendTLSPolicyValidation struct for Hostname field by @mayuka-c in https://github.com/kubernetes-sigs/gateway-api/pull/3923 +* Fix malformed URL typo in index.md by @HaeyoonJo in https://github.com/kubernetes-sigs/gateway-api/pull/3926 +* Lint required optional by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3929 +* Fix Gateway API community meeting schedule documentation by @jgreeer in https://github.com/kubernetes-sigs/gateway-api/pull/3975 +* ListenerSet adjust PortNumber kubebuilder validations by @dprotaso in https://github.com/kubernetes-sigs/gateway-api/pull/3750 +* Fix OpenAPI validations by adding API list markers by @erikgb in https://github.com/kubernetes-sigs/gateway-api/pull/3964 +* fix typo by @maheshrijal in https://github.com/kubernetes-sigs/gateway-api/pull/3976 +* Add gateway class label to generated objects by @howardjohn in https://github.com/kubernetes-sigs/gateway-api/pull/3955 +* Change to ignore Mesh features in GWC instead of erroring out. by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/3938 +* fix(docs): remove unnecessary array in incorrect example @ gep-1767 by @EyalPazz in https://github.com/kubernetes-sigs/gateway-api/pull/3991 +* Update devguide.md to include docker as a pre-req for verify by @PronomitaDey in https://github.com/kubernetes-sigs/gateway-api/pull/4000 +* Add ResolvedRefs condition for BackendTLSPolicy by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/3994 +* Update status fields with clearer definitions by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/4008 +* Add API changes for HTTP External Auth by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/4001 +* remove http non mesh features from mesh profile by @LiorLieberman in https://github.com/kubernetes-sigs/gateway-api/pull/4029 +* Move BackendTLS configuration to GatewayTLSConfig by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/4009 +* Fix cors cel by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/4032 +* simplify BackendTLSPolicy test infrastructure and remove unnecessary code by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4016 +* Upgrade dependencies to K8s 1.34 by @erikgb in https://github.com/kubernetes-sigs/gateway-api/pull/4044 +* chore(build): Clean up excessive warnings from "make generate" by @kflynn in https://github.com/kubernetes-sigs/gateway-api/pull/4045 +* Update release manager role description by @youngnick in https://github.com/kubernetes-sigs/gateway-api/pull/4040 +* Clarify terminology for gateway TLS by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/4036 +* add BackendTLSPolicyExtendedFeatures to AllFeatures list by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4047 +* Fix PortNumber type to support controller-gen by @erikgb in https://github.com/kubernetes-sigs/gateway-api/pull/4049 +* prevent controller-runtime stack traces logger by @aojea in https://github.com/kubernetes-sigs/gateway-api/pull/4054 +* Add new BackendTLSPolicy configuration options to documentation by @08volt in https://github.com/kubernetes-sigs/gateway-api/pull/3563 +* Add default timeout to UDPRoute test and improve logs by @cnvergence in https://github.com/kubernetes-sigs/gateway-api/pull/4027 +* API for default Gateways by @kflynn in https://github.com/kubernetes-sigs/gateway-api/pull/4031 +* Improve some ListenetSet gep descriptions by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/3978 +* Update index.md field after moving BackendTLS struct by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/4041 +* concepts/tooling.md: Add Headlamp tool by @illume in https://github.com/kubernetes-sigs/gateway-api/pull/4083 + +## New Contributors + +* @szviagintsev made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3782 +* @jonstacks made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3784 +* @naruse666 made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3780 +* @08volt made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3564 +* @bexxmodd made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3807 +* @davinkevin made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3818 +* @FelipeYepez made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3816 +* @samcrichard made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3775 +* @dawid-nowak made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3813 +* @syw14 made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3845 +* @zetxqx made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3853 +* @arihantg made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3844 +* @Seo-yul made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3874 +* @carsontham made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3855 +* @rostislavbobo made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3872 +* @mayuka-c made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3923 +* @rikatz made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3917 +* @HaeyoonJo made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3926 +* @furykerry made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3968 +* @jgreeer made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3975 +* @erikgb made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3964 +* @maheshrijal made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3976 +* @PronomitaDey made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4000 +* @idebeijer made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4018 +* @fabian4 made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4038 +* @sarthyparty made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3962 +* @aaronjwood made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3906 +* @illume made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4083 + +**Full Changelog**: https://github.com/kubernetes-sigs/gateway-api/compare/v1.3.0...v1.4.0-rc.1 diff --git a/CHANGELOG/1.4-TEAM.md b/CHANGELOG/1.4-TEAM.md new file mode 100644 index 0000000000..9b63916789 --- /dev/null +++ b/CHANGELOG/1.4-TEAM.md @@ -0,0 +1,39 @@ +# v1.4 Release Team + +Release Manager: @shaneutt + +## Standard + +| Enhancement | Leads | +| - | - | +| [BackendTLSPolicy] | @candita @kl52752 @snorwin | +| [SupportedFeatures] | @liorlieberman @bexxmodd | +| [Name in HTTPRouteRule & HTTPRouteMatch] | @guicassolato | + +[BackendTLSPolicy]:https://github.com/kubernetes-sigs/gateway-api/issues/1897 +[SupportedFeatures]:https://github.com/kubernetes-sigs/gateway-api/issues/3164 +[Name in HTTPRouteRule & HTTPRouteMatch]:https://github.com/kubernetes-sigs/gateway-api/issues/995 + +## Experimental + +| Enhancement | Leads | +| - | - | +| [Mesh Resource] | @kflynn | +| [Default Gateways] | @kflynn | + +[Mesh Resource]:https://github.com/kubernetes-sigs/gateway-api/issues/3949 +[Default Gateways]:https://github.com/kubernetes-sigs/gateway-api/issues/3793 + +## Special Iteration + +> **Note**: The "special iterations" above indicate items that are either only +> partially moving forward, were already far along in status, or have some other +> special circumstance that brought them in scope. + +| Enhancement | Leads | +| - | - | +| [Gateway/HTTPRoute level authentication] | @youngnick | +| [Client Certificate Verification for Gateway Listeners] | @arkodg | + +[Gateway/HTTPRoute level authentication]:https://github.com/kubernetes-sigs/gateway-api/issues/1494 +[Client Certificate Verification for Gateway Listeners]:https://github.com/kubernetes-sigs/gateway-api/issues/91 From a413c5c84dd8dbc8d0f153c29d47a9242178aa29 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 17 Sep 2025 11:44:03 -0400 Subject: [PATCH 194/224] chore: bump bundle version to v1.4.0-rc.1 Signed-off-by: Shane Utt --- pkg/consts/consts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 3ef3980581..8b558d385c 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -27,7 +27,7 @@ const ( // BundleVersion is the value used for the "gateway.networking.k8s.io/bundle-version" annotation. // These value must be updated during the release process. - BundleVersion = "v1.3.0" + BundleVersion = "v1.4.0-rc.1" // ApprovalLink is the value used for the "api-approved.kubernetes.io" annotation. // These value must be updated during the release process. From 9a0d498d235d9d742358dc569841cf652a13d78a Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 17 Sep 2025 11:44:15 -0400 Subject: [PATCH 195/224] chore: run generators Signed-off-by: Shane Utt --- .../gateway.networking.k8s.io_backendtlspolicies.yaml | 2 +- .../experimental/gateway.networking.k8s.io_gatewayclasses.yaml | 2 +- config/crd/experimental/gateway.networking.k8s.io_gateways.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_httproutes.yaml | 2 +- .../experimental/gateway.networking.k8s.io_referencegrants.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_tcproutes.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_udproutes.yaml | 2 +- .../gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml | 2 +- .../experimental/gateway.networking.x-k8s.io_xlistenersets.yaml | 2 +- .../crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml | 2 +- .../standard/gateway.networking.k8s.io_backendtlspolicies.yaml | 2 +- .../crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_gateways.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_httproutes.yaml | 2 +- .../crd/standard/gateway.networking.k8s.io_referencegrants.yaml | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index 4cf0053506..acb50051fe 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index e022113f1f..ace25e4bf1 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index dc78ec615e..1fbd20a972 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index d10b0530d6..b40275f361 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index e3538d5991..85a5fc4779 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index 65afd84fc1..b65b6594ba 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: referencegrants.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 159d6a73d8..ab17dc3e85 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: tcproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 2961ddd945..3196e57eb7 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: tlsroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 12faf4df0a..86a2b81ac8 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: udproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 1a3881759d..9a80b8ad51 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 0d5def81a0..30af99dee9 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: xlistenersets.gateway.networking.x-k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml index ef8e4024ed..0c7a87af72 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: experimental name: xmeshes.gateway.networking.x-k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml index f218dbd0e9..5faedd15d1 100644 --- a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index a1973f5b64..2372cb882f 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 43ab793f8a..9ab97f5e45 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index b02f9a41d1..dd0a9817eb 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index b57a508f39..b844524812 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index d25ccd2753..768b50b34b 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.3.0 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 gateway.networking.k8s.io/channel: standard name: referencegrants.gateway.networking.k8s.io spec: From 260cd1d70699c1f47c560b299b51b51748e7c396 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 04:39:45 -0700 Subject: [PATCH 196/224] build(deps): bump the k8s-io group with 5 updates (#4085) Bumps the k8s-io group with 5 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.34.0` | `0.34.1` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.34.0` | `0.34.1` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.34.0` | `0.34.1` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.34.0` | `0.34.1` | | [k8s.io/code-generator](https://github.com/kubernetes/code-generator) | `0.34.0` | `0.34.1` | Updates `k8s.io/api` from 0.34.0 to 0.34.1 - [Commits](https://github.com/kubernetes/api/compare/v0.34.0...v0.34.1) Updates `k8s.io/apiextensions-apiserver` from 0.34.0 to 0.34.1 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.34.0...v0.34.1) Updates `k8s.io/apimachinery` from 0.34.0 to 0.34.1 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.34.0...v0.34.1) Updates `k8s.io/client-go` from 0.34.0 to 0.34.1 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.34.0...v0.34.1) Updates `k8s.io/code-generator` from 0.34.0 to 0.34.1 - [Commits](https://github.com/kubernetes/code-generator/compare/v0.34.0...v0.34.1) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/code-generator dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 070b21f600..c9637a81ce 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( google.golang.org/grpc v1.75.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.8 - k8s.io/api v0.34.0 - k8s.io/apiextensions-apiserver v0.34.0 - k8s.io/apimachinery v0.34.0 - k8s.io/client-go v0.34.0 - k8s.io/code-generator v0.34.0 + k8s.io/api v0.34.1 + k8s.io/apiextensions-apiserver v0.34.1 + k8s.io/apimachinery v0.34.1 + k8s.io/client-go v0.34.1 + k8s.io/code-generator v0.34.1 k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d sigs.k8s.io/controller-runtime v0.21.0 diff --git a/go.sum b/go.sum index 6abcd96c8a..aa112eb6fb 100644 --- a/go.sum +++ b/go.sum @@ -245,16 +245,16 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE= -k8s.io/api v0.34.0/go.mod h1:YzgkIzOOlhl9uwWCZNqpw6RJy9L2FK4dlJeayUoydug= -k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc= -k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0= -k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0= -k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo= -k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY= -k8s.io/code-generator v0.34.0 h1:Ze2i1QsvUprIlX3oHiGv09BFQRLCz+StA8qKwwFzees= -k8s.io/code-generator v0.34.0/go.mod h1:Py2+4w2HXItL8CGhks8uI/wS3Y93wPKO/9mBQUYNua0= +k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= +k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= +k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= +k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= +k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= +k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= From 01ab02706d26a06cc2fd470dbadd4f6dc46813c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 04:39:51 -0700 Subject: [PATCH 197/224] build(deps): bump sigs.k8s.io/controller-runtime from 0.21.0 to 0.22.1 (#4086) Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.21.0 to 0.22.1. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.21.0...v0.22.1) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-version: 0.22.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 7 +++++-- go.sum | 6 ++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c9637a81ce..8842e5f935 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( k8s.io/code-generator v0.34.1 k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d - sigs.k8s.io/controller-runtime v0.21.0 + sigs.k8s.io/controller-runtime v0.22.1 sigs.k8s.io/controller-tools v0.18.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 @@ -28,7 +28,8 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/blang/semver/v4 v4.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect @@ -63,6 +64,8 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.17.0 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.7 // indirect diff --git a/go.sum b/go.sum index aa112eb6fb..496ee74bd4 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,6 @@ 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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -263,8 +261,8 @@ k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaC k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= -sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= +sigs.k8s.io/controller-runtime v0.22.1 h1:Ah1T7I+0A7ize291nJZdS1CabF/lB4E++WizgV24Eqg= +sigs.k8s.io/controller-runtime v0.22.1/go.mod h1:FwiwRjkRPbiN+zp2QRp7wlTCzbUXxZ/D4OzuQUDwBHY= sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE= sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= From 2d40c3d070154ff2b748300f3c2454acf25cdb83 Mon Sep 17 00:00:00 2001 From: John Howard Date: Thu, 18 Sep 2025 17:36:12 -0700 Subject: [PATCH 198/224] conformance: fix per-test cleanup (#4104) Fixes https://github.com/kubernetes-sigs/gateway-api/issues/4102 --- conformance/utils/suite/conformance.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/utils/suite/conformance.go b/conformance/utils/suite/conformance.go index 436b3ed2ce..12db14d6df 100644 --- a/conformance/utils/suite/conformance.go +++ b/conformance/utils/suite/conformance.go @@ -68,7 +68,7 @@ func (test *ConformanceTest) Run(t *testing.T, suite *ConformanceTestSuite) { for _, manifestLocation := range test.Manifests { tlog.Logf(t, "Applying %s", manifestLocation) - suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, manifestLocation, suite.Cleanup) + suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, manifestLocation, true) } if featuresInfo != "" { From 6b6e6086ad0afd3a867c615598feb32a627f9425 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Thu, 18 Sep 2025 21:54:13 -0300 Subject: [PATCH 199/224] Update GEP template with some clarifying sections (#4073) * Update GEP template with some clarifying sections * Apply suggestions on GEP template update Co-authored-by: Nick Young --------- Co-authored-by: Nick Young --- geps/gep-696/index.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/geps/gep-696/index.md b/geps/gep-696/index.md index 6082b30907..da58798f7f 100644 --- a/geps/gep-696/index.md +++ b/geps/gep-696/index.md @@ -13,16 +13,27 @@ (Primary goals of this proposal.) +## Longer Term Goals (optional) + +(goals that are not covered initially on this proposal but may be considered long term) + ## Non-Goals (What is out of scope for this proposal.) -## Introduction +## Introduction/Overview (Can link to external doc -- but we should bias towards copying the content into the GEP as online documents are easier to lose -- e.g. owner messes up the permissions, accidental deletion) +Write here "What" we want to do. What is the proposal aiming to do? + +## Purpose (Why and Who) + +Write here "Why" we want to do it. What problems are being solved? What personas are +the target of this proposal, and why will this proposal will make their lives better? + ## API (... details, can point to PR with changes) @@ -32,6 +43,17 @@ the content into the GEP as online documents are easier to lose ### Gateway For Mesh (East/West) (Include East/West API considerations, examples, and if different - APIs) +## Request flow +Example on the usage flow of this proposal/enhancement. It is suggested to contain +at least one manifest as example. + +Example of a flow description: + +* A client makes a request to https://foo.example.com. +* DNS resolves the name to a `Gateway` address. +* The reverse proxy receives the request on a `Listener` and does something with it +* The reverse proxy passes the request through `XPTORoute` modifying the headers to contain `XYZ` + ## Conformance Details (from https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-2162/index.md#standardize-features-and-conformance-tests-names) @@ -60,6 +82,11 @@ In any case, the conformance tests file names should be meaningful and easy to u (Make sure to also include conformance tests that cover mesh) +When describing the new feature, write down some conformance test scenarios the feature should manage, +to guarantee that future implementors understand what "Conformance" means and what will be tested. + +At least _some_ tests should be added at each phase, starting with Provisional. + ## Alternatives (List other design alternatives and why we did not go in that From df8c96c254e1ac6d5f5e0d70617f36143723d479 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Fri, 19 Sep 2025 17:42:11 -0700 Subject: [PATCH 200/224] Added flag for running mesh conformance suite and automatically inferring supported features from Mesh.Status (#4097) * Read SupportedFeatures from XMesh status for conformance test. * Defined Mesh flag for testing. * Renamed mesh flag. * renamed fetched mesh features set. * suite_test formatting. * Set mesh flag empty default value --- conformance/conformance.go | 1 + conformance/utils/flags/flags.go | 1 + conformance/utils/suite/suite.go | 63 +++++++++++--- conformance/utils/suite/suite_test.go | 118 ++++++++++++++++++++++++-- 4 files changed, 167 insertions(+), 16 deletions(-) diff --git a/conformance/conformance.go b/conformance/conformance.go index 3921310575..642a6eb280 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -93,6 +93,7 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { ExemptFeatures: exemptFeatures, ManifestFS: []fs.FS{&Manifests}, GatewayClassName: *flags.GatewayClassName, + MeshName: *flags.MeshName, Implementation: implementation, Mode: *flags.Mode, NamespaceAnnotations: namespaceAnnotations, diff --git a/conformance/utils/flags/flags.go b/conformance/utils/flags/flags.go index 95da9eaad1..1465df68b9 100644 --- a/conformance/utils/flags/flags.go +++ b/conformance/utils/flags/flags.go @@ -30,6 +30,7 @@ const ( var ( GatewayClassName = flag.String("gateway-class", "gateway-conformance", "Name of GatewayClass to use for tests") + MeshName = flag.String("mesh-name", "", "Name of Mesh to use for tests") ShowDebug = flag.Bool("debug", false, "Whether to print debug logs") CleanupBaseResources = flag.Bool("cleanup-base-resources", true, "Whether to cleanup base test resources after the run") SupportedFeatures = flag.String("supported-features", "", "Supported features included in conformance tests suites") diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 31db06c596..8dcd009e86 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -39,6 +39,7 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1beta1" + xmeshv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1" "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/flags" @@ -65,6 +66,7 @@ type ConformanceTestSuite struct { RoundTripper roundtripper.RoundTripper GRPCClient grpc.Client GatewayClassName string + MeshName string ControllerName string Debug bool Cleanup bool @@ -136,6 +138,7 @@ type ConformanceOptions struct { Clientset clientset.Interface RestConfig *rest.Config GatewayClassName string + MeshName string AddressType string Debug bool RoundTripper roundtripper.RoundTripper @@ -206,20 +209,23 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, supportedFeatures = features.SetsToNamesSet(features.AllFeatures) } else if shouldInferSupportedFeatures(&options) { var err error - supportedFeatures, err = fetchSupportedFeatures(options.Client, options.GatewayClassName) - if err != nil { - return nil, fmt.Errorf("cannot infer supported features: %w", err) + if options.GatewayClassName != "" { + supportedFeatures, err = fetchGatewayClassSupportedFeatures(options.Client, options.GatewayClassName) + if err != nil { + return nil, fmt.Errorf("cannot infer supported features from GWC: %w", err) + } } - // If Mesh features are populated in the GatewayClass we remove them from the supported features set. - meshFeatureNames := features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures) - for _, f := range supportedFeatures.UnsortedList() { - if meshFeatureNames.Has(f) { - supportedFeatures.Delete(f) - fmt.Printf("WARNING: Mesh feature %q should not be populated in GatewayClass, skipping...", f) + supportedMeshFeatures := FeaturesSet{} + if options.MeshName != "" { + supportedMeshFeatures, err = fetchMeshSupportedFeatures(options.Client, options.MeshName) + if err != nil { + return nil, fmt.Errorf("cannot infer supported features from XMesh: %w", err) } } + source = supportedFeaturesSourceInferred + supportedFeatures = supportedFeatures.Union(supportedMeshFeatures) } // If features were not inferred from Status, it's a GWC issue. @@ -606,24 +612,59 @@ func ParseConformanceProfiles(p string) sets.Set[ConformanceProfileName] { return res } -func fetchSupportedFeatures(client client.Client, gatewayClassName string) (FeaturesSet, error) { +func fetchGatewayClassSupportedFeatures(client client.Client, gatewayClassName string) (FeaturesSet, error) { if gatewayClassName == "" { return nil, fmt.Errorf("GatewayClass name must be provided to fetch supported features") } gwc := &gatewayv1.GatewayClass{} err := client.Get(context.TODO(), types.NamespacedName{Name: gatewayClassName}, gwc) if err != nil { - return nil, fmt.Errorf("fetchSupportedFeatures(): %w", err) + return nil, fmt.Errorf("fetchGatewayClassSupportedFeatures(): %w", err) } fs := FeaturesSet{} for _, feature := range gwc.Status.SupportedFeatures { fs.Insert(features.FeatureName(feature.Name)) } + + // If Mesh features are populated in the GatewayClass we remove them from the supported features set. + meshFeatureNames := features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures) + for _, f := range fs.UnsortedList() { + if meshFeatureNames.Has(f) { + fs.Delete(f) + fmt.Printf("WARNING: Mesh feature %q should not be populated in GatewayClass, skipping...", f) + } + } fmt.Printf("Supported features for GatewayClass %s: %v\n", gatewayClassName, fs.UnsortedList()) return fs, nil } +func fetchMeshSupportedFeatures(client client.Client, meshName string) (FeaturesSet, error) { + if meshName == "" { + return nil, fmt.Errorf("mesh name must be provided to fetch supported features") + } + xmesh := &xmeshv1alpha1.XMesh{} + err := client.Get(context.TODO(), types.NamespacedName{Name: meshName}, xmesh) + if err != nil { + return nil, fmt.Errorf("fetchMeshSupportedFeatures(): %w", err) + } + + fs := FeaturesSet{} + for _, feature := range xmesh.Status.SupportedFeatures { + fs.Insert(features.FeatureName(feature.Name)) + } + + gwcFeatureNames := features.SetsToNamesSet(features.GatewayCoreFeatures, features.GatewayExtendedFeatures) + for _, f := range fs.UnsortedList() { + if gwcFeatureNames.Has(f) { + fs.Delete(f) + fmt.Printf("WARNING: Mesh feature %q should not be populated in XMesh.Status, skipping...", f) + } + } + fmt.Printf("Supported features for XMesh%s: %v\n", meshName, fs.UnsortedList()) + return fs, nil +} + // shouldInferSupportedFeatures checks if any flags were supplied for manually // picking what to test. Inferred supported features are only used when no flags // are set. diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index 778afa7180..674e74808c 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + xmeshv1alpha1 "sigs.k8s.io/gateway-api/apisx/v1alpha1" confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1" "sigs.k8s.io/gateway-api/pkg/consts" "sigs.k8s.io/gateway-api/pkg/features" @@ -411,7 +412,7 @@ func TestSuiteReport(t *testing.T) { } } -var statusFeatureNames = []string{ +var gwcStatusFeatureNames = []string{ "Gateway", "GatewayPort8080", "HTTPRoute", @@ -423,7 +424,7 @@ var statusFeatureNames = []string{ "ReferenceGrant", } -func TestInferSupportedFeatures(t *testing.T) { +func TestInferGWCSupportedFeatures(t *testing.T) { testCases := []struct { name string allowAllFeatures bool @@ -435,7 +436,7 @@ func TestInferSupportedFeatures(t *testing.T) { }{ { name: "properly infer supported features", - expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedFeatures: namesToFeatureSet(gwcStatusFeatureNames), expectedSource: supportedFeaturesSourceInferred, }, { @@ -460,7 +461,7 @@ func TestInferSupportedFeatures(t *testing.T) { { name: "supports conformance profile - core", ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), - expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedFeatures: namesToFeatureSet(gwcStatusFeatureNames), expectedSource: supportedFeaturesSourceInferred, }, } @@ -482,7 +483,7 @@ func TestInferSupportedFeatures(t *testing.T) { Message: "GatewayClass is accepted and ready for use", }, }, - SupportedFeatures: featureNamesToSet(statusFeatureNames), + SupportedFeatures: featureNamesToSet(gwcStatusFeatureNames), }, } scheme := runtime.NewScheme() @@ -524,6 +525,113 @@ func TestInferSupportedFeatures(t *testing.T) { } } +var meshStatusFeatureNames = []string{ + "Mesh", + "MeshClusterIPMatching", + "MeshNamespaceSelector", + "MeshServiceAccountSelector", + "MeshTLS", + "MeshTLSClientCert", + "MeshTrafficSplit", + "MeshAccessControl", + "HTTPRoute", +} + +func TestXMeshInferSupportedFeatures(t *testing.T) { + testCases := []struct { + name string + allowAllFeatures bool + supportedFeatures FeaturesSet + exemptFeatures FeaturesSet + ConformanceProfile sets.Set[ConformanceProfileName] + expectedFeatures FeaturesSet + expectedSource supportedFeaturesSource + }{ + { + name: "properly infer mesh supported features", + expectedFeatures: namesToFeatureSet(meshStatusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, + }, + { + name: "no features", + supportedFeatures: sets.New[features.FeatureName]("Mesh"), + expectedFeatures: sets.New[features.FeatureName]("Mesh"), + expectedSource: supportedFeaturesSourceManual, + }, + { + name: "remove exempt features", + supportedFeatures: sets.New[features.FeatureName]("MeshTLS", "MeshAccessControl"), + exemptFeatures: sets.New[features.FeatureName]("MeshAccessControl"), + expectedFeatures: sets.New[features.FeatureName]("MeshTLS"), + expectedSource: supportedFeaturesSourceManual, + }, + { + name: "supports conformance profile - core", + ConformanceProfile: sets.New(MeshHTTPConformanceProfileName), + expectedFeatures: namesToFeatureSet(meshStatusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, + }, + } + + meshName := "xochopintre" + xmesh := &xmeshv1alpha1.XMesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: meshName, + }, + Spec: xmeshv1alpha1.MeshSpec{ + ControllerName: "example.com/mesh-controller", + }, + Status: xmeshv1alpha1.MeshStatus{ + Conditions: []metav1.Condition{ + { + Type: string(xmeshv1alpha1.MeshConditionAccepted), + Status: metav1.ConditionTrue, + Reason: "Accepted", + Message: "XMesh is accepted and ready for use", + }, + }, + SupportedFeatures: featureNamesToSet(meshStatusFeatureNames), + }, + } + scheme := runtime.NewScheme() + scheme.AddKnownTypes(xmeshv1alpha1.SchemeGroupVersion, &xmeshv1alpha1.XMesh{}) + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(xmesh). + WithLists(&apiextensionsv1.CustomResourceDefinitionList{}). + Build() + + xmeshv1alpha1.Install(fakeClient.Scheme()) + apiextensionsv1.AddToScheme(fakeClient.Scheme()) + + for _, tc := range testCases { + options := ConformanceOptions{ + AllowCRDsMismatch: true, + MeshName: meshName, + EnableAllSupportedFeatures: tc.allowAllFeatures, + SupportedFeatures: tc.supportedFeatures, + ExemptFeatures: tc.exemptFeatures, + ConformanceProfiles: tc.ConformanceProfile, + Client: fakeClient, + } + + t.Run(tc.name, func(t *testing.T) { + cSuite, err := NewConformanceTestSuite(options) + if err != nil { + t.Fatalf("error initializing conformance suite: %v", err) + } + + if cSuite.supportedFeaturesSource != tc.expectedSource { + t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.supportedFeaturesSource, tc.expectedSource) + } + + if equal := cSuite.SupportedFeatures.Equal(tc.expectedFeatures); !equal { + t.Errorf("SupportedFeatures mismatch: got %v, want %v", cSuite.SupportedFeatures.UnsortedList(), tc.expectedFeatures.UnsortedList()) + } + }) + } +} + func TestGWCPublishedMeshFeatures(t *testing.T) { gwcName := "ochopintre" gwc := &gatewayv1.GatewayClass{ From 0e40edd205ac7a98a4d892661015f43ee917a004 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Mon, 22 Sep 2025 05:36:17 -0700 Subject: [PATCH 201/224] Fixed couple of typos in conformance tests. (#4106) --- conformance/tests/backendtlspolicy-observed-generation-bump.go | 2 +- conformance/tests/grpcroute-named-rule.go | 2 +- conformance/tests/grpcroute-weight.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.go b/conformance/tests/backendtlspolicy-observed-generation-bump.go index 83c12378fb..85f44a70c6 100644 --- a/conformance/tests/backendtlspolicy-observed-generation-bump.go +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.go @@ -39,7 +39,7 @@ func init() { var BackendTLSPolicyObservedGenerationBump = suite.ConformanceTest{ ShortName: "BackendTLSPolicyObservedGenerationBump", - Description: "A BackendTLSPolicy in the gateway-conformance-infra namespace should update the observedGeneration in all of it's Status.Conditions after an update to the spec", + Description: "A BackendTLSPolicy in the gateway-conformance-infra namespace should update the observedGeneration in all of its Status.Conditions after an update to the spec", Features: []features.FeatureName{ features.SupportGateway, features.SupportHTTPRoute, diff --git a/conformance/tests/grpcroute-named-rule.go b/conformance/tests/grpcroute-named-rule.go index 2c738a5660..c5b80ab6f4 100644 --- a/conformance/tests/grpcroute-named-rule.go +++ b/conformance/tests/grpcroute-named-rule.go @@ -35,7 +35,7 @@ func init() { var GRPCRouteNamedRule = suite.ConformanceTest{ ShortName: "GRPCRouteNamedRule", - Description: "An GRPCRoute with a named GRPCRouteRule", + Description: "A GRPCRoute with a named GRPCRouteRule", Manifests: []string{"tests/grpcroute-named-rule.yaml"}, Features: []features.FeatureName{ features.SupportGateway, diff --git a/conformance/tests/grpcroute-weight.go b/conformance/tests/grpcroute-weight.go index ba5a4d5681..644349121f 100644 --- a/conformance/tests/grpcroute-weight.go +++ b/conformance/tests/grpcroute-weight.go @@ -38,7 +38,7 @@ func init() { var GRPCRouteWeight = suite.ConformanceTest{ ShortName: "GRPCRouteWeight", - Description: "An GRPCRoute with weighted backends", + Description: "A GRPCRoute with weighted backends", Manifests: []string{"tests/grpcroute-weight.yaml"}, Features: []features.FeatureName{ features.SupportGateway, From 123ae41501a13b89e08753766433f765c7252191 Mon Sep 17 00:00:00 2001 From: Candace Holman Date: Mon, 22 Sep 2025 20:18:12 -0400 Subject: [PATCH 202/224] Issue 3940: Update BackendTLSPolicy GEP (#4099) Move BackendTLSPolicy to standard and update gep, metadata, and toc. modified: geps/gep-1897/index.md modified: geps/gep-1897/metadata.yaml modified: nav.yml --- geps/gep-1897/index.md | 430 ++++++++++++++++++++++++++++++++---- geps/gep-1897/metadata.yaml | 4 +- nav.yml | 2 +- 3 files changed, 386 insertions(+), 50 deletions(-) diff --git a/geps/gep-1897/index.md b/geps/gep-1897/index.md index 149d6c649e..2b2159f71b 100644 --- a/geps/gep-1897/index.md +++ b/geps/gep-1897/index.md @@ -1,7 +1,7 @@ # GEP-1897: BackendTLSPolicy - Explicit Backend TLS Connection Configuration * Issue: [#1897](https://github.com/kubernetes-sigs/gateway-api/issues/1897) -* Status: Experimental +* Status: Standard ## TLDR @@ -30,11 +30,9 @@ Gateway to backend**, such as server name indication and trusted CA certificates ## Longer Term Goals These are worthy goals, but deserve a different GEP for proper attention. This GEP is concerned entirely with the -the hop between gateway client and backend. - -1. [TCPRoute](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TCPRoute) and -[GRPCRoute](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.GRPCRoute) use cases -are not addressed here, because at this point in time these two route types are not graduated to beta. +hop between gateway client and backend. +1. [TCPRoute](../../apis/v1alpha2/tcproute_types.go) use cases are not addressed here, because at this point in time +TCPRoute is not graduated to beta. 2. Mutual TLS (mTLS) use cases are intentionally out of scope for this GEP for two reasons. First, the design of Gateway API is backend-attached and does not currently support mutual authentication, and also because this GEP does not address the case where connections to TLS are **implicitly configured** on behalf of the user, which is the norm for mTLS. @@ -52,18 +50,21 @@ These are worthy goals, but will not be covered by this GEP. 2. Providing a mechanism to decorate multiple route instances 3. TLSRoute use cases 4. UDPRoute use cases -5. Controlling TLS versions or cipher suites used in TLS handshakes. (Use case #5 in [Gateway API TLS Use Cases](#references)) -6. Controlling certificates used by more than one workload (#6 in [Gateway API TLS Use Cases](#references)) -7. Client certificate settings used in TLS **from external clients to the +5. GRPCRoute use cases +6. Controlling TLS versions or cipher suites used in TLS handshakes. (Use case #5 in [Gateway API TLS Use Cases](#references)) +7. Controlling certificates used by more than one workload (#6 in [Gateway API TLS Use Cases](#references)) +8. Client certificate settings used in TLS **from external clients to the Listener** (#7 in [Gateway API TLS Use Cases](#references)) -8. Service Mesh "mesh transport security". -9. Providing a mechanism for the cluster operator to override gateway to backend TLS settings. +9. Service Mesh "mesh transport security". +10. Providing a mechanism for the cluster operator to override gateway to backend TLS settings. -> It is very common for service mesh implementations to implement some form of transparent transport security, whether that is WireGuard, mTLS, or others. -> This is completely orthogonal to the use cases being tackled by this GEP. -> * The "mesh transport security" is something invisible to the user's application, and is simply used to secure communication between components in the mesh. +> It is very common for service mesh implementations to implement some form of transparent transport security, whether +> that is WireGuard, mTLS, or others. This is completely orthogonal to the use cases being tackled by this GEP. +> * The "mesh transport security" is something invisible to the user's application, and is simply used to secure +> communication between components in the mesh. > * This proposal, instead, explicitly calls for sending TLS **to the user's application**. -> However, this does not mean service meshes are outside of scope for this proposal, merely that only the application-level TLS configuration is in scope. +> However, this does not mean service meshes are outside of scope for this proposal, merely that only the +> application-level TLS configuration is in scope. ![](images/mesh.png "Mesh transport") @@ -84,7 +85,6 @@ backend pod). As mentioned, this solution satisfies the use case in which the b has its own certificate and the gateway client needs to know how to connect to the backend pod. ![image depicting TLS termination types](images/1897-TLStermtypes.png "TLS termination types") - Gateway API is missing a mechanism for separately providing the details for the backend TLS handshake, including (but not limited to): @@ -157,8 +157,8 @@ substituted without blocking acceptance of the content of the API change. The selection of the applicable Gateway API persona is important in the design of BackendTLSPolicy, because it provides a way to explicitly describe the _expectations_ of the connection to the application. -In this GEP, BackendTLSPolicy will be configured only by the application developer Gateway API persona to tell gateway clients how to connect to -the application, from a TLS perspective. +In this GEP, BackendTLSPolicy will be configured only by the application developer Gateway API persona to tell gateway +clients how to connect to the application, from a TLS perspective. Future iterations *may* expand this to additionally allow consumer overrides; see [Future plans](#future-plans). During the course of discussion of this proposal, we did consider allowing the cluster operator persona to have some access @@ -181,7 +181,8 @@ as a TLS Client: BackendTLSPolicy is defined as a Direct Policy Attachment without defaults or overrides, applied to a Service that accesses the backend in question, where the BackendTLSPolicy resides in the same namespace as the Service it is applied to. For now, the BackendTLSPolicy and the Service must reside in the same namespace in order to prevent the -complications involved with sharing trust across namespace boundaries (see [Future plans](#future-plans)). We chose the Service resource as a target, +complications involved with sharing trust across namespace boundaries (see [Future plans](#future-plans)). We chose the Service +resource as a target, rather than the Route resource, so that we can reuse the same BackendTLSPolicy for all the different Routes that might point to this Service. @@ -196,7 +197,10 @@ that is appropriate, such as one of the HTTP error codes: 400 (Bad Request), 401 other signal that makes the failure sufficiently clear to the requester without revealing too much about the transaction, based on established security requirements. -BackendTLSPolicy applies only to TCP traffic. If a policy explicitly attaches to a UDP port of a Service (that is, the `targetRef` has a `sectionName` specifying a single port or the service has only 1 port), the `Accepted: False` Condition with `Reason: Invalid` MUST be set. If the policy attaches to a mix of TCP and UDP ports, implementations SHOULD include a warning in the `Accepted` condition message (`ancestors.conditions`); the policy will only be effective for the TCP ports. +BackendTLSPolicy applies only to TCP traffic. If a policy explicitly attaches to a UDP port of a Service (that is, the +`targetRef` has a `sectionName` specifying a single port or the service has only 1 port), the `Accepted: False` Condition +with `Reason: Invalid` MUST be set. If the policy attaches to a mix of TCP and UDP ports, implementations SHOULD include +a warning in the `Accepted` condition message (`ancestors.conditions`); the policy will only be effective for the TCP ports. All policy resources must include `TargetRefs` with the fields specified in [PolicyTargetReference](https://github.com/kubernetes-sigs/gateway-api/blob/a33a934af9ec6997b34fd9b00d2ecd13d143e48b/apis/v1alpha2/policy_types.go#L24-L41). @@ -214,12 +218,20 @@ configuration. CACertificateRefs is an implementation-specific slice of named object references, each containing a single cert. We originally proposed to follow the convention established by the [CertificateRefs field on Gateway](https://github.com/kubernetes-sigs/gateway-api/blob/18e79909f7310aafc625ba7c862dfcc67b385250/apis/v1beta1/gateway_types.go#L340) , but the CertificateRef requires both a tls.key and tls.crt and a certificate reference only requires the tls.crt. -If any of the CACertificateRefs cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured (e.g., ConfigMap does not contain a key named `ca.crt`), the `ResolvedRefs` status condition MUST be set to `False` with `Reason: InvalidCACertificateRef`. Connections using that CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. -References to objects with an unsupported Group and Kind are not valid, and MUST be rejected by the implementation with the `ResolvedRefs` status condition set to `False` and `Reason: InvalidKind`. -Implementations MAY perform further validation of the certificate content (i.e., checking expiry or enforcing specific formats). If they do, they MUST ensure that the `ResolvedRefs` Condition is `False` and use an implementation-specific `Reason`, like `ExpiredCertificate` or similar. -If `ResolvedRefs` Condition is `False` implementations SHOULD include a message specifying which references are invalid and explaining why. - -If all CertificateRefs cannot be resolved, the BackendTLSPolicy is considered invalid and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `NoValidCACertificate` and a message explaining this. +If any of the CACertificateRefs cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured +(e.g., ConfigMap does not contain a key named `ca.crt`), the `ResolvedRefs` status condition MUST be set to `False` with +`Reason: InvalidCACertificateRef`. Connections using that CACertificateRef MUST fail, and the client MUST receive an +HTTP 5xx error response. +References to objects with an unsupported Group and Kind are not valid, and MUST be rejected by the implementation with +the `ResolvedRefs` status condition set to `False` and `Reason: InvalidKind`. +Implementations MAY perform further validation of the certificate content (i.e., checking expiry or enforcing specific +formats). If they do, they MUST ensure that the `ResolvedRefs` Condition is `False` and use an implementation-specific +`Reason`, like `ExpiredCertificate` or similar. +If `ResolvedRefs` Condition is `False` implementations SHOULD include a message specifying which references are invalid +and explaining why. + +If all CertificateRefs cannot be resolved, the BackendTLSPolicy is considered invalid and the implementation MUST set +the `Accepted` Condition to `False`, with a reason of `NoValidCACertificate` and a message explaining this. WellKnownCACertificates is an optional enum that allows users to specify whether to use the set of CA certificates trusted by the Gateway (WellKnownCACertificates specified as "System"), or to use the existing CACertificateRefs (WellKnownCACertificates @@ -228,13 +240,17 @@ these certificates are obtained from the underlying operating system. CACertific references to Kubernetes objects that contain PEM-encoded TLS certificates, which are used to establish a TLS handshake between the gateway and backend pod. References to a resource in a different namespace are invalid. If ClientCertificateRefs is unspecified, then WellKnownCACertificates must be set to "System" for a valid configuration. -If WellKnownCACertificates is unspecified, then CACertificateRefs must be specified with at least one entry for a valid configuration. -If an implementation does not support the WellKnownCACertificates, or the provided value is unsupported,the BackendTLSPolicy is considered invalid, and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `Invalid` and a message explaining this. +If WellKnownCACertificates is unspecified, then CACertificateRefs must be specified with at least one entry for a valid +configuration. +If an implementation does not support the WellKnownCACertificates, or the provided value is unsupported,the +BackendTLSPolicy is considered invalid, and the implementation MUST set the `Accepted` Condition to `False`, with a +reason of `Invalid` and a message explaining this. For an invalid BackendTLSPolicy, implementations MUST NOT fall back to unencrypted (plaintext) connections. Instead, the corresponding TLS connection MUST fail, and the client MUST receive an HTTP 5xx error response. -Implementations MUST NOT modify any status other than their own. Ownership of a status is determined by the `controllerName`, which identifies the responsible controller. +Implementations MUST NOT modify any status other than their own. Ownership of a status is determined by the `controllerName`, +which identifies the responsible controller. The `Hostname` field is required and is to be used to configure the SNI the Gateway should use to connect to the backend. Implementations must validate that at least one name in the certificate served by the backend matches this field. @@ -245,10 +261,309 @@ but may be added in the future. We originally proposed allowing the configuration of expected TLS versions, but determined that this was [not needed in the first round](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092). -Thus, the following additions would be made to the Gateway API: +Thus, the following additions would be made to Gateway API. See the +[BackendTLSPolicy API](https://kubernetes-sigs/gateway-api/blob/main/apis/v1/backendtlspolicy_types.go) for more +details. ```go -//TODO: Will update this section once API changes from PR 2955 are approved. +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:categories=gateway-api,shortName=btlspolicy +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +// BackendTLSPolicy is a Direct Attached Policy. +// +kubebuilder:metadata:labels="gateway.networking.k8s.io/policy=Direct" + +// BackendTLSPolicy provides a way to configure how a Gateway +// connects to a Backend via TLS. +type BackendTLSPolicy struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of BackendTLSPolicy. + // +required + Spec BackendTLSPolicySpec `json:"spec"` + + // Status defines the current state of BackendTLSPolicy. + // +optional + Status PolicyStatus `json:"status,omitempty"` +} + +// BackendTLSPolicyList contains a list of BackendTLSPolicies +// +kubebuilder:object:root=true +type BackendTLSPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BackendTLSPolicy `json:"items"` +} + +// BackendTLSPolicySpec defines the desired state of BackendTLSPolicy. +// +// Support: Extended +type BackendTLSPolicySpec struct { + // TargetRefs identifies an API object to apply the policy to. + // Only Services have Extended support. Implementations MAY support + // additional objects, with Implementation Specific support. + // Note that this config applies to the entire referenced resource + // by default, but this default may change in the future to provide + // a more granular application of the policy. + // + // TargetRefs must be _distinct_. This means either that: + // + // * They select different targets. If this is the case, then targetRef + // entries are distinct. In terms of fields, this means that the + // multi-part key defined by `group`, `kind`, and `name` must + // be unique across all targetRef entries in the BackendTLSPolicy. + // * They select different sectionNames in the same target. + // + // + // When more than one BackendTLSPolicy selects the same target and + // sectionName, implementations MUST determine precedence using the + // following criteria, continuing on ties: + // + // * The older policy by creation timestamp takes precedence. For + // example, a policy with a creation timestamp of "2021-07-15 + // 01:02:03" MUST be given precedence over a policy with a + // creation timestamp of "2021-07-15 01:02:04". + // * The policy appearing first in alphabetical order by {name}. + // For example, a policy named `bar` is given precedence over a + // policy named `baz`. + // + // For any BackendTLSPolicy that does not take precedence, the + // implementation MUST ensure the `Accepted` Condition is set to + // `status: False`, with Reason `Conflicted`. + // + // Support: Extended for Kubernetes Service + // + // Support: Implementation-specific for any other resource + // + // +required + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:message="sectionName must be specified when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" + // +kubebuilder:validation:XValidation:message="sectionName must be unique when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName))))" + TargetRefs []LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"` + + // Validation contains backend TLS validation configuration. + // +required + Validation BackendTLSPolicyValidation `json:"validation"` + + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} + +// BackendTLSPolicyValidation contains backend TLS validation configuration. +// +kubebuilder:validation:XValidation:message="must not contain both CACertificateRefs and WellKnownCACertificates",rule="!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" +// +kubebuilder:validation:XValidation:message="must specify either CACertificateRefs or WellKnownCACertificates",rule="(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != \"\")" +type BackendTLSPolicyValidation struct { + // CACertificateRefs contains one or more references to Kubernetes objects that + // contain a PEM-encoded TLS CA certificate bundle, which is used to + // validate a TLS handshake between the Gateway and backend Pod. + // + // If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be + // specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, + // not both. If CACertificateRefs is empty or unspecified, the configuration for + // WellKnownCACertificates MUST be honored instead if supported by the implementation. + // + // A CACertificateRef is invalid if: + // + // * It refers to a resource that cannot be resolved (e.g., the referenced resource + // does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + // named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + // and the Message of the Condition must indicate which reference is invalid and why. + // + // * It refers to an unknown or unsupported kind of resource. In this case, the Reason + // must be set to `InvalidKind` and the Message of the Condition must explain which + // kind of resource is unknown or unsupported. + // + // * It refers to a resource in another namespace. This may change in future + // spec updates. + // + // Implementations MAY choose to perform further validation of the certificate + // content (e.g., checking expiry or enforcing specific formats). In such cases, + // an implementation-specific Reason and Message must be set for the invalid reference. + // + // In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + // the BackendTLSPolicy is set to `status: False`, with a Reason and Message + // that indicate the cause of the error. Connections using an invalid + // CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + // response. If ALL CACertificateRefs are invalid, the implementation MUST also + // ensure the `Accepted` Condition on the BackendTLSPolicy is set to + // `status: False`, with a Reason `NoValidCACertificate`. + // + // + // A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a backend, but this behavior is implementation-specific. + // + // Support: Core - An optional single reference to a Kubernetes ConfigMap, + // with the CA certificate in a key named `ca.crt`. + // + // Support: Implementation-specific - More than one reference, other kinds + // of resources, or a single reference that includes multiple certificates. + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MaxItems=8 + CACertificateRefs []LocalObjectReference `json:"caCertificateRefs,omitempty"` + + // WellKnownCACertificates specifies whether system CA certificates may be used in + // the TLS handshake between the gateway and backend pod. + // + // If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs + // must be specified with at least one entry for a valid configuration. Only one of + // CACertificateRefs or WellKnownCACertificates may be specified, not both. + // If an implementation does not support the WellKnownCACertificates field, or + // the supplied value is not recognized, the implementation MUST ensure the + // `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + // a Reason `Invalid`. + // + // Support: Implementation-specific + // + // +optional + // +listType=atomic + WellKnownCACertificates *WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` + + // Hostname is used for two purposes in the connection between Gateways and + // backends: + // + // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). + // 2. Hostname MUST be used for authentication and MUST match the certificate + // served by the matching backend, unless SubjectAltNames is specified. + // 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + // but MUST NOT be used for authentication. If you want to use the value + // of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. + // + // Support: Core + // + // +required + Hostname PreciseHostname `json:"hostname"` + + // SubjectAltNames contains one or more Subject Alternative Names. + // When specified the certificate served from the backend MUST + // have at least one Subject Alternate Name matching one of the specified SubjectAltNames. + // + // Support: Extended + // + // +optional + // +listType=atomic + // +kubebuilder:validation:MaxItems=5 + SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` +} + +// SubjectAltName represents Subject Alternative Name. +// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain Hostname, if Type is set to Hostname",rule="!(self.type == \"Hostname\" && (!has(self.hostname) || self.hostname == \"\"))" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain Hostname, if Type is not set to Hostname",rule="!(self.type != \"Hostname\" && has(self.hostname) && self.hostname != \"\")" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must contain URI, if Type is set to URI",rule="!(self.type == \"URI\" && (!has(self.uri) || self.uri == \"\"))" +// +kubebuilder:validation:XValidation:message="SubjectAltName element must not contain URI, if Type is not set to URI",rule="!(self.type != \"URI\" && has(self.uri) && self.uri != \"\")" +type SubjectAltName struct { + // Type determines the format of the Subject Alternative Name. Always required. + // + // Support: Core + // + // +required + Type SubjectAltNameType `json:"type"` + + // Hostname contains Subject Alternative Name specified in DNS name format. + // Required when Type is set to Hostname, ignored otherwise. + // + // Support: Core + // + // +optional + Hostname Hostname `json:"hostname,omitempty"` + + // URI contains Subject Alternative Name specified in a full URI format. + // It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + // Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + // Required when Type is set to URI, ignored otherwise. + // + // Support: Core + // + // +optional + URI AbsoluteURI `json:"uri,omitempty"` +} + +// WellKnownCACertificatesType is the type of CA certificate that will be used +// when the caCertificateRefs field is unspecified. +// +kubebuilder:validation:Enum=System +type WellKnownCACertificatesType string + +const ( + // WellKnownCACertificatesSystem indicates that well known system CA certificates should be used. + WellKnownCACertificatesSystem WellKnownCACertificatesType = "System" +) + +// SubjectAltNameType is the type of the Subject Alternative Name. +// +kubebuilder:validation:Enum=Hostname;URI +type SubjectAltNameType string + +const ( + // HostnameSubjectAltNameType specifies hostname-based SAN. + // + // Support: Core + HostnameSubjectAltNameType SubjectAltNameType = "Hostname" + + // URISubjectAltNameType specifies URI-based SAN, e.g. SPIFFE id. + // + // Support: Core + URISubjectAltNameType SubjectAltNameType = "URI" +) + +const ( + // This reason is used with the "Accepted" condition when it is + // set to false because all CACertificateRefs of the + // BackendTLSPolicy are invalid. + BackendTLSPolicyReasonNoValidCACertificate PolicyConditionReason = "NoValidCACertificate" +) + +const ( + // This condition indicates whether the controller was able to resolve all + // object references for the BackendTLSPolicy. + // + // Possible reasons for this condition to be True are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCACertificateRef" + // * "InvalidKind" + // + // Controllers may raise this condition with other reasons, but should + // prefer to use the reasons listed above to improve interoperability. + BackendTLSPolicyConditionResolvedRefs PolicyConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + BackendTLSPolicyReasonResolvedRefs PolicyConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs is invalid. + // A CACertificateRef is considered invalid when it refers to a nonexistent + // resource or when the data within that resource is malformed. + BackendTLSPolicyReasonInvalidCACertificateRef PolicyConditionReason = "InvalidCACertificateRef" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs references an unknown or unsupported + // Group and/or Kind. + BackendTLSPolicyReasonInvalidKind PolicyConditionReason = "InvalidKind" +) ``` ## How a client behaves @@ -262,12 +577,16 @@ For instance, the following will all have the gateway client add TLS if the back * A Gateway accepts and terminates TLS on an HTTPS listener * A Gateway accepts traffic on a TCP listener -There is no need for a Gateway that accepts traffic with `Mode: Passthrough` to do anything differently here, but implementations MAY choose to treat TLS passthrough as a special case. Implementations that do this SHOULD clearly document their approach if BackendTLSPolicy is treated differently for TLS passthrough. +There is no need for a Gateway that accepts traffic with `Mode: Passthrough` to do anything differently here, but +implementations MAY choose to treat TLS passthrough as a special case. Implementations that do this SHOULD clearly +document their approach if BackendTLSPolicy is treated differently for TLS passthrough. Note that there are cases where these patterns may result in multiple layers of TLS on a single connection. -There may be even cases where the gateway implementation is unaware of this; for example, processing TCPRoute traffic -- the traffic may or may not be TLS, and the gateway would be unaware. +There may be even cases where the gateway implementation is unaware of this; for example, processing TCPRoute traffic -- +the traffic may or may not be TLS, and the gateway would be unaware. This is intentional to allow full fidelity of the API, as this is commonly desired for tunneling scenarios. -When users do not want this, they should ensure that the BackendTLSPolicy is not incorrectly applied to traffic that is already TLS. +When users do not want this, they should ensure that the BackendTLSPolicy is not incorrectly applied to traffic that is +already TLS. The [Future Plans](#future-plans) include more controls over the API to make this easier to manage. ## Request Flow @@ -285,20 +604,26 @@ i.e. Service, in the cluster based on backendRefs rules of the HTTPRoute **and t ## Future plans -In order to scope this GEP, some some changes are deferred to a near-future GEP. -This GEP intends to add the ability for additional control by gateway clients to override TLS settings, following previously established patterns of [consumer and producer policies]([glossary](https://gateway-api.sigs.k8s.io/concepts/glossary/?h=gloss#producer-route)). -Additionally, more contextual control over when to apply the policies will be explored, to enable use cases like "apply TLS only from this route" ([issue](https://github.com/kubernetes-sigs/gateway-api/issues/3856)). +In order to scope this GEP, some changes are deferred to a near-future GEP. +This GEP intends to add the ability for additional control by gateway clients to override TLS settings, following previously +established patterns of [consumer and producer policies]([glossary](https://gateway-api.sigs.k8s.io/concepts/glossary/?h=gloss#producer-route)). +Additionally, more contextual control over when to apply the policies will be explored, to enable use cases like "apply +TLS only from this route" ([issue](https://github.com/kubernetes-sigs/gateway-api/issues/3856)). -While the details of these plans are out of scope for this GEP it is important to be aware of the future plans for the API to ensure the immediate-term plans are future-proofed against the proposed plans. +While the details of these plans are out of scope for this GEP it is important to be aware of the future plans for the +API to ensure the immediate-term plans are future-proofed against the proposed plans. -Implementations should plan for the existence of future fields that may be added that will control where the TLS policy applies. +Implementations should plan for the existence of future fields that may be added that will control where the TLS policy +applies. These may include, but are not limited to: * `spec.targetRefs.namespace` * `spec.targetRefs.from` * `spec.mode` -While in some cases adding new fields may be seen as a backwards compatibility risk, due to older implementations not knowing to respect the fields, these fields (or similar, should future GEPs decide on new names) are pre-approved to be added in a future release, should the GEPs to add them are approved in the first place. +While in some cases adding new fields may be seen as a backwards compatibility risk, due to older implementations not +knowing to respect the fields, these fields (or similar, should future GEPs decide on new names) are pre-approved to be +added in a future release, should the GEPs to add them are approved in the first place. ## Alternatives Most alternatives are enumerated in the section "The history of backend TLS". A couple of additional @@ -396,28 +721,37 @@ developer to provide the appropriate configuration for TLS. The implementation provided by the application and verify that it satisfies the requirements of the route-as-client, including SAN information. Sometimes the backend owner and route owner are the same entity. -A. This was most recently addressed by -adding hostname for SNI and removing allowed SANs. +A. This was most recently addressed by adding hostname for SNI and removing allowed SANs. + +Q. Rob Scott is interested in extending the TargetRef to optionally include port, since we are targeting the entirety +of a Service. See the discussion in https://github.com/kubernetes-sigs/gateway-api/pull/2113/files#r1231594914, +and follow-up issue in https://github.com/kubernetes-sigs/gateway-api/issues/2147. + +A. TargetRef has been changed to `LocalPolicyTargetReferenceWithSectionName`, wherein the `SectionName` field is +interpreted as a port name for a Service. ## Graduation Criteria This section is to record issues that were requested for discussion in the API section before this GEP graduates out of `Provisional` status. -1. Rob Scott is interested in extending the TargetRef to optionally include port, since we are targeting the entirety -of a Service. See the discussion in https://github.com/kubernetes-sigs/gateway-api/pull/2113/files#r1231594914, -and follow up issue in https://github.com/kubernetes-sigs/gateway-api/issues/2147 -2. Michael Pleshakov asked about conflicts that could arise when multiple implementations are running in a cluster. +1. Michael Pleshakov asked about conflicts that could arise when multiple implementations are running in a cluster. This is a gap in our policy attachment model that needs to be addressed. See the discussion in https://github.com/kubernetes-sigs/gateway-api/pull/2113/files#r1235750540. Graduating this GEP to implementable requires an update to the Policy GEP to define how status can be nested to support multiple implementations. This will likely look very similar to Route status. -See [comment](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092). -3. Rob Scott [wanted to note](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092) that + +>This question has been converted to a Gateway API enhancement request for Policy: +https://github.com/kubernetes-sigs/gateway-api/issues/4098. + +2. Rob Scott [wanted to note](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092) that when this graduates to the standard channel, implementations of HTTPRoute may also be required to watch the BackendTLSPolicy. If one of these policies is attached to a Service targeted by an HTTPRoute, the implementation would be required to fully implement the policy or mark the backend invalid. +>This comment may be added to the release notes for v1.4.0 of Gateway API, along with other special notes for the introduction +of the first standard Policy type. + ## References [Gateway API TLS Use Cases](https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit#heading=h.cxuq8vo8pcxm) diff --git a/geps/gep-1897/metadata.yaml b/geps/gep-1897/metadata.yaml index 716cf3d042..99d5444aa3 100644 --- a/geps/gep-1897/metadata.yaml +++ b/geps/gep-1897/metadata.yaml @@ -2,12 +2,14 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 1897 name: BackendTLSPolicy - Explicit Backend TLS Connection Configuration -status: Experimental +status: Standard authors: - candita - brianehlert - robscott - youngnick + - howardjohn + - snorwin relationships: obsoletes: - number: 1282 diff --git a/nav.yml b/nav.yml index dd16ff3274..a51849e367 100644 --- a/nav.yml +++ b/nav.yml @@ -72,7 +72,6 @@ nav: - geps/gep-1731/index.md - geps/gep-1748/index.md - geps/gep-1767/index.md - - geps/gep-1897/index.md - geps/gep-2162/index.md - geps/gep-3155/index.md - Standard: @@ -93,6 +92,7 @@ nav: - geps/gep-1742/index.md - geps/gep-1762/index.md - geps/gep-1867/index.md + - geps/gep-1897/index.md - geps/gep-1911/index.md - geps/gep-2257/index.md - geps/gep-3171/index.md From 57c52a3e5cd1abfdbbdf34a16a50a836f2369762 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Mon, 22 Sep 2025 21:28:14 -0700 Subject: [PATCH 203/224] Removing experimental annotation from SupportedFeatures in GWC Status. (#4115) * Removing experimental annotation from supportedFeatures in GWC Status. * Run make generate to update generated files --- apis/v1/gatewayclass_types.go | 1 - ...eway.networking.k8s.io_gatewayclasses.yaml | 38 +++++++++++++++++++ pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/apis/v1/gatewayclass_types.go b/apis/v1/gatewayclass_types.go index f9b779c7b3..972d350450 100644 --- a/apis/v1/gatewayclass_types.go +++ b/apis/v1/gatewayclass_types.go @@ -304,7 +304,6 @@ type GatewayClassStatus struct { // +optional // +listType=map // +listMapKey=name - // // +kubebuilder:validation:MaxItems=64 SupportedFeatures []SupportedFeature `json:"supportedFeatures,omitempty"` } diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 2372cb882f..68060bf305 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -236,6 +236,25 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + supportedFeatures: + description: |- + SupportedFeatures is the set of features the GatewayClass support. + It MUST be sorted in ascending alphabetical order by the Name key. + items: + properties: + name: + description: |- + FeatureName is used to describe distinct features that are covered by + conformance tests. + type: string + required: + - name + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map type: object required: - spec @@ -461,6 +480,25 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + supportedFeatures: + description: |- + SupportedFeatures is the set of features the GatewayClass support. + It MUST be sorted in ascending alphabetical order by the Name key. + items: + properties: + name: + description: |- + FeatureName is used to describe distinct features that are covered by + conformance tests. + type: string + required: + - name + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map type: object required: - spec diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index b11d00af1b..34b5ca191d 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -4269,7 +4269,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayClassStatus(ref common.Referenc }, }, SchemaProps: spec.SchemaProps{ - Description: "SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order by the Name key. ", + Description: "SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order by the Name key.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From 4c403cfad2dca7fb8525a3d021f647b953dca301 Mon Sep 17 00:00:00 2001 From: John Howard Date: Mon, 22 Sep 2025 22:08:15 -0700 Subject: [PATCH 204/224] conformance: fix invalid BackendTLSPolicy conformance test (#4105) * conformance: fix invalid BackendTLSPolicy conformance test * Move to a real one --- .../tests/backendtlspolicy-observed-generation-bump.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.yaml b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml index e7d4d40cae..8a46c8eaad 100644 --- a/conformance/tests/backendtlspolicy-observed-generation-bump.yaml +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml @@ -41,5 +41,5 @@ spec: - group: "" kind: ConfigMap # This ConfigMap is generated dynamically by the test suite. - name: "backend-tls-checks-certificate" + name: "tls-checks-ca-certificate" hostname: "abc.example.com" From c26512f2207d7c6fd0c12bf6f98ff10bed50b05f Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Tue, 23 Sep 2025 21:44:16 +0200 Subject: [PATCH 205/224] fix: use inferred supported features to set extendedSupportedFeatures (#4113) * fix: use inferred supported features to set extendedSupportedFeatures Signed-off-by: Norwin Schnyder * extend unit tests with assertion for extendedSupportedFeatures Signed-off-by: Norwin Schnyder * refactor NewConformanceTestSuite Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- conformance/utils/suite/suite.go | 51 ++++++++++----------------- conformance/utils/suite/suite_test.go | 46 +++++++++++++++++++----- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 8dcd009e86..5df2c722d9 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -233,6 +233,22 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, return nil, fmt.Errorf("no supported features were determined for test suite") } + extendedSupportedFeatures := make(map[ConformanceProfileName]FeaturesSet, 0) + extendedUnsupportedFeatures := make(map[ConformanceProfileName]FeaturesSet, 0) + + for _, conformanceProfileName := range options.ConformanceProfiles.UnsortedList() { + conformanceProfile, err := getConformanceProfileForName(conformanceProfileName) + if err != nil { + return nil, fmt.Errorf("failed to retrieve conformance profile: %w", err) + } + // the use of a conformance profile implicitly enables any features of + // that profile which are supported at a Core level of support. + supportedFeatures = supportedFeatures.Union(conformanceProfile.CoreFeatures) + + extendedSupportedFeatures[conformanceProfileName] = conformanceProfile.ExtendedFeatures.Intersection(supportedFeatures) + extendedUnsupportedFeatures[conformanceProfileName] = conformanceProfile.ExtendedFeatures.Difference(supportedFeatures) + } + config.SetupTimeoutConfig(&options.TimeoutConfig) roundTripper := options.RoundTripper @@ -290,8 +306,8 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, UsableNetworkAddresses: options.UsableNetworkAddresses, UnusableNetworkAddresses: options.UnusableNetworkAddresses, results: make(map[string]testResult), - extendedUnsupportedFeatures: make(map[ConformanceProfileName]sets.Set[features.FeatureName]), - extendedSupportedFeatures: make(map[ConformanceProfileName]sets.Set[features.FeatureName]), + extendedUnsupportedFeatures: extendedUnsupportedFeatures, + extendedSupportedFeatures: extendedSupportedFeatures, conformanceProfiles: options.ConformanceProfiles, implementation: options.Implementation, mode: mode, @@ -301,37 +317,6 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, Hook: options.Hook, } - for _, conformanceProfileName := range options.ConformanceProfiles.UnsortedList() { - conformanceProfile, err := getConformanceProfileForName(conformanceProfileName) - if err != nil { - return nil, fmt.Errorf("failed to retrieve conformance profile: %w", err) - } - // the use of a conformance profile implicitly enables any features of - // that profile which are supported at a Core level of support. - for _, f := range conformanceProfile.CoreFeatures.UnsortedList() { - if !options.SupportedFeatures.Has(f) { - suite.SupportedFeatures.Insert(f) - } - } - for _, f := range conformanceProfile.ExtendedFeatures.UnsortedList() { - if options.SupportedFeatures.Has(f) { - if suite.extendedSupportedFeatures[conformanceProfileName] == nil { - suite.extendedSupportedFeatures[conformanceProfileName] = FeaturesSet{} - } - suite.extendedSupportedFeatures[conformanceProfileName].Insert(f) - } else { - if suite.extendedUnsupportedFeatures[conformanceProfileName] == nil { - suite.extendedUnsupportedFeatures[conformanceProfileName] = FeaturesSet{} - } - suite.extendedUnsupportedFeatures[conformanceProfileName].Insert(f) - } - // Add Exempt Features into unsupported features list - if options.ExemptFeatures.Has(f) { - suite.extendedUnsupportedFeatures[conformanceProfileName].Insert(f) - } - } - } - // apply defaults if suite.BaseManifests == "" { suite.BaseManifests = "base/manifests.yaml" diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index 674e74808c..0b692b56c7 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -419,20 +419,21 @@ var gwcStatusFeatureNames = []string{ "HTTPRouteHostRewrite", "HTTPRouteMethodMatching", "HTTPRoutePathRewrite", - "TTPRouteQueryParamMatching", + "HTTPRouteQueryParamMatching", "HTTPRouteResponseHeaderModification", "ReferenceGrant", } func TestInferGWCSupportedFeatures(t *testing.T) { testCases := []struct { - name string - allowAllFeatures bool - supportedFeatures FeaturesSet - exemptFeatures FeaturesSet - ConformanceProfile sets.Set[ConformanceProfileName] - expectedFeatures FeaturesSet - expectedSource supportedFeaturesSource + name string + allowAllFeatures bool + supportedFeatures FeaturesSet + exemptFeatures FeaturesSet + ConformanceProfile sets.Set[ConformanceProfileName] + expectedFeatures FeaturesSet + expectedExtendedFeatures map[ConformanceProfileName]sets.Set[features.FeatureName] + expectedSource supportedFeaturesSource }{ { name: "properly infer supported features", @@ -459,10 +460,32 @@ func TestInferGWCSupportedFeatures(t *testing.T) { expectedSource: supportedFeaturesSourceManual, }, { - name: "supports conformance profile - core", + name: "supports conformance profile core with specified extended features", + ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), + supportedFeatures: sets.New[features.FeatureName]("GatewayPort8080"), + expectedFeatures: sets.New[features.FeatureName]("Gateway", "HTTPRoute", "GatewayPort8080", "ReferenceGrant"), + expectedSource: supportedFeaturesSourceManual, + expectedExtendedFeatures: map[ConformanceProfileName]sets.Set[features.FeatureName]{ + GatewayHTTPConformanceProfileName: namesToFeatureSet([]string{ + "GatewayPort8080", + }), + }, + }, + { + name: "supports conformance profile core with inferred extended features", ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), expectedFeatures: namesToFeatureSet(gwcStatusFeatureNames), expectedSource: supportedFeaturesSourceInferred, + expectedExtendedFeatures: map[ConformanceProfileName]sets.Set[features.FeatureName]{ + GatewayHTTPConformanceProfileName: namesToFeatureSet([]string{ + "GatewayPort8080", + "HTTPRouteHostRewrite", + "HTTPRouteMethodMatching", + "HTTPRoutePathRewrite", + "HTTPRouteQueryParamMatching", + "HTTPRouteResponseHeaderModification", + }), + }, }, } @@ -521,6 +544,11 @@ func TestInferGWCSupportedFeatures(t *testing.T) { if equal := cSuite.SupportedFeatures.Equal(tc.expectedFeatures); !equal { t.Errorf("SupportedFeatures mismatch: got %v, want %v", cSuite.SupportedFeatures.UnsortedList(), tc.expectedFeatures.UnsortedList()) } + + if tc.expectedExtendedFeatures == nil { + tc.expectedExtendedFeatures = make(map[ConformanceProfileName]sets.Set[features.FeatureName]) + } + assert.Equal(t, tc.expectedExtendedFeatures, cSuite.extendedSupportedFeatures, "expectedExtendedFeatures mismatch") }) } } From ab6b5a251c59844b199b57bb2f2dfac50e82c706 Mon Sep 17 00:00:00 2001 From: John Howard Date: Wed, 24 Sep 2025 11:02:16 -0700 Subject: [PATCH 206/224] conformance: make backend TLS tests IPv6-safe (#4120) otherwise we send requests to `http://[fc00/backendtlspolicy-nonexistent-ca-certificate-ref"` which is very wrong --- conformance/utils/kubernetes/helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index d37d16affa..d32899e20e 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -344,7 +344,7 @@ func GatewayAndRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig // If the Gateway has multiple listeners, get a portless gwAddr. // Otherwise, you get the first listener's port, which might not be the one you want. if !usePort { - gwAddr, _, _ = strings.Cut(gwAddr, ":") + gwAddr, _, _ = net.SplitHostPort(gwAddr) } ns := gatewayv1.Namespace(gw.Namespace) From 8f9ee2c6bfc0483005d4565a2e27e89235f13016 Mon Sep 17 00:00:00 2001 From: zirain Date: Thu, 25 Sep 2025 09:24:15 +0800 Subject: [PATCH 207/224] docs: update implements page (#3996) * fix: implements page show wrong result if there's more than one mode/version/project * remove print * add core result * update * semver compare * update * remove prefix * display on 1.3.0 --- Makefile | 5 ++++- hack/mkdocs-generate-conformance.py | 24 ++++++++++++++++++------ hack/mkdocs/image/requirements.txt | 3 ++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 3b8c45e0b9..f5032e1931 100644 --- a/Makefile +++ b/Makefile @@ -166,10 +166,13 @@ release-staging: image.multiarch.setup # Docs +DOCS_BUILD_CONTAINER_NAME ?= gateway-api-mkdocs + .PHONY: build-docs build-docs: docker build --pull -t gaie/mkdocs hack/mkdocs/image - docker run --rm -v ${PWD}:/docs gaie/mkdocs build + docker rm -f $(DOCS_BUILD_CONTAINER_NAME) || true + docker run --name $(DOCS_BUILD_CONTAINER_NAME) --rm -v ${PWD}:/docs gaie/mkdocs build .PHONY: build-docs-netlify build-docs-netlify: diff --git a/hack/mkdocs-generate-conformance.py b/hack/mkdocs-generate-conformance.py index bec9ecdef1..55c8251e06 100644 --- a/hack/mkdocs-generate-conformance.py +++ b/hack/mkdocs-generate-conformance.py @@ -22,6 +22,7 @@ import glob import os import re +import semver log = logging.getLogger(f'mkdocs.plugins.{__name__}') @@ -149,7 +150,7 @@ def generate_conformance_tables(reports, currVersion, mkdocsConfig): return new_file -def generate_profiles_report(reports, route,version): +def generate_profiles_report(reports, route, version): http_reports = reports.loc[reports["name"] == route] http_reports.set_index('organization') @@ -159,21 +160,32 @@ def generate_profiles_report(reports, route,version): columns=http_reports['organization']) http_table = http_reports[['organization', 'project', - 'version','mode', 'extended.supportedFeatures']].T + 'version', 'mode', 'core.result', 'extended.supportedFeatures']].T http_table.columns = http_table.iloc[0] http_table = http_table[1:].T + # change core.result value for row in http_table.itertuples(): - if type(row._4) is list: - for feat in row._4: + if row._4 == "success": + http_table.loc[(row.Index, 'core.result')] = ':white_check_mark:' + else: + http_table.loc[(row.Index, 'core.result')] = ':x:' + + if type(row._5) is list: + for feat in row._5: # Process feature name before using it as a column processed_feat = process_feature_name(feat) - http_table.loc[row.Index, processed_feat] = ':white_check_mark:' + http_table.loc[(http_table.index == row.Index) & \ + (http_table['project'] == row.project) & \ + (http_table['version'] == row.version) & \ + (http_table['mode'] == row.mode), processed_feat] = ':white_check_mark:' http_table = http_table.fillna(':x:') http_table = http_table.drop(['extended.supportedFeatures'], axis=1) http_table = http_table.rename( - columns={"project": "Project", "version": "Version", "mode":"Mode"}) + columns={"project": "Project", "version": "Version", "mode": "Mode", "core.result": "Core"}) + if semver.compare(version.removeprefix('v'), '1.3.0') < 0: + http_table = http_table.drop(columns=["Core"]) if version == 'v1.0.0': http_table = http_table.drop(columns=["Mode"]) return http_table diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 940b186b39..ad5df248a2 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -20,4 +20,5 @@ pymdown-extensions==10.16.1 PyYAML==6.0.2 six==1.17.0 tabulate==0.9.0 -tornado==6.5.2 \ No newline at end of file +tornado==6.5.2 +semver==3.0.4 From e7b1bdbf3528af9392aaceee3461c4b9da408075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:08:17 -0700 Subject: [PATCH 208/224] build(deps): bump mkdocs-mermaid2-plugin in /hack/mkdocs/image (#4053) Bumps [mkdocs-mermaid2-plugin](https://github.com/fralau/mkdocs-mermaid2-plugin) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/fralau/mkdocs-mermaid2-plugin/releases) - [Changelog](https://github.com/fralau/mkdocs-mermaid2-plugin/blob/master/CHANGELOG.md) - [Commits](https://github.com/fralau/mkdocs-mermaid2-plugin/compare/v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: mkdocs-mermaid2-plugin dependency-version: 1.2.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index ad5df248a2..71dd3f328c 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -12,7 +12,7 @@ mkdocs-awesome-pages-plugin==2.10.1 mkdocs-macros-plugin==1.3.7 mkdocs-material==9.6.18 mkdocs-redirects==1.2.2 -mkdocs-mermaid2-plugin==1.2.1 +mkdocs-mermaid2-plugin==1.2.2 pandas>=2.0.3 pep562==1.1 Pygments==2.19.2 From 83e4d751093dc713961d8320cd04239b05726e77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:08:24 -0700 Subject: [PATCH 209/224] build(deps): update markdown requirement in /hack/mkdocs/image (#4070) Updates the requirements on [markdown](https://github.com/Python-Markdown/markdown) to permit the latest version. - [Release notes](https://github.com/Python-Markdown/markdown/releases) - [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md) - [Commits](https://github.com/Python-Markdown/markdown/compare/3.8...3.9.0) --- updated-dependencies: - dependency-name: markdown dependency-version: '3.9' dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 71dd3f328c..0221bf84bc 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -5,7 +5,7 @@ jsmin==3.0.1 livereload==2.7.1 # mkdocs 2.4.1 requires Markdown < 3.4.0 # https://github.com/kubernetes-sigs/gateway-api/pull/1671#issuecomment-1400586465 -markdown~=3.8 +markdown~=3.9 MarkupSafe==3.0.2 mkdocs==1.6.1 mkdocs-awesome-pages-plugin==2.10.1 From ac959eb39267f5a803a7535adab22a90ae57787c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:08:31 -0700 Subject: [PATCH 210/224] build(deps): bump google.golang.org/grpc from 1.75.0 to 1.75.1 (#4107) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.0 to 1.75.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.75.0...v1.75.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.75.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8842e5f935..18820c5bb2 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/stretchr/testify v1.11.0 golang.org/x/net v0.43.0 golang.org/x/sync v0.16.0 - google.golang.org/grpc v1.75.0 + google.golang.org/grpc v1.75.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.8 k8s.io/api v0.34.1 diff --git a/go.sum b/go.sum index 496ee74bd4..8a18f878c1 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= -google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= From 059287c1e9164fdb4bda48b5a3735a15c5653bac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:08:37 -0700 Subject: [PATCH 211/224] build(deps): bump mkdocs-material in /hack/mkdocs/image (#4110) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.18 to 9.6.20. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.18...9.6.20) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.20 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 0221bf84bc..92dade9d07 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -10,7 +10,7 @@ MarkupSafe==3.0.2 mkdocs==1.6.1 mkdocs-awesome-pages-plugin==2.10.1 mkdocs-macros-plugin==1.3.7 -mkdocs-material==9.6.18 +mkdocs-material==9.6.20 mkdocs-redirects==1.2.2 mkdocs-mermaid2-plugin==1.2.2 pandas>=2.0.3 From 3e9f7744d25684f4bb5325d9c24854ec587e61f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:24:16 -0700 Subject: [PATCH 212/224] build(deps): bump sigs.k8s.io/controller-tools from 0.18.0 to 0.19.0 (#4052) Bumps [sigs.k8s.io/controller-tools](https://github.com/kubernetes-sigs/controller-tools) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/kubernetes-sigs/controller-tools/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-tools/blob/main/envtest-releases.yaml) - [Commits](https://github.com/kubernetes-sigs/controller-tools/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-tools dependency-version: 0.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 18820c5bb2..8c30afdfa3 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d sigs.k8s.io/controller-runtime v0.22.1 - sigs.k8s.io/controller-tools v0.18.0 + sigs.k8s.io/controller-tools v0.19.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 sigs.k8s.io/yaml v1.6.0 ) diff --git a/go.sum b/go.sum index 8a18f878c1..e8363ca99d 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,21 @@ +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -23,6 +31,8 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= @@ -49,6 +59,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -60,6 +72,8 @@ 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/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= @@ -107,8 +121,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= -github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk= +github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -128,6 +142,8 @@ github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wx github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -145,8 +161,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= @@ -155,6 +177,8 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -170,6 +194,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= @@ -220,6 +246,8 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= @@ -249,10 +277,14 @@ k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJb k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA= +k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0= k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= +k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= +k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= @@ -261,10 +293,12 @@ k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaC k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-runtime v0.22.1 h1:Ah1T7I+0A7ize291nJZdS1CabF/lB4E++WizgV24Eqg= sigs.k8s.io/controller-runtime v0.22.1/go.mod h1:FwiwRjkRPbiN+zp2QRp7wlTCzbUXxZ/D4OzuQUDwBHY= -sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE= -sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U= +sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk= +sigs.k8s.io/controller-tools v0.19.0/go.mod h1:y5HY/iNDFkmFla2CfQoVb2AQXMsBk4ad84iR1PLANB0= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= From c7508f70ed17f2b1bcd3f2a551ccc40d9a28dfb9 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Fri, 26 Sep 2025 14:22:16 +1000 Subject: [PATCH 213/224] Update deadline extension policy (#4111) This commit updates the deadline extension request policy with some timing details. Signed-off-by: Nick Young --- RELEASE_MANAGEMENT.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/RELEASE_MANAGEMENT.md b/RELEASE_MANAGEMENT.md index b4dcbe8e5c..9734e23e24 100644 --- a/RELEASE_MANAGEMENT.md +++ b/RELEASE_MANAGEMENT.md @@ -125,10 +125,18 @@ this are based on the Kubernetes process: * Extensions can be granted on a per-GEP basis * The owners of the GEP have to ask and provide a timeline (measured in days) as to when they believe the GEP will be ready for merge. -* The request and approval for a GEP extension needs to be in public. +* The request and approval for a GEP extension must be on the original GEP issue. +* An extension can only be granted for a time period up to the distance from + the deadline when the extension is requested. So, an extension of a week + must be asked for at least a week out from a deadline, while an extension of + day must be asked for at least a day out from the deadline. Extension requests + not meeting this timing criteria will be denied. * Extensions can only be granted with a majority agreement by maintainers - / release-managers + / release-managers. -For our purposes we use GitHub discussions as the public place for -requesting/approving extensions. Contributors should use an existing -discussion for the release when feasible, otherwise create a discussion. +For our purposes we use GitHub issues, specifically the related GEP issue, +as the public place for requesting/approving extensions. + +This extension policy also affects reviews. +If feedback is submitted sufficiently late that it is impossible to address within these guidelines, +the feedback (not necessarily the GEP) may be deferred to a future release. From bc79ea670daf4fb00693ccc3f0f10945cb7f0d7d Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Fri, 26 Sep 2025 14:28:17 -0400 Subject: [PATCH 214/224] v1.4.0-rc.2 (#4130) * chore: bump to v1.4.0-rc.2 Signed-off-by: Shane Utt * docs: add the v1.4.0-rc.2 CHANGELOG entry Signed-off-by: Shane Utt --------- Signed-off-by: Shane Utt --- CHANGELOG/1.4-CHANGELOG.md | 34 +++++++++++++++++++ ....networking.k8s.io_backendtlspolicies.yaml | 2 +- ...eway.networking.k8s.io_gatewayclasses.yaml | 2 +- .../gateway.networking.k8s.io_gateways.yaml | 2 +- .../gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../gateway.networking.k8s.io_httproutes.yaml | 2 +- ...way.networking.k8s.io_referencegrants.yaml | 2 +- .../gateway.networking.k8s.io_tcproutes.yaml | 2 +- .../gateway.networking.k8s.io_tlsroutes.yaml | 2 +- .../gateway.networking.k8s.io_udproutes.yaml | 2 +- ...king.x-k8s.io_xbackendtrafficpolicies.yaml | 2 +- ...way.networking.x-k8s.io_xlistenersets.yaml | 2 +- .../gateway.networking.x-k8s.io_xmeshes.yaml | 2 +- ....networking.k8s.io_backendtlspolicies.yaml | 2 +- ...eway.networking.k8s.io_gatewayclasses.yaml | 2 +- .../gateway.networking.k8s.io_gateways.yaml | 2 +- .../gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../gateway.networking.k8s.io_httproutes.yaml | 2 +- ...way.networking.k8s.io_referencegrants.yaml | 2 +- pkg/consts/consts.go | 2 +- 20 files changed, 53 insertions(+), 19 deletions(-) diff --git a/CHANGELOG/1.4-CHANGELOG.md b/CHANGELOG/1.4-CHANGELOG.md index 65c00e5aa3..ab86248b7b 100644 --- a/CHANGELOG/1.4-CHANGELOG.md +++ b/CHANGELOG/1.4-CHANGELOG.md @@ -2,8 +2,40 @@ ## Table of Contents +- [v1.4.0-rc.2](#v140-rc2) - [v1.4.0-rc.1](#v140-rc1) +## Changes Since v1.4.0-rc.1 + +* Allow preprepared CoreDNS image to be used by @aaronjwood in https://github.com/kubernetes-sigs/gateway-api/pull/3906 +* Update index.md field after moving BackendTLS struct by @kl52752 in https://github.com/kubernetes-sigs/gateway-api/pull/4041 +* Issue 3940: Move BackendTLSPolicy to standard by @candita in https://github.com/kubernetes-sigs/gateway-api/pull/4074 +* Add allowOrigins configuration to CORSAllowCredentialsBehavior and perform cleanup by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4094 +* fix: fix validation and wording when making gateway spec addresses value optional by @bjee19 in https://github.com/kubernetes-sigs/gateway-api/pull/4084 +* Fix broken link in TLS Configuration page by @4n86rakam1 in https://github.com/kubernetes-sigs/gateway-api/pull/4091 +* Automate GEP TOC generation and validate by @rikatz in https://github.com/kubernetes-sigs/gateway-api/pull/4075 +* conformance: fix per-test cleanup by @howardjohn in https://github.com/kubernetes-sigs/gateway-api/pull/4104 +* Added flag for running mesh conformance suite and automatically inferring supported features from Mesh.Status by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/4097 +* Fixed couple of typos in conformance tests. by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/4106 +* Issue 3940: Update BackendTLSPolicy GEP to move to standard by @candita in https://github.com/kubernetes-sigs/gateway-api/pull/4099 +* Removing experimental annotation from SupportedFeatures in GWC Status. by @bexxmodd in https://github.com/kubernetes-sigs/gateway-api/pull/4115 +* conformance: fix invalid BackendTLSPolicy conformance test by @howardjohn in https://github.com/kubernetes-sigs/gateway-api/pull/4105 +* fix: use inferred supported features to set extendedSupportedFeatures by @snorwin in https://github.com/kubernetes-sigs/gateway-api/pull/4113 +* conformance: make backend TLS tests IPv6-safe by @howardjohn in https://github.com/kubernetes-sigs/gateway-api/pull/4120 +* concepts/tooling.md: Add Headlamp tool by @illume in https://github.com/kubernetes-sigs/gateway-api/pull/4083 +* docs: update implements page by @zirain in https://github.com/kubernetes-sigs/gateway-api/pull/3996 +* Fix broken link in TLS Configuration page by @4n86rakam1 in https://github.com/kubernetes-sigs/gateway-api/pull/4091 + +## New Contributors + +* @aaronjwood made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3906 +* @illume made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4083 +* @4n86rakam1 made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4091 + +## Full Changelog + +**Full Changelog**: https://github.com/kubernetes-sigs/gateway-api/compare/v1.4.0-rc.1...v1.4.0-rc2 + # v1.4.0-rc.1 ## Major Changes since v1.3.0 @@ -220,4 +252,6 @@ and `HTTPRouteMatch`. * @aaronjwood made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/3906 * @illume made their first contribution in https://github.com/kubernetes-sigs/gateway-api/pull/4083 +## Full Changelog + **Full Changelog**: https://github.com/kubernetes-sigs/gateway-api/compare/v1.3.0...v1.4.0-rc.1 diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index acb50051fe..f87397d127 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index ace25e4bf1..e5dc5ae951 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 1fbd20a972..4836d0fd19 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index b40275f361..f3069ef8f4 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 85a5fc4779..252da3ba62 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index b65b6594ba..b0195c3c61 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: referencegrants.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index ab17dc3e85..259e414b89 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: tcproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 3196e57eb7..cce85ef3c3 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: tlsroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 86a2b81ac8..354f0c9976 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: udproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 9a80b8ad51..018d40c4e5 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 30af99dee9..5a3389d467 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: xlistenersets.gateway.networking.x-k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml index 0c7a87af72..de048d8e0c 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: experimental name: xmeshes.gateway.networking.x-k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml index 5faedd15d1..b7a7307f60 100644 --- a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 68060bf305..4da9f54fb3 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 9ab97f5e45..33c250e9f9 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index dd0a9817eb..c39cca9d14 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index b844524812..20c385221c 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index 768b50b34b..f803a2f957 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.1 + gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 gateway.networking.k8s.io/channel: standard name: referencegrants.gateway.networking.k8s.io spec: diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 8b558d385c..13c7ff5d3c 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -27,7 +27,7 @@ const ( // BundleVersion is the value used for the "gateway.networking.k8s.io/bundle-version" annotation. // These value must be updated during the release process. - BundleVersion = "v1.4.0-rc.1" + BundleVersion = "v1.4.0-rc.2" // ApprovalLink is the value used for the "api-approved.kubernetes.io" annotation. // These value must be updated during the release process. From 278ff95f5c580242591d81553007ee676a95d70a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:44:16 -0700 Subject: [PATCH 215/224] build(deps): bump golang.org/x/net from 0.43.0 to 0.44.0 (#4108) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.43.0 to 0.44.0. - [Commits](https://github.com/golang/net/compare/v0.43.0...v0.44.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-version: 0.44.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 8c30afdfa3..71bd89a478 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ require ( github.com/elastic/crd-ref-docs v0.2.0 github.com/miekg/dns v1.1.68 github.com/stretchr/testify v1.11.0 - golang.org/x/net v0.43.0 - golang.org/x/sync v0.16.0 + golang.org/x/net v0.44.0 + golang.org/x/sync v0.17.0 google.golang.org/grpc v1.75.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.8 @@ -74,12 +74,12 @@ require ( go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.41.0 // indirect + golang.org/x/crypto v0.42.0 // indirect golang.org/x/mod v0.27.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.36.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect diff --git a/go.sum b/go.sum index e8363ca99d..2a3d95a603 100644 --- a/go.sum +++ b/go.sum @@ -192,8 +192,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -204,28 +204,28 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 1601ee5b6a2b216a4524823071b156aed933b31c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:00:17 -0700 Subject: [PATCH 216/224] build(deps): bump github.com/stretchr/testify from 1.11.0 to 1.11.1 (#4050) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.11.0...v1.11.1) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-version: 1.11.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 71bd89a478..49d60fca96 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.0 require ( github.com/elastic/crd-ref-docs v0.2.0 github.com/miekg/dns v1.1.68 - github.com/stretchr/testify v1.11.0 + github.com/stretchr/testify v1.11.1 golang.org/x/net v0.44.0 golang.org/x/sync v0.17.0 google.golang.org/grpc v1.75.1 diff --git a/go.sum b/go.sum index 2a3d95a603..61a0cb1b5e 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= -github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From ea6c746a919b8d5901d2c4f1950832b78fce3b3f Mon Sep 17 00:00:00 2001 From: Keith Walsh Date: Fri, 26 Sep 2025 15:16:16 -0400 Subject: [PATCH 217/224] Fix "Red Hat" spelling in implementation docs. (#3989) --- site-src/implementations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index aab49663ff..4fc28fec57 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -199,7 +199,7 @@ In this section you will find specific links to blog posts, documentation and ot ### Airlock Microgateway [![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Airlock%20Microgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/airlock-microgateway) -[Airlock Microgateway][airlock-microgateway] is a Kubernetes native WAAP (Web Application and API Protection, formerly known as WAF) solution optimized for Kubernetes environments and certified for RedHat OpenShift. +[Airlock Microgateway][airlock-microgateway] is a Kubernetes native WAAP (Web Application and API Protection, formerly known as WAF) solution optimized for Kubernetes environments and certified for Red Hat OpenShift. Modern application security is embedded in the development workflow and follows DevSecOps paradigms. Airlock Microgateway protects your applications and microservices with the tried-and-tested Airlock security features against attacks, while also providing a high degree of scalability. From f0859eabd95e5fe46cf24193b68c0ea595003a2b Mon Sep 17 00:00:00 2001 From: Siyi Wang <32469039+syw14@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:36:16 -0700 Subject: [PATCH 218/224] Upload gke-gateway conformance report for v1.3.0 (#4122) * Upload gke-gateway conformanc-report * Modify gke version in the report --- .../reports/v1.3.0/gke-gateway/README.md | 43 ++++++++++++++ .../standard-1.33.4-gxlb-report.yaml | 57 +++++++++++++++++++ site-src/implementations.md | 4 +- 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 conformance/reports/v1.3.0/gke-gateway/README.md create mode 100644 conformance/reports/v1.3.0/gke-gateway/standard-1.33.4-gxlb-report.yaml diff --git a/conformance/reports/v1.3.0/gke-gateway/README.md b/conformance/reports/v1.3.0/gke-gateway/README.md new file mode 100644 index 0000000000..60c30d79a0 --- /dev/null +++ b/conformance/reports/v1.3.0/gke-gateway/README.md @@ -0,0 +1,43 @@ +# GKE (Google Kubernetes Engine) Gateway + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|standard|1.33.4-gke.1134000|gke-l7-global-external-managed|[v1.33.4 gxlb report](./standard-1.33.4-gxlb-report.yaml)| + +## Reproduce + +GKE Gateway conformance report can be reproduced by the following steps. + +1. create a GKE cluster with Gateway API enabled (the minimum cluster version that supports v1.3.0 CRD is `1.33.2-gke.1335000`) + +``` +gcloud container clusters create "${cluster_name}" --gateway-api=standard --location="${location}" +``` + +2. create a proxy-only subnet if using a regional Gateway following [guide](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways#configure_a_proxy-only_subnet) + +3. run the following command from within the [GKE Gateway repo](https://github.com/GoogleCloudPlatform/gke-gateway-api) + +``` +go test ./conformance -run TestConformance -v -timeout=3h -args \ + --gateway-class=gke-l7-global-external-managed \ + --conformance-profiles=GATEWAY-HTTP \ + --organization=GKE \ + --project=gke-gateway \ + --url=https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api \ + --version=1.33.4-gke.1134000 \ + --contact=gke-gateway-dev@google.com \ + --report-output="/path/to/report" +``` + +or run a single conformance test case + +``` +go test ./conformance -run TestConformance -v -args \ + --gateway-class=gke-l7-global-external-managed \ + --run-test=HTTPRouteRequestMirror +``` + +Note: the repro result can be flaky in some cases because the conformance framework doesn't isolate test cases enough. diff --git a/conformance/reports/v1.3.0/gke-gateway/standard-1.33.4-gxlb-report.yaml b/conformance/reports/v1.3.0/gke-gateway/standard-1.33.4-gxlb-report.yaml new file mode 100644 index 0000000000..007cc526a3 --- /dev/null +++ b/conformance/reports/v1.3.0/gke-gateway/standard-1.33.4-gxlb-report.yaml @@ -0,0 +1,57 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-09-14T21:45:48-07:00" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - gke-gateway-dev@google.com + organization: GKE + project: gke-gateway + url: https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api + version: 1.33.4-gke.1134000 +kind: ConformanceReport +mode: default +profiles: +- core: + result: partial + skippedTests: + - HTTPRouteHostnameIntersection + statistics: + Failed: 0 + Passed: 32 + Skipped: 1 + extended: + result: success + statistics: + Failed: 0 + Passed: 7 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRoutePathRedirect + - HTTPRouteRequestMirror + - HTTPRouteRequestPercentageMirror + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests partially succeeded with 1 test skips. Extended tests succeeded. +succeededProvisionalTests: +- HTTPRouteRequestPercentageMirror diff --git a/site-src/implementations.md b/site-src/implementations.md index 4fc28fec57..aa2a7ce7ce 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -386,7 +386,7 @@ Google Cloud Service Mesh supports [Envoy-based sidecar mesh][envoy-sidecar-mesh ### Google Kubernetes Engine -[![Conformance](https://img.shields.io/badge/Gateway_API_Partial_Conformance_v1.1.0-Google_Kubernetes_Engine-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/gke-gateway) +[![Conformance](https://img.shields.io/badge/Gateway_API_Partial_Conformance_v1.3.0-Google_Kubernetes_Engine-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/gke-gateway) [Google Kubernetes Engine (GKE)][gke] is a managed Kubernetes platform offered by Google Cloud. GKE's implementation of the Gateway API is through the [GKE @@ -399,7 +399,7 @@ advanced routing, multi-cluster load balancing and more. See the docs to deploy Gateways][gke-multi-cluster-gateway]. The GKE Gateway controller passes all the core Gateway API conformance tests in the -v1.1.0 release for the GATEWAY_HTTP conformance profile except `HTTPRouteHostnameIntersection`. +v1.3.0 release for the GATEWAY_HTTP conformance profile except `HTTPRouteHostnameIntersection`. [gke]:https://cloud.google.com/kubernetes-engine [gke-gateway]:https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api From 530c1ee46e0d851d369810e4500f0339c40d8aa1 Mon Sep 17 00:00:00 2001 From: Carmal Shaktan <54744891+carmal891@users.noreply.github.com> Date: Mon, 29 Sep 2025 18:44:19 +0530 Subject: [PATCH 219/224] Adds a clean-generated target to remove stale generated files (#4082) * Adds a clean-generated target to remove stale generated files * Update the docs for make generate --- Makefile | 8 +++++++- site-src/contributing/devguide.md | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f5032e1931..9c6f7c6821 100644 --- a/Makefile +++ b/Makefile @@ -60,9 +60,15 @@ CEL_TEST_CRD_CHANNEL ?= standard all: generate vet fmt verify test +.PHONY: clean-generated +clean-generated: + rm -rf pkg/client/clientset + rm -rf pkg/client/listers + rm -rf pkg/client/informers + # Run generators for protos, Deepcopy funcs, CRDs, and docs. .PHONY: generate -generate: update-codegen +generate: clean-generated update-codegen .PHONY: update-codegen update-codegen: diff --git a/site-src/contributing/devguide.md b/site-src/contributing/devguide.md index ee5e5bd4c2..ae3dfae2e6 100644 --- a/site-src/contributing/devguide.md +++ b/site-src/contributing/devguide.md @@ -61,7 +61,7 @@ outside $GOPATH as well. ### Build the Code -The project uses `make` to drive the build. `make` will run code generators, and +The project uses `make` to drive the build. `make` will clean up previously generated code, run code generators, and run static analysis against the code and generate Kubernetes CRDs. You can kick off an overall build from the top-level makefile: From dd24e83fa0ca215b4dccf980912bdd37e2b31ee5 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Wed, 1 Oct 2025 12:02:15 +1000 Subject: [PATCH 220/224] Update GEP process docs with more details (#4109) This commit updates the GEP process documentation with some more information on what is required to move between GEP states. Also updates the GEP template to match the documented requirements for shifting levels. Signed-off-by: Nick Young --- geps/gep-696/index.md | 65 +++++++++++++++++++++-- geps/overview.md | 89 +++++++++++++++++++++++--------- site-src/implementations/v1.2.md | 36 ++++++------- site-src/implementations/v1.3.md | 28 +++++----- 4 files changed, 161 insertions(+), 57 deletions(-) diff --git a/geps/gep-696/index.md b/geps/gep-696/index.md index da58798f7f..83bcfe94ec 100644 --- a/geps/gep-696/index.md +++ b/geps/gep-696/index.md @@ -7,10 +7,14 @@ ## TLDR +[required_in]: # (Provisional status and above) + (1-2 sentence summary of the proposal) ## Goals +[required_in]: # (Provisional status and above) + (Primary goals of this proposal.) ## Longer Term Goals (optional) @@ -19,10 +23,14 @@ ## Non-Goals +[required_in]: # (Provisional status and above) + (What is out of scope for this proposal.) ## Introduction/Overview +[required_in]: # (Provisional status and above) + (Can link to external doc -- but we should bias towards copying the content into the GEP as online documents are easier to lose -- e.g. owner messes up the permissions, accidental deletion) @@ -31,10 +39,15 @@ Write here "What" we want to do. What is the proposal aiming to do? ## Purpose (Why and Who) +[required_in]: # (Provisional status and above) + Write here "Why" we want to do it. What problems are being solved? What personas are the target of this proposal, and why will this proposal will make their lives better? ## API + +[required_in]: # (Implementable status and above) + (... details, can point to PR with changes) ### Gateway for Ingress (North/South) @@ -56,10 +69,14 @@ Example of a flow description: ## Conformance Details +[required_in]: # (Provisional status and above) + (from https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-2162/index.md#standardize-features-and-conformance-tests-names) #### Feature Names +[required_in]: # (Experimental status and above) + (Does it require separate feature(s) for mesh? Please add them if necessary) Every feature should: @@ -71,7 +88,36 @@ Every feature should: GEPs cannot move to Experimental without a Feature Name. -### Conformance tests +### Conformance test scenarios + +This section records the scenarios that Conformance tests will check. + +It _does not_ need to include code, although code _may_ be used to illustrate the scenarios +if required. Tables are also acceptable for describing complex interactions. + +Scenarios _should_ be able to be summarized without code. + +These scenario summaries can then be used to determine the names of the tests and their files. + +#### Example test scenario 1, please remove: HTTPRoute Simple, Same Namespace + +A HTTPRoute with a basic routing configuration, in the same namespace as its +parent Gateway, should route traffic to the specified backend. + +#### Example test scenario 2, please remove: HTTPRoute Path Rewrite + +A HTTPRoute with a Path Rewrite filter should rewrite the path according to +the specification, routing traffic to the backend. + +* A Match of `/prefix/one` with a `ReplacePrefixMatch` of `/one` should route requests + to `/prefix/one/two` to `/one/two` instead. +* A Match of `/strip-prefix` with a `ReplacePrefixMatch` of `/` should route requests to + `/strip-prefix/three` to `/three` instead. +* A Match of `/full/one` with a `ReplaceFullPath` of `/one` should route requests to + `/full/one/two` to `/one` instead. +* ... and so on. + +#### Conformance test file names Conformance tests file names should try to follow the `pascal-case-name.go` format. For example for `HTTPRoutePortRedirect` - the test file would be `httproute-port-redirect.go`. @@ -82,10 +128,21 @@ In any case, the conformance tests file names should be meaningful and easy to u (Make sure to also include conformance tests that cover mesh) -When describing the new feature, write down some conformance test scenarios the feature should manage, -to guarantee that future implementors understand what "Conformance" means and what will be tested. -At least _some_ tests should be added at each phase, starting with Provisional. +## `Standard` Graduation Criteria + +( This section outlines the criteria required for graduation to Standard. It MUST +contain at least the items in the template, but more MAY be added if necessary. ) + +( Required for Experimental status and above) + +* At least one Feature Name must be listed. +* The `Conformance Details` must be filled out, with conformance test scenarios listed. +* Conformance tests must be implemented that test all the listed test scenarios. +* At least three (3) implementations must have submitted conformance reports that pass + those conformance tests. +* At least six months must have passed from when the GEP moved to `Experimental`. + ## Alternatives diff --git a/geps/overview.md b/geps/overview.md index d270e820a7..79037f039f 100644 --- a/geps/overview.md +++ b/geps/overview.md @@ -21,11 +21,11 @@ This diagram shows the state diagram of the GEP process at a high level, but the flowchart TD D([Discuss with
the community]) --> C C([Issue Created]) -------> Memorandum - C([Issue Created]) --> Provisional - Provisional -->|If practical
work needed| Prototyping - Provisional -->|GEP Doc PR
done| Implementable - Prototyping -->|GEP Doc PR
done| Implementable - Implementable -->|Gateway API
work completed| Experimental + C([Issue Created]) -->|GEP PR with Who/What/Why merged| Provisional + Provisional -->|GEP Doc PR with _proposed_ API details merged| Prototyping + Provisional -->|GEP Doc PR with agreed API details merged| Implementable + Prototyping -->|GEP Doc PR with agreed API details merged| Implementable + Implementable -->|API Changes implemented in Go types and YAML| Experimental Experimental -->|Supported in
multiple implementations
+ Conformance tests| Standard Standard -->|Entire change is GA or implemented| Completed @@ -111,22 +111,38 @@ Please default to GitHub discussions: they work a lot like GitHub issues which makes them easy to search. ### 2. Create an Issue + [Create a GEP issue](https://github.com/kubernetes-sigs/gateway-api/issues/new?assignees=&labels=kind%2Ffeature&template=enhancement.md) in the repo describing your change. At this point, you should copy the outcome of any other conversations or documents into this document. -### 3. Agree on the Goals +### 3. `Provisional` - Agree on the Goals + Although it can be tempting to start writing out all the details of your proposal, it's important to first ensure we all agree on the goals. For API GEPs, the first version of your GEP should aim for a "Provisional" status and leave out any implementation details, focusing primarily on -"Goals" and "Non-Goals". +"Goals" and "Non-Goals", and documenting "Who" the GEP is for, "What" the +GEP will do, and "Why" it is needed. For this reason, the `Provisional` +state is also sometimes called the "Who/What/Why" stage. For Memorandum GEPs, the first version of your GEP will be the only one, as Memorandums have only a single stage - `Accepted`. -### 3. Document Implementation Details +The `Provisional` state is different to other states (aside from `Memorandum`), +in that iteration on it can occur outside of the usual Gateway API release process. +To put this another way, until we have agreement on the "Who/What/Why", +then the PR does not fall into the regular release process. + +GEPs entering the `Provisional` phase need the following to have occurred: + +* A GEP PR using the template in GEP-696 merged into the `geps/` directory, + describing the "Who", "What", and "Why" of the proposal, along with Goals + and Non-Goals. + +### 3. `Implementable` - Document Implementation Details + Now that everyone agrees on the goals, it is time to start writing out your proposed implementation details. These implementation details should be very thorough, including the proposed API spec, and covering any relevant edge cases. @@ -138,7 +154,29 @@ alternatives. Be sure to document all of these in the GEP, and why we decided against them. At this stage, the GEP should be targeting the "Implementable" stage. -### 4. Implement the GEP as "Experimental" +For a GEP to enter the `Implementable` phase, there are some additional +requirements: + +* One or more Gateway API maintainers must agree that the GEP is in-scope + for the project. +* At least two (2) implementations must agree that they are interested in + implementing the feature within six (6) months of it reaching `Experimental`. + This is to ensure that there's community interest outside of the GEP owner. +* At least one "shepherd" who will help with navigating the GEP through the + rest of the process. This shepherd can be any community member, but someone + with experience of the GEP process will be the most helpful. The shepherd + for that GEP will be responsible for initial review, as well as to be + available to answer questions for the GEP owner about the process. Being + a GEP Shepherd is a reasonably significant time commitment, with the + time required scaling up sharply as a GEP becomes more complex and/or + controversial. This shepherd should be recorded on the GEP issue. +* A GEP PR that updates the existing `Provisional` documentation with details + that will be required to actually make the changes. This must include any + API changes, as well as an initial set of test scenarios for implementations + and conformance tests to target. Note that, at this stage, _only_ changes to + GEP document must be included. + +### 4. `Experimental` - Make the API changes With the GEP marked as "Implementable", it is time to actually make those proposed changes in our API. In some cases, these changes will be documentation @@ -150,10 +188,13 @@ use the `experimental` Golang build tag to denote experimental functionality. Some other requirements must be met before marking a GEP `Experimental`: -- the graduation criteria to reach `Standard` MUST be filled out -- the GEP must have at least one Feature Name for features described inside that +* Any API changes must be made to the Go types. +* The graduation criteria to reach `Standard` MUST be filled out. Note that this + must include sufficient conformance testing at a minimum, and should include + any other relevant criteria for that GEP. +* The GEP must have at least one Feature Name for features described inside that will need to be tested by conformance tests. -- a proposed probationary period (see next section) must be included in the GEP +* A proposed probationary period (see next section) must be included in the GEP and approved by maintainers. Before changes are released they MUST be documented. GEPs that have not been @@ -184,26 +225,28 @@ new strategy for achieving their graduation criteria can be established. Any such plan to take a GEP "off the shelf" must be reviewed and accepted by the maintainers. -> **Warning**: It is extremely important** that projects which implement +> **Warning**: It is **extremely important** that projects which implement > `Experimental` features clearly document that these features may be removed in > future releases. -### 5. Graduate the GEP to "Standard" +### 5. `Standard` - Graduate the GEP Once this feature has met the [graduation criteria](../concepts/versioning.md#graduation-criteria), it is -time to graduate it to the "Standard" channel of the API. Depending on the feature, this may include -any of the following: +time to graduate it to the "Standard" channel of the API. Depending on the feature, this will usually +include one or more of the following: -1. Graduating the resource to beta -2. Graduating fields to "standard" by removing `` tags -3. Graduating a concept to "standard" by updating documentation +* Graduating the resource to `v1`, and ensuring it is included in the Standard channel API Group and + YAML install files. +* Graduating fields to "standard" by removing `` tags. +* Graduating a concept to "standard" by updating documentation. ### 6. Close out the GEP issue -The GEP issue should only be closed once the feature has: -- Moved to the standard channel for distribution (if necessary) -- Moved to a "v1" `apiVersion` for CRDs -- been completely implemented and has wide acceptance (for process changes). +The GEP issue should only be closed once the feature has been: + +* Moved to the standard channel for distribution (if necessary). +* Moved to a "v1" `apiVersion` for CRDs. +* Completely implemented and has wide acceptance (for process changes). In short, the GEP issue should only be closed when the work is "done" (whatever that means for that GEP). diff --git a/site-src/implementations/v1.2.md b/site-src/implementations/v1.2.md index a3728f6aca..640baf0e5d 100644 --- a/site-src/implementations/v1.2.md +++ b/site-src/implementations/v1.2.md @@ -16,30 +16,30 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | HTTPRoute Destination Port Matching | HTTPRoute Path Redirect | HTTPRoute Port Redirect | HTTPRoute Scheme Redirect | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Parent Ref Port | HTTPRoute Request Timeout | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | -|:----------------|:-----------------------------------|:----------|:-----------------------|:-------------------------|:----------------------------|:-------------------------|:---------------------------------|:-----------------------------------------|:--------------------------------------|:--------------------------|:--------------------------|:----------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:----------------------------|:----------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Microsoft Azure | Application Gateway for Containers | 1.7.9 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.7.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | -| kubvernor | kubvernor | 0.1.0 | default | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v2.0.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | -| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Path Rewrite | HTTPRoute Response Header Modification | HTTPRoute Method Matching | HTTPRoute Query Param Matching | HTTPRoute Destination Port Matching | HTTPRoute Path Redirect | HTTPRoute Port Redirect | HTTPRoute Scheme Redirect | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Parent Ref Port | HTTPRoute Request Timeout | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | +|:----------------|:-----------------------------------|:----------|:-----------------------|:-------------------------|:-------------------------|:-----------------------------------------|:----------------------------|:---------------------------------|:--------------------------------------|:--------------------------|:--------------------------|:----------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:----------------------------|:----------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.7.9 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.7.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | +| kubvernor | kubvernor | 0.1.0 | default | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | ### GRPCRoute | Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | |:----------------|:-----------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | | Microsoft Azure | Application Gateway for Containers | 1.7.9 | default | :x: | :x: | :x: | :x: | | cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | diff --git a/site-src/implementations/v1.3.md b/site-src/implementations/v1.3.md index 653a8b8077..19bcb53105 100644 --- a/site-src/implementations/v1.3.md +++ b/site-src/implementations/v1.3.md @@ -16,18 +16,20 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | -|:---------------|:---------------------|:------------|:-----------------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------| -| agentgateway | agentgateway | v0.6.0-dev | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| airlock | microgateway | 4.6.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| airlock | microgateway | 4.7.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.5.0 | GatewayNamespace | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kgateway-dev | kgateway | v2.1.0-main | default | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | +|:---------------|:---------------------|:---------------|:-----------------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------| +| agentgateway | agentgateway | v0.6.0-dev | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| airlock | microgateway | 4.6.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| airlock | microgateway | 4.7.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | GatewayNamespace | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.1.0-main | default | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| sigs.k8s.io | cloud-provider-kind | v0.8.0-alpha.1 | default | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| traefik | traefik | v3.5 | default | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | ### GRPCRoute @@ -39,6 +41,7 @@ Implementations only appear in this page if they pass Core conformance for the r | istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | | nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| traefik | traefik | v3.5 | default | :x: | :x: | :x: | :x: | :x: | ### TLSRoute @@ -50,6 +53,7 @@ Implementations only appear in this page if they pass Core conformance for the r | istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | | nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| traefik | traefik | v3.5 | default | :x: | :x: | :x: | :x: | :x: | ## Mesh Profile From 1cf7222095c28ec983b064de318b4bfc3776dc02 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Mon, 6 Oct 2025 12:44:58 -0400 Subject: [PATCH 221/224] chore: merge in updates from release v1.4.0 (#4146) * chore: update consts.go for v1.4.0 Signed-off-by: Shane Utt * chore: run generators Signed-off-by: Shane Utt * docs: bump main guide for v1.4.0 release Signed-off-by: Shane Utt * docs: bump README.md for v1.4.0 release Signed-off-by: Shane Utt * docs: update nav for v1.4.0 Signed-off-by: Shane Utt --------- Signed-off-by: Shane Utt --- README.md | 4 ++-- .../gateway.networking.k8s.io_backendtlspolicies.yaml | 2 +- .../gateway.networking.k8s.io_gatewayclasses.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_gateways.yaml | 2 +- .../experimental/gateway.networking.k8s.io_grpcroutes.yaml | 2 +- .../experimental/gateway.networking.k8s.io_httproutes.yaml | 2 +- .../gateway.networking.k8s.io_referencegrants.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_tcproutes.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml | 2 +- .../crd/experimental/gateway.networking.k8s.io_udproutes.yaml | 2 +- .../gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml | 2 +- .../gateway.networking.x-k8s.io_xlistenersets.yaml | 2 +- .../crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml | 2 +- .../gateway.networking.k8s.io_backendtlspolicies.yaml | 2 +- .../standard/gateway.networking.k8s.io_gatewayclasses.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_gateways.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml | 2 +- config/crd/standard/gateway.networking.k8s.io_httproutes.yaml | 2 +- .../standard/gateway.networking.k8s.io_referencegrants.yaml | 2 +- hack/mkdocs-generate-conformance.py | 2 +- nav.yml | 1 + nav.yml.tmpl | 1 + pkg/consts/consts.go | 2 +- site-src/guides/index.md | 4 ++-- 24 files changed, 26 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e8ebd1ad5b..e6a7ebad8c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ the specification and Custom Resource Definitions (CRDs). ## Status The latest supported version is `v1` as released by -the [v1.3.0 release][gh_release] of this project. +the [v1.4.0 release][gh_release] of this project. This version of the API is has GA level support for the following resources: @@ -71,7 +71,7 @@ Participation in the Kubernetes community is governed by the [spec]: https://gateway-api.sigs.k8s.io/reference/spec/ [concepts]: https://gateway-api.sigs.k8s.io/concepts/api-overview [security-model]: https://gateway-api.sigs.k8s.io/concepts/security-model -[gh_release]: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.3.0 +[gh_release]: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.4.0 [godoc]: https://pkg.go.dev/sigs.k8s.io/gateway-api [conformance-docs]: https://gateway-api.sigs.k8s.io/concepts/conformance/ [reports-readme]: ./conformance/reports/README.md diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index f87397d127..5f0de9ad22 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index e5dc5ae951..ebdee85705 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 4836d0fd19..1d27104859 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index f3069ef8f4..a5a39bc7a6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 252da3ba62..1d0b55c9af 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index b0195c3c61..0533671487 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: referencegrants.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 259e414b89..55d504b5de 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: tcproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index cce85ef3c3..c3cb1792da 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: tlsroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 354f0c9976..39db999d86 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: udproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 018d40c4e5..49f0474d38 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 5a3389d467..3d566b97c9 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: xlistenersets.gateway.networking.x-k8s.io spec: diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml index de048d8e0c..1557b94422 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xmeshes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: experimental name: xmeshes.gateway.networking.x-k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml index b7a7307f60..f90aba8bf3 100644 --- a/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard labels: gateway.networking.k8s.io/policy: Direct diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 4da9f54fb3..4d54568c1a 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: gatewayclasses.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 33c250e9f9..0930cff5a9 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: gateways.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index c39cca9d14..6cb625fb1b 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: grpcroutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 20c385221c..42c5b4b1ee 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: httproutes.gateway.networking.k8s.io spec: diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index f803a2f957..61e9a756b7 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -3,7 +3,7 @@ kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 - gateway.networking.k8s.io/bundle-version: v1.4.0-rc.2 + gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: referencegrants.gateway.networking.k8s.io spec: diff --git a/hack/mkdocs-generate-conformance.py b/hack/mkdocs-generate-conformance.py index 55c8251e06..9abeaf68bd 100644 --- a/hack/mkdocs-generate-conformance.py +++ b/hack/mkdocs-generate-conformance.py @@ -184,7 +184,7 @@ def generate_profiles_report(reports, route, version): http_table = http_table.rename( columns={"project": "Project", "version": "Version", "mode": "Mode", "core.result": "Core"}) - if semver.compare(version.removeprefix('v'), '1.3.0') < 0: + if semver.compare(version.removeprefix('v'), '1.4.0') < 0: http_table = http_table.drop(columns=["Core"]) if version == 'v1.0.0': http_table = http_table.drop(columns=["Mode"]) diff --git a/nav.yml b/nav.yml index a51849e367..570856a3f5 100644 --- a/nav.yml +++ b/nav.yml @@ -19,6 +19,7 @@ nav: - Implementations: - List: implementations.md - Comparisons: + - v1.4: implementations/v1.4.md - v1.3: implementations/v1.3.md - v1.2: implementations/v1.2.md - v1.1: implementations/v1.1.md diff --git a/nav.yml.tmpl b/nav.yml.tmpl index 94e9a0aa1d..c7c0d84248 100644 --- a/nav.yml.tmpl +++ b/nav.yml.tmpl @@ -19,6 +19,7 @@ nav: - Implementations: - List: implementations.md - Comparisons: + - v1.4: implementations/v1.4.md - v1.3: implementations/v1.3.md - v1.2: implementations/v1.2.md - v1.1: implementations/v1.1.md diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 13c7ff5d3c..715f975d6a 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -27,7 +27,7 @@ const ( // BundleVersion is the value used for the "gateway.networking.k8s.io/bundle-version" annotation. // These value must be updated during the release process. - BundleVersion = "v1.4.0-rc.2" + BundleVersion = "v1.4.0" // ApprovalLink is the value used for the "api-approved.kubernetes.io" annotation. // These value must be updated during the release process. diff --git a/site-src/guides/index.md b/site-src/guides/index.md index 21fbe942b1..6d9411595e 100644 --- a/site-src/guides/index.md +++ b/site-src/guides/index.md @@ -45,7 +45,7 @@ beta, including GatewayClass, Gateway, HTTPRoute, and ReferenceGrant. To install this channel, run the following kubectl command: ```bash -kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml ``` ### Install Experimental Channel @@ -63,7 +63,7 @@ documentation](../concepts/versioning.md). To install the experimental channel, run the following kubectl command: ```bash -kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/experimental-install.yaml +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/experimental-install.yaml ``` ### v1.2 Upgrade Notes From cb5da2f32854dcfb946aefa7441dfeed66518a65 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Tue, 7 Oct 2025 12:17:05 -0400 Subject: [PATCH 222/224] docs: add rikatz to OWNERS_ALIASES (#4147) @rikatz has offered to become a GEP reviewer, spending time helping us ensure proposals move forward and consensus is built. This adds him to the corresponding alias. Thank you @rikatz! --- OWNERS_ALIASES | 1 + 1 file changed, 1 insertion(+) diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 510384849d..3de45922f0 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -46,3 +46,4 @@ aliases: - gcs278 - kflynn - LiorLieberman + - rikatz From 4c4ed1408863e4498d1af225099b0d85521007f7 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Wed, 8 Oct 2025 14:41:01 +0200 Subject: [PATCH 223/224] docs: add provisional GEP for extending TLS Validation in BackendTLSPolicy (#4153) * docs: add provisional GEP for flexible TLS Validation in BackendTLSPolicy Signed-off-by: Norwin Schnyder * Update metadata Signed-off-by: Norwin Schnyder * Add goal for runtime indicators Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- geps/gep-1897/metadata.yaml | 3 ++ geps/gep-4152/index.md | 67 +++++++++++++++++++++++++++++++++++++ geps/gep-4152/metadata.yaml | 10 ++++++ 3 files changed, 80 insertions(+) create mode 100644 geps/gep-4152/index.md create mode 100644 geps/gep-4152/metadata.yaml diff --git a/geps/gep-1897/metadata.yaml b/geps/gep-1897/metadata.yaml index 99d5444aa3..afad0e64bc 100644 --- a/geps/gep-1897/metadata.yaml +++ b/geps/gep-1897/metadata.yaml @@ -15,3 +15,6 @@ relationships: - number: 1282 name: Describing Backend Properties description: Implements just part of the Backend Properties GEP. +extendedBy: + - number: 4152 + name: Extending TLS Validation in BackendTLSPolicy diff --git a/geps/gep-4152/index.md b/geps/gep-4152/index.md new file mode 100644 index 0000000000..662db855b6 --- /dev/null +++ b/geps/gep-4152/index.md @@ -0,0 +1,67 @@ +# GEP-4152: Extending TLS Validation in BackendTLSPolicy + +* Issue: [#4152](https://github.com/kubernetes-sigs/gateway-api/issues/4152) +* Status: Provisional + +## TLDR + +The ability for the `BackendTLSPolicy` to skip TLS verification or to validate +certificates based on their fingerprint or public key hash. + +## Motivation + +The current `BackendTLSPolicy` follows a secure-by-default approach that requires +users to provide a trusted CA certificate bundle or rely on the system’s default +certificate store (which typically includes root CAs) to validate backend server +certificates. However, real-world deployments include cases where strict +certificate validation may not be possible or practical, e.g., Development and +testing environments that use self-signed certificates generated dynamically at +runtime. + +In such scenarios, users may need the flexibility to disable certificate +verification or to use certificate pinning. Certificate pinning offers a safer +and more controlled alternative, instead of bypassing TLS validation, the gateway +verifies that the backend’s certificate matches a known fingerprint or public key +hash. This preserves the confidentiality and integrity guarantees of TLS while +removing the operational overhead of managing full certificate chains or trusted +CA bundles. + +### User Stories + +* As an application developer, I want the option to disable backend TLS + certificate verification on a per-backend basis, so I can connect to services + using dynamically generated or self-signed certificates during development or + testing. +* As an application developer, I want secure-by-default behavior, ensuring that + certificate verification is always enabled unless I explicitly opt out, to + prevent accidentally deploying insecure configurations to production. +* As an application developer, I want an alternative to disabling verification, + such as certificate or SPKI pinning, so I can securely communicate with + backends using self-signed certificates without managing CA bundles. +* As a gateway operator, I want to control whether skipping TLS validation is + permitted for specific Gateways. +* As a security officer, I want transparency and auditability into where TLS + verification has been disabled. + +## Goals + +* Enable connecting to backends over TLS without requiring certificate + verification. +* Support certificate and SPKI pinning as alternatives to disabling verification + or relying on CA trust chains. +* Maintain a secure-by-default approach, with certificate verification enabled + unless explicitly opted out. +* Provide operator-level controls so Gateway constraints can restrict or permit + the use of skip-verify. +* Provide clear runtime indicators that security is degraded when TLS validation + is disabled. + +## API + +**TODO**: First PR will not include any implementation details, in favor of +building consensus on the motivation, goals and non-goals first. _"How?"_ we +implement shall be left open-ended until _"What?"_ and _"Why?"_ are solid. + +## References + +* [GEP-1897: BackendTLSPolicy - Explicit Backend TLS Connection Configuration](https://gateway-api.sigs.k8s.io/geps/gep-1897/) diff --git a/geps/gep-4152/metadata.yaml b/geps/gep-4152/metadata.yaml new file mode 100644 index 0000000000..e1c16ce5eb --- /dev/null +++ b/geps/gep-4152/metadata.yaml @@ -0,0 +1,10 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 4152 +name: Extending TLS Validation in BackendTLSPolicy +status: Provisional +authors: + - snorwin +extends: + - number: 1897 + name: BackendTLSPolicy - Explicit Backend TLS Connection Configuration From 4c66a5f813572c094409a7d9a87427fb77b66361 Mon Sep 17 00:00:00 2001 From: Lin Sun Date: Wed, 8 Oct 2025 18:19:06 -0400 Subject: [PATCH 224/224] Update implementations.md (#4157) fix broken link --- site-src/implementations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index aa2a7ce7ce..c52210e815 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -170,7 +170,7 @@ other functions (like managing DNS or creating certificates). [37]:#kgateway [38]:#google-cloud-service-mesh [39]:#kubvernor -[40]:#agentgateway-with-kgateway +[40]:#agent-gateway-with-kgateway [41]:#kruise-rollouts

OOhL z9n2wcU1Y~r9tDa4uK76E^T(_Q+?fiC3EovNmA>zUT)LG@)&*dfqd@;K4BQW0G7xMt zDukWl7hDflDs8JIT-xC;+9q`TwTR|`LR@XfEKVa92mYovnzZo|iGu^SQ5|J%3vND} zf9m>eI73ov3paA(m?UcW_b?h78*>gn!B7zkN~Lc~k=(`xU@!*kMDFU5paMgf6P9*+MwXW@q&X9lbh z{QHUi6@L+ zCLG;J1-j~e=X5^b1r8NiRsklxgo1bb76S0A%TEx-e*sHKQG>3E7Z&5n(zq{-hD#z| z>wS%^jV6o$`MZ7UP!;_yYw%a~#!SMUO3m%f4_KS~5K(aI1G&vozJDVUeJUdHt3^KP z_KkJ!X9o{kp8vNVOJ6%(avT(7((V5&3f8ZW^V1U`k(KLI>GOj}?y@bdX}#jG<}gtS z0hG{D`*MfqDC!ZgF4uh4=O@UHcn|M=`fC`xuuT{^>E1kZ6YEEn-yO9LKAvfAcm|?~ z7=#So82$e<I8mAF93$2Y!+ zo^j62LX=z*JG_|H5m)$dGXKmWFZPv<8xx@gNeHnkOtzjJ2Mq5(1nL+!RE;x@_UYHN zS?0nTBkI?(N%tBMml!Dh>~F@O(hg#@xuAvtYHG#dOzlqYD8^(M(~l zk-%e!bdlz*7F98|fW|R>S()qcU__;O1ZO|7X1eQI;Y7vq@g9aSVli}8EDf$k?9B0W6EDDmWoZ_uwN(2bbg$wH)gZrl{}JKZTtLIiaP{xE2%t-Iy}a}A3Q@qFl0Wr{XN{g)8g5=5KZi+*N7$sGIU?^K zP|LqDG3}5odElQPTipCP``EE=f8W|7z3lq_wMSg+;Ou^-dE#IA%R zKc>|y`neS4l2njghzqMy9&ncq8n^U%>}7ugaOkBw#T;t!pIM-U9IoBh$~_i58!YKR zRo0A0^{t}}z=+))O(yIIf^y#%e!T1-N;*{p3P(ycD;nVj$$u%yFX#K%P-t^7cI#g? z-rHNj-DFRNuTmc}C4vq7NQ$a4UCC+sp8nkKPHfbaz+}2ybBHR+;wq#jG!) zf69ATwgG`XtU@koA>box)+>SiKuEhu_S$;}PE92Mx6%M-`2EBtm7)pPFz`ajB=ZXI zVV`(eO1SfqN@LXv1e5i}tN7QQDgN|CrDZhgQWXs-`&R??3%soxzyX_pMK z-rpsnpi9DNzcDAq){VO3Q^GLE2JqCck6>kC3l4>0A1q?v1>J+T|K1C%e{c8pOdtIJ zpn^Zy5%AuxgwIkH2p_T`w!;-+iEQjc86O%@pTo5#q=y&r8R-9!=JN4eImDhxd~gA~ z-3H$ndh-k;wzy~YP$K^}3a!Hq52raiS z$q0CTnudXdE%X#&K&Sl;kCDi+0bgIiiK_92B%NMjCE!j$67Gb;#r+FtTjA^Q)-{0g z5f;^3k(g=N-#|tr6a|f(J3hbbm`%9Yz8;8-3dxp7j2H|g8Y;EU8+3>%N$p3NKH>aHcIDV?2 z^(E-6+I~9iHOmuP8G8IIqi!ya4{h!;ncI9GtkXj2;1j~NZm4gw#aVxzPkyonYWG#FH1p?2W zAY`@r7g;&^59NIVcq+BWiaQje$-=E7nM4&kb6N(T;zFNR?cek~g*p?2yaWg8_LCJ| z2oYjw6>lBhhcI?HzL-((w(EKwis%RIFJ{&Z#J zk!|OlFBIwc_=@9>)Br}?1VAN}9vwXjYdym>ukYRyIN&__XBdsUHr(NrdaxlgLi;B! zuRL@JyYj`+wXB$=PS8GKhzaoHT$-%#8qw9^B@nV{bv^)fp=9!~9K0GZeR{-Bpf5Nf z6sI{@)zZHDS&4!XqA=A$RJYWeKhrnQ_kjSNltDCd#713Esf2pMagSr`o-zvkqI?Xf z3ZbVd3cswxOE78s1kFWF7!Xd8ZZ+@G4~&nEtF#3~8T%&;Mbo%^9nZejYk2|P=ppI} z`U4{aS9bfx4$rg78*pdX# z@K`0q@w!pp*=t`J^{`PP_YQDKWOslGpfGsL0gRL4sZ~Nd(h>&Tp-1gIG3%QemvE@v z(=Uobwl;XYj|Mg9;rT*8@2i)86k^;)iQT8oV!5O-FgQzt(vt=>70nYkhAlh^YfR6w3sq?$KWr)hp zMi2&ZSMJ%1ms_1h$pShp1qG|~w(<5T8qkcycgdP15021CwN-60 za4P+qt4gzrPxogvpoIN={sPg}8oro~Fa6T(glh^(`mAkpXVR1qCQp|FTlwvMgz`-I z|Jag8rshQ@5(K7(;F|6ofE14z2@T}B?RDS|Dyz{R<`;l!FQtehli_BYePu7_!OQZ0~RORdV0e()YckLysQ zYM<_Hb=Hj^2n-WkMjeBSVA3%B@yT_W`_Lhv24lbeH96Hj2-K3_K;#EtE@U0#V6>Yj z;Z>LlI9QNSoaMnE$8XI2_?yhm+w9RkN;~>Jw@V%$P{?a&{P!9^;)bNcB2k|3K~WFQ z8vv;R)m-a0|Fkg#i!{#E<})7X76grV?UqEL1VM<*OJ!`10e?KD5DoL4phS@=83)UIPbZV0h8~$?2HX z*)Y^$Ok0(Vq;FO(Iqx-imFO9?@}_@iy*5tssrHK(~1lXI8F&AnMF zDXpCT`49VrZ(kA$vp*yIstiK~`GR-Owwg9FRDC@-WI)g6fcbBu>$K8}!R}lpeqYEM`SMG+xhNVDIy4$XP@@EBF z(a&$@+aAy=G*DJD>EZWC{ztiYfuE`CAsUcp^R|%J^3plXeOk~Lr>+9?AinQm#OoQx zl^F>xcw_QG&#&`?r@$Cz_@!3LRh5OcjdwqP0#UE2s7YS#xT4vw9BnJ(zY}&co2p3j zI7&M9`@a!^#{bBO(l5E5krQ^m;UMT^UO3v?ckos~6Q-Z}#gZ#E~8 zX3)C-LSNn}p`2F9$Nr<*CXBE8q z2(Quy5qC8rBEKS^WMar@Br$hnQ&{H0q5bZom)E>{3sE@#wgoSN*&h6?iYP%Yl!1P| z5K$fdKt48ASP}_)q$m6g`+N{hG~!E;IW*TOR4;`o41utWm#!kZ%ZkJXM!QAeaBU~B zr+vXIWj2zqWN<|F!-0_Knnr;yVo4FnEBZV7A&p($8X*n!#jJ9{_XiXq#6kLz{AL&t z#T3Nu`D-!J=LQl!@yhz14z?J=0sBdL2j&X5_AZ!1q_6YN$>fP}UT* z(K|)iB*aX{GVB%x0S%f^JjB=pck361b%r>3QN*Ir!&(Q5ABZyTDKUHKNWY|zj|{{( zprUzs-Ba8JV^cYp&ST9@n{i?ULfCd{%~m^%E8iDE6Jog zCUVD1E*`344Z<%S7V`h(9!2Lw?&kXp4Op@n#q6%jU>({<0x1u;y7U62|$KYsdc=F$~}YKOSXukMw`N$_LtCfS<)%Yr0h3R|njfBW4bxYOZ^wq;dgte>umEu-xL zFZhJ+*Tdj3_}HNqZHOD0gnICl3f0|d@F@xja4OE#!hn(k=?0B{HB>R$NDzVnjgHx_ zx8RyLNUoknDW{Q0$*IO&r7}$#Y@3&mw`9eZ6F;j}AncM~ZBX0=xWUz?`!|Y0BsTXm z_qe$a@<$oEQ3lFGkM~ib&an6Oh}|kCq%h4s0DM-a%DsL=2$xZPE#OAHeAvY=KsjBp z=8=CDK-8hD?{PUPI0Kc6h-QgbDaueDAG$M^fGG~cNG3%xhj4(ztHoCyL?9%SP7CH( z-gW|MFK$dWJXD_uidp!XV(GGb{HHIbceDk%H!YfU5rPI^dg5$%`bs#(_iMd~_JUxj z+Af1u;m5D=%p13z55WgJ8UuSHIyf9qqMPw?9Ie9{nl)SZH14doWYVZ(lPd(Q(KCqV zNG&Q#*l*B*`wxX<`(|H^?P9>{RbTJn8P__XE+)ww7O=_GAnuUF>gj6{cD?mH607K4 zc^Ni*7;e4$yQ>#MDG+}8Ru`!}lY_~5pywbFJr0bIU?U`&=QOKcSh^3>u5u_$V>}ua z;bY~`(Lmeyua_4>-zXzifgD&EMiBIVTR;L@tODaDse6hC*oyEjq;6)c#TuiE4Dag` zMu;r{&?1OG;SW#Qz*EPVj<&^$Y2O6-g@B2<*J$HuM=fAAhn|GPJz$$r`MuQ)EMGZb zBX@=z*?LQ;Z@PVwep-y3+&3 zE1f~J`B4R&mM5@h3CHN`V%;)I|3#k&-q86#L8^3u$V)P&k(ivEOK7eEE+Irw&QO|i zqZ>88>yhOowD!Y2A0%);XEHr9cD)d4K^Hxg_Xvwf5pe5c>~(`La|*5I^!`#w_plBQ zgO-MgVVKqTMFj8*Q$5H$HdpU9f6f@ll35^%*srFLy#7VhY~b4oc>KN^obNG%%FiK) zWRZ^Q(KO~BzV^VI^6dE>k@NQ}DNNM{Nx<93G{G@>3FJUru>hvuSY5y8R&o62wZKa= zlb?_TD!i731FqglUupUcjkZ=#Gm{g~BGqRk6HgZmHa#i6qPn*>GU5o<0dP47s{jPN z^5;1%7GGDE_&v?>`o|uMTc#4auTnn;WHLKbQaoy{f2V5|SwbxztR^91HUA%*2%Qat zl4hxC!Y)3FE1i2&O-xSLoSq)|NZ{Xnk1OXQ|cblIVJ!7$mwT0N;F>K`I{5Fw$EJ29n>iYq=PeK7C ztbw^IZkP=4p$?_<08aqkiOAa8jy&L^gWX)d#HOg6bmRYP>$~Hr?*I37B0FSei%@2E z=1CJ-$;g&n=CKK#PRhF{d|A-r-whp@qVr6 zysqnY4))vVx;U}=GrpaBkBo6L$O|f&>r>OBRUuUT;(_h-)P}&HxOdd;E~{aWYQ7EX zA`n81uWuw0=>C{9u(Y<Fh&t!ZLwZc3pR6VWaFONuv3dr z0=#x%zO^3(Cum~GTZwRyKzN^qCxDgm^jwcgL6@P}X3G;ki3HS43=#!!oA98nmtOU@bhX^-R!eiq|T!3O@{TeoFY)7b4h$BR3A=C+)=q~?V6M+D&*#cvm>z>5u+{@#orGaV#QUDbu0@fjMbV&x~6IDxP=gK!eg!}ZHrC>#_7&K8kt zT8H+p^B1~Ua(iU=S7~r_Wg24UP(Mns+R}{9yH8OLXZnm8bHmPulP6b*AE(J0@KXpl zKD=v0)>YXue7oWaB&}&^FCEOHzpg^1=&Ms*zIiYi9%FczWe}98Af+8T8uhIm7vRW% z?J4tI9+hqMNO_DO(<1B2K2B_V2--mPLPfW*=3+AjWhP|GYdcS&jOUTmZ+~x_aJYIT zd^p*!?VI1684g5R5Nycm-D=%br9}ka7tDuNa_z>*=Y~hJ>fgdPlkV!_4K-NE`G{vH z7Bh8_;&P-fMb0M6q|;Ytfhp{?&Ik15lEeu?6W6uB4{fW94`Lh>O5bet{q6;Fh`r0c z$x1H^aVfMp%^WDGJP)~0(*~pjJqmkB{W>Kpf1NV)TZ}VH08|8seRlD}Gmi6gS)9zj zf(m4m^YDkdS2g{@I1JqUfUCusp5oW~Ht-};BZ z7pBCCC+fRBiu3gR2$d+ePGXJ2T7H^*sN2|f?ki*L`ibd;8o=M1C?@3T3rFXE%@$QG z*qQ);fmMbO5ToGgYO#C*MeWIQAuR$nSR4%*veo!@c&7~ZI%CtsNbx&;e*t8|w1S#2 zs@eJE;eIUjBtgdxf7g(!u8yepArZ61yjxXq|NwzlU6k2FuWk^k%I4K^p><7GQD zv~Kb^@nPdAP0yQ7U;lGVE@0O#vO;p|3W@QnLuwU^A!#vVu|Io>$7iS|^^>d$6M;8s zQ^U>=-;XPia^l3ckVCKC%yl@bDAqt5I^5*0RY@Nv?Id~f(6l@4NvaJ4;qfT{Q$QhT{*jzuNBp6)HU zPS_pGLTKSBcygA#OE9)g{k&0>Sj;1XXX(sNre01@qSm+N~5m76?w$Wxh zQH2E~()~A6*i=)ds|}>u#fr>e(Tg``!m1sj@7~-Y#BADLbM6S{s%SdZQjFZf1?h`) zFvhPRc5w_HkBOYq91cL8Xm22T@7EAhx)rmkip$6|sRL($H? zJWfZUbEmI=h)(?6ER&gAX%88gn(?X_q1Egoelcz3>UG!xw!UVElpchQO87dqyfT{X zr=+;=H@wA!f|sVNVVA#$v6a15bQMc$FjUr4C6lU>=P(|A140UPx;u9M?Wok_IalRd z){!JK!(u+RUX9TNmj_TjqrL9(Qfo5jdg=Ca2T(uN2Yz>yND$^K#*ewkr<9B6j8O-( zL2VI*v8!HL-CL~XXq9I#f+!v2Yf&F?)#%`J#N($iYL;h%J5|A>(t}s?#Q2Y03 z$5Q->qx8ui9)9vrk4^Um3Oc+yWk3sU(Y7FBh0o4dR>yghGvF{cu=AVM7s-TL`8<<9=-i&~~n+0c)ZC=-hDJd%>d#UJ=3X=p0(57mRH=9r+_+Pp(VGs}tsGSL3 z1SGzV7^6QxEgM(Q=`+LJYDSl*Z+1lHAtH8(@x7RiQB9|(l`EBfc z>?_!w__VXHQMa5TNs2%6==e)b)fpOw_GdP`5NZp-&4*}`i|GTyAz*{fcN*-1D_Kmc zPQmD$jfC2>&y1tqj%9~z9gYzhBQp$fHJr%fO{5!x5(=+E4hes|U0Ig`BGtHYy)MK0 z$Ge)#1na3FiF|d zXzdh^h2B_4B(BoR<<$U}_fev{n%V2U^z9__B28|ei|K3TrB{oi55aZB4X;^lsq^s= z8;0IBp>EtLy2UNq5ty{?yjZI7j%>4caNA!cvR`T=2p$NK`P$uDMjC7ZFIW(WT>>8% zAn1XoD)@k~O_q$Tq7xf7kId%ys{oo3M?Qgn4gnhPgNtOfmg#w2xlZ9NC`WMRH}XCv}LsfyQ&PhD4#0H}=s zMl&bn_IhMb^|yU4piW^bbr0k*qUL$ogVw%Ia0;{s3d~57C8twbl+7X=?ZN^Qk>Vct zmZ1ot@E39s7QUGgd9BLQy|IV{=L>N`&jX=3)^)IeWnXrt>`zIBw=*S}k(AHCRKITp znc;2Wc`GyGZGot}e2-|eIvqXC%)5V=F(1$7?<#cxjkB+RIpz-t!f>FfcH7@tolVM` z!`>Y`%IH#fs1C%Ps5hg`%hh`PfJbM8?Z}KpG{_dMV{u7{DOvhp_3XL2XT;2sV}|VV z(WsCUa&l=05gP2ccizfdkuXnK8+`O;4;P0jFiMajFX-Q7h=Z`;qRA}EL8tmF;~mGC zc*{c=abd`}gcx4$1QpgaB@g>pZsqb@Slx^#EAV%1GHEY1VaRk-EKFdlq4z_3WWV4_ z5b(DHB%MfTc>4XC*kQECZW9;mwU6%Gi0kC>j~ODbkWE%zt6hE{(QDdcAlr&>w-Y%rIPw;utu&c z$D7Ipq;x@ip`ZpM7TWjo{p|T6MKln}ffGIvvR{=V#stGBoBnv=0KrVM?XRbv2*!@K z!g??>iE7{Y(Q||HA=*8e>xTaio13M+c8Eq3Bw=Mg$p%W5*)037{6!vfYUClhY0x>9 zKr+2OA6uz|LLMau+lycjEXT;d;?d)XXxx>X+-m;vqyZM8frANO`5gI_mG}sL- zxB7ELDSB?MH~9ApN3k7SvySJ-DRoc&*P zs;^1{gNkdb_6VNz%f@)85 zn>-;_KVejLwqf7==Ov zRDhBkL6N|q+e2sMH^0Y)=cyOykrnNl-KSL*+c9E9z|aK-2s)ynBX?Lr?o6I>I)i$m zbZs-}O-{GI7X84DL)Rn1@*RA@7qJSHp3S^t!^6P{20NPdBh!>jG@zitOE2rZ&NIG9 z6|?-!!W2y>6QpbQCpO?me;-Wt&88Jpdp6-ZTq>fYq!5nqVk7O@&qA6gH+QKv1>O!v z$n-mT^P)(nm_>6~R9T*0!B6Jl2p*4Cfb6FEV@~I3S5|HjHL8ic&0-(xUUqe{QS8B0 z-L)=5Ygy6`1w>0~O|G~#P${{FDK%g8Q>Z9114DK8x?E}B^_=UJigcU}<2N}oVADV@NiYjxE+*_5H0y!s@wuT~6GIBYFhR0*2Ob6z`M zq>(WMk|Zk4k;T=`mUmYBRkx)j2?WXwb{!xOoT>5FiEiYX`AYn?f+&4Ji&t%fQxpu!} zwPuAbei9uS9Au}c!#jvFP)G1r&Wa?(ogbBjGZ@rOFN@E4P@rQqfEZJF>8b}AqD>cK z-pVj58BG>UzNz^rj1|RbRORr{3hmfGRDHOq&^WrYzxybf%r0oMuw05mmAOhU{Jb0+ z6t5UDHoUxW$91j=hX0VuE85UkB`Z>7nf}}` z-Ir2&OyLa@o1;LD62q3{Dy|c0;va4hj?Sx{cR|N?%ZVV0dqA25xCyqCLSHKV)Pu3_ zHGTS;p!wo4s?BV{@Z&1y&T%@_2Qq++utpxc#*Y@dD&Di|+;sxb_pR7k^qey0kd|S9 z*2mHKyVe0mB(99jil}O2ZFCR&bl?>7BSi*_nv@)^|)w-lxasxDlvEoIt4XDl+LGSV4ypD@@PzIO%plR z;J7WTMM}5h9WyvCmI$OU`M4^-`QZVS54`;}LugRDkxm&7XunBy9TqN0Qz8T*vKYbq z0&D+ZG0c8q$(M(+5c>CC9RR) z*!Es!eN?*H9i2(%keU^u^sjU8uTG*L636z^Sn3`Ye(x(9{yKVJm8^57sO65KBN*+S zIFCR9Z%tsL&?Nu^wy4^%M&j@)Y-P1*&{MM|3Ke6~8pKe)d~08w{j_CNKL33D++lUY z-DZZBi!j{K{Q2{;;qh#dS8=^mK;oK~%i)JjN;!SWp6_eayj2v)RqR%^!+4dtc**q| z135|Qbn>7pjp(%64P&w*7xAe6TE-#QZ%9uVi^5kNxvX1cO4mw#45M4Rz-Bmv55P)h zGhb=XeA+1&5g*A*@L7<^G8_3EVaj;mZ!s~acf|0k3bi@PWx~-)Ch4-Sat6hd&d1U1 zWt7&;f0*FEA`GM%bFcEg5PDGwRYqC+mR%{4jfz2aDGaCl z;b?4TeoZ5BPRo;}JSWM3XNO)xo1+D)!0w@NzhE(WITi2a@j7WCNdu95(S66=6K+B@ zy6Ej6G1e&O@&-fmXF&f@-*DdAn;V*>o zxf$!t$Xq^2=VC&z1C%AROo6S~Ige(c!H9IUDWwff6GiQ(gNp-%%()RQ_dAKZrt zc#tV~JW&{}%%7G<5#xjG4mz4w!y`GRkE3-bPZ;KD`d`j?tWeY zSd&gU>L7#T`ZQ1U0{m$x*;jD00?lzdpBn@@H~|Fmsw`DrcM_z;Mo^em&>!qsq-yd< zBe?4==OFgW?T!7u%yKDl5*nw$36qXy#_!BeKXNWaQb!EzQPGyF8@`$v0cu>IEu;HO z+CCP}p@fpUpIU^=21Fq=E#ibyrl+Yu+vCwjJ z-CXA#S55d|C(NDA<$5f>$vm)k=9fUj^?nOc$CFn3*AvO%5(N8DvRMVa>~|Rizdv@$ zZ9z-1N?xf{@w}I}lnR~mfu$7dhb5D2{V?>L%W=L>T=ng6VGnLYh*y=L`f@T7*U;VB zX!Q$|-j{gKpewzm(XRMSjdS4265udUwuqBq<1N&ye$8!ePaAf#*Xefdn@edw>~Iro ze$+i^B*;O68LtL{Lgrw%!`=>}N!otJ-Qb{&&Q7ihsasnfzs4wAxsthD_s@IydyZ?* zx{X&~bvIbwE~jpa6`BJ>;@d03$Y};ord``!&ipX2=DvL+aqXoCM>1D7rHad69rM}2 zh9VJTzVeb{d)q`r)KY4fF5FBJwRpcA!NylF+?O~~A6?g6 zZoN=$=2wW$X*+HUsKzY)AB)B@l^Si3ybBU*Wb`5f?kW|{pW5(F!M|#y%2hHe zFV{*DVb=<^j;5}4YHx;l;;tPGzUS!aJNi7FTI1;R8Bh6y>o*$O9T+Yv48E`?s(60t z1h<*?o-IXXj#*{vWvbu7No&h1H?KOARKFGoTDqd+~%(E1R>*;$$=Ts zPFDPpquZ2uu^^?_LHL$$7Z)G_>R}IHkp+or|at@eh4dt1d%prtkYGaykO@t zYnL)+*Rm$p{co6qkw*K;y~jyhxyhUL0#j^-yOw3bGm`ilQ|JN%vz=sT*Eb{u6$aaK zB|mL_nqZ!!=0lb7G*4r3hT_s9`70g`b`AJQ%vMN??KgboZNIdJg_|?)ns&_J&@i&~ zNMMZtfn&NLM2cZO(Uq;`42&LJ0|2k)9ZNeaUm!b$c44@wE@8zZjX)Uv!zLW*tVCS} zeOb)}{NgZ=q@Tb}SX%CXYvktH8OLno?@8jRGS+bYu3vXk@EGSH#m!qmIt>Cg&x!j$ z?LihZi59BhrY7&p>gf#tH!ZLEps-v!@jX6|LPPJd_5FfiPlMD@4FIBXa<86W$mD9$9;Ho8law^R5nRAf(`De2496ohVhR5wl&xr>sK1x(t zJ!?iGXUI_>Ar*By3*RbpF}QB;)$DVs{&Dn74x*7}>#@fzWNik4bjqo8Q(Nh(=9yqy zVZv>d!={UHqL8VrdDxlIBD7s~~n?##E^|6lRkubygabg+rZ)2IBj}o%gwUsx;dA~(y&*I&0UUmnHtn-2j z)uoQ(WefnmL_)){Z)C#XRzf*;iN3+0Rs&T^{I2wat13 zVz7o+g>QHl@&~)RDz8UK^9h>7>{U(!`wd@>qn>gJZEqcucgoxYIGAqb29c@1DyxAq7_&0yF z+Snj|&gJ`tC0pcvaIl!V^>Zm#=trA0$%;+;6o=s3sf4RCbPbcI@of`uabQR-u#I?;Lygn;2Y({KC5WYYUI6vD&e^yi zfxY@B`b;cxR}4-W^5)o^PQZ`1-*EtT&gXNXSZeH?O*Z9DwR5fk_mH3e?3-mhi>JYJ zn~Qq`Tbr9fK@%FwYfmK3;)Vaq#yg3?^>e|&Uvd$$7QCXlX&v_*CaUM`{nuk-J>K5K zcqTiVIwUfrWKC!mPG+UhhbA)Vgte8^xUF)&cM4h>8pyGUEc)N z$ISaBbiG$E>GD*+=rd{%laiUV%ZxS*cHU#IJ#Ru|{BEWV!Q(3efonpjTh z+bMtlen#-K=ik=ZG|~T_gF_k`NI+prc3dGI^1T*+^x9dYjP~hz1#%Lk~^P!Z&@Kf*O3qa1_Fz^uEX zM1*SSU%!Tgl>utV$h6lIzkA95f2<>@5V&4I9mGsTc;NqC=3z8kLoQC>wDlAI%kK_H z#MXi)_gFP0(SO+3|DDh_2gM~WFxTTkYN&{|FQ(aQv*TSzrL)e z|C<>5zt2ZzX1N5af!d!ac#F6HJ`b!iX!Evzy*m3Fm-_dD#eG2@JmPbN=-<0U_z9W| zrWv? It is very common for service mesh implementations to implement some form of transparent transport security, whether that is WireGuard, mTLS, or others. +> This is completely orthogonal to the use cases being tackled by this GEP. +> * The "mesh transport security" is something invisible to the user's application, and is simply used to secure communication between components in the mesh. +> * This proposal, instead, explicitly calls for sending TLS **to the user's application**. +> However, this does not mean service meshes are outside of scope for this proposal, merely that only the application-level TLS configuration is in scope. + +![](images/mesh.png "Mesh transport") ## Already Solved TLS Use Cases @@ -83,16 +89,16 @@ Gateway API is missing a mechanism for separately providing the details for the including (but not limited to): * intent to use TLS on the backend hop -* client certificate of the gateway -* system certificates to use in the absence of client certificates +* CA certificates to trust +* other properties of the TLS handshake, such as SNI and SAN validation +* client certificate of the gateway (outside of scope for this GEP) ## Purpose - why do we want to do this? This proposal is _very_ tightly scoped because we have tried and failed to address this well-known gap in the API specification. The lack of support for this fundamental concept is holding back -Gateway API adoption by users that require a solution to the use case. One of the recurring themes -that has held up the prior art has been interest related to service mesh, and as such this proposal -focuses explicitly on the ingress use case in the initial round. Another reason for the tight scope +Gateway API adoption by users that require a solution to the use case. +Another reason for the tight scope is that we have been too focused on a generic representation of everything that TLS can do, which covers too much ground to address in a single GEP. @@ -150,10 +156,10 @@ Because naming is hard, a new name may be substituted without blocking acceptance of the content of the API change. The selection of the applicable Gateway API persona is important in the design of BackendTLSPolicy, because it provides -a way to explicitly describe the _expectations_ of the connection to the application. BackendTLSPolicy is configured -by the application developer Gateway API persona to signal what the application developer _expects_ in connections to -the application, from a TLS perspective. Only the application developer can know what the application expects, so it is -important that this configuration be managed by that persona. +a way to explicitly describe the _expectations_ of the connection to the application. +In this GEP, BackendTLSPolicy will be configured only by the application developer Gateway API persona to tell gateway clients how to connect to +the application, from a TLS perspective. +Future iterations *may* expand this to additionally allow consumer overrides; see [Future plans](#future-plans). During the course of discussion of this proposal, we did consider allowing the cluster operator persona to have some access to Gateway cert validation, but as mentioned, BackendTLSPolicy is used primarily to signal what the application @@ -170,18 +176,14 @@ as a TLS Client: - An explicit signal that TLS should be used by this connection. - A hostname the Gateway should use to connect to the backend. -- A reference to one or more certificates to use in the TLS handshake, signed by a CA or self-signed. -- An indication that system certificates may be used. +- A reference to one or more CA certificates (which could include "system certificates") to validate the server's TLS certificates. BackendTLSPolicy is defined as a Direct Policy Attachment without defaults or overrides, applied to a Service that accesses the backend in question, where the BackendTLSPolicy resides in the same namespace as the Service it is -applied to. The BackendTLSPolicy and the Service must reside in the same namespace in order to prevent the -complications involved with sharing trust across namespace boundaries. We chose the Service resource as a target, +applied to. For now, the BackendTLSPolicy and the Service must reside in the same namespace in order to prevent the +complications involved with sharing trust across namespace boundaries (see [Future plans](#future-plans)). We chose the Service resource as a target, rather than the Route resource, so that we can reuse the same BackendTLSPolicy for all the different Routes that might point to this Service. -For the use case where certificates are stored in their own namespace, users may create Secrets and use ReferenceGrants -for a BackendTLSPolicy-to-Secret binding. Implementations must respect a ReferenceGrant for cross-namespace Secret -sharing to BackendTLSPolicy, even if they don't for other cross-namespace sharing. One of the areas of concern for this API is that we need to indicate how and when the API implementations should use the backend destination certificate authority. This solution proposes, as introduced in @@ -194,6 +196,8 @@ that is appropriate, such as one of the HTTP error codes: 400 (Bad Request), 401 other signal that makes the failure sufficiently clear to the requester without revealing too much about the transaction, based on established security requirements. +BackendTLSPolicy applies only to TCP traffic. If a policy explicitly attaches to a UDP port of a Service (that is, the `targetRef` has a `sectionName` specifying a single port or the service has only 1 port), the `Accepted: False` Condition with `Reason: Invalid` MUST be set. If the policy attaches to a mix of TCP and UDP ports, implementations SHOULD include a warning in the `Accepted` condition message (`ancestors.conditions`); the policy will only be effective for the TCP ports. + All policy resources must include `TargetRefs` with the fields specified in [PolicyTargetReference](https://github.com/kubernetes-sigs/gateway-api/blob/a33a934af9ec6997b34fd9b00d2ecd13d143e48b/apis/v1alpha2/policy_types.go#L24-L41). In an upcoming [extension](https://github.com/kubernetes-sigs/gateway-api/issues/2147) to TargetRefs, policy resources @@ -238,35 +242,22 @@ Thus, the following additions would be made to the Gateway API: ## How a client behaves -This table describes the effect that a BackendTLSPolicy has on a Route. There are only two cases where the -BackendTLSPolicy will signal a Route to connect to a backend using TLS, an HTTPRoute with a backend that is targeted -by a BackendTLSPolicy, either with or without listener TLS configured. (There are a few other cases where it may be -possible, but is implementation dependent.) - -Every implementation that claims supports for BackendTLSPolicy should document for which Routes it is being implemented. - -| Route Type | Gateway Config | Backend is targeted by a BackendTLSPolicy? | Connect to backend with TLS? | -|------------|----------------------------|-----------------------------------------------|-------------------------------| -| HTTPRoute | Listener tls | Yes | **Yes** | -| HTTPRoute | No listener tls | Yes | **Yes** | -| HTTPRoute | Listener tls | No | No | -| HTTPRoute | No listener tls | No | No | -| TLSRoute | Listener Mode: Passthrough | Yes | No | -| TLSRoute | Listener Mode: Terminate | Yes | Implementation-dependent | -| TLSRoute | Listener Mode: Passthrough | No | No | -| TLSRoute | Listener Mode: Terminate | No | No | -| TCPRoute | Listener TLS | Yes | Implementation-dependent | -| TCPRoute | No listener TLS | Yes | Implementation-dependent | -| TCPRoute | Listener TLS | No | No | -| TCPRoute | No listener TLS | No | No | -| UDPRoute | Listener TLS | Yes | No | -| UDPRoute | No listener TLS | Yes | No | -| UDPRoute | Listener TLS | No | No | -| UDPRoute | No listener TLS | No | No | -| GRPCRoute | Listener TLS | Yes | Implementation-dependent | -| GRPCRoute | No Listener TLS | Yes | Implementation-dependent | -| GRPCRoute | Listener TLS | No | No | -| GRPCRoute | No Listener TLS | No | No | +The `BackendTLSPolicy` tells a client "Connect to this service using TLS". +This is unconditional to the type of traffic the gateway client is forwarding. + +For instance, the following will all have the gateway client add TLS if the backend is targeted by a BackendTLSPolicy: + +* A Gateway accepts traffic on an HTTP listener +* A Gateway accepts and terminates TLS on an HTTPS listener +* A Gateway accepts traffic on a TCP listener + +There is no need for a Gateway that accepts traffic with `Mode: Passthrough` to do anything differently here, but implementations MAY choose to treat TLS passthrough as a special case. Implementations that do this SHOULD clearly document their approach if BackendTLSPolicy is treated differently for TLS passthrough. + +Note that there are cases where these patterns may result in multiple layers of TLS on a single connection. +There may be even cases where the gateway implementation is unaware of this; for example, processing TCPRoute traffic -- the traffic may or may not be TLS, and the gateway would be unaware. +This is intentional to allow full fidelity of the API, as this is commonly desired for tunneling scenarios. +When users do not want this, they should ensure that the BackendTLSPolicy is not incorrectly applied to traffic that is already TLS. +The [Future Plans](#future-plans) include more controls over the API to make this easier to manage. ## Request Flow @@ -281,6 +272,23 @@ reverse proxy. This is shown as **bolded** additions in step 6 below. 6. Lastly, the reverse proxy **optionally performs a TLS handshake** and forwards the request to one or more objects, i.e. Service, in the cluster based on backendRefs rules of the HTTPRoute **and the TargetRefs of the BackendTLSPolicy**. +## Future plans + +In order to scope this GEP, some some changes are deferred to a near-future GEP. +This GEP intends to add the ability for additional control by gateway clients to override TLS settings, following previously established patterns of [consumer and producer policies]([glossary](https://gateway-api.sigs.k8s.io/concepts/glossary/?h=gloss#producer-route)). +Additionally, more contextual control over when to apply the policies will be explored, to enable use cases like "apply TLS only from this route" ([issue](https://github.com/kubernetes-sigs/gateway-api/issues/3856)). + +While the details of these plans are out of scope for this GEP it is important to be aware of the future plans for the API to ensure the immediate-term plans are future-proofed against the proposed plans. + +Implementations should plan for the existence of future fields that may be added that will control where the TLS policy applies. +These may include, but are not limited to: + +* `spec.targetRefs.namespace` +* `spec.targetRefs.from` +* `spec.mode` + +While in some cases adding new fields may be seen as a backwards compatibility risk, due to older implementations not knowing to respect the fields, these fields (or similar, should future GEPs decide on new names) are pre-approved to be added in a future release, should the GEPs to add them are approved in the first place. + ## Alternatives Most alternatives are enumerated in the section "The history of backend TLS". A couple of additional alternatives are also listed here. From 3842b4c75be349e1557bb281e44f6eee357de684 Mon Sep 17 00:00:00 2001 From: Flynn Date: Sun, 29 Jun 2025 22:36:31 -0400 Subject: [PATCH 064/224] Oops. It's GEP-3779, not GEP-3379. (#3888) Signed-off-by: Flynn --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 4688e7f585..1753230778 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -130,7 +130,7 @@ nav: - geps/gep-1494/index.md - geps/gep-1651/index.md - geps/gep-2648/index.md - - geps/gep-3379/index.md + - geps/gep-3779/index.md - geps/gep-3792/index.md - geps/gep-3793/index.md - Implementable: From 564720a533f9ff28e65bdf898c1274ace1865245 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Tue, 1 Jul 2025 13:05:25 +0200 Subject: [PATCH 065/224] feat(conformance): validate implementation flags (#3715) * feat(conformance): validate implementation flags Signed-off-by: Mattia Lavacca * chore: gofumpt Signed-off-by: Mattia Lavacca --------- Signed-off-by: Mattia Lavacca --- conformance/conformance.go | 5 +- conformance/utils/suite/suite.go | 26 +++++++- conformance/utils/suite/suite_test.go | 86 +++++++++++++++++++++++++++ pkg/test/cel/grpcroute_test.go | 3 +- 4 files changed, 114 insertions(+), 6 deletions(-) diff --git a/conformance/conformance.go b/conformance/conformance.go index 12e5884968..8ea5799e58 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -72,13 +72,14 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { namespaceAnnotations := suite.ParseKeyValuePairs(*flags.NamespaceAnnotations) conformanceProfiles := suite.ParseConformanceProfiles(*flags.ConformanceProfiles) - implementation := suite.ParseImplementation( + implementation, err := suite.ParseImplementation( *flags.ImplementationOrganization, *flags.ImplementationProject, *flags.ImplementationURL, *flags.ImplementationVersion, *flags.ImplementationContact, ) + require.NoError(t, err, "error parsing implementation details") return suite.ConformanceOptions{ AllowCRDsMismatch: *flags.AllowCRDsMismatch, @@ -92,7 +93,7 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { ExemptFeatures: exemptFeatures, ManifestFS: []fs.FS{&Manifests}, GatewayClassName: *flags.GatewayClassName, - Implementation: implementation, + Implementation: *implementation, Mode: *flags.Mode, NamespaceAnnotations: namespaceAnnotations, NamespaceLabels: namespaceLabels, diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index f1164fa2fe..2402821e6f 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io/fs" + neturl "net/url" "slices" "sort" "strings" @@ -558,14 +559,33 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) { // ParseImplementation parses implementation-specific flag arguments and // creates a *confv1a1.Implementation. -func ParseImplementation(org, project, url, version, contact string) confv1.Implementation { - return confv1.Implementation{ +func ParseImplementation(org, project, url, version, contact string) (*confv1.Implementation, error) { + if org == "" { + return nil, errors.New("organization must be set") + } + if project == "" { + return nil, errors.New("project must be set") + } + if url == "" { + return nil, errors.New("url must be set") + } + if version == "" { + return nil, errors.New("version must be set") + } + if contact == "" { + return nil, errors.New("contact must be set") + } + if _, err := neturl.ParseRequestURI(url); err != nil { + return nil, errors.New("url is malformed") + } + + return &confv1.Implementation{ Organization: org, Project: project, URL: url, Version: version, Contact: strings.Split(contact, ","), - } + }, nil } // ParseConformanceProfiles parses flag arguments and converts the string to diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index ccb259adb0..69b7d3d979 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -538,3 +538,89 @@ func namesToFeatureSet(names []string) FeaturesSet { } return featureSet } + +func TestParseImplementation(t *testing.T) { + testCases := []struct { + name string + org string + project string + url string + version string + contact string + expected *confv1.Implementation + expectedErr error + }{ + { + name: "missing organization", + project: "test-project", + url: "https://example.com", + version: "v1.0.0", + contact: "test@example.com", + expectedErr: errors.New("organization must be set"), + }, + { + name: "missing project", + org: "test-org", + url: "https://example.com", + version: "v1.0.0", + contact: "test@example.com", + expectedErr: errors.New("project must be set"), + }, + { + name: "missing url", + org: "test-org", + project: "test-project", + version: "v1.0.0", + contact: "test@example.com", + expectedErr: errors.New("url must be set"), + }, + { + name: "missing version", + org: "test-org", + project: "test-project", + url: "https://example.com", + contact: "test@example.com", + expectedErr: errors.New("version must be set"), + }, + { + name: "missing contact", + org: "test-org", + project: "test-project", + url: "https://example.com", + version: "v1.0.0", + expectedErr: errors.New("contact must be set"), + }, + { + name: "malformed url", + org: "test-org", + project: "test-project", + url: "invalid-url", + version: "v1.0.0", + contact: "test@example.com", + expectedErr: errors.New("url is malformed"), + }, + { + name: "valid input", + org: "test-org", + project: "test-project", + url: "https://example.com", + version: "v1.0.0", + contact: "test@example.com,test2@example.com", + expected: &confv1.Implementation{ + Organization: "test-org", + Project: "test-project", + URL: "https://example.com", + Version: "v1.0.0", + Contact: []string{"test@example.com", "test2@example.com"}, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := ParseImplementation(tc.org, tc.project, tc.url, tc.version, tc.contact) + assert.Equal(t, tc.expected, result) + assert.Equal(t, tc.expectedErr, err) + }) + } +} diff --git a/pkg/test/cel/grpcroute_test.go b/pkg/test/cel/grpcroute_test.go index 628de66ae9..2940ce3291 100644 --- a/pkg/test/cel/grpcroute_test.go +++ b/pkg/test/cel/grpcroute_test.go @@ -341,7 +341,8 @@ func TestGRPCRouteRule(t *testing.T) { } return rules }(), - }} + }, + } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { From 63921d1e14fee57b6c63d29cc1dafeee461820af Mon Sep 17 00:00:00 2001 From: Guilherme Cassolato Date: Thu, 3 Jul 2025 13:19:27 +0200 Subject: [PATCH 066/224] Move HTTPRouteRule and GRPCRouteRule 'name' fields to Standard (#3826) * Promote HTTPRouteRule and GRPCRouteRule 'name' fields to Standard Signed-off-by: Guilherme Cassolato * tests: conformance: httproute and grpcroute named rules Signed-off-by: Guilherme Cassolato * tests: mesh conformance tests for httproute Signed-off-by: Guilherme Cassolato * feature names: HTTPRouteNamedRouteRule and GRPCRouteNamedRouteRule Signed-off-by: Guilherme Cassolato * fix: mesh conformance features and object name/namespace Signed-off-by: Guilherme Cassolato * lint: fix var declaration and comment Signed-off-by: Guilherme Cassolato * different name for HTTPRouteRuleNamedRouteRule feature for mesh Signed-off-by: Guilherme Cassolato * conformance tests flagged as provisional Signed-off-by: Guilherme Cassolato * fix: typo Signed-off-by: Guilherme Cassolato --------- Signed-off-by: Guilherme Cassolato --- apis/v1/grpcroute_types.go | 1 - apis/v1/httproute_types.go | 1 - .../gateway.networking.k8s.io_grpcroutes.yaml | 9 +++ .../gateway.networking.k8s.io_httproutes.yaml | 18 +++++ conformance/tests/grpcroute-named-rule.go | 72 +++++++++++++++++++ conformance/tests/grpcroute-named-rule.yaml | 24 +++++++ conformance/tests/httproute-named-rule.go | 71 ++++++++++++++++++ conformance/tests/httproute-named-rule.yaml | 24 +++++++ .../tests/mesh/httproute-named-rule.go | 68 ++++++++++++++++++ .../tests/mesh/httproute-named-rule.yaml | 27 +++++++ geps/gep-995/index.md | 2 +- geps/gep-995/metadata.yaml | 2 +- mkdocs.yml | 2 +- pkg/features/grpcroute.go | 24 ++++++- pkg/features/httproute.go | 9 +++ pkg/features/mesh.go | 10 +++ pkg/generated/openapi/zz_generated.openapi.go | 4 +- 17 files changed, 360 insertions(+), 8 deletions(-) create mode 100644 conformance/tests/grpcroute-named-rule.go create mode 100644 conformance/tests/grpcroute-named-rule.yaml create mode 100644 conformance/tests/httproute-named-rule.go create mode 100644 conformance/tests/httproute-named-rule.yaml create mode 100644 conformance/tests/mesh/httproute-named-rule.go create mode 100644 conformance/tests/mesh/httproute-named-rule.yaml diff --git a/apis/v1/grpcroute_types.go b/apis/v1/grpcroute_types.go index 0cae5e5020..c6eeb0f3ea 100644 --- a/apis/v1/grpcroute_types.go +++ b/apis/v1/grpcroute_types.go @@ -156,7 +156,6 @@ type GRPCRouteRule struct { // // Support: Extended // +optional - // Name *SectionName `json:"name,omitempty"` // Matches define conditions used for matching the rule against incoming diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 6fec27d6e0..f0aa550559 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -138,7 +138,6 @@ type HTTPRouteRule struct { // // Support: Extended // +optional - // Name *SectionName `json:"name,omitempty"` // Matches define conditions used for matching the rule against incoming diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 3bbc0af4ca..4f7d8f1323 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -1760,6 +1760,15 @@ spec: type: object maxItems: 64 type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string type: object maxItems: 16 type: array diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 7f3b970a7a..8533381fc2 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2432,6 +2432,15 @@ spec: type: object maxItems: 64 type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string timeouts: description: |- Timeouts defines the timeouts that can be configured for an HTTP request. @@ -5227,6 +5236,15 @@ spec: type: object maxItems: 64 type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string timeouts: description: |- Timeouts defines the timeouts that can be configured for an HTTP request. diff --git a/conformance/tests/grpcroute-named-rule.go b/conformance/tests/grpcroute-named-rule.go new file mode 100644 index 0000000000..223e22b595 --- /dev/null +++ b/conformance/tests/grpcroute-named-rule.go @@ -0,0 +1,72 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + v1 "sigs.k8s.io/gateway-api/apis/v1" + pb "sigs.k8s.io/gateway-api/conformance/echo-basic/grpcechoserver" + "sigs.k8s.io/gateway-api/conformance/utils/grpc" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, GRPCRouteNamedRule) +} + +var GRPCRouteNamedRule = suite.ConformanceTest{ + ShortName: "GRPCRouteNamedRule", + Description: "An GRPCRoute with a named GRPCRouteRule", + Manifests: []string{"tests/grpcroute-named-rule.yaml"}, + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportGRPCRoute, + features.SupportGRPCRouteNamedRouteRule, + }, + Provisional: true, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "grpc-named-rules", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, routeNN) + + testCases := []grpc.ExpectedResponse{ + { + EchoRequest: &pb.EchoRequest{}, + Backend: "grpc-infra-backend-v1", + Namespace: ns, + }, { + EchoTwoRequest: &pb.EchoRequest{}, + Backend: "grpc-infra-backend-v2", + Namespace: ns, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.GRPCClient, suite.TimeoutConfig, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/grpcroute-named-rule.yaml b/conformance/tests/grpcroute-named-rule.yaml new file mode 100644 index 0000000000..fac94dbe2c --- /dev/null +++ b/conformance/tests/grpcroute-named-rule.yaml @@ -0,0 +1,24 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: grpc-named-rules + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - name: named-rule + matches: + - method: + service: gateway_api_conformance.echo_basic.grpcecho.GrpcEcho + method: Echo + backendRefs: + - name: grpc-infra-backend-v1 + port: 8080 + - matches: + - method: + service: gateway_api_conformance.echo_basic.grpcecho.GrpcEcho + method: EchoTwo + backendRefs: + - name: grpc-infra-backend-v2 + port: 8080 diff --git a/conformance/tests/httproute-named-rule.go b/conformance/tests/httproute-named-rule.go new file mode 100644 index 0000000000..77cdccc567 --- /dev/null +++ b/conformance/tests/httproute-named-rule.go @@ -0,0 +1,71 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteNamedRule) +} + +var HTTPRouteNamedRule = suite.ConformanceTest{ + ShortName: "HTTPRouteNamedRule", + Description: "An HTTPRoute with a named HTTPRouteRule", + Manifests: []string{"tests/httproute-named-rule.yaml"}, + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportHTTPRouteNamedRouteRule, + }, + Provisional: true, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-named-rules", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{Path: "/named"}, + Response: http.Response{StatusCode: 200}, + Namespace: ns, + }, { + Request: http.Request{Path: "/unnamed"}, + Response: http.Response{StatusCode: 200}, + Namespace: ns, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/httproute-named-rule.yaml b/conformance/tests/httproute-named-rule.yaml new file mode 100644 index 0000000000..eb95c2cf03 --- /dev/null +++ b/conformance/tests/httproute-named-rule.yaml @@ -0,0 +1,24 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-named-rules + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - name: named-rule + matches: + - path: + type: PathPrefix + value: /named + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /unnamed + backendRefs: + - name: infra-backend-v2 + port: 8080 diff --git a/conformance/tests/mesh/httproute-named-rule.go b/conformance/tests/mesh/httproute-named-rule.go new file mode 100644 index 0000000000..9c7faf122e --- /dev/null +++ b/conformance/tests/mesh/httproute-named-rule.go @@ -0,0 +1,68 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteNamedRule) +} + +var MeshHTTPRouteNamedRule = suite.ConformanceTest{ + ShortName: "MeshHTTPRouteNamedRule", + Description: "An HTTPRoute with a named HTTPRouteRule", + Manifests: []string{"tests/mesh/httproute-named-rule.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportHTTPRoute, + features.SupportMeshHTTPRouteNamedRouteRule, + }, + Provisional: true, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-mesh" + client := echo.ConnectToApp(t, suite, echo.MeshAppEchoV1) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{Path: "/named"}, + ExpectedRequest: &http.ExpectedRequest{Request: http.Request{Path: "/named"}}, + Backend: "echo-v1", + Namespace: ns, + }, { + Request: http.Request{Path: "/unnamed"}, + ExpectedRequest: &http.ExpectedRequest{Request: http.Request{Path: "/named"}}, + Backend: "echo-v2", + Namespace: ns, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, suite.TimeoutConfig) + }) + } + }, +} diff --git a/conformance/tests/mesh/httproute-named-rule.yaml b/conformance/tests/mesh/httproute-named-rule.yaml new file mode 100644 index 0000000000..9075968512 --- /dev/null +++ b/conformance/tests/mesh/httproute-named-rule.yaml @@ -0,0 +1,27 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: mesh-http-named-rules + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 80 + rules: + - name: named-rule + matches: + - path: + type: PathPrefix + value: /named + backendRefs: + - name: echo-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /unnamed + backendRefs: + - name: echo-v2 + port: 8080 diff --git a/geps/gep-995/index.md b/geps/gep-995/index.md index 972fde1080..25c40c747f 100644 --- a/geps/gep-995/index.md +++ b/geps/gep-995/index.md @@ -1,7 +1,7 @@ # GEP-995: Named route rules * Issue: [#995](https://github.com/kubernetes-sigs/gateway-api/issues/995) -* Status: Experimental +* Status: Standard ## TLDR diff --git a/geps/gep-995/metadata.yaml b/geps/gep-995/metadata.yaml index 547d7bfdfa..2552744a95 100644 --- a/geps/gep-995/metadata.yaml +++ b/geps/gep-995/metadata.yaml @@ -2,7 +2,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 995 name: Named route rules -status: Experimental +status: Standard authors: - guicassolato changelog: diff --git a/mkdocs.yml b/mkdocs.yml index 1753230778..7765e320d3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -137,7 +137,6 @@ nav: - geps/gep-91/index.md - geps/gep-3567/index.md - Experimental: - - geps/gep-995/index.md - geps/gep-1619/index.md - geps/gep-1713/index.md - geps/gep-1731/index.md @@ -158,6 +157,7 @@ nav: - geps/gep-820/index.md - geps/gep-851/index.md - geps/gep-957/index.md + - geps/gep-995/index.md - geps/gep-1016/index.md - geps/gep-1294/index.md - geps/gep-1323/index.md diff --git a/pkg/features/grpcroute.go b/pkg/features/grpcroute.go index ffa3f38318..3ee21b41f5 100644 --- a/pkg/features/grpcroute.go +++ b/pkg/features/grpcroute.go @@ -19,7 +19,7 @@ package features import "k8s.io/apimachinery/pkg/util/sets" // ----------------------------------------------------------------------------- -// Features - GRPCRoute Conformance +// Features - GRPCRoute Conformance (Core) // ----------------------------------------------------------------------------- const ( @@ -38,3 +38,25 @@ var GRPCRouteFeature = Feature{ var GRPCRouteCoreFeatures = sets.New( GRPCRouteFeature, ) + +// ----------------------------------------------------------------------------- +// Features - GRPCRoute Conformance (Extended) +// ----------------------------------------------------------------------------- + +const ( + // This option indicates support for the name field in the GRPCRouteRule (extended conformance) + SupportGRPCRouteNamedRouteRule FeatureName = "GRPCRouteNamedRouteRule" +) + +// GRPCRouteNamedRouteRule contains metadata for the SupportGRPCRouteNamedRouteRule feature. +var GRPCRouteNamedRouteRule = Feature{ + Name: SupportGRPCRouteNamedRouteRule, + Channel: FeatureChannelStandard, +} + +// GRPCRouteExtendedFeatures includes all extended features for GRPCRoute +// conformance and can be used to opt-in to run all GRPCRoute extended features tests. +// This does not include any Core Features. +var GRPCRouteExtendedFeatures = sets.New( + GRPCRouteNamedRouteRule, +) diff --git a/pkg/features/httproute.go b/pkg/features/httproute.go index dbc62ce1a0..6c484da96c 100644 --- a/pkg/features/httproute.go +++ b/pkg/features/httproute.go @@ -97,6 +97,9 @@ const ( // This option indicates support for HTTPRoute with a backendref with an appProtocol 'kubernetes.io/ws' (extended conformance) SupportHTTPRouteBackendProtocolWebSocket FeatureName = "HTTPRouteBackendProtocolWebSocket" + + // This option indicates support for the name field in the HTTPRouteRule (extended conformance) + SupportHTTPRouteNamedRouteRule FeatureName = "HTTPRouteNamedRouteRule" ) var ( @@ -190,6 +193,11 @@ var ( Name: SupportHTTPRouteBackendProtocolWebSocket, Channel: FeatureChannelStandard, } + // HTTPRouteNamedRouteRule contains metadata for the SupportHTTPRouteNamedRouteRule feature. + HTTPRouteNamedRouteRule = Feature{ + Name: SupportHTTPRouteNamedRouteRule, + Channel: FeatureChannelStandard, + } ) // HTTPRouteExtendedFeatures includes all extended features for HTTPRoute @@ -214,4 +222,5 @@ var HTTPRouteExtendedFeatures = sets.New( HTTPRouteParentRefPortFeature, HTTPRouteBackendProtocolH2CFeature, HTTPRouteBackendProtocolWebSocketFeature, + HTTPRouteNamedRouteRule, ) diff --git a/pkg/features/mesh.go b/pkg/features/mesh.go index 4d7ca20b29..910e3c9687 100644 --- a/pkg/features/mesh.go +++ b/pkg/features/mesh.go @@ -60,6 +60,8 @@ const ( SupportMeshHTTPRouteBackendRequestHeaderModification FeatureName = "MeshHTTPRouteBackendRequestHeaderModification" // This option indicates mesh support for HTTPRoute query param matching (extended conformance). SupportMeshHTTPRouteQueryParamMatching FeatureName = "MeshHTTPRouteQueryParamMatching" + // This option indicates support for the name field in the HTTPRouteRule (extended conformance) + SupportMeshHTTPRouteNamedRouteRule FeatureName = "MeshHTTPRouteNamedRouteRule" ) var ( @@ -103,11 +105,18 @@ var ( Name: SupportMeshHTTPRouteBackendRequestHeaderModification, Channel: FeatureChannelStandard, } + // MeshHTTPRouteRedirectPath contains metadata for the MeshHTTPRouteRedirectPath feature. MeshHTTPRouteQueryParamMatching = Feature{ Name: SupportMeshHTTPRouteQueryParamMatching, Channel: FeatureChannelStandard, } + + // MeshHTTPRouteNamedRouteRule contains metadata for the MeshHTTPRouteNamedRouteRule feature. + MeshHTTPRouteNamedRouteRule = Feature{ + Name: SupportMeshHTTPRouteNamedRouteRule, + Channel: FeatureChannelStandard, + } ) // MeshExtendedFeatures includes all the supported features for the service mesh at @@ -121,4 +130,5 @@ var MeshExtendedFeatures = sets.New( MeshHTTPRouteRedirectPath, MeshHTTPRouteBackendRequestHeaderModification, MeshHTTPRouteQueryParamMatching, + MeshHTTPRouteNamedRouteRule, ) diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index c91725bc50..99214c9fcd 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3439,7 +3439,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteRule(ref common.ReferenceCall Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Description: "Name is the name of the route rule. This name MUST be unique within a Route if it is set.\n\nSupport: Extended ", + Description: "Name is the name of the route rule. This name MUST be unique within a Route if it is set.\n\nSupport: Extended", Type: []string{"string"}, Format: "", }, @@ -5018,7 +5018,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteRule(ref common.ReferenceCall Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Description: "Name is the name of the route rule. This name MUST be unique within a Route if it is set.\n\nSupport: Extended ", + Description: "Name is the name of the route rule. This name MUST be unique within a Route if it is set.\n\nSupport: Extended", Type: []string{"string"}, Format: "", }, From 9f27e4ba99f1bd6ac2f04c7a0ee75f0078daa433 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 04:57:25 -0700 Subject: [PATCH 067/224] build(deps): bump golang.org/x/sync from 0.13.0 to 0.15.0 (#3889) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.13.0 to 0.15.0. - [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.15.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-version: 0.15.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9db23934e..53b9c32c69 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/miekg/dns v1.1.65 github.com/stretchr/testify v1.10.0 golang.org/x/net v0.39.0 - golang.org/x/sync v0.13.0 + golang.org/x/sync v0.15.0 google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 diff --git a/go.sum b/go.sum index 2b6eb53c72..75b64fe43f 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 4dcfc5618b184c504228a900dd41167298b5943a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:09:30 -0700 Subject: [PATCH 068/224] build(deps): bump github.com/miekg/dns from 1.1.65 to 1.1.66 (#3790) Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.65 to 1.1.66. - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](https://github.com/miekg/dns/compare/v1.1.65...v1.1.66) --- updated-dependencies: - dependency-name: github.com/miekg/dns dependency-version: 1.1.66 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 53b9c32c69..294f724987 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/elastic/crd-ref-docs v0.1.0 - github.com/miekg/dns v1.1.65 + github.com/miekg/dns v1.1.66 github.com/stretchr/testify v1.10.0 golang.org/x/net v0.39.0 golang.org/x/sync v0.15.0 @@ -67,13 +67,13 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.37.0 // indirect - golang.org/x/mod v0.23.0 // indirect + golang.org/x/mod v0.24.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/sys v0.32.0 // indirect golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.30.0 // indirect + golang.org/x/tools v0.32.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index 75b64fe43f..8e1d8223a4 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc= -github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= @@ -165,8 +165,8 @@ golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -199,8 +199,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 33e9aa990d0c159961edb123d50fcc2e02b86f59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:27:28 -0700 Subject: [PATCH 069/224] build(deps): bump sigs.k8s.io/controller-tools from 0.17.3 to 0.18.0 (#3791) Bumps [sigs.k8s.io/controller-tools](https://github.com/kubernetes-sigs/controller-tools) from 0.17.3 to 0.18.0. - [Release notes](https://github.com/kubernetes-sigs/controller-tools/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-tools/blob/main/envtest-releases.yaml) - [Commits](https://github.com/kubernetes-sigs/controller-tools/compare/v0.17.3...v0.18.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-tools dependency-version: 0.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 294f724987..0819f5d332 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.20.4 - sigs.k8s.io/controller-tools v0.17.3 + sigs.k8s.io/controller-tools v0.18.0 sigs.k8s.io/structured-merge-diff/v4 v4.7.0 sigs.k8s.io/yaml v1.4.0 ) diff --git a/go.sum b/go.sum index 8e1d8223a4..bbde100af4 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -250,8 +250,8 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6J k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= -sigs.k8s.io/controller-tools v0.17.3 h1:lwFPLicpBKLgIepah+c8ikRBubFW5kOQyT88r3EwfNw= -sigs.k8s.io/controller-tools v0.17.3/go.mod h1:1ii+oXcYZkxcBXzwv3YZBlzjt1fvkrCGjVF73blosJI= +sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE= +sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= From 3c2c3d90d3a1ce92fb58f493e468f2a02fde5bca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:27:35 -0700 Subject: [PATCH 070/224] build(deps): bump mkdocs-material in /hack/mkdocs/image (#3797) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.11 to 9.6.14. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.11...9.6.14) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 6164a48242..896f6e0ca6 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -10,7 +10,7 @@ MarkupSafe==3.0.2 mkdocs==1.6.1 mkdocs-awesome-pages-plugin==2.10.1 mkdocs-macros-plugin==1.3.7 -mkdocs-material==9.6.11 +mkdocs-material==9.6.15 mkdocs-redirects==1.2.2 mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 From 67456850b0b8ebc0365d1de6b74ead35e5ae22e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:27:41 -0700 Subject: [PATCH 071/224] build(deps): bump tornado from 6.4.2 to 6.5.1 in /hack/mkdocs/image (#3815) Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.4.2 to 6.5.1. - [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst) - [Commits](https://github.com/tornadoweb/tornado/compare/v6.4.2...v6.5.1) --- updated-dependencies: - dependency-name: tornado dependency-version: 6.5.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 896f6e0ca6..4dfa0a2359 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -20,4 +20,4 @@ pymdown-extensions==10.14.3 PyYAML==6.0.2 six==1.17.0 tabulate==0.9.0 -tornado==6.4.2 \ No newline at end of file +tornado==6.5.1 \ No newline at end of file From 3987a0814e49d925e69438d847033d1e4ff63d51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:27:48 -0700 Subject: [PATCH 072/224] build(deps): bump pymdown-extensions in /hack/mkdocs/image (#3878) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.14.3 to 10.16. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.14.3...10.16) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: '10.16' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 4dfa0a2359..3550d265df 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -16,7 +16,7 @@ mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 pep562==1.1 Pygments==2.19.1 -pymdown-extensions==10.14.3 +pymdown-extensions==10.16 PyYAML==6.0.2 six==1.17.0 tabulate==0.9.0 From e6eff8779d3355ca2629726426c3f2c82c3e8ab8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 06:43:26 -0700 Subject: [PATCH 073/224] build(deps): bump pygments from 2.19.1 to 2.19.2 in /hack/mkdocs/image (#3879) Bumps [pygments](https://github.com/pygments/pygments) from 2.19.1 to 2.19.2. - [Release notes](https://github.com/pygments/pygments/releases) - [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES) - [Commits](https://github.com/pygments/pygments/compare/2.19.1...2.19.2) --- updated-dependencies: - dependency-name: pygments dependency-version: 2.19.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 3550d265df..a075a43182 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -15,7 +15,7 @@ mkdocs-redirects==1.2.2 mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 pep562==1.1 -Pygments==2.19.1 +Pygments==2.19.2 pymdown-extensions==10.16 PyYAML==6.0.2 six==1.17.0 From 1b2b35fadc59c34fa95f6c1166ee6a02e23ef857 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 07:03:26 -0700 Subject: [PATCH 074/224] build(deps): bump golang.org/x/net from 0.39.0 to 0.41.0 (#3843) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.39.0 to 0.41.0. - [Commits](https://github.com/golang/net/compare/v0.39.0...v0.41.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-version: 0.41.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 0819f5d332..60ab92ab6c 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/elastic/crd-ref-docs v0.1.0 github.com/miekg/dns v1.1.66 github.com/stretchr/testify v1.10.0 - golang.org/x/net v0.39.0 + golang.org/x/net v0.41.0 golang.org/x/sync v0.15.0 google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 @@ -66,14 +66,14 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/mod v0.24.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/mod v0.25.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.26.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.32.0 // indirect + golang.org/x/tools v0.33.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index bbde100af4..599f1c0700 100644 --- a/go.sum +++ b/go.sum @@ -161,18 +161,18 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -185,22 +185,22 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From a241e4a9624df39ac8792753e5a9f085eca6dda1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 07:03:33 -0700 Subject: [PATCH 075/224] build(deps): bump sigs.k8s.io/controller-runtime from 0.20.4 to 0.21.0 (#3858) Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.20.4 to 0.21.0. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.20.4...v0.21.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 60ab92ab6c..a2eca0cfc6 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( k8s.io/code-generator v0.33.2 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/controller-runtime v0.20.4 + sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/controller-tools v0.18.0 sigs.k8s.io/structured-merge-diff/v4 v4.7.0 sigs.k8s.io/yaml v1.4.0 diff --git a/go.sum b/go.sum index 599f1c0700..e08b99f8e9 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -248,8 +250,8 @@ k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUy k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= -sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= +sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE= sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= From ef544aefc24b9974ad752006025633ace19e4975 Mon Sep 17 00:00:00 2001 From: Kundan Kumar Date: Thu, 3 Jul 2025 23:11:25 +0530 Subject: [PATCH 076/224] kubecon talk link updated. (#3660) * kubecon talk link updated. * Update site-src/contributing/index.md Co-authored-by: Nick Young * Apply suggestions from code review --------- Co-authored-by: Shane Utt Co-authored-by: Nick Young --- site-src/contributing/index.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/site-src/contributing/index.md b/site-src/contributing/index.md index 613b15decc..05798beb42 100644 --- a/site-src/contributing/index.md +++ b/site-src/contributing/index.md @@ -102,13 +102,35 @@ service mesh use cases can be found in a separate | Date | Title | | |----------------|-------|----| -| November, 2019 | [Kubecon 2019 San Diego: Evolving the Kubernetes Ingress APIs to GA and Beyond][2019-kubecon-na-slides] | [slides][2019-kubecon-na-slides], [video][2019-kubecon-na-video]| +| Mar, 2024 | Kubecon 2024 Paris: Configuring Your Service Mesh with Gateway API | [video][2024-kubecon-video-1]| +| Mar, 2024 | Kubecon 2024 Paris: Gateway API: Beyond GA | [video][2024-kubecon-video-2]| +| Mar, 2024 | Kubecon 2024 Paris: Tutorial: Configuring Your Service Mesh with Gateway API | [video][2024-kubecon-video-3]| +| Oct, 2023 | Kubecon 2023 Chicago: Gateway API: The Most Collaborative API in Kubernetes History Is GA | [video][2023-kubecon-video-3]| +| May, 2023 | Kubecon 2023 Amsterdam: Emissary-Ingress: Self-Service APIs and the Kubernetes Gateway API | [video][2023-kubecon-video-1]| +| May, 2023 | Kubecon 2023 Amsterdam: Exiting Ingress 201: A Primer on Extension Mechanisms in Gateway API | [video][2023-kubecon-video-2]| +| Oct, 2022 | Kubecon 2022 Detroit: One API To Rule Them All? What the Gateway API Means For Service Meshes | [video][2022-kubecon-video-4]| +| Oct, 2022 | Kubecon 2022 Detroit: Exiting Ingress With the Gateway API | [video][2022-kubecon-video-3]| +| Oct, 2022 | Kubecon 2022 Detroit: Flagger, Linkerd, And Gateway API: Oh My! | [video][2022-kubecon-video-2]| +| May, 2022 | Kubecon 2022 Valencia: Gateway API: Beta to GA | [video][2022-kubecon-video-1]| +| May, 2021 | Kubecon 2021 Virtual: Google Cloud - Multi-cluster, Blue-green Traffic Splitting with the Gateway API | [video][2021-kubecon-video-2]| +| May, 2021 | Kubecon 2021 Virtual: Gateway API: A New Set of Kubernetes APIs for Advanced Traffic Routing | [video][2021-kubecon-video-1]| +| November, 2019 | Kubecon 2019 San Diego: Evolving the Kubernetes Ingress APIs to GA and Beyond | [video][2019-kubecon-na-video]| | November, 2019 | Kubecon 2019 San Diego: SIG-NETWORK Service/Ingress Evolution Discussion | [slides][2019-kubecon-na-community-slides] | | May, 2019 | [Kubecon 2019 Barcelona: Ingress V2 and Multicluster Services][2019-kubecon-eu] | [slides][2019-kubecon-eu-slides], [video][2019-kubecon-eu-video]| | March, 2018 | SIG-NETWORK: Ingress user survey | [data][survey-data], [slides][survey-slides] | -[2019-kubecon-na]: https://kccncna19.sched.com/event/UaYG/evolving-the-kubernetes-ingress-apis-to-ga-and-beyond-christopher-m-luciano-ibm-bowei-du-google -[2019-kubecon-na-slides]: https://static.sched.com/hosted_files/kccncna19/a5/Kubecon%20San%20Diego%202019%20-%20Evolving%20the%20Kubernetes%20Ingress%20APIs%20to%20GA%20and%20Beyond%20%5BPUBLIC%5D.pdf +[2024-kubecon-video-1]: https://www.youtube.com/watch?v=UMGRp0fGk3o +[2024-kubecon-video-2]: https://www.youtube.com/watch?v=LITg6TvctjM +[2024-kubecon-video-3]: https://www.youtube.com/watch?v=UMGRp0fGk3o +[2023-kubecon-video-3]: https://www.youtube.com/watch?v=V3Vu_FWb4l4 +[2023-kubecon-video-1]: https://www.youtube.com/watch?v=piDYmZObh_M +[2023-kubecon-video-2]: https://www.youtube.com/watch?v=7P55G8GsYRs: +[2022-kubecon-video-4]: https://www.youtube.com/watch?v=vYGP5XdP2TA +[2022-kubecon-video-3]: https://www.youtube.com/watch?v=sTQv4QOC-TI +[2022-kubecon-video-2]: https://www.youtube.com/watch?v=9Ag45POgnKw +[2022-kubecon-video-1]: https://www.youtube.com/watch?v=YPiuicxC8UU +[2021-kubecon-video-2]: https://www.youtube.com/watch?v=vs8YrjdRJJU +[2021-kubecon-video-1]: https://www.youtube.com/watch?v=lCRuzWFJBO0 [2019-kubecon-na-video]: https://www.youtube.com/watch?v=cduG0FrjdJA [2019-kubecon-eu]: https://kccnceu19.sched.com/event/MPb6/ingress-v2-and-multicluster-services-rohit-ramkumar-bowei-du-google [2019-kubecon-eu-slides]: https://static.sched.com/hosted_files/kccnceu19/97/%5Bwith%20speaker%20notes%5D%20Kubecon%20EU%202019_%20Ingress%20V2%20%26%20Multi-Cluster%20Services.pdf From 28504b14171ca202859e572cb8d0680cd71c36d9 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Fri, 4 Jul 2025 09:01:25 +0200 Subject: [PATCH 077/224] gep: update the possible statuses in GEP-696 (#3901) Signed-off-by: Mattia Lavacca --- geps/gep-696/index.md | 2 +- geps/gep-696/metadata.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/geps/gep-696/index.md b/geps/gep-696/index.md index 4a4a97dd19..6082b30907 100644 --- a/geps/gep-696/index.md +++ b/geps/gep-696/index.md @@ -1,7 +1,7 @@ # GEP-696: GEP template * Issue: [#696](https://github.com/kubernetes-sigs/gateway-api/issues/696) -* Status: Provisional|Implementable|Experimental|Standard|Deferred|Rejected|Withdrawn|Replaced +* Status: Provisional|Prototyping|Implementable|Experimental|Standard|Completed|Memorandum|Deferred|Declined|Withdrawn (See [status definitions](../overview.md#gep-states).) diff --git a/geps/gep-696/metadata.yaml b/geps/gep-696/metadata.yaml index 0eedd6cabe..cc3c2ce20f 100644 --- a/geps/gep-696/metadata.yaml +++ b/geps/gep-696/metadata.yaml @@ -10,6 +10,7 @@ authors: - robscott - youngnick - dprotaso + - mlavacca relationships: # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field From 24803c32d8070e38cf90f020987d4d3656ad5896 Mon Sep 17 00:00:00 2001 From: Saylor Berman Date: Tue, 8 Jul 2025 17:05:26 -0600 Subject: [PATCH 078/224] Update NGINX Gateway Fabric conformance (#3907) Missed a conformance test in the report that is passing. --- .../experimental-2.0.0-default-report.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml index d6d0353a10..571ab045c8 100644 --- a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml +++ b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.0.0-default-report.yaml @@ -25,11 +25,11 @@ profiles: Passed: 1 Skipped: 0 supportedFeatures: + - GatewayAddressEmpty - GatewayHTTPListenerIsolation - GatewayInfrastructurePropagation - GatewayPort8080 unsupportedFeatures: - - GatewayAddressEmpty - GatewayStaticAddresses name: GATEWAY-GRPC summary: Core tests succeeded. Extended tests succeeded. @@ -43,9 +43,10 @@ profiles: result: success statistics: Failed: 0 - Passed: 14 + Passed: 15 Skipped: 0 supportedFeatures: + - GatewayAddressEmpty - GatewayHTTPListenerIsolation - GatewayInfrastructurePropagation - GatewayPort8080 @@ -60,7 +61,6 @@ profiles: - HTTPRouteResponseHeaderModification - HTTPRouteSchemeRedirect unsupportedFeatures: - - GatewayAddressEmpty - GatewayStaticAddresses - HTTPRouteBackendProtocolH2C - HTTPRouteBackendProtocolWebSocket @@ -85,11 +85,11 @@ profiles: Passed: 1 Skipped: 0 supportedFeatures: + - GatewayAddressEmpty - GatewayHTTPListenerIsolation - GatewayInfrastructurePropagation - GatewayPort8080 unsupportedFeatures: - - GatewayAddressEmpty - GatewayStaticAddresses name: GATEWAY-TLS summary: Core tests succeeded. Extended tests succeeded. From 2322922004a5d4d4f4bf2d49d82717f1f38c33a4 Mon Sep 17 00:00:00 2001 From: John Howard Date: Wed, 9 Jul 2025 15:55:27 -0700 Subject: [PATCH 079/224] conformance: add Agent Gateway (#3908) * conformance: add Agent Gateway * Update site-src/implementations.md Co-authored-by: Rob Scott --------- Co-authored-by: Rob Scott --- .../agentgateway-agentgateway/README.md | 22 ++++++++ .../experimental-0.6.0-report.yaml | 55 +++++++++++++++++++ site-src/implementations.md | 7 +++ 3 files changed, 84 insertions(+) create mode 100644 conformance/reports/v1.3.0/agentgateway-agentgateway/README.md create mode 100644 conformance/reports/v1.3.0/agentgateway-agentgateway/experimental-0.6.0-report.yaml diff --git a/conformance/reports/v1.3.0/agentgateway-agentgateway/README.md b/conformance/reports/v1.3.0/agentgateway-agentgateway/README.md new file mode 100644 index 0000000000..2f3ce8ab39 --- /dev/null +++ b/conformance/reports/v1.3.0/agentgateway-agentgateway/README.md @@ -0,0 +1,22 @@ +# Agent Gateway (with kgateway) + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|experimental|[v0.6.0]|default|[report](./experimental-0.6.0-report.yaml)| + +## Reproduce + +``` +go test./conformance -run TestConformance -args \ + --report-output /tmp/report.yaml \ + --conformance-profiles=GATEWAY-HTTP \ + --gateway-class agentgateway \ + --all-features \ + --organization agentgateway \ + --project agentgateway \ + --url http://agentgateway.dev/ \ + --version v0.6.0-dev \ + --contact "github.com/agentgateway/agentgateway/issues/new/choose" +``` diff --git a/conformance/reports/v1.3.0/agentgateway-agentgateway/experimental-0.6.0-report.yaml b/conformance/reports/v1.3.0/agentgateway-agentgateway/experimental-0.6.0-report.yaml new file mode 100644 index 0000000000..459ca1196f --- /dev/null +++ b/conformance/reports/v1.3.0/agentgateway-agentgateway/experimental-0.6.0-report.yaml @@ -0,0 +1,55 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-07-09T12:34:09-07:00" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - github.com/agentgateway/agentgateway/issues/new/choose + organization: agentgateway + project: agentgateway + url: http://agentgateway.dev/ + version: v0.6.0-dev +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 25 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure +- HTTPRouteRequestPercentageMirror diff --git a/site-src/implementations.md b/site-src/implementations.md index 1b11204072..93f6dc2c89 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -84,6 +84,7 @@ other functions (like managing DNS or creating certificates). ## Gateway Controller Implementation Status - [Acnodal EPIC][1] +- [Agent Gateway][40] - [Airlock Microgateway][34] - [Amazon Elastic Kubernetes Service][23] (GA) - [Apache APISIX][2] (beta) @@ -168,6 +169,7 @@ other functions (like managing DNS or creating certificates). [37]:#kgateway [38]:#google-cloud-service-mesh [39]:#kubvernor +[40]:#agentgateway-with-kgateway [gamma]:mesh/index.md @@ -187,6 +189,11 @@ In this section you will find specific links to blog posts, documentation and ot [epicdocs]:https://www.epic-gateway.org/ [epicsource]:https://github.com/epic-gateway +### Agent Gateway (with Kgateway) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Agentgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/airlock-microgateway) + +[Agent Gateway](https://agentgateway.dev/) is an open source Gateway API implementation focusing on AI use cases, including LLM consumption, LLM serving, agent-to-agent ([A2A](https://a2aproject.github.io/A2A/latest/)), and agent-to-tool ([MCP](https://modelcontextprotocol.io/introduction)). It is the first and only proxy designed specifically for the Kubernetes Gateway API, powered by a high performance and scalable Rust dataplane implementation. + ### Airlock Microgateway [![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Airlock%20Microgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/airlock-microgateway) From 682a03fefa41037adc8863ba80e17eca1fbe6f1f Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 10 Jul 2025 08:55:47 -0400 Subject: [PATCH 080/224] docs: update GEP 1767 to remove TrueField type Signed-off-by: Shane Utt --- geps/gep-1767/index.md | 84 +++++++++++++++++++++++++------------ geps/gep-1767/metadata.yaml | 1 + 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/geps/gep-1767/index.md b/geps/gep-1767/index.md index 3f1018bdb1..c115dbf116 100644 --- a/geps/gep-1767/index.md +++ b/geps/gep-1767/index.md @@ -129,16 +129,6 @@ If `HTTPCORSFilter` is set, then the gateway will generate the response of the " For the actual cross-origin request, the gateway will add CORS headers to the response before it is sent to the client. ```golang -// AllowCredentialsType describes valid value of config `AllowCredentials`. -// -// +kubebuilder:validation:Enum=true -type AllowCredentialsType string - -const ( - // The actual cross-origin request allows to include credentials. - AllowCredentials AllowCredentialsType = "true" -) - const ( // HTTPRouteFilterCORS can be used to add CORS headers to an // HTTP response before it is sent to the client. @@ -222,7 +212,7 @@ type HTTPCORSFilter struct { // Output: // // The `Access-Control-Allow-Origin` response header can only use `*` - // wildcard as value when the `AllowCredentials` field is unspecified. + // wildcard as value when the `AllowCredentials` field is false. // // Input: // Origin: https://foo.example @@ -233,7 +223,7 @@ type HTTPCORSFilter struct { // Output: // Access-Control-Allow-Origin: * // - // When the `AllowCredentials` field is specified and `AllowOrigins` + // When the `AllowCredentials` field is true and `AllowOrigins` // field specified with the `*` wildcard, the gateway must return a // single origin in the value of the `Access-Control-Allow-Origin` // response header, instead of specifying the `*` wildcard. The value @@ -259,8 +249,8 @@ type HTTPCORSFilter struct { // AllowCredentials indicates whether the actual cross-origin request // allows to include credentials. // - // The only valid value for the `Access-Control-Allow-Credentials` - // response header is true (case-sensitive). + // When set to true, the gateway will include the `Access-Control-Allow-Credentials` + // response header with value true (case-sensitive). // // Input: // Origin: https://foo.example @@ -272,14 +262,12 @@ type HTTPCORSFilter struct { // Access-Control-Allow-Origin: https://foo.example // Access-Control-Allow-Credentials: true // - // If the credentials are not allowed in cross-origin requests, - // the gateway will omit the header `Access-Control-Allow-Credentials` - // entirely rather than setting its value to false. + // When set to false, the gateway will omit the header + // `Access-Control-Allow-Credentials` entirely (this is the standard CORS + // behavior). // // Support: Extended - // - // +optional - AllowCredentials AllowCredentialsType `json:"allowCredentials,omitempty"` + AllowCredentials *bool `json:"allowCredentials,omitempty"` // AllowMethods indicates which HTTP methods are supported // for accessing the requested resource. @@ -317,7 +305,7 @@ type HTTPCORSFilter struct { // Access-Control-Allow-Methods: GET, POST, DELETE, PATCH, OPTIONS // // The `Access-Control-Allow-Methods` response header can only use `*` - // wildcard as value when the `AllowCredentials` field is unspecified. + // wildcard as value when the `AllowCredentials` field is false. // // Input: // Access-Control-Request-Method: PUT @@ -328,7 +316,7 @@ type HTTPCORSFilter struct { // Output: // Access-Control-Allow-Methods: * // - // When the `AllowCredentials` field is specified and `AllowMethods` + // When the `AllowCredentials` field is true and the `AllowMethods` // field specified with the `*` wildcard, the gateway must specify one // HTTP method in the value of the Access-Control-Allow-Methods response // header. The value of the header `Access-Control-Allow-Methods` is same @@ -386,7 +374,7 @@ type HTTPCORSFilter struct { // // A wildcard indicates that the requests with all HTTP headers are allowed. // The `Access-Control-Allow-Headers` response header can only use `*` wildcard - // as value when the `AllowCredentials` field is unspecified. + // as value when the `AllowCredentials` field is false. // // Input: // Access-Control-Request-Headers: Content-Type, Cache-Control @@ -397,8 +385,8 @@ type HTTPCORSFilter struct { // Output: // Access-Control-Allow-Headers: * // - // When the `AllowCredentials` field is specified and `AllowHeaders` field - // specified with the `*` wildcard, the gateway must specify one or more + // When the `AllowCredentials` field is true and the `AllowHeaders` field + // is specified with the `*` wildcard, the gateway must specify one or more // HTTP headers in the value of the `Access-Control-Allow-Headers` response // header. The value of the header `Access-Control-Allow-Headers` is same as // the `Access-Control-Request-Headers` header provided by the client. If @@ -456,7 +444,7 @@ type HTTPCORSFilter struct { // // A wildcard indicates that the responses with all HTTP headers are exposed // to clients. The `Access-Control-Expose-Headers` response header can only use - // `*` wildcard as value when the `AllowCredentials` field is unspecified. + // `*` wildcard as value when the `AllowCredentials` field is false. // // Config: // exposeHeaders: ["*"] @@ -590,7 +578,7 @@ spec: - allowOrigins: - https://foo.example - http://foo.example - allowCredentials: "true" + allowCredentials: true allowMethods: - GET - PUT @@ -656,6 +644,48 @@ Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Request Access-Control-Expose-Headers: Content-Security-Policy ``` +### Disabling credentials + +To disable credentials for cross-origin requests, simply don't set the +`allowCredentials` field at all. If you prefer to be explicit, you can +set it to `false`, although this will generally not be necessary: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-route-cors-no-credentials +spec: + hostnames: + - http.route.cors.com + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: http-gateway + rules: + - backendRefs: + - kind: Service + name: http-route-cors + port: 80 + matches: + - path: + type: PathPrefix + value: /resource/bar + filters: + - cors: + allowOrigins: + - https://foo.example + allowCredentials: false + allowMethods: + - GET + - POST + type: CORS +``` + +Omitting the field, and setting it to `false` both mean `false`. In this +configuration the gateway will _not_ include the +`Access-Control-Allow-Credentials` header in responses. + ## Prior Art Some implementations already support CORS. diff --git a/geps/gep-1767/metadata.yaml b/geps/gep-1767/metadata.yaml index c7fe532b81..e319aacd1c 100644 --- a/geps/gep-1767/metadata.yaml +++ b/geps/gep-1767/metadata.yaml @@ -7,6 +7,7 @@ authors: - lianglli - robscott - EyalPazz + - shaneutt references: - https://github.com/kubernetes-sigs/gateway-api/pull/3435 - https://github.com/kubernetes-sigs/gateway-api/pull/3637 From b8de0b89f98e9d6458edf017ce6d08fa5f5543fb Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 10 Jul 2025 08:54:59 -0400 Subject: [PATCH 081/224] chore: remove the TrueField API type Signed-off-by: Shane Utt --- apis/v1/httproute_types.go | 2 +- apis/v1/shared_types.go | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index f0aa550559..93d4f4d4b3 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1371,7 +1371,7 @@ type HTTPCORSFilter struct { // Support: Extended // // +optional - AllowCredentials TrueField `json:"allowCredentials,omitempty"` + AllowCredentials *bool `json:"allowCredentials,omitempty"` // AllowMethods indicates which HTTP methods are supported for accessing the // requested resource. diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index e059b98145..226c776372 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -764,11 +764,6 @@ type HeaderName string // +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` type Duration string -// TrueField is a boolean value that can only be set to true -// -// +kubebuilder:validation:Enum=true -type TrueField bool - const ( // A textual representation of a numeric IP address. IPv4 // addresses must be in dotted-decimal form. IPv6 addresses From 8d0a087933462069f4eb102c56da3c061f653009 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 10 Jul 2025 08:56:10 -0400 Subject: [PATCH 082/224] docs: update godoc for new AllowCredentials Signed-off-by: Shane Utt --- apis/v1/httproute_types.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 93d4f4d4b3..e59ebf7bcc 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1344,9 +1344,9 @@ type HTTPCORSFilter struct { // Therefore, the client doesn't attempt the actual cross-origin request. // // The `Access-Control-Allow-Origin` response header can only use `*` - // wildcard as value when the `AllowCredentials` field is unspecified. + // wildcard as value when the `AllowCredentials` field is false or omitted. // - // When the `AllowCredentials` field is specified and `AllowOrigins` field + // When the `AllowCredentials` field is true and `AllowOrigins` field // specified with the `*` wildcard, the gateway must return a single origin // in the value of the `Access-Control-Allow-Origin` response header, // instead of specifying the `*` wildcard. The value of the header @@ -1361,12 +1361,12 @@ type HTTPCORSFilter struct { // AllowCredentials indicates whether the actual cross-origin request allows // to include credentials. // - // The only valid value for the `Access-Control-Allow-Credentials` response - // header is true (case-sensitive). + // When set to true, the gateway will include the `Access-Control-Allow-Credentials` + // response header with value true (case-sensitive). // - // If the credentials are not allowed in cross-origin requests, the gateway - // will omit the header `Access-Control-Allow-Credentials` entirely rather - // than setting its value to false. + // When set to false or omitted the gateway will omit the header + // `Access-Control-Allow-Credentials` entirely (this is the standard CORS + // behavior). // // Support: Extended // @@ -1400,9 +1400,9 @@ type HTTPCORSFilter struct { // side. // // The `Access-Control-Allow-Methods` response header can only use `*` - // wildcard as value when the `AllowCredentials` field is unspecified. + // wildcard as value when the `AllowCredentials` field is false or omitted. // - // When the `AllowCredentials` field is specified and `AllowMethods` field + // When the `AllowCredentials` field is true and `AllowMethods` field // specified with the `*` wildcard, the gateway must specify one HTTP method // in the value of the Access-Control-Allow-Methods response header. The // value of the header `Access-Control-Allow-Methods` is same as the @@ -1442,9 +1442,9 @@ type HTTPCORSFilter struct { // // A wildcard indicates that the requests with all HTTP headers are allowed. // The `Access-Control-Allow-Headers` response header can only use `*` - // wildcard as value when the `AllowCredentials` field is unspecified. + // wildcard as value when the `AllowCredentials` field is false or omitted. // - // When the `AllowCredentials` field is specified and `AllowHeaders` field + // When the `AllowCredentials` field is true and `AllowHeaders` field // specified with the `*` wildcard, the gateway must specify one or more // HTTP headers in the value of the `Access-Control-Allow-Headers` response // header. The value of the header `Access-Control-Allow-Headers` is same as @@ -1487,8 +1487,7 @@ type HTTPCORSFilter struct { // // A wildcard indicates that the responses with all HTTP headers are exposed // to clients. The `Access-Control-Expose-Headers` response header can only - // use `*` wildcard as value when the `AllowCredentials` field is - // unspecified. + // use `*` wildcard as value when the `AllowCredentials` field is false or omitted. // // Support: Extended // From 1f2525f31256608353e136fdfb0665b1ac186ed9 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 10 Jul 2025 08:56:34 -0400 Subject: [PATCH 083/224] chore: run golang generators Signed-off-by: Shane Utt --- apis/v1/zz_generated.deepcopy.go | 5 +++++ applyconfiguration/apis/v1/httpcorsfilter.go | 4 ++-- pkg/generated/openapi/zz_generated.openapi.go | 10 +++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index 0f32a067ee..9bc1c8c53e 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -910,6 +910,11 @@ func (in *HTTPCORSFilter) DeepCopyInto(out *HTTPCORSFilter) { *out = make([]AbsoluteURI, len(*in)) copy(*out, *in) } + if in.AllowCredentials != nil { + in, out := &in.AllowCredentials, &out.AllowCredentials + *out = new(bool) + **out = **in + } if in.AllowMethods != nil { in, out := &in.AllowMethods, &out.AllowMethods *out = make([]HTTPMethodWithWildcard, len(*in)) diff --git a/applyconfiguration/apis/v1/httpcorsfilter.go b/applyconfiguration/apis/v1/httpcorsfilter.go index c2cf023c25..cc556b3e8a 100644 --- a/applyconfiguration/apis/v1/httpcorsfilter.go +++ b/applyconfiguration/apis/v1/httpcorsfilter.go @@ -26,7 +26,7 @@ import ( // with apply. type HTTPCORSFilterApplyConfiguration struct { AllowOrigins []apisv1.AbsoluteURI `json:"allowOrigins,omitempty"` - AllowCredentials *apisv1.TrueField `json:"allowCredentials,omitempty"` + AllowCredentials *bool `json:"allowCredentials,omitempty"` AllowMethods []apisv1.HTTPMethodWithWildcard `json:"allowMethods,omitempty"` AllowHeaders []apisv1.HTTPHeaderName `json:"allowHeaders,omitempty"` ExposeHeaders []apisv1.HTTPHeaderName `json:"exposeHeaders,omitempty"` @@ -52,7 +52,7 @@ func (b *HTTPCORSFilterApplyConfiguration) WithAllowOrigins(values ...apisv1.Abs // WithAllowCredentials sets the AllowCredentials field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the AllowCredentials field is set to the value of the last call. -func (b *HTTPCORSFilterApplyConfiguration) WithAllowCredentials(value apisv1.TrueField) *HTTPCORSFilterApplyConfiguration { +func (b *HTTPCORSFilterApplyConfiguration) WithAllowCredentials(value bool) *HTTPCORSFilterApplyConfiguration { b.AllowCredentials = &value return b } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 99214c9fcd..13ff9ab516 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -4306,7 +4306,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "AllowOrigins indicates whether the response can be shared with requested resource from the given `Origin`.\n\nThe `Origin` consists of a scheme and a host, with an optional port, and takes the form `://(:)`.\n\nValid values for scheme are: `http` and `https`.\n\nValid values for port are any integer between 1 and 65535 (the list of available TCP/UDP ports). Note that, if not included, port `80` is assumed for `http` scheme origins, and port `443` is assumed for `https` origins. This may affect origin matching.\n\nThe host part of the origin may contain the wildcard character `*`. These wildcard characters behave as follows:\n\n* `*` is a greedy match to the _left_, including any number of\n DNS labels to the left of its position. This also means that\n `*` will include any number of period `.` characters to the\n left of its position.\n* A wildcard by itself matches all hosts.\n\nAn origin value that includes _only_ the `*` character indicates requests from all `Origin`s are allowed.\n\nWhen the `AllowOrigins` field is configured with multiple origins, it means the server supports clients from multiple origins. If the request `Origin` matches the configured allowed origins, the gateway must return the given `Origin` and sets value of the header `Access-Control-Allow-Origin` same as the `Origin` header provided by the client.\n\nThe status code of a successful response to a \"preflight\" request is always an OK status (i.e., 204 or 200).\n\nIf the request `Origin` does not match the configured allowed origins, the gateway returns 204/200 response but doesn't set the relevant cross-origin response headers. Alternatively, the gateway responds with 403 status to the \"preflight\" request is denied, coupled with omitting the CORS headers. The cross-origin request fails on the client side. Therefore, the client doesn't attempt the actual cross-origin request.\n\nThe `Access-Control-Allow-Origin` response header can only use `*` wildcard as value when the `AllowCredentials` field is unspecified.\n\nWhen the `AllowCredentials` field is specified and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header `Access-Control-Allow-Origin` is same as the `Origin` header provided by the client.\n\nSupport: Extended", + Description: "AllowOrigins indicates whether the response can be shared with requested resource from the given `Origin`.\n\nThe `Origin` consists of a scheme and a host, with an optional port, and takes the form `://(:)`.\n\nValid values for scheme are: `http` and `https`.\n\nValid values for port are any integer between 1 and 65535 (the list of available TCP/UDP ports). Note that, if not included, port `80` is assumed for `http` scheme origins, and port `443` is assumed for `https` origins. This may affect origin matching.\n\nThe host part of the origin may contain the wildcard character `*`. These wildcard characters behave as follows:\n\n* `*` is a greedy match to the _left_, including any number of\n DNS labels to the left of its position. This also means that\n `*` will include any number of period `.` characters to the\n left of its position.\n* A wildcard by itself matches all hosts.\n\nAn origin value that includes _only_ the `*` character indicates requests from all `Origin`s are allowed.\n\nWhen the `AllowOrigins` field is configured with multiple origins, it means the server supports clients from multiple origins. If the request `Origin` matches the configured allowed origins, the gateway must return the given `Origin` and sets value of the header `Access-Control-Allow-Origin` same as the `Origin` header provided by the client.\n\nThe status code of a successful response to a \"preflight\" request is always an OK status (i.e., 204 or 200).\n\nIf the request `Origin` does not match the configured allowed origins, the gateway returns 204/200 response but doesn't set the relevant cross-origin response headers. Alternatively, the gateway responds with 403 status to the \"preflight\" request is denied, coupled with omitting the CORS headers. The cross-origin request fails on the client side. Therefore, the client doesn't attempt the actual cross-origin request.\n\nThe `Access-Control-Allow-Origin` response header can only use `*` wildcard as value when the `AllowCredentials` field is false or omitted.\n\nWhen the `AllowCredentials` field is true and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header `Access-Control-Allow-Origin` is same as the `Origin` header provided by the client.\n\nSupport: Extended", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -4321,7 +4321,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal }, "allowCredentials": { SchemaProps: spec.SchemaProps{ - Description: "AllowCredentials indicates whether the actual cross-origin request allows to include credentials.\n\nThe only valid value for the `Access-Control-Allow-Credentials` response header is true (case-sensitive).\n\nIf the credentials are not allowed in cross-origin requests, the gateway will omit the header `Access-Control-Allow-Credentials` entirely rather than setting its value to false.\n\nSupport: Extended", + Description: "AllowCredentials indicates whether the actual cross-origin request allows to include credentials.\n\nWhen set to true, the gateway will include the `Access-Control-Allow-Credentials` response header with value true (case-sensitive).\n\nWhen set to false or omitted the gateway will omit the header `Access-Control-Allow-Credentials` entirely (this is the standard CORS behavior).\n\nSupport: Extended", Type: []string{"boolean"}, Format: "", }, @@ -4333,7 +4333,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "AllowMethods indicates which HTTP methods are supported for accessing the requested resource.\n\nValid values are any method defined by RFC9110, along with the special value `*`, which represents all HTTP methods are allowed.\n\nMethod names are case sensitive, so these values are also case-sensitive. (See https://www.rfc-editor.org/rfc/rfc2616#section-5.1.1)\n\nMultiple method names in the value of the `Access-Control-Allow-Methods` response header are separated by a comma (\",\").\n\nA CORS-safelisted method is a method that is `GET`, `HEAD`, or `POST`. (See https://fetch.spec.whatwg.org/#cors-safelisted-method) The CORS-safelisted methods are always allowed, regardless of whether they are specified in the `AllowMethods` field.\n\nWhen the `AllowMethods` field is configured with one or more methods, the gateway must return the `Access-Control-Allow-Methods` response header which value is present in the `AllowMethods` field.\n\nIf the HTTP method of the `Access-Control-Request-Method` request header is not included in the list of methods specified by the response header `Access-Control-Allow-Methods`, it will present an error on the client side.\n\nThe `Access-Control-Allow-Methods` response header can only use `*` wildcard as value when the `AllowCredentials` field is unspecified.\n\nWhen the `AllowCredentials` field is specified and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the `Access-Control-Request-Method` header provided by the client. If the header `Access-Control-Request-Method` is not included in the request, the gateway will omit the `Access-Control-Allow-Methods` response header, instead of specifying the `*` wildcard. A Gateway implementation may choose to add implementation-specific default methods.\n\nSupport: Extended", + Description: "AllowMethods indicates which HTTP methods are supported for accessing the requested resource.\n\nValid values are any method defined by RFC9110, along with the special value `*`, which represents all HTTP methods are allowed.\n\nMethod names are case sensitive, so these values are also case-sensitive. (See https://www.rfc-editor.org/rfc/rfc2616#section-5.1.1)\n\nMultiple method names in the value of the `Access-Control-Allow-Methods` response header are separated by a comma (\",\").\n\nA CORS-safelisted method is a method that is `GET`, `HEAD`, or `POST`. (See https://fetch.spec.whatwg.org/#cors-safelisted-method) The CORS-safelisted methods are always allowed, regardless of whether they are specified in the `AllowMethods` field.\n\nWhen the `AllowMethods` field is configured with one or more methods, the gateway must return the `Access-Control-Allow-Methods` response header which value is present in the `AllowMethods` field.\n\nIf the HTTP method of the `Access-Control-Request-Method` request header is not included in the list of methods specified by the response header `Access-Control-Allow-Methods`, it will present an error on the client side.\n\nThe `Access-Control-Allow-Methods` response header can only use `*` wildcard as value when the `AllowCredentials` field is false or omitted.\n\nWhen the `AllowCredentials` field is true and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the `Access-Control-Request-Method` header provided by the client. If the header `Access-Control-Request-Method` is not included in the request, the gateway will omit the `Access-Control-Allow-Methods` response header, instead of specifying the `*` wildcard. A Gateway implementation may choose to add implementation-specific default methods.\n\nSupport: Extended", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -4353,7 +4353,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "AllowHeaders indicates which HTTP request headers are supported for accessing the requested resource.\n\nHeader names are not case sensitive.\n\nMultiple header names in the value of the `Access-Control-Allow-Headers` response header are separated by a comma (\",\").\n\nWhen the `AllowHeaders` field is configured with one or more headers, the gateway must return the `Access-Control-Allow-Headers` response header which value is present in the `AllowHeaders` field.\n\nIf any header name in the `Access-Control-Request-Headers` request header is not included in the list of header names specified by the response header `Access-Control-Allow-Headers`, it will present an error on the client side.\n\nIf any header name in the `Access-Control-Allow-Headers` response header does not recognize by the client, it will also occur an error on the client side.\n\nA wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` wildcard as value when the `AllowCredentials` field is unspecified.\n\nWhen the `AllowCredentials` field is specified and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as the `Access-Control-Request-Headers` header provided by the client. If the header `Access-Control-Request-Headers` is not included in the request, the gateway will omit the `Access-Control-Allow-Headers` response header, instead of specifying the `*` wildcard. A Gateway implementation may choose to add implementation-specific default headers.\n\nSupport: Extended", + Description: "AllowHeaders indicates which HTTP request headers are supported for accessing the requested resource.\n\nHeader names are not case sensitive.\n\nMultiple header names in the value of the `Access-Control-Allow-Headers` response header are separated by a comma (\",\").\n\nWhen the `AllowHeaders` field is configured with one or more headers, the gateway must return the `Access-Control-Allow-Headers` response header which value is present in the `AllowHeaders` field.\n\nIf any header name in the `Access-Control-Request-Headers` request header is not included in the list of header names specified by the response header `Access-Control-Allow-Headers`, it will present an error on the client side.\n\nIf any header name in the `Access-Control-Allow-Headers` response header does not recognize by the client, it will also occur an error on the client side.\n\nA wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` wildcard as value when the `AllowCredentials` field is false or omitted.\n\nWhen the `AllowCredentials` field is true and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as the `Access-Control-Request-Headers` header provided by the client. If the header `Access-Control-Request-Headers` is not included in the request, the gateway will omit the `Access-Control-Allow-Headers` response header, instead of specifying the `*` wildcard. A Gateway implementation may choose to add implementation-specific default headers.\n\nSupport: Extended", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -4373,7 +4373,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "ExposeHeaders indicates which HTTP response headers can be exposed to client-side scripts in response to a cross-origin request.\n\nA CORS-safelisted response header is an HTTP header in a CORS response that it is considered safe to expose to the client scripts. The CORS-safelisted response headers include the following headers: `Cache-Control` `Content-Language` `Content-Length` `Content-Type` `Expires` `Last-Modified` `Pragma` (See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name) The CORS-safelisted response headers are exposed to client by default.\n\nWhen an HTTP header name is specified using the `ExposeHeaders` field, this additional header will be exposed as part of the response to the client.\n\nHeader names are not case sensitive.\n\nMultiple header names in the value of the `Access-Control-Expose-Headers` response header are separated by a comma (\",\").\n\nA wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only use `*` wildcard as value when the `AllowCredentials` field is unspecified.\n\nSupport: Extended", + Description: "ExposeHeaders indicates which HTTP response headers can be exposed to client-side scripts in response to a cross-origin request.\n\nA CORS-safelisted response header is an HTTP header in a CORS response that it is considered safe to expose to the client scripts. The CORS-safelisted response headers include the following headers: `Cache-Control` `Content-Language` `Content-Length` `Content-Type` `Expires` `Last-Modified` `Pragma` (See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name) The CORS-safelisted response headers are exposed to client by default.\n\nWhen an HTTP header name is specified using the `ExposeHeaders` field, this additional header will be exposed as part of the response to the client.\n\nHeader names are not case sensitive.\n\nMultiple header names in the value of the `Access-Control-Expose-Headers` response header are separated by a comma (\",\").\n\nA wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only use `*` wildcard as value when the `AllowCredentials` field is false or omitted.\n\nSupport: Extended", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From fb6aa5cd3a72d5686b1dfcef76c9f5dad1d64e6c Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 10 Jul 2025 08:56:42 -0400 Subject: [PATCH 084/224] chore: generate manifests Signed-off-by: Shane Utt --- .../gateway.networking.k8s.io_httproutes.yaml | 108 ++++++++---------- 1 file changed, 48 insertions(+), 60 deletions(-) diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 9f5f93d222..cf2b274655 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -468,16 +468,14 @@ spec: AllowCredentials indicates whether the actual cross-origin request allows to include credentials. - The only valid value for the `Access-Control-Allow-Credentials` response - header is true (case-sensitive). + When set to true, the gateway will include the `Access-Control-Allow-Credentials` + response header with value true (case-sensitive). - If the credentials are not allowed in cross-origin requests, the gateway - will omit the header `Access-Control-Allow-Credentials` entirely rather - than setting its value to false. + When set to false or omitted the gateway will omit the header + `Access-Control-Allow-Credentials` entirely (this is the standard CORS + behavior). Support: Extended - enum: - - true type: boolean allowHeaders: description: |- @@ -504,9 +502,9 @@ spec: A wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowHeaders` field + When the `AllowCredentials` field is true and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as @@ -567,9 +565,9 @@ spec: side. The `Access-Control-Allow-Methods` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowMethods` field + When the `AllowCredentials` field is true and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the @@ -645,9 +643,9 @@ spec: Therefore, the client doesn't attempt the actual cross-origin request. The `Access-Control-Allow-Origin` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowOrigins` field + When the `AllowCredentials` field is true and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header @@ -698,8 +696,7 @@ spec: A wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only - use `*` wildcard as value when the `AllowCredentials` field is - unspecified. + use `*` wildcard as value when the `AllowCredentials` field is false or omitted. Support: Extended items: @@ -1695,16 +1692,14 @@ spec: AllowCredentials indicates whether the actual cross-origin request allows to include credentials. - The only valid value for the `Access-Control-Allow-Credentials` response - header is true (case-sensitive). + When set to true, the gateway will include the `Access-Control-Allow-Credentials` + response header with value true (case-sensitive). - If the credentials are not allowed in cross-origin requests, the gateway - will omit the header `Access-Control-Allow-Credentials` entirely rather - than setting its value to false. + When set to false or omitted the gateway will omit the header + `Access-Control-Allow-Credentials` entirely (this is the standard CORS + behavior). Support: Extended - enum: - - true type: boolean allowHeaders: description: |- @@ -1731,9 +1726,9 @@ spec: A wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowHeaders` field + When the `AllowCredentials` field is true and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as @@ -1794,9 +1789,9 @@ spec: side. The `Access-Control-Allow-Methods` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowMethods` field + When the `AllowCredentials` field is true and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the @@ -1872,9 +1867,9 @@ spec: Therefore, the client doesn't attempt the actual cross-origin request. The `Access-Control-Allow-Origin` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowOrigins` field + When the `AllowCredentials` field is true and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header @@ -1925,8 +1920,7 @@ spec: A wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only - use `*` wildcard as value when the `AllowCredentials` field is - unspecified. + use `*` wildcard as value when the `AllowCredentials` field is false or omitted. Support: Extended items: @@ -4094,16 +4088,14 @@ spec: AllowCredentials indicates whether the actual cross-origin request allows to include credentials. - The only valid value for the `Access-Control-Allow-Credentials` response - header is true (case-sensitive). + When set to true, the gateway will include the `Access-Control-Allow-Credentials` + response header with value true (case-sensitive). - If the credentials are not allowed in cross-origin requests, the gateway - will omit the header `Access-Control-Allow-Credentials` entirely rather - than setting its value to false. + When set to false or omitted the gateway will omit the header + `Access-Control-Allow-Credentials` entirely (this is the standard CORS + behavior). Support: Extended - enum: - - true type: boolean allowHeaders: description: |- @@ -4130,9 +4122,9 @@ spec: A wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowHeaders` field + When the `AllowCredentials` field is true and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as @@ -4193,9 +4185,9 @@ spec: side. The `Access-Control-Allow-Methods` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowMethods` field + When the `AllowCredentials` field is true and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the @@ -4271,9 +4263,9 @@ spec: Therefore, the client doesn't attempt the actual cross-origin request. The `Access-Control-Allow-Origin` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowOrigins` field + When the `AllowCredentials` field is true and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header @@ -4324,8 +4316,7 @@ spec: A wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only - use `*` wildcard as value when the `AllowCredentials` field is - unspecified. + use `*` wildcard as value when the `AllowCredentials` field is false or omitted. Support: Extended items: @@ -5321,16 +5312,14 @@ spec: AllowCredentials indicates whether the actual cross-origin request allows to include credentials. - The only valid value for the `Access-Control-Allow-Credentials` response - header is true (case-sensitive). + When set to true, the gateway will include the `Access-Control-Allow-Credentials` + response header with value true (case-sensitive). - If the credentials are not allowed in cross-origin requests, the gateway - will omit the header `Access-Control-Allow-Credentials` entirely rather - than setting its value to false. + When set to false or omitted the gateway will omit the header + `Access-Control-Allow-Credentials` entirely (this is the standard CORS + behavior). Support: Extended - enum: - - true type: boolean allowHeaders: description: |- @@ -5357,9 +5346,9 @@ spec: A wildcard indicates that the requests with all HTTP headers are allowed. The `Access-Control-Allow-Headers` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowHeaders` field + When the `AllowCredentials` field is true and `AllowHeaders` field specified with the `*` wildcard, the gateway must specify one or more HTTP headers in the value of the `Access-Control-Allow-Headers` response header. The value of the header `Access-Control-Allow-Headers` is same as @@ -5420,9 +5409,9 @@ spec: side. The `Access-Control-Allow-Methods` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowMethods` field + When the `AllowCredentials` field is true and `AllowMethods` field specified with the `*` wildcard, the gateway must specify one HTTP method in the value of the Access-Control-Allow-Methods response header. The value of the header `Access-Control-Allow-Methods` is same as the @@ -5498,9 +5487,9 @@ spec: Therefore, the client doesn't attempt the actual cross-origin request. The `Access-Control-Allow-Origin` response header can only use `*` - wildcard as value when the `AllowCredentials` field is unspecified. + wildcard as value when the `AllowCredentials` field is false or omitted. - When the `AllowCredentials` field is specified and `AllowOrigins` field + When the `AllowCredentials` field is true and `AllowOrigins` field specified with the `*` wildcard, the gateway must return a single origin in the value of the `Access-Control-Allow-Origin` response header, instead of specifying the `*` wildcard. The value of the header @@ -5551,8 +5540,7 @@ spec: A wildcard indicates that the responses with all HTTP headers are exposed to clients. The `Access-Control-Expose-Headers` response header can only - use `*` wildcard as value when the `AllowCredentials` field is - unspecified. + use `*` wildcard as value when the `AllowCredentials` field is false or omitted. Support: Extended items: From 6d76ec6e574cab4719351767ae6c42ef23e62240 Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Mon, 14 Jul 2025 20:00:23 +0200 Subject: [PATCH 085/224] TLSRoute: Require hostnames and bump version to v1alpha3 (#3872) * TLSRoute: Require hostnames * TLSRoute: Move to v1alpha3 TLSRoute: Update config crd TLSRoute: Update pkg TLSRoute: Update hack example * TLSRoute: Bring TLSRoute back to v1alpha2 * TLSRoute: Update conformance helpers * TLSRoute: Remove storageversion from v1alpha3 * TLSRoute: Update invalid example * TLSRoute: v1alpha3 example * TLSRoute: Make v1alpha3 storage --- apis/v1alpha2/tlsroute_types.go | 1 - apis/v1alpha3/shared_types.go | 89 ++ apis/v1alpha3/tlsroute_types.go | 106 +++ apis/v1alpha3/zz_generated.deepcopy.go | 87 ++ apis/v1alpha3/zz_generated.register.go | 2 + applyconfiguration/apis/v1alpha3/tlsroute.go | 265 ++++++ .../apis/v1alpha3/tlsrouterule.go | 58 ++ .../apis/v1alpha3/tlsroutespec.go | 75 ++ .../apis/v1alpha3/tlsroutestatus.go | 48 ++ applyconfiguration/internal/internal.go | 42 + applyconfiguration/utils.go | 4 + .../gateway.networking.k8s.io_tlsroutes.yaml | 770 ++++++++++++++++++ .../v1alpha2/tls-routing/gateway.yaml | 12 + .../v1alpha2/tls-routing/tls-route.yaml | 12 + .../v1alpha3/tls-routing/gateway.yaml | 12 + .../v1alpha3/tls-routing/tls-route.yaml | 14 + .../experimental/tlsroute/no-hostname.yaml | 8 + .../typed/apis/v1alpha3/apis_client.go | 5 + .../apis/v1alpha3/fake/fake_apis_client.go | 4 + .../typed/apis/v1alpha3/fake/fake_tlsroute.go | 51 ++ .../apis/v1alpha3/generated_expansion.go | 2 + .../versioned/typed/apis/v1alpha3/tlsroute.go | 74 ++ .../apis/v1alpha3/interface.go | 7 + .../apis/v1alpha3/tlsroute.go | 102 +++ .../informers/externalversions/generic.go | 2 + .../apis/v1alpha3/expansion_generated.go | 8 + pkg/client/listers/apis/v1alpha3/tlsroute.go | 70 ++ pkg/generated/openapi/zz_generated.openapi.go | 161 ++++ 28 files changed, 2090 insertions(+), 1 deletion(-) create mode 100644 apis/v1alpha3/shared_types.go create mode 100644 apis/v1alpha3/tlsroute_types.go create mode 100644 applyconfiguration/apis/v1alpha3/tlsroute.go create mode 100644 applyconfiguration/apis/v1alpha3/tlsrouterule.go create mode 100644 applyconfiguration/apis/v1alpha3/tlsroutespec.go create mode 100644 applyconfiguration/apis/v1alpha3/tlsroutestatus.go create mode 100644 examples/experimental/v1alpha2/tls-routing/gateway.yaml create mode 100644 examples/experimental/v1alpha2/tls-routing/tls-route.yaml create mode 100644 examples/experimental/v1alpha3/tls-routing/gateway.yaml create mode 100644 examples/experimental/v1alpha3/tls-routing/tls-route.yaml create mode 100644 hack/invalid-examples/experimental/tlsroute/no-hostname.yaml create mode 100644 pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_tlsroute.go create mode 100644 pkg/client/clientset/versioned/typed/apis/v1alpha3/tlsroute.go create mode 100644 pkg/client/informers/externalversions/apis/v1alpha3/tlsroute.go create mode 100644 pkg/client/listers/apis/v1alpha3/tlsroute.go diff --git a/apis/v1alpha2/tlsroute_types.go b/apis/v1alpha2/tlsroute_types.go index f21fe3fc50..f1b3814cf7 100644 --- a/apis/v1alpha2/tlsroute_types.go +++ b/apis/v1alpha2/tlsroute_types.go @@ -24,7 +24,6 @@ import ( // +kubebuilder:object:root=true // +kubebuilder:resource:categories=gateway-api // +kubebuilder:subresource:status -// +kubebuilder:storageversion // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` // The TLSRoute resource is similar to TCPRoute, but can be configured diff --git a/apis/v1alpha3/shared_types.go b/apis/v1alpha3/shared_types.go new file mode 100644 index 0000000000..fa487f96d4 --- /dev/null +++ b/apis/v1alpha3/shared_types.go @@ -0,0 +1,89 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha3 + +import v1 "sigs.k8s.io/gateway-api/apis/v1" + +// CommonRouteSpec defines the common attributes that all Routes MUST include +// within their spec. +// +k8s:deepcopy-gen=false +type CommonRouteSpec = v1.CommonRouteSpec + +// BackendRef defines how a Route should forward a request to a Kubernetes +// resource. +// +// Note that when a namespace different than the local namespace is specified, a +// ReferenceGrant object is required in the referent namespace to allow that +// namespace's owner to accept the reference. See the ReferenceGrant +// documentation for details. +// +k8s:deepcopy-gen=false +type BackendRef = v1.BackendRef + +// RouteStatus defines the common attributes that all Routes MUST include within +// their status. +// +k8s:deepcopy-gen=false +type RouteStatus = v1.RouteStatus + +// Hostname is the fully qualified domain name of a network host. This matches +// the RFC 1123 definition of a hostname with 2 notable exceptions: +// +// 1. IPs are not allowed. +// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard +// label must appear by itself as the first label. +// +// Hostname can be "precise" which is a domain name without the terminating +// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a +// domain name prefixed with a single wildcard label (e.g. `*.example.com`). +// +// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +// alphanumeric characters or '-', and must start and end with an alphanumeric +// character. No other punctuation is allowed. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Hostname = v1.Hostname + +// SectionName is the name of a section in a Kubernetes resource. +// +// In the following resources, SectionName is interpreted as the following: +// +// * Gateway: Listener name +// * HTTPRoute: HTTPRouteRule name +// * Service: Port name +// +// Section names can have a variety of forms, including RFC 1123 subdomains, +// RFC 1123 labels, or RFC 1035 labels. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "example" +// * "foo-example" +// * "example.com" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type SectionName = v1.SectionName diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go new file mode 100644 index 0000000000..7bcb48e74b --- /dev/null +++ b/apis/v1alpha3/tlsroute_types.go @@ -0,0 +1,106 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha3 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// The TLSRoute resource is similar to TCPRoute, but can be configured +// to match against TLS-specific metadata. This allows more flexibility +// in matching streams for a given TLS listener. +// +// If you need to forward traffic to a single target for a TLS listener, you +// could choose to use a TCPRoute with a TLS listener. +type TLSRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of TLSRoute. + Spec TLSRouteSpec `json:"spec"` + + // Status defines the current state of TLSRoute. + Status v1alpha2.TLSRouteStatus `json:"status,omitempty"` +} + +// TLSRouteSpec defines the desired state of a TLSRoute resource. +type TLSRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of SNI hostnames that should match against the + // SNI attribute of TLS ClientHello message in TLS handshake. This matches + // the RFC 1123 definition of a hostname with 2 notable exceptions: + // + // 1. IPs are not allowed in SNI hostnames per RFC 6066. + // 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + // label must appear by itself as the first label. + // + // If a hostname is specified by both the Listener and TLSRoute, there + // must be at least one intersecting hostname for the TLSRoute to be + // attached to the Listener. For example: + // + // * A Listener with `test.example.com` as the hostname matches TLSRoutes + // that have either not specified any hostnames, or have specified at + // least one of `test.example.com` or `*.example.com`. + // * A Listener with `*.example.com` as the hostname matches TLSRoutes + // that have either not specified any hostnames or have specified at least + // one hostname that matches the Listener hostname. For example, + // `test.example.com` and `*.example.com` would both match. On the other + // hand, `example.com` and `test.example.net` would not match. + // + // If both the Listener and TLSRoute have specified hostnames, any + // TLSRoute hostnames that do not match the Listener hostname MUST be + // ignored. For example, if a Listener specified `*.example.com`, and the + // TLSRoute specified `test.example.com` and `test.example.net`, + // `test.example.net` must not be considered for a match. + // + // If both the Listener and TLSRoute have specified hostnames, and none + // match with the criteria above, then the TLSRoute is not accepted. The + // implementation must raise an 'Accepted' Condition with a status of + // `False` in the corresponding RouteParentStatus. + // + // Support: Core + // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of TLS matchers and actions. + // + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // + Rules []v1alpha2.TLSRouteRule `json:"rules"` +} + +// +kubebuilder:object:root=true + +// TLSRouteList contains a list of TLSRoute +type TLSRouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TLSRoute `json:"items"` +} diff --git a/apis/v1alpha3/zz_generated.deepcopy.go b/apis/v1alpha3/zz_generated.deepcopy.go index 876ac9f7b6..9b659eadab 100644 --- a/apis/v1alpha3/zz_generated.deepcopy.go +++ b/apis/v1alpha3/zz_generated.deepcopy.go @@ -159,3 +159,90 @@ func (in *SubjectAltName) DeepCopy() *SubjectAltName { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSRoute) DeepCopyInto(out *TLSRoute) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSRoute. +func (in *TLSRoute) DeepCopy() *TLSRoute { + if in == nil { + return nil + } + out := new(TLSRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TLSRoute) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSRouteList) DeepCopyInto(out *TLSRouteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TLSRoute, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSRouteList. +func (in *TLSRouteList) DeepCopy() *TLSRouteList { + if in == nil { + return nil + } + out := new(TLSRouteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TLSRouteList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSRouteSpec) DeepCopyInto(out *TLSRouteSpec) { + *out = *in + in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) + if in.Hostnames != nil { + in, out := &in.Hostnames, &out.Hostnames + *out = make([]Hostname, len(*in)) + copy(*out, *in) + } + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]v1alpha2.TLSRouteRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSRouteSpec. +func (in *TLSRouteSpec) DeepCopy() *TLSRouteSpec { + if in == nil { + return nil + } + out := new(TLSRouteSpec) + in.DeepCopyInto(out) + return out +} diff --git a/apis/v1alpha3/zz_generated.register.go b/apis/v1alpha3/zz_generated.register.go index d1caca01be..bc61a8b310 100644 --- a/apis/v1alpha3/zz_generated.register.go +++ b/apis/v1alpha3/zz_generated.register.go @@ -63,6 +63,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &BackendTLSPolicy{}, &BackendTLSPolicyList{}, + &TLSRoute{}, + &TLSRouteList{}, ) // AddToGroupVersion allows the serialization of client types like ListOptions. v1.AddToGroupVersion(scheme, SchemeGroupVersion) diff --git a/applyconfiguration/apis/v1alpha3/tlsroute.go b/applyconfiguration/apis/v1alpha3/tlsroute.go new file mode 100644 index 0000000000..ff65509c71 --- /dev/null +++ b/applyconfiguration/apis/v1alpha3/tlsroute.go @@ -0,0 +1,265 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" + v1 "k8s.io/client-go/applyconfigurations/meta/v1" + apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + v1alpha2 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha2" + internal "sigs.k8s.io/gateway-api/applyconfiguration/internal" +) + +// TLSRouteApplyConfiguration represents a declarative configuration of the TLSRoute type for use +// with apply. +type TLSRouteApplyConfiguration struct { + v1.TypeMetaApplyConfiguration `json:",inline"` + *v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *TLSRouteSpecApplyConfiguration `json:"spec,omitempty"` + Status *v1alpha2.TLSRouteStatusApplyConfiguration `json:"status,omitempty"` +} + +// TLSRoute constructs a declarative configuration of the TLSRoute type for use with +// apply. +func TLSRoute(name, namespace string) *TLSRouteApplyConfiguration { + b := &TLSRouteApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("TLSRoute") + b.WithAPIVersion("gateway.networking.k8s.io/v1alpha3") + return b +} + +// ExtractTLSRoute extracts the applied configuration owned by fieldManager from +// tLSRoute. If no managedFields are found in tLSRoute for fieldManager, a +// TLSRouteApplyConfiguration is returned with only the Name, Namespace (if applicable), +// APIVersion and Kind populated. It is possible that no managed fields were found for because other +// field managers have taken ownership of all the fields previously owned by fieldManager, or because +// the fieldManager never owned fields any fields. +// tLSRoute must be a unmodified TLSRoute API object that was retrieved from the Kubernetes API. +// ExtractTLSRoute provides a way to perform a extract/modify-in-place/apply workflow. +// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously +// applied if another fieldManager has updated or force applied any of the previously applied fields. +// Experimental! +func ExtractTLSRoute(tLSRoute *apisv1alpha3.TLSRoute, fieldManager string) (*TLSRouteApplyConfiguration, error) { + return extractTLSRoute(tLSRoute, fieldManager, "") +} + +// ExtractTLSRouteStatus is the same as ExtractTLSRoute except +// that it extracts the status subresource applied configuration. +// Experimental! +func ExtractTLSRouteStatus(tLSRoute *apisv1alpha3.TLSRoute, fieldManager string) (*TLSRouteApplyConfiguration, error) { + return extractTLSRoute(tLSRoute, fieldManager, "status") +} + +func extractTLSRoute(tLSRoute *apisv1alpha3.TLSRoute, fieldManager string, subresource string) (*TLSRouteApplyConfiguration, error) { + b := &TLSRouteApplyConfiguration{} + err := managedfields.ExtractInto(tLSRoute, internal.Parser().Type("io.k8s.sigs.gateway-api.apis.v1alpha3.TLSRoute"), fieldManager, b, subresource) + if err != nil { + return nil, err + } + b.WithName(tLSRoute.Name) + b.WithNamespace(tLSRoute.Namespace) + + b.WithKind("TLSRoute") + b.WithAPIVersion("gateway.networking.k8s.io/v1alpha3") + return b, nil +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithKind(value string) *TLSRouteApplyConfiguration { + b.TypeMetaApplyConfiguration.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithAPIVersion(value string) *TLSRouteApplyConfiguration { + b.TypeMetaApplyConfiguration.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithName(value string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithGenerateName(value string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithNamespace(value string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithUID(value types.UID) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithResourceVersion(value string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithGeneration(value int64) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithCreationTimestamp(value metav1.Time) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *TLSRouteApplyConfiguration) WithLabels(entries map[string]string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *TLSRouteApplyConfiguration) WithAnnotations(entries map[string]string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *TLSRouteApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *TLSRouteApplyConfiguration) WithFinalizers(values ...string) *TLSRouteApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i]) + } + return b +} + +func (b *TLSRouteApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithSpec(value *TLSRouteSpecApplyConfiguration) *TLSRouteApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *TLSRouteApplyConfiguration) WithStatus(value *v1alpha2.TLSRouteStatusApplyConfiguration) *TLSRouteApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Name +} diff --git a/applyconfiguration/apis/v1alpha3/tlsrouterule.go b/applyconfiguration/apis/v1alpha3/tlsrouterule.go new file mode 100644 index 0000000000..3b0bfe3b04 --- /dev/null +++ b/applyconfiguration/apis/v1alpha3/tlsrouterule.go @@ -0,0 +1,58 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + v1 "sigs.k8s.io/gateway-api/apis/v1" + apisv1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" +) + +// TLSRouteRuleApplyConfiguration represents a declarative configuration of the TLSRouteRule type for use +// with apply. +type TLSRouteRuleApplyConfiguration struct { + Name *v1.SectionName `json:"name,omitempty"` + BackendRefs []apisv1.BackendRefApplyConfiguration `json:"backendRefs,omitempty"` +} + +// TLSRouteRuleApplyConfiguration constructs a declarative configuration of the TLSRouteRule type for use with +// apply. +func TLSRouteRule() *TLSRouteRuleApplyConfiguration { + return &TLSRouteRuleApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *TLSRouteRuleApplyConfiguration) WithName(value v1.SectionName) *TLSRouteRuleApplyConfiguration { + b.Name = &value + return b +} + +// WithBackendRefs adds the given value to the BackendRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the BackendRefs field. +func (b *TLSRouteRuleApplyConfiguration) WithBackendRefs(values ...*apisv1.BackendRefApplyConfiguration) *TLSRouteRuleApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithBackendRefs") + } + b.BackendRefs = append(b.BackendRefs, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1alpha3/tlsroutespec.go b/applyconfiguration/apis/v1alpha3/tlsroutespec.go new file mode 100644 index 0000000000..47c7e06fd6 --- /dev/null +++ b/applyconfiguration/apis/v1alpha3/tlsroutespec.go @@ -0,0 +1,75 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" + v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" + v1alpha2 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha2" +) + +// TLSRouteSpecApplyConfiguration represents a declarative configuration of the TLSRouteSpec type for use +// with apply. +type TLSRouteSpecApplyConfiguration struct { + v1.CommonRouteSpecApplyConfiguration `json:",inline"` + Hostnames []apisv1.Hostname `json:"hostnames,omitempty"` + Rules []v1alpha2.TLSRouteRuleApplyConfiguration `json:"rules,omitempty"` +} + +// TLSRouteSpecApplyConfiguration constructs a declarative configuration of the TLSRouteSpec type for use with +// apply. +func TLSRouteSpec() *TLSRouteSpecApplyConfiguration { + return &TLSRouteSpecApplyConfiguration{} +} + +// WithParentRefs adds the given value to the ParentRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the ParentRefs field. +func (b *TLSRouteSpecApplyConfiguration) WithParentRefs(values ...*v1.ParentReferenceApplyConfiguration) *TLSRouteSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithParentRefs") + } + b.CommonRouteSpecApplyConfiguration.ParentRefs = append(b.CommonRouteSpecApplyConfiguration.ParentRefs, *values[i]) + } + return b +} + +// WithHostnames adds the given value to the Hostnames field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Hostnames field. +func (b *TLSRouteSpecApplyConfiguration) WithHostnames(values ...apisv1.Hostname) *TLSRouteSpecApplyConfiguration { + for i := range values { + b.Hostnames = append(b.Hostnames, values[i]) + } + return b +} + +// WithRules adds the given value to the Rules field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Rules field. +func (b *TLSRouteSpecApplyConfiguration) WithRules(values ...*v1alpha2.TLSRouteRuleApplyConfiguration) *TLSRouteSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithRules") + } + b.Rules = append(b.Rules, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1alpha3/tlsroutestatus.go b/applyconfiguration/apis/v1alpha3/tlsroutestatus.go new file mode 100644 index 0000000000..3b5a1f319b --- /dev/null +++ b/applyconfiguration/apis/v1alpha3/tlsroutestatus.go @@ -0,0 +1,48 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + v1 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1" +) + +// TLSRouteStatusApplyConfiguration represents a declarative configuration of the TLSRouteStatus type for use +// with apply. +type TLSRouteStatusApplyConfiguration struct { + v1.RouteStatusApplyConfiguration `json:",inline"` +} + +// TLSRouteStatusApplyConfiguration constructs a declarative configuration of the TLSRouteStatus type for use with +// apply. +func TLSRouteStatus() *TLSRouteStatusApplyConfiguration { + return &TLSRouteStatusApplyConfiguration{} +} + +// WithParents adds the given value to the Parents field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Parents field. +func (b *TLSRouteStatusApplyConfiguration) WithParents(values ...*v1.RouteParentStatusApplyConfiguration) *TLSRouteStatusApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithParents") + } + b.RouteStatusApplyConfiguration.Parents = append(b.RouteStatusApplyConfiguration.Parents, *values[i]) + } + return b +} diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 7a69ee3876..0403df0d63 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -1585,6 +1585,48 @@ var schemaYAML = typed.YAMLObject(`types: - name: uri type: scalar: string +- name: io.k8s.sigs.gateway-api.apis.v1alpha3.TLSRoute + map: + fields: + - name: apiVersion + type: + scalar: string + - name: kind + type: + scalar: string + - name: metadata + type: + namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta + default: {} + - name: spec + type: + namedType: io.k8s.sigs.gateway-api.apis.v1alpha3.TLSRouteSpec + default: {} + - name: status + type: + namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteStatus + default: {} +- name: io.k8s.sigs.gateway-api.apis.v1alpha3.TLSRouteSpec + map: + fields: + - name: hostnames + type: + list: + elementType: + scalar: string + elementRelationship: atomic + - name: parentRefs + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.ParentReference + elementRelationship: atomic + - name: rules + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1alpha2.TLSRouteRule + elementRelationship: atomic - name: io.k8s.sigs.gateway-api.apis.v1beta1.Gateway map: fields: diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 8e23441166..8014f68c7c 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -212,6 +212,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1alpha3.BackendTLSPolicyValidationApplyConfiguration{} case v1alpha3.SchemeGroupVersion.WithKind("SubjectAltName"): return &apisv1alpha3.SubjectAltNameApplyConfiguration{} + case v1alpha3.SchemeGroupVersion.WithKind("TLSRoute"): + return &apisv1alpha3.TLSRouteApplyConfiguration{} + case v1alpha3.SchemeGroupVersion.WithKind("TLSRouteSpec"): + return &apisv1alpha3.TLSRouteSpecApplyConfiguration{} // Group=gateway.networking.k8s.io, Version=v1beta1 case v1beta1.SchemeGroupVersion.WithKind("Gateway"): diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index eaac6b6692..4392eff57f 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -721,6 +721,776 @@ spec: the name and port of the selected port must match both specified values. + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha3 + schema: + openAPIV3Schema: + description: |- + The TLSRoute resource is similar to TCPRoute, but can be configured + to match against TLS-specific metadata. This allows more flexibility + in matching streams for a given TLS listener. + + If you need to forward traffic to a single target for a TLS listener, you + could choose to use a TCPRoute with a TLS listener. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TLSRoute. + properties: + hostnames: + description: |- + Hostnames defines a set of SNI hostnames that should match against the + SNI attribute of TLS ClientHello message in TLS handshake. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed in SNI hostnames per RFC 6066. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + If a hostname is specified by both the Listener and TLSRoute, there + must be at least one intersecting hostname for the TLSRoute to be + attached to the Listener. For example: + + * A Listener with `test.example.com` as the hostname matches TLSRoutes + that have either not specified any hostnames, or have specified at + least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches TLSRoutes + that have either not specified any hostnames or have specified at least + one hostname that matches the Listener hostname. For example, + `test.example.com` and `*.example.com` would both match. On the other + hand, `example.com` and `test.example.net` would not match. + + If both the Listener and TLSRoute have specified hostnames, any + TLSRoute hostnames that do not match the Listener hostname MUST be + ignored. For example, if a Listener specified `*.example.com`, and the + TLSRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. + + If both the Listener and TLSRoute have specified hostnames, and none + match with the criteria above, then the TLSRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status of + `False` in the corresponding RouteParentStatus. + + Support: Core + items: + description: |- + Hostname is the fully qualified domain name of a network host. This matches + the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + + Hostname can be "precise" which is a domain name without the terminating + dot of a network host (e.g. "foo.example.com") or "wildcard", which is a + domain name prefixed with a single wildcard label (e.g. `*.example.com`). + + Note that as per RFC1035 and RFC1123, a *label* must consist of lower case + alphanumeric characters or '-', and must start and end with an alphanumeric + character. No other punctuation is allowed. + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + minItems: 1 + type: array + parentRefs: + description: |- + ParentRefs references the resources (usually Gateways) that a Route wants + to be attached to. Note that the referenced parent resource needs to + allow this for the attachment to be complete. For Gateways, that means + the Gateway needs to allow attachment from Routes of this kind and + namespace. For Services, that means the Service must either be in the same + namespace for a "producer" route, or the mesh implementation must support + and allow "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not possible to + create a "producer" route for a Service in a different namespace from the + Route. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + ParentRefs must be _distinct_. This means either that: + + * They select different objects. If this is the case, then parentRef + entries are distinct. In terms of fields, this means that the + multi-part key defined by `group`, `kind`, `namespace`, and `name` must + be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field used, + each ParentRef that selects the same object must set the same set of + optional fields to different values. If one ParentRef sets a + combination of optional fields, all must set the same combination. + + Some examples: + + * If one ParentRef sets `sectionName`, all ParentRefs referencing the + same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. + * If one ParentRef sets `sectionName` and `port`, all ParentRefs + referencing the same object must also set `sectionName` and `port`. + + It is possible to separately reference multiple distinct objects that may + be collapsed by an implementation. For example, some implementations may + choose to merge compatible Gateway Listeners together. If that is the + case, the list of routes attached to those resources should also be + merged. + + Note that for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example, + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable other kinds of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + description: Rules are a list of TLS matchers and actions. + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: |- + BackendRefs defines the backend(s) where matching requests should be + sent. If unspecified or invalid (refers to a nonexistent resource or + a Service with no endpoints), the rule performs no forwarding; if no + filters are specified that would result in a response being sent, the + underlying implementation must actively reject request attempts to this + backend, by rejecting the connection or returning a 500 status code. + Request rejections must respect weight; if an invalid backend is + requested to have 80% of requests, then 80% of requests must be rejected + instead. + + Support: Core for Kubernetes Service + + Support: Extended for Kubernetes ServiceImport + + Support: Implementation-specific for any other resource + + Support for weight: Extended + items: + description: |- + BackendRef defines how a Route should forward a request to a Kubernetes + resource. + + Note that when a namespace different than the local namespace is specified, a + ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + When the BackendRef points to a Kubernetes Service, implementations SHOULD + honor the appProtocol field if it is set for the target Service Port. + + Implementations supporting appProtocol SHOULD recognize the Kubernetes + Standard Application Protocols defined in KEP-3726. + + If a Service appProtocol isn't specified, an implementation MAY infer the + backend protocol through its own means. Implementations MAY infer the + protocol from the Route type referring to the backend Service. + + If a Route is not able to send traffic to the backend using the specified + protocol then the backend is considered invalid. Implementations MUST set the + "ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + Note that when the BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. See the fields + where this struct is used for more information about the exact behavior. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: |- + Weight specifies the proportion of requests forwarded to the referenced + backend. This is computed as weight/(sum of all weights in this + BackendRefs list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If only one backend is specified and it has a weight greater than 0, 100% + of the traffic is forwarded to that backend. If weight is set to 0, no + traffic should be forwarded for this entry. If unspecified, weight + defaults to 1. + + Support for this field varies based on the context where used. + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + minItems: 1 + type: array + name: + description: |- + Name is the name of the route rule. This name MUST be unique within a Route if it is set. + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-validations: + - message: Rule name must be unique within the route + rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) + && l1.name == l2.name)) + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + properties: + parents: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the route, and the status of the route with respect to + each parent. When this route attaches to a parent, the controller that + manages the parent must add an entry to this list when the controller + first sees the route and should update the entry as appropriate when the + route or gateway is modified. + + Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this API + can only populate Route status for the Gateways/parent resources they are + responsible for. + + A maximum of 32 Gateways will be represented in this list. An empty list + means the route has not been attached to any Gateway. + items: + description: |- + RouteParentStatus describes the status of a route with respect to an + associated Parent. + properties: + conditions: + description: |- + Conditions describes the status of the route with respect to the Gateway. + Note that the route's availability is also subject to the Gateway's own + status conditions and listener status. + + If the Route's ParentRef specifies an existing Gateway that supports + Routes of this kind AND that Gateway's controller has sufficient access, + then that Gateway's controller MUST set the "Accepted" condition on the + Route, to indicate whether the route has been accepted or rejected by the + Gateway, and why. + + A Route MUST be considered "Accepted" if at least one of the Route's + rules is implemented by the Gateway. + + There are a number of cases where the "Accepted" condition may not be set + due to lack of controller visibility, that includes when: + + * The Route refers to a nonexistent parent. + * The Route is of a type that the controller does not support. + * The Route is in a namespace the controller does not have access to. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: |- + ParentRef corresponds with a ParentRef in the spec that this + RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: |- + Name is the name of the referent. + + Support: Core + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. diff --git a/examples/experimental/v1alpha2/tls-routing/gateway.yaml b/examples/experimental/v1alpha2/tls-routing/gateway.yaml new file mode 100644 index 0000000000..a02bd52ee5 --- /dev/null +++ b/examples/experimental/v1alpha2/tls-routing/gateway.yaml @@ -0,0 +1,12 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: example-gateway +spec: + gatewayClassName: example-gateway-class + listeners: + - name: tls + protocol: TLS + port: 443 + tls: + mode: Passthrough diff --git a/examples/experimental/v1alpha2/tls-routing/tls-route.yaml b/examples/experimental/v1alpha2/tls-routing/tls-route.yaml new file mode 100644 index 0000000000..dd2f8527d5 --- /dev/null +++ b/examples/experimental/v1alpha2/tls-routing/tls-route.yaml @@ -0,0 +1,12 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + name: example-route +spec: + parentRefs: + - name: example-gateway + sectionName: tls + rules: + - backendRefs: + - name: example-svc + port: 443 diff --git a/examples/experimental/v1alpha3/tls-routing/gateway.yaml b/examples/experimental/v1alpha3/tls-routing/gateway.yaml new file mode 100644 index 0000000000..a02bd52ee5 --- /dev/null +++ b/examples/experimental/v1alpha3/tls-routing/gateway.yaml @@ -0,0 +1,12 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: example-gateway +spec: + gatewayClassName: example-gateway-class + listeners: + - name: tls + protocol: TLS + port: 443 + tls: + mode: Passthrough diff --git a/examples/experimental/v1alpha3/tls-routing/tls-route.yaml b/examples/experimental/v1alpha3/tls-routing/tls-route.yaml new file mode 100644 index 0000000000..1679ba6ac4 --- /dev/null +++ b/examples/experimental/v1alpha3/tls-routing/tls-route.yaml @@ -0,0 +1,14 @@ +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: TLSRoute +metadata: + name: example-route +spec: + parentRefs: + - name: example-gateway + sectionName: tls + hostnames: + - "example.com" + rules: + - backendRefs: + - name: example-svc + port: 443 diff --git a/hack/invalid-examples/experimental/tlsroute/no-hostname.yaml b/hack/invalid-examples/experimental/tlsroute/no-hostname.yaml new file mode 100644 index 0000000000..a2c137467d --- /dev/null +++ b/hack/invalid-examples/experimental/tlsroute/no-hostname.yaml @@ -0,0 +1,8 @@ +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: TLSRoute +metadata: + name: no-hostname +spec: + rules: + - backendRefs: + - name: foo diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go index 681d5090ed..e98418eee4 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/apis_client.go @@ -29,6 +29,7 @@ import ( type GatewayV1alpha3Interface interface { RESTClient() rest.Interface BackendTLSPoliciesGetter + TLSRoutesGetter } // GatewayV1alpha3Client is used to interact with features provided by the gateway.networking.k8s.io group. @@ -40,6 +41,10 @@ func (c *GatewayV1alpha3Client) BackendTLSPolicies(namespace string) BackendTLSP return newBackendTLSPolicies(c, namespace) } +func (c *GatewayV1alpha3Client) TLSRoutes(namespace string) TLSRouteInterface { + return newTLSRoutes(c, namespace) +} + // NewForConfig creates a new GatewayV1alpha3Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_apis_client.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_apis_client.go index 0ab453c2a8..e3144393ea 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_apis_client.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_apis_client.go @@ -32,6 +32,10 @@ func (c *FakeGatewayV1alpha3) BackendTLSPolicies(namespace string) v1alpha3.Back return newFakeBackendTLSPolicies(c, namespace) } +func (c *FakeGatewayV1alpha3) TLSRoutes(namespace string) v1alpha3.TLSRouteInterface { + return newFakeTLSRoutes(c, namespace) +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeGatewayV1alpha3) RESTClient() rest.Interface { diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_tlsroute.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_tlsroute.go new file mode 100644 index 0000000000..03542e1060 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/fake/fake_tlsroute.go @@ -0,0 +1,51 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + gentype "k8s.io/client-go/gentype" + v1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + apisv1alpha3 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha3" + typedapisv1alpha3 "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/typed/apis/v1alpha3" +) + +// fakeTLSRoutes implements TLSRouteInterface +type fakeTLSRoutes struct { + *gentype.FakeClientWithListAndApply[*v1alpha3.TLSRoute, *v1alpha3.TLSRouteList, *apisv1alpha3.TLSRouteApplyConfiguration] + Fake *FakeGatewayV1alpha3 +} + +func newFakeTLSRoutes(fake *FakeGatewayV1alpha3, namespace string) typedapisv1alpha3.TLSRouteInterface { + return &fakeTLSRoutes{ + gentype.NewFakeClientWithListAndApply[*v1alpha3.TLSRoute, *v1alpha3.TLSRouteList, *apisv1alpha3.TLSRouteApplyConfiguration]( + fake.Fake, + namespace, + v1alpha3.SchemeGroupVersion.WithResource("tlsroutes"), + v1alpha3.SchemeGroupVersion.WithKind("TLSRoute"), + func() *v1alpha3.TLSRoute { return &v1alpha3.TLSRoute{} }, + func() *v1alpha3.TLSRouteList { return &v1alpha3.TLSRouteList{} }, + func(dst, src *v1alpha3.TLSRouteList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha3.TLSRouteList) []*v1alpha3.TLSRoute { return gentype.ToPointerSlice(list.Items) }, + func(list *v1alpha3.TLSRouteList, items []*v1alpha3.TLSRoute) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/generated_expansion.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/generated_expansion.go index 68c5693b88..1c0cd8245b 100644 --- a/pkg/client/clientset/versioned/typed/apis/v1alpha3/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/generated_expansion.go @@ -19,3 +19,5 @@ limitations under the License. package v1alpha3 type BackendTLSPolicyExpansion interface{} + +type TLSRouteExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/apis/v1alpha3/tlsroute.go b/pkg/client/clientset/versioned/typed/apis/v1alpha3/tlsroute.go new file mode 100644 index 0000000000..e5b3aaa581 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/apis/v1alpha3/tlsroute.go @@ -0,0 +1,74 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" + apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + applyconfigurationapisv1alpha3 "sigs.k8s.io/gateway-api/applyconfiguration/apis/v1alpha3" + scheme "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned/scheme" +) + +// TLSRoutesGetter has a method to return a TLSRouteInterface. +// A group's client should implement this interface. +type TLSRoutesGetter interface { + TLSRoutes(namespace string) TLSRouteInterface +} + +// TLSRouteInterface has methods to work with TLSRoute resources. +type TLSRouteInterface interface { + Create(ctx context.Context, tLSRoute *apisv1alpha3.TLSRoute, opts v1.CreateOptions) (*apisv1alpha3.TLSRoute, error) + Update(ctx context.Context, tLSRoute *apisv1alpha3.TLSRoute, opts v1.UpdateOptions) (*apisv1alpha3.TLSRoute, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, tLSRoute *apisv1alpha3.TLSRoute, opts v1.UpdateOptions) (*apisv1alpha3.TLSRoute, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*apisv1alpha3.TLSRoute, error) + List(ctx context.Context, opts v1.ListOptions) (*apisv1alpha3.TLSRouteList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apisv1alpha3.TLSRoute, err error) + Apply(ctx context.Context, tLSRoute *applyconfigurationapisv1alpha3.TLSRouteApplyConfiguration, opts v1.ApplyOptions) (result *apisv1alpha3.TLSRoute, err error) + // Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus(). + ApplyStatus(ctx context.Context, tLSRoute *applyconfigurationapisv1alpha3.TLSRouteApplyConfiguration, opts v1.ApplyOptions) (result *apisv1alpha3.TLSRoute, err error) + TLSRouteExpansion +} + +// tLSRoutes implements TLSRouteInterface +type tLSRoutes struct { + *gentype.ClientWithListAndApply[*apisv1alpha3.TLSRoute, *apisv1alpha3.TLSRouteList, *applyconfigurationapisv1alpha3.TLSRouteApplyConfiguration] +} + +// newTLSRoutes returns a TLSRoutes +func newTLSRoutes(c *GatewayV1alpha3Client, namespace string) *tLSRoutes { + return &tLSRoutes{ + gentype.NewClientWithListAndApply[*apisv1alpha3.TLSRoute, *apisv1alpha3.TLSRouteList, *applyconfigurationapisv1alpha3.TLSRouteApplyConfiguration]( + "tlsroutes", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *apisv1alpha3.TLSRoute { return &apisv1alpha3.TLSRoute{} }, + func() *apisv1alpha3.TLSRouteList { return &apisv1alpha3.TLSRouteList{} }, + ), + } +} diff --git a/pkg/client/informers/externalversions/apis/v1alpha3/interface.go b/pkg/client/informers/externalversions/apis/v1alpha3/interface.go index 468614d4f4..adeb3dc54c 100644 --- a/pkg/client/informers/externalversions/apis/v1alpha3/interface.go +++ b/pkg/client/informers/externalversions/apis/v1alpha3/interface.go @@ -26,6 +26,8 @@ import ( type Interface interface { // BackendTLSPolicies returns a BackendTLSPolicyInformer. BackendTLSPolicies() BackendTLSPolicyInformer + // TLSRoutes returns a TLSRouteInformer. + TLSRoutes() TLSRouteInformer } type version struct { @@ -43,3 +45,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (v *version) BackendTLSPolicies() BackendTLSPolicyInformer { return &backendTLSPolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// TLSRoutes returns a TLSRouteInformer. +func (v *version) TLSRoutes() TLSRouteInformer { + return &tLSRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/apis/v1alpha3/tlsroute.go b/pkg/client/informers/externalversions/apis/v1alpha3/tlsroute.go new file mode 100644 index 0000000000..11d171c8b3 --- /dev/null +++ b/pkg/client/informers/externalversions/apis/v1alpha3/tlsroute.go @@ -0,0 +1,102 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + context "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + gatewayapiapisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + versioned "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + internalinterfaces "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions/internalinterfaces" + apisv1alpha3 "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1alpha3" +) + +// TLSRouteInformer provides access to a shared informer and lister for +// TLSRoutes. +type TLSRouteInformer interface { + Informer() cache.SharedIndexInformer + Lister() apisv1alpha3.TLSRouteLister +} + +type tLSRouteInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTLSRouteInformer constructs a new informer for TLSRoute type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewTLSRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTLSRouteInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredTLSRouteInformer constructs a new informer for TLSRoute type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredTLSRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().TLSRoutes(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().TLSRoutes(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().TLSRoutes(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.GatewayV1alpha3().TLSRoutes(namespace).Watch(ctx, options) + }, + }, + &gatewayapiapisv1alpha3.TLSRoute{}, + resyncPeriod, + indexers, + ) +} + +func (f *tLSRouteInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTLSRouteInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *tLSRouteInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&gatewayapiapisv1alpha3.TLSRoute{}, f.defaultInformer) +} + +func (f *tLSRouteInformer) Lister() apisv1alpha3.TLSRouteLister { + return apisv1alpha3.NewTLSRouteLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 1d90930c0c..b777993d4e 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -81,6 +81,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=gateway.networking.k8s.io, Version=v1alpha3 case v1alpha3.SchemeGroupVersion.WithResource("backendtlspolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha3().BackendTLSPolicies().Informer()}, nil + case v1alpha3.SchemeGroupVersion.WithResource("tlsroutes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Gateway().V1alpha3().TLSRoutes().Informer()}, nil // Group=gateway.networking.k8s.io, Version=v1beta1 case v1beta1.SchemeGroupVersion.WithResource("gateways"): diff --git a/pkg/client/listers/apis/v1alpha3/expansion_generated.go b/pkg/client/listers/apis/v1alpha3/expansion_generated.go index 5cba22fc90..a47937d93c 100644 --- a/pkg/client/listers/apis/v1alpha3/expansion_generated.go +++ b/pkg/client/listers/apis/v1alpha3/expansion_generated.go @@ -25,3 +25,11 @@ type BackendTLSPolicyListerExpansion interface{} // BackendTLSPolicyNamespaceListerExpansion allows custom methods to be added to // BackendTLSPolicyNamespaceLister. type BackendTLSPolicyNamespaceListerExpansion interface{} + +// TLSRouteListerExpansion allows custom methods to be added to +// TLSRouteLister. +type TLSRouteListerExpansion interface{} + +// TLSRouteNamespaceListerExpansion allows custom methods to be added to +// TLSRouteNamespaceLister. +type TLSRouteNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/apis/v1alpha3/tlsroute.go b/pkg/client/listers/apis/v1alpha3/tlsroute.go new file mode 100644 index 0000000000..efc0e9016c --- /dev/null +++ b/pkg/client/listers/apis/v1alpha3/tlsroute.go @@ -0,0 +1,70 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" + apisv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" +) + +// TLSRouteLister helps list TLSRoutes. +// All objects returned here must be treated as read-only. +type TLSRouteLister interface { + // List lists all TLSRoutes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apisv1alpha3.TLSRoute, err error) + // TLSRoutes returns an object that can list and get TLSRoutes. + TLSRoutes(namespace string) TLSRouteNamespaceLister + TLSRouteListerExpansion +} + +// tLSRouteLister implements the TLSRouteLister interface. +type tLSRouteLister struct { + listers.ResourceIndexer[*apisv1alpha3.TLSRoute] +} + +// NewTLSRouteLister returns a new TLSRouteLister. +func NewTLSRouteLister(indexer cache.Indexer) TLSRouteLister { + return &tLSRouteLister{listers.New[*apisv1alpha3.TLSRoute](indexer, apisv1alpha3.Resource("tlsroute"))} +} + +// TLSRoutes returns an object that can list and get TLSRoutes. +func (s *tLSRouteLister) TLSRoutes(namespace string) TLSRouteNamespaceLister { + return tLSRouteNamespaceLister{listers.NewNamespaced[*apisv1alpha3.TLSRoute](s.ResourceIndexer, namespace)} +} + +// TLSRouteNamespaceLister helps list and get TLSRoutes. +// All objects returned here must be treated as read-only. +type TLSRouteNamespaceLister interface { + // List lists all TLSRoutes in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apisv1alpha3.TLSRoute, err error) + // Get retrieves the TLSRoute from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*apisv1alpha3.TLSRoute, error) + TLSRouteNamespaceListerExpansion +} + +// tLSRouteNamespaceLister implements the TLSRouteNamespaceLister +// interface. +type tLSRouteNamespaceLister struct { + listers.ResourceIndexer[*apisv1alpha3.TLSRoute] +} diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 13ff9ab516..b26723bcec 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -178,6 +178,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicySpec": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicySpec(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.BackendTLSPolicyValidation": schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref), "sigs.k8s.io/gateway-api/apis/v1alpha3.SubjectAltName": schema_sigsk8sio_gateway_api_apis_v1alpha3_SubjectAltName(ref), + "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRoute": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRoute(ref), + "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteList": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteList(ref), + "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteSpec": schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref), "sigs.k8s.io/gateway-api/apis/v1beta1.Gateway": schema_sigsk8sio_gateway_api_apis_v1beta1_Gateway(ref), "sigs.k8s.io/gateway-api/apis/v1beta1.GatewayClass": schema_sigsk8sio_gateway_api_apis_v1beta1_GatewayClass(ref), "sigs.k8s.io/gateway-api/apis/v1beta1.GatewayClassList": schema_sigsk8sio_gateway_api_apis_v1beta1_GatewayClassList(ref), @@ -7168,6 +7171,164 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_SubjectAltName(ref common.Refere } } +func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRoute(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "The TLSRoute resource is similar to TCPRoute, but can be configured to match against TLS-specific metadata. This allows more flexibility in matching streams for a given TLS listener.\n\nIf you need to forward traffic to a single target for a TLS listener, you could choose to use a TCPRoute with a TLS listener.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "Spec defines the desired state of TLSRoute.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "Status defines the current state of TLSRoute.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.TLSRouteStatus"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "sigs.k8s.io/gateway-api/apis/v1alpha2.TLSRouteStatus", "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRouteSpec"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TLSRouteList contains a list of TLSRoute", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRoute"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "sigs.k8s.io/gateway-api/apis/v1alpha3.TLSRoute"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TLSRouteSpec defines the desired state of a TLSRoute resource.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "parentRefs": { + SchemaProps: spec.SchemaProps{ + Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ParentReference"), + }, + }, + }, + }, + }, + "hostnames": { + SchemaProps: spec.SchemaProps{ + Description: "Hostnames defines a set of SNI hostnames that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed in SNI hostnames per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames, or have specified at\n least one of `test.example.com` or `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames or have specified at least\n one hostname that matches the Listener hostname. For example,\n `test.example.com` and `*.example.com` would both match. On the other\n hand, `example.com` and `test.example.net` would not match.\n\nIf both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nSupport: Core", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "rules": { + SchemaProps: spec.SchemaProps{ + Description: "Rules are a list of TLS matchers and actions.\n\n", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1alpha2.TLSRouteRule"), + }, + }, + }, + }, + }, + }, + Required: []string{"rules"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.ParentReference", "sigs.k8s.io/gateway-api/apis/v1alpha2.TLSRouteRule"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1beta1_Gateway(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ From a07680f5ade11bbd90278e586322eedabeb29d44 Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Tue, 15 Jul 2025 16:22:24 +0200 Subject: [PATCH 086/224] TLSRoute: Require hostnames via +required (#3918) * TLSRoute: Require hostnames, no omitempty * TLSRoute: Require hostnames using +required --- apis/v1alpha3/tlsroute_types.go | 1 + .../crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml | 1 + pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go index 7bcb48e74b..60e2dc7b99 100644 --- a/apis/v1alpha3/tlsroute_types.go +++ b/apis/v1alpha3/tlsroute_types.go @@ -86,6 +86,7 @@ type TLSRouteSpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 + // +required Hostnames []Hostname `json:"hostnames,omitempty"` // Rules are a list of TLS matchers and actions. diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 4392eff57f..923fa49ba5 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -1277,6 +1277,7 @@ spec: rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) && l1.name == l2.name)) required: + - hostnames - rules type: object status: diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index b26723bcec..7dcbaa33b6 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7321,7 +7321,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, }, }, - Required: []string{"rules"}, + Required: []string{"hostnames", "rules"}, }, }, Dependencies: []string{ From 35e6bea8424431d96f1cb8f61a96130ea6d573ff Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Tue, 15 Jul 2025 09:04:24 -0700 Subject: [PATCH 087/224] Revert "feat(conformance): validate implementation flags (#3715)" (#3920) This reverts commit 564720a533f9ff28e65bdf898c1274ace1865245. --- conformance/conformance.go | 5 +- conformance/utils/suite/suite.go | 26 +------- conformance/utils/suite/suite_test.go | 86 --------------------------- pkg/test/cel/grpcroute_test.go | 3 +- 4 files changed, 6 insertions(+), 114 deletions(-) diff --git a/conformance/conformance.go b/conformance/conformance.go index 8ea5799e58..12e5884968 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -72,14 +72,13 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { namespaceAnnotations := suite.ParseKeyValuePairs(*flags.NamespaceAnnotations) conformanceProfiles := suite.ParseConformanceProfiles(*flags.ConformanceProfiles) - implementation, err := suite.ParseImplementation( + implementation := suite.ParseImplementation( *flags.ImplementationOrganization, *flags.ImplementationProject, *flags.ImplementationURL, *flags.ImplementationVersion, *flags.ImplementationContact, ) - require.NoError(t, err, "error parsing implementation details") return suite.ConformanceOptions{ AllowCRDsMismatch: *flags.AllowCRDsMismatch, @@ -93,7 +92,7 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { ExemptFeatures: exemptFeatures, ManifestFS: []fs.FS{&Manifests}, GatewayClassName: *flags.GatewayClassName, - Implementation: *implementation, + Implementation: implementation, Mode: *flags.Mode, NamespaceAnnotations: namespaceAnnotations, NamespaceLabels: namespaceLabels, diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 2402821e6f..f1164fa2fe 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "io/fs" - neturl "net/url" "slices" "sort" "strings" @@ -559,33 +558,14 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) { // ParseImplementation parses implementation-specific flag arguments and // creates a *confv1a1.Implementation. -func ParseImplementation(org, project, url, version, contact string) (*confv1.Implementation, error) { - if org == "" { - return nil, errors.New("organization must be set") - } - if project == "" { - return nil, errors.New("project must be set") - } - if url == "" { - return nil, errors.New("url must be set") - } - if version == "" { - return nil, errors.New("version must be set") - } - if contact == "" { - return nil, errors.New("contact must be set") - } - if _, err := neturl.ParseRequestURI(url); err != nil { - return nil, errors.New("url is malformed") - } - - return &confv1.Implementation{ +func ParseImplementation(org, project, url, version, contact string) confv1.Implementation { + return confv1.Implementation{ Organization: org, Project: project, URL: url, Version: version, Contact: strings.Split(contact, ","), - }, nil + } } // ParseConformanceProfiles parses flag arguments and converts the string to diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index 69b7d3d979..ccb259adb0 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -538,89 +538,3 @@ func namesToFeatureSet(names []string) FeaturesSet { } return featureSet } - -func TestParseImplementation(t *testing.T) { - testCases := []struct { - name string - org string - project string - url string - version string - contact string - expected *confv1.Implementation - expectedErr error - }{ - { - name: "missing organization", - project: "test-project", - url: "https://example.com", - version: "v1.0.0", - contact: "test@example.com", - expectedErr: errors.New("organization must be set"), - }, - { - name: "missing project", - org: "test-org", - url: "https://example.com", - version: "v1.0.0", - contact: "test@example.com", - expectedErr: errors.New("project must be set"), - }, - { - name: "missing url", - org: "test-org", - project: "test-project", - version: "v1.0.0", - contact: "test@example.com", - expectedErr: errors.New("url must be set"), - }, - { - name: "missing version", - org: "test-org", - project: "test-project", - url: "https://example.com", - contact: "test@example.com", - expectedErr: errors.New("version must be set"), - }, - { - name: "missing contact", - org: "test-org", - project: "test-project", - url: "https://example.com", - version: "v1.0.0", - expectedErr: errors.New("contact must be set"), - }, - { - name: "malformed url", - org: "test-org", - project: "test-project", - url: "invalid-url", - version: "v1.0.0", - contact: "test@example.com", - expectedErr: errors.New("url is malformed"), - }, - { - name: "valid input", - org: "test-org", - project: "test-project", - url: "https://example.com", - version: "v1.0.0", - contact: "test@example.com,test2@example.com", - expected: &confv1.Implementation{ - Organization: "test-org", - Project: "test-project", - URL: "https://example.com", - Version: "v1.0.0", - Contact: []string{"test@example.com", "test2@example.com"}, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - result, err := ParseImplementation(tc.org, tc.project, tc.url, tc.version, tc.contact) - assert.Equal(t, tc.expected, result) - assert.Equal(t, tc.expectedErr, err) - }) - } -} diff --git a/pkg/test/cel/grpcroute_test.go b/pkg/test/cel/grpcroute_test.go index 2940ce3291..628de66ae9 100644 --- a/pkg/test/cel/grpcroute_test.go +++ b/pkg/test/cel/grpcroute_test.go @@ -341,8 +341,7 @@ func TestGRPCRouteRule(t *testing.T) { } return rules }(), - }, - } + }} for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { From b7ebf2a137c52c739e59f857128f38d8261b5d14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 23:18:24 -0700 Subject: [PATCH 088/224] build(deps): bump golang.org/x/sync from 0.15.0 to 0.16.0 (#3915) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-version: 0.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a2eca0cfc6..82f05190d0 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/miekg/dns v1.1.66 github.com/stretchr/testify v1.10.0 golang.org/x/net v0.41.0 - golang.org/x/sync v0.15.0 + golang.org/x/sync v0.16.0 google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 diff --git a/go.sum b/go.sum index e08b99f8e9..85b14c3ac1 100644 --- a/go.sum +++ b/go.sum @@ -180,8 +180,8 @@ golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From b285585b881d49b0c7961c9f6c5efe374d79b5e2 Mon Sep 17 00:00:00 2001 From: Mayuka Channankaiah <57181320+mayuka-c@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:22:27 +0530 Subject: [PATCH 089/224] Fix Godoc for BackendTLSPolicyValidation struct for Hostname field (#3923) * Fix Godoc for BackendTLSPolicyValidation struct for Hostname field * Run make generate --- apis/v1alpha3/backendtlspolicy_types.go | 2 -- .../gateway.networking.k8s.io_backendtlspolicies.yaml | 2 -- pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index 394fa46c23..75655f5d63 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -152,8 +152,6 @@ type BackendTLSPolicyValidation struct { // // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). // 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. - // authentication and MUST match the certificate served by the matching - // backend. // // Support: Core Hostname v1.PreciseHostname `json:"hostname"` diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index 6a9e653a31..a2a5506c17 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -233,8 +233,6 @@ spec: 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. - authentication and MUST match the certificate served by the matching - backend. Support: Core maxLength: 253 diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 7dcbaa33b6..8d76a3bf19 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7106,7 +7106,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, "hostname": { SchemaProps: spec.SchemaProps{ - Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified.\n authentication and MUST match the certificate served by the matching\n backend.\n\nSupport: Core", + Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified.\n\nSupport: Core", Default: "", Type: []string{"string"}, Format: "", From d7c5992fc896a11a12c28f0fba746825a0c554df Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Wed, 16 Jul 2025 12:20:25 -0300 Subject: [PATCH 090/224] Enable Kubernetes API Linter (#3917) * Add kubeapi linter * Enable duplicatemarkers linter * Enable jsontags linter * Enable nofloats linter * Enable nomaps linter * Enable nophase linter * Enable requiredfields linter * Enable statussubresource linter * Enable uniquemarkers linter * Enable Kube API Linter Github Workflow * Pin lint version correctly and fix config file spacing * Fix kal github actions spacing and remove requiredfields linter --- .custom-gcl.yml | 6 ++++ .github/workflows/kal.yml | 25 +++++++++++++ .golangci-kal.yml | 36 +++++++++++++++++++ apis/v1/httproute_types.go | 1 - .../gateway.networking.k8s.io_httproutes.yaml | 8 ----- .../gateway.networking.k8s.io_httproutes.yaml | 8 ----- 6 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 .custom-gcl.yml create mode 100644 .github/workflows/kal.yml create mode 100644 .golangci-kal.yml diff --git a/.custom-gcl.yml b/.custom-gcl.yml new file mode 100644 index 0000000000..84754359fa --- /dev/null +++ b/.custom-gcl.yml @@ -0,0 +1,6 @@ +version: v2.2.1 +name: golangci-kube-api-linter +destination: ./bin +plugins: +- module: 'sigs.k8s.io/kube-api-linter' + version: 'v0.0.0-20250715075424-4fab82d26a8e' # Pin to a commit while there's no tag diff --git a/.github/workflows/kal.yml b/.github/workflows/kal.yml new file mode 100644 index 0000000000..d657969f5d --- /dev/null +++ b/.github/workflows/kal.yml @@ -0,0 +1,25 @@ +name: PR golangci-lint + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +# Remove all permissions from GITHUB_TOKEN except metadata. +permissions: {} + +jobs: + golangci: + name: kube-api-lint + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 + - name: Install Golang CI Lint + run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.2.1 + - name: Build KAL + run: golangci-lint custom + - name: run api linter + run: ./bin/golangci-kube-api-linter run -c ./.golangci-kal.yml ./... diff --git a/.golangci-kal.yml b/.golangci-kal.yml new file mode 100644 index 0000000000..aad23ab40d --- /dev/null +++ b/.golangci-kal.yml @@ -0,0 +1,36 @@ +version: "2" +linters: + default: none + enable: + - kubeapilinter + settings: + custom: + kubeapilinter: + type: module + description: Kube API LInter lints Kube like APIs based on API conventions and best practices. + settings: + linters: + enable: + - "duplicatemarkers" # Ensure there are no exact duplicate markers. for types and fields. + - "jsontags" # Ensure every field has a json tag. + - "nofloats" # Ensure floats are not used. + - "nomaps" # Ensure maps are not used. + - "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead. + - "statussubresource" # All root objects that have a `status` field should have a status subresource. + - "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once. + disable: + - "*" + lintersConfig: {} + exclusions: + generated: strict + paths: + - conformance/ + paths-except: + - apis/ + - apisx/ +issues: + max-issues-per-linter: 0 + max-same-issues: 0 +run: + timeout: 5m + tests: false diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index e59ebf7bcc..157932e971 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1590,7 +1590,6 @@ type HTTPBackendRef struct { // +optional // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" // +kubebuilder:validation:XValidation:message="RequestRedirect filter cannot be repeated",rule="self.filter(f, f.type == 'RequestRedirect').size() <= 1" diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index cf2b274655..fe5b7f0330 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -1524,10 +1524,6 @@ spec: maxItems: 16 type: array x-kubernetes-validations: - - message: May specify either httpRouteFilterRequestRedirect - or httpRouteFilterRequestRewrite, but not both - rule: '!(self.exists(f, f.type == ''RequestRedirect'') - && self.exists(f, f.type == ''URLRewrite''))' - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: '!(self.exists(f, f.type == ''RequestRedirect'') @@ -5144,10 +5140,6 @@ spec: maxItems: 16 type: array x-kubernetes-validations: - - message: May specify either httpRouteFilterRequestRedirect - or httpRouteFilterRequestRewrite, but not both - rule: '!(self.exists(f, f.type == ''RequestRedirect'') - && self.exists(f, f.type == ''URLRewrite''))' - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: '!(self.exists(f, f.type == ''RequestRedirect'') diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 8533381fc2..1824bd5e19 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -1191,10 +1191,6 @@ spec: maxItems: 16 type: array x-kubernetes-validations: - - message: May specify either httpRouteFilterRequestRedirect - or httpRouteFilterRequestRewrite, but not both - rule: '!(self.exists(f, f.type == ''RequestRedirect'') - && self.exists(f, f.type == ''URLRewrite''))' - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: '!(self.exists(f, f.type == ''RequestRedirect'') @@ -3995,10 +3991,6 @@ spec: maxItems: 16 type: array x-kubernetes-validations: - - message: May specify either httpRouteFilterRequestRedirect - or httpRouteFilterRequestRewrite, but not both - rule: '!(self.exists(f, f.type == ''RequestRedirect'') - && self.exists(f, f.type == ''URLRewrite''))' - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: '!(self.exists(f, f.type == ''RequestRedirect'') From b92e49bedd0c7c71de0c366e14752d5433162338 Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Wed, 16 Jul 2025 18:52:28 +0200 Subject: [PATCH 091/224] TLSRoute: Hostnames godoc (#3925) --- apis/v1alpha3/tlsroute_types.go | 12 ++++++------ .../gateway.networking.k8s.io_tlsroutes.yaml | 12 ++++++------ pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go index 60e2dc7b99..82345f9080 100644 --- a/apis/v1alpha3/tlsroute_types.go +++ b/apis/v1alpha3/tlsroute_types.go @@ -63,13 +63,13 @@ type TLSRouteSpec struct { // attached to the Listener. For example: // // * A Listener with `test.example.com` as the hostname matches TLSRoutes - // that have either not specified any hostnames, or have specified at - // least one of `test.example.com` or `*.example.com`. + // that have specified at least one of `test.example.com` or + // `*.example.com`. // * A Listener with `*.example.com` as the hostname matches TLSRoutes - // that have either not specified any hostnames or have specified at least - // one hostname that matches the Listener hostname. For example, - // `test.example.com` and `*.example.com` would both match. On the other - // hand, `example.com` and `test.example.net` would not match. + // that have specified at least one hostname that matches the Listener + // hostname. For example, `test.example.com` and `*.example.com` would both + // match. On the other hand, `example.com` and `test.example.net` would not + // match. // // If both the Listener and TLSRoute have specified hostnames, any // TLSRoute hostnames that do not match the Listener hostname MUST be diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 923fa49ba5..8843c2f0d3 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -837,13 +837,13 @@ spec: attached to the Listener. For example: * A Listener with `test.example.com` as the hostname matches TLSRoutes - that have either not specified any hostnames, or have specified at - least one of `test.example.com` or `*.example.com`. + that have specified at least one of `test.example.com` or + `*.example.com`. * A Listener with `*.example.com` as the hostname matches TLSRoutes - that have either not specified any hostnames or have specified at least - one hostname that matches the Listener hostname. For example, - `test.example.com` and `*.example.com` would both match. On the other - hand, `example.com` and `test.example.net` would not match. + that have specified at least one hostname that matches the Listener + hostname. For example, `test.example.com` and `*.example.com` would both + match. On the other hand, `example.com` and `test.example.net` would not + match. If both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 8d76a3bf19..cc919c61da 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7293,7 +7293,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "hostnames": { SchemaProps: spec.SchemaProps{ - Description: "Hostnames defines a set of SNI hostnames that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed in SNI hostnames per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames, or have specified at\n least one of `test.example.com` or `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames or have specified at least\n one hostname that matches the Listener hostname. For example,\n `test.example.com` and `*.example.com` would both match. On the other\n hand, `example.com` and `test.example.net` would not match.\n\nIf both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nSupport: Core", + Description: "Hostnames defines a set of SNI hostnames that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed in SNI hostnames per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches TLSRoutes\n that have specified at least one of `test.example.com` or\n `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches TLSRoutes\n that have specified at least one hostname that matches the Listener\n hostname. For example, `test.example.com` and `*.example.com` would both\n match. On the other hand, `example.com` and `test.example.net` would not\n match.\n\nIf both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nSupport: Core", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From 25f974cee49a8096a0d79712df8253dab65f749f Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:12:25 -0700 Subject: [PATCH 092/224] [GEP-2162] Updated a new field on supported features inference from boolean to enum and remove from report. (#3885) * Update inferred supported features report from bool to enum to account for exceptional case when only Mesh profile is being tested and no GWC available to determine supported features. * Changed enum names. * Added comment to report enum * Revert change caused by merge. * Converted enums from int to string for better readability. * Removed unused import. * Updated unit tests to reflect enum change to strings. * Removed skip tests from determining if supported features are inferred or manually selected. * Removed source update. * Updated unit tests. * Removed source enum from report. * start error string with lowercase. * Removed source getter. * removed undefined enum and added check for mesh features. * return error if mesh features are populated in gwc. * Updated unit tests. * Removed check for mesh profile before throwing error for publishing mesh features. As with this error we want to prevent mesh features under GWC, not mesh profiles for testing. * removed extra else * Removed not needed field from function. * Cleanup of extra field --- conformance/apis/v1/conformancereport.go | 4 -- conformance/utils/suite/suite.go | 42 +++++++++------ conformance/utils/suite/suite_test.go | 69 ++++++++++++++++++++---- 3 files changed, 86 insertions(+), 29 deletions(-) diff --git a/conformance/apis/v1/conformancereport.go b/conformance/apis/v1/conformancereport.go index dcea92dffc..7f4f4d5325 100644 --- a/conformance/apis/v1/conformancereport.go +++ b/conformance/apis/v1/conformancereport.go @@ -50,10 +50,6 @@ type ConformanceReport struct { // SucceededProvisionalTests is a list of the names of the provisional tests that // have been successfully run. SucceededProvisionalTests []string `json:"succeededProvisionalTests,omitempty"` - - // InferredSupportedFeatures indicates whether the supported features were - // automatically detected by the conformance suite. - InferredSupportedFeatures bool `json:"inferredSupportedFeatures"` } // Implementation provides metadata information on the downstream diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index f1164fa2fe..5b30598886 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -84,7 +84,7 @@ type ConformanceTestSuite struct { // If SupportedFeatures are automatically determined from GWC Status. // This will be required to report in future iterations as the passing // will be determined based on this. - isInferredSupportedFeatures bool + supportedFeaturesSource supportedFeaturesSource // mode is the operating mode of the implementation. // The default value for it is "default". @@ -188,24 +188,37 @@ const ( undefinedKeyword = "UNDEFINED" ) +// SupportedFeaturesSource represents the source from which supported features are derived. +// It is used to distinguish between them being inferred from GWC Status or manually +// supplied for the conformance report. +type supportedFeaturesSource string + +const ( + supportedFeaturesSourceManual supportedFeaturesSource = "Manual" + supportedFeaturesSourceInferred supportedFeaturesSource = "Inferred" +) + // NewConformanceTestSuite is a helper to use for creating a new ConformanceTestSuite. func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, error) { supportedFeatures := options.SupportedFeatures.Difference(options.ExemptFeatures) - isInferred := false - switch { - case options.EnableAllSupportedFeatures: + source := supportedFeaturesSourceManual + if options.EnableAllSupportedFeatures { supportedFeatures = features.SetsToNamesSet(features.AllFeatures) - case shouldInferSupportedFeatures(&options): + } else if shouldInferSupportedFeatures(&options) { var err error supportedFeatures, err = fetchSupportedFeatures(options.Client, options.GatewayClassName) if err != nil { - return nil, fmt.Errorf("Cannot infer supported features: %w", err) + return nil, fmt.Errorf("cannot infer supported features: %w", err) + } + + if hasMeshFeatures(supportedFeatures) { + return nil, fmt.Errorf("mesh features should not be populated in GatewayClass") } - isInferred = true + source = supportedFeaturesSourceInferred } // If features were not inferred from Status, it's a GWC issue. - if isInferred && supportedFeatures.Len() == 0 { + if source == supportedFeaturesSourceInferred && supportedFeatures.Len() == 0 { return nil, fmt.Errorf("no supported features were determined for test suite") } @@ -273,7 +286,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, mode: mode, apiVersion: apiVersion, apiChannel: apiChannel, - isInferredSupportedFeatures: isInferred, + supportedFeaturesSource: source, Hook: options.Hook, } @@ -394,10 +407,6 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) } } -func (suite *ConformanceTestSuite) IsInferredSupportedFeatures() bool { - return suite.isInferredSupportedFeatures -} - func (suite *ConformanceTestSuite) setClientsetForTest(test ConformanceTest) error { featureNames := []string{} for _, v := range test.Features { @@ -552,7 +561,6 @@ func (suite *ConformanceTestSuite) Report() (*confv1.ConformanceReport, error) { GatewayAPIChannel: suite.apiChannel, ProfileReports: profileReports.list(), SucceededProvisionalTests: succeededProvisionalTests, - InferredSupportedFeatures: suite.IsInferredSupportedFeatures(), }, nil } @@ -610,8 +618,6 @@ func shouldInferSupportedFeatures(opts *ConformanceOptions) bool { return !opts.EnableAllSupportedFeatures && opts.SupportedFeatures.Len() == 0 && opts.ExemptFeatures.Len() == 0 && - opts.ConformanceProfiles.Len() == 0 && - len(opts.SkipTests) == 0 && opts.RunTest == "" } @@ -645,3 +651,7 @@ func getAPIVersionAndChannel(crds []apiextensionsv1.CustomResourceDefinition) (v return version, channel, nil } + +func hasMeshFeatures(f FeaturesSet) bool { + return f.HasAny(features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures).UnsortedList()...) +} diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index ccb259adb0..311da616a2 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -280,7 +280,6 @@ func TestSuiteReport(t *testing.T) { coreProvisionalTest.ShortName, extendedProvisionalTest.ShortName, }, - InferredSupportedFeatures: true, }, }, { @@ -390,7 +389,6 @@ func TestSuiteReport(t *testing.T) { }, }, }, - InferredSupportedFeatures: true, }, }, } @@ -434,33 +432,37 @@ func TestInferSupportedFeatures(t *testing.T) { exemptFeatures FeaturesSet ConformanceProfile sets.Set[ConformanceProfileName] expectedFeatures FeaturesSet - expectedIsInferred bool + expectedSource supportedFeaturesSource }{ { - name: "properly infer supported features", - expectedFeatures: namesToFeatureSet(statusFeatureNames), - expectedIsInferred: true, + name: "properly infer supported features", + expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, }, { name: "no features", supportedFeatures: sets.New[features.FeatureName]("Gateway"), expectedFeatures: sets.New[features.FeatureName]("Gateway"), + expectedSource: supportedFeaturesSourceManual, }, { name: "remove exempt features", supportedFeatures: sets.New[features.FeatureName]("Gateway", "HTTPRoute"), exemptFeatures: sets.New[features.FeatureName]("HTTPRoute"), expectedFeatures: sets.New[features.FeatureName]("Gateway"), + expectedSource: supportedFeaturesSourceManual, }, { name: "allow all features", allowAllFeatures: true, expectedFeatures: features.SetsToNamesSet(features.AllFeatures), + expectedSource: supportedFeaturesSourceManual, }, { name: "supports conformance profile - core", ConformanceProfile: sets.New(GatewayHTTPConformanceProfileName), - expectedFeatures: namesToFeatureSet([]string{"Gateway", "HTTPRoute", "ReferenceGrant"}), + expectedFeatures: namesToFeatureSet(statusFeatureNames), + expectedSource: supportedFeaturesSourceInferred, }, } @@ -512,8 +514,8 @@ func TestInferSupportedFeatures(t *testing.T) { t.Fatalf("error initializing conformance suite: %v", err) } - if cSuite.IsInferredSupportedFeatures() != tc.expectedIsInferred { - t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.IsInferredSupportedFeatures(), tc.expectedIsInferred) + if cSuite.supportedFeaturesSource != tc.expectedSource { + t.Errorf("InferredSupportedFeatures mismatch: got %v, want %v", cSuite.supportedFeaturesSource, tc.expectedSource) } if equal := cSuite.SupportedFeatures.Equal(tc.expectedFeatures); !equal { @@ -523,6 +525,55 @@ func TestInferSupportedFeatures(t *testing.T) { } } +func TestGWCPublishedMeshFeatures(t *testing.T) { + gwcName := "ochopintre" + gwc := &gatewayv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: gwcName, + }, + Spec: gatewayv1.GatewayClassSpec{ + ControllerName: "example.com/gateway-controller", + }, + Status: gatewayv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: string(gatewayv1.GatewayConditionAccepted), + Status: metav1.ConditionTrue, + Reason: "Accepted", + Message: "GatewayClass is accepted and ready for use", + }, + }, + SupportedFeatures: featureNamesToSet([]string{ + string(features.SupportGateway), + string(features.SupportGatewayStaticAddresses), + string(features.SupportMeshClusterIPMatching), + string(features.SupportMeshConsumerRoute), + }), + }, + } + scheme := runtime.NewScheme() + scheme.AddKnownTypes(gatewayv1.SchemeGroupVersion, &gatewayv1.GatewayClass{}) + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(gwc). + WithLists(&apiextensionsv1.CustomResourceDefinitionList{}). + Build() + + gatewayv1.Install(fakeClient.Scheme()) + apiextensionsv1.AddToScheme(fakeClient.Scheme()) + + options := ConformanceOptions{ + AllowCRDsMismatch: true, + GatewayClassName: gwcName, + Client: fakeClient, + } + + _, err := NewConformanceTestSuite(options) + if err == nil { + t.Fatalf("expected an error but got nil") + } +} + func featureNamesToSet(set []string) []gatewayv1.SupportedFeature { var features []gatewayv1.SupportedFeature for _, feature := range set { From bc08c0ff375ad76fdda7089121c6e1e06662c137 Mon Sep 17 00:00:00 2001 From: HaeyoonJo Date: Wed, 16 Jul 2025 23:38:24 +0300 Subject: [PATCH 093/224] Fix malformed URL typo in index.md (#3926) --- geps/gep-3792/index.md | 4 ++-- geps/gep-3793/index.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/geps/gep-3792/index.md b/geps/gep-3792/index.md index b0c5d80b6b..802d729c97 100644 --- a/geps/gep-3792/index.md +++ b/geps/gep-3792/index.md @@ -19,8 +19,8 @@ cluster, for various reasons which are out of the scope of this GEP. Chihiro and Ian want to be able to use these out-of-cluster proxies effectively and safely, though they recognize that this may require additional configuration. -[Chihiro]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro -[Ian]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian +[Chihiro]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro +[Ian]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian ### Nomenclature and Background diff --git a/geps/gep-3793/index.md b/geps/gep-3793/index.md index 0c8ba3e6ae..9f15ead87d 100644 --- a/geps/gep-3793/index.md +++ b/geps/gep-3793/index.md @@ -19,7 +19,7 @@ really doesn't care what the Gateway is called. Therefore, Ana would like a way to be able to rely on a default Gateway that she doesn't have to explicitly name, and can simply trust to exist. -[Ana]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana +[Ana]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana ## Goals @@ -156,8 +156,8 @@ Ana has easy access to this information, and that it's clear enough for her to understand, is clearly important for many more reasons than just default Gateways. -[Chihiro]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro -[Ian]: https://https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian +[Chihiro]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro +[Ian]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian ## API From 0fd1805d4f97b4ee6a57339f3a411a26018ad699 Mon Sep 17 00:00:00 2001 From: Candace Holman Date: Mon, 21 Jul 2025 11:44:28 -0400 Subject: [PATCH 094/224] Issue 3138 - Conformance Tests for BackendTLSPolicy - normative (#3212) * Issue 3138 - add normative conformance test for BackendTLSPolicy. * Fix where the new go module needed by echo-basic resides, but keep the original as well. See https://github.com/kubernetes-sigs/gateway-api/pull/2745/files#diff-cf5b4a9b433acc91f8c7cc2dc802e29aa712c8d820887742f3bc5ae45b7a9d0fR24-R28 * Rebase and make requested updates. * Update tests after implementation testing conformance/base/manifests.yaml - fix yaml conformance/tests/backendtlspolicy.yaml - fix yaml conformance/tests/tlsroute-simple-same-namespace.go - rename cert for sharing conformance/utils/suite/conformance.go - fix a bug in cleanup-base-resources flag application conformance/utils/suite/suite.go - rename cert for sharing * Incorporate Shane and Flynn's feedback * Add unit testing for generateCACert, new HTTPS call, some debugging, and fix yaml * Update echo-basic images * Fix lint errors and condition evaluation in tests * Fix yaml for httpRoute and backendTLSPolicy. Fix CA generation. Fix certificate unit test. * Refactor test, fix yaml * Fix the tests for normative BackendTLSPolicy # Conflicts: # conformance/utils/http/http.go * Make changes from review comments. Add conformance profiles to logged information. * Address further review comments * Address review comments: Remove echo-basic changes, fix cert building, and adjust the port used for gateways with multiple listeners Co-authored-by: Norwin Schnyder * Address the last of the review comments --------- Co-authored-by: Norwin Schnyder --- conformance/base/manifests.yaml | 4 +- conformance/conformance.go | 4 - conformance/tests/backendtlspolicy.go | 90 +++++++++++ conformance/tests/backendtlspolicy.yaml | 153 ++++++++++++++++++ .../tests/grpcroute-exact-method-matching.go | 2 +- .../tests/grpcroute-header-matching.go | 2 +- .../grpcroute-listener-hostname-matching.go | 6 +- conformance/tests/grpcroute-named-rule.go | 2 +- conformance/tests/httproute-weight.go | 2 +- .../tests/tlsroute-simple-same-namespace.go | 2 +- conformance/utils/http/http.go | 22 ++- conformance/utils/kubernetes/certificate.go | 152 ++++++++++++++++- .../utils/kubernetes/certificate_test.go | 101 ++++++++++++ conformance/utils/kubernetes/helpers.go | 48 ++++-- .../utils/roundtripper/roundtripper.go | 20 +++ conformance/utils/suite/conformance.go | 2 +- conformance/utils/suite/suite.go | 4 + conformance/utils/tls/tls.go | 3 +- docker/Dockerfile.echo-basic | 9 +- pkg/features/backendtlspolicy.go | 40 +++++ pkg/features/features.go | 3 +- 21 files changed, 624 insertions(+), 47 deletions(-) create mode 100644 conformance/tests/backendtlspolicy.go create mode 100644 conformance/tests/backendtlspolicy.yaml create mode 100644 conformance/utils/kubernetes/certificate_test.go create mode 100644 pkg/features/backendtlspolicy.go diff --git a/conformance/base/manifests.yaml b/conformance/base/manifests.yaml index a3163bf837..9380223ea0 100644 --- a/conformance/base/manifests.yaml +++ b/conformance/base/manifests.yaml @@ -138,7 +138,7 @@ spec: spec: containers: - name: infra-backend-v1 - # From https://github.com/kubernetes-sigs/ingress-controller-conformance/tree/master/images/echoserver + # Originally from https://github.com/kubernetes-sigs/ingress-controller-conformance/tree/master/images/echoserver image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd env: - name: POD_NAME @@ -300,7 +300,7 @@ spec: volumes: - name: secret-volume secret: - secretName: tls-passthrough-checks-certificate + secretName: tls-checks-certificate items: - key: tls.crt path: crt diff --git a/conformance/conformance.go b/conformance/conformance.go index 12e5884968..ce7a465c60 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -29,14 +29,11 @@ import ( "sigs.k8s.io/gateway-api/conformance/tests" conformanceconfig "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/flags" - "sigs.k8s.io/gateway-api/conformance/utils/suite" "github.com/stretchr/testify/require" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - clientset "k8s.io/client-go/kubernetes" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/yaml" @@ -66,7 +63,6 @@ func DefaultOptions(t *testing.T) suite.ConformanceOptions { supportedFeatures := suite.ParseSupportedFeatures(*flags.SupportedFeatures) exemptFeatures := suite.ParseSupportedFeatures(*flags.ExemptFeatures) - skipTests := suite.ParseSkipTests(*flags.SkipTests) namespaceLabels := suite.ParseKeyValuePairs(*flags.NamespaceLabels) namespaceAnnotations := suite.ParseKeyValuePairs(*flags.NamespaceAnnotations) diff --git a/conformance/tests/backendtlspolicy.go b/conformance/tests/backendtlspolicy.go new file mode 100644 index 0000000000..1d55627816 --- /dev/null +++ b/conformance/tests/backendtlspolicy.go @@ -0,0 +1,90 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + h "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/tls" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicy) +} + +var BackendTLSPolicy = suite.ConformanceTest{ + ShortName: "BackendTLSPolicy", + Description: "A single service that is targeted by a BackendTLSPolicy must successfully complete TLS termination", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + }, + Manifests: []string{"tests/backendtlspolicy.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: ns} + gwNN := types.NamespacedName{Name: "gateway-backendtlspolicy", Namespace: ns} + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + serverStr := "abc.example.com" + + // Verify that the response to a backend-tls-only call to /backendTLS will return the matching SNI. + t.Run("Simple HTTP request targeting BackendTLSPolicy should reach infra-backend", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLS", + SNI: serverStr, + }, + Response: h.Response{StatusCode: 200}, + }) + }) + + // For the re-encrypt case, we need to use the cert for the frontend tls listener. + certNN := types.NamespacedName{Name: "tls-checks-certificate", Namespace: ns} + cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) + if err != nil { + t.Fatalf("unexpected error finding TLS secret: %v", err) + } + // Verify that the response to a re-encrypted call to /backendTLS will return the matching SNI. + t.Run("Re-encrypt HTTPS request targeting BackendTLSPolicy should reach infra-backend", func(t *testing.T) { + tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, keyPem, serverStr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLS", + SNI: serverStr, + }, + Response: h.Response{StatusCode: 200}, + }) + }) + }, +} diff --git a/conformance/tests/backendtlspolicy.yaml b/conformance/tests/backendtlspolicy.yaml new file mode 100644 index 0000000000..91f6a590f9 --- /dev/null +++ b/conformance/tests/backendtlspolicy.yaml @@ -0,0 +1,153 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: gateway-backendtlspolicy + namespace: gateway-conformance-infra +spec: + gatewayClassName: "{GATEWAY_CLASS_NAME}" + listeners: + - name: http + port: 80 + protocol: HTTP + hostname: "abc.example.com" + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: HTTPRoute + - name: https + port: 443 + protocol: HTTPS + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-checks-certificate + hostname: "abc.example.com" + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: HTTPRoute +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: normative-test-backendtlspolicy + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-test" + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-checks-certificate" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: gateway-conformance-infra-test + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: gateway-backendtlspolicy + namespace: gateway-conformance-infra + hostnames: + - abc.example.com + rules: + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLS +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-test + ports: + - name: "btls" + protocol: TCP + port: 443 + targetPort: 8443 +--- +# Deployment must not be applied until after the secret is generated. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backendtlspolicy-test + namespace: gateway-conformance-infra + labels: + app: backendtlspolicy-test +spec: + replicas: 1 + selector: + matchLabels: + app: backendtlspolicy-test + template: + metadata: + labels: + app: backendtlspolicy-test + spec: + containers: + - name: backendtlspolicy-test + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd + volumeMounts: + - name: ca-volume + mountPath: /etc/ca-volume + - name: secret-volume + mountPath: /etc/secret-volume + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CA_CERT + value: /etc/ca-volume/crt + - name: CA_CERT_KEY + value: /etc/ca-volume/key + - name: TLS_SERVER_CERT + value: /etc/secret-volume/crt + - name: TLS_SERVER_PRIVKEY + value: /etc/secret-volume/key + resources: + requests: + cpu: 10m + volumes: + - name: ca-volume + configMap: + # This configMap is generated dynamically by the test suite. + name: backend-tls-checks-certificate + items: + - key: ca.crt + path: crt + - key: key.crt + path: key + - name: secret-volume + secret: + # This secret is generated dynamically by the test suite. + secretName: tls-checks-certificate + items: + - key: tls.crt + path: crt + - key: tls.key + path: key diff --git a/conformance/tests/grpcroute-exact-method-matching.go b/conformance/tests/grpcroute-exact-method-matching.go index 384cf3ae02..c70c034b6c 100644 --- a/conformance/tests/grpcroute-exact-method-matching.go +++ b/conformance/tests/grpcroute-exact-method-matching.go @@ -46,7 +46,7 @@ var GRPCExactMethodMatching = suite.ConformanceTest{ ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "exact-matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} - gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, routeNN) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, true, routeNN) testCases := []grpc.ExpectedResponse{ { diff --git a/conformance/tests/grpcroute-header-matching.go b/conformance/tests/grpcroute-header-matching.go index 48b6e0da66..2db1819d3e 100644 --- a/conformance/tests/grpcroute-header-matching.go +++ b/conformance/tests/grpcroute-header-matching.go @@ -46,7 +46,7 @@ var GRPCRouteHeaderMatching = suite.ConformanceTest{ ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "grpc-header-matching", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} - gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, routeNN) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, true, routeNN) testCases := []grpc.ExpectedResponse{{ EchoRequest: &pb.EchoRequest{}, diff --git a/conformance/tests/grpcroute-listener-hostname-matching.go b/conformance/tests/grpcroute-listener-hostname-matching.go index 0e0492e764..ba8ee64226 100644 --- a/conformance/tests/grpcroute-listener-hostname-matching.go +++ b/conformance/tests/grpcroute-listener-hostname-matching.go @@ -52,15 +52,15 @@ var GRPCRouteListenerHostnameMatching = suite.ConformanceTest{ gwNN := types.NamespacedName{Name: "grpcroute-listener-hostname-matching", Namespace: ns} _ = kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, - kubernetes.NewGatewayRef(gwNN, "listener-1"), &v1.GRPCRoute{}, + kubernetes.NewGatewayRef(gwNN, "listener-1"), &v1.GRPCRoute{}, true, types.NamespacedName{Namespace: ns, Name: "backend-v1"}, ) _ = kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, - kubernetes.NewGatewayRef(gwNN, "listener-2"), &v1.GRPCRoute{}, + kubernetes.NewGatewayRef(gwNN, "listener-2"), &v1.GRPCRoute{}, true, types.NamespacedName{Namespace: ns, Name: "backend-v2"}, ) gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, - kubernetes.NewGatewayRef(gwNN, "listener-3", "listener-4"), &v1.GRPCRoute{}, + kubernetes.NewGatewayRef(gwNN, "listener-3", "listener-4"), &v1.GRPCRoute{}, true, types.NamespacedName{Namespace: ns, Name: "backend-v3"}, ) diff --git a/conformance/tests/grpcroute-named-rule.go b/conformance/tests/grpcroute-named-rule.go index 223e22b595..2c738a5660 100644 --- a/conformance/tests/grpcroute-named-rule.go +++ b/conformance/tests/grpcroute-named-rule.go @@ -47,7 +47,7 @@ var GRPCRouteNamedRule = suite.ConformanceTest{ ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "grpc-named-rules", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} - gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, routeNN) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, true, routeNN) testCases := []grpc.ExpectedResponse{ { diff --git a/conformance/tests/httproute-weight.go b/conformance/tests/httproute-weight.go index 2a3e21afee..2c1a520dc0 100644 --- a/conformance/tests/httproute-weight.go +++ b/conformance/tests/httproute-weight.go @@ -105,7 +105,7 @@ func testDistribution(t *testing.T, suite *suite.ConformanceTestSuite, gwAddr st if err != nil { return fmt.Errorf("failed to roundtrip request: %w", err) } - if err := http.CompareRequest(t, &req, cReq, cRes, expected); err != nil { + if err := http.CompareRoundTrip(t, &req, cReq, cRes, expected); err != nil { return fmt.Errorf("response expectation failed for request: %w", err) } diff --git a/conformance/tests/tlsroute-simple-same-namespace.go b/conformance/tests/tlsroute-simple-same-namespace.go index 51db62aeff..b8704c4b8b 100644 --- a/conformance/tests/tlsroute-simple-same-namespace.go +++ b/conformance/tests/tlsroute-simple-same-namespace.go @@ -49,7 +49,7 @@ var TLSRouteSimpleSameNamespace = suite.ConformanceTest{ ns := "gateway-conformance-infra" routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: ns} gwNN := types.NamespacedName{Name: "gateway-tlsroute", Namespace: ns} - certNN := types.NamespacedName{Name: "tls-passthrough-checks-certificate", Namespace: ns} + certNN := types.NamespacedName{Name: "tls-checks-certificate", Namespace: ns} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index 18b5e1feb0..e1aca27d54 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -58,6 +58,10 @@ type ExpectedResponse struct { // User Given TestCase name TestCaseName string + + // ServerName indicates the hostname to which the client attempts to connect, + // and which is seen by the backend. + ServerName string } // Request can be used as both the request to make and a means to verify @@ -71,6 +75,7 @@ type Request struct { UnfollowRedirect bool Protocol string Body string + SNI string } // ExpectedRequest defines expected properties of a request that reaches a backend. @@ -130,7 +135,7 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch path, query, _ := strings.Cut(expected.Request.Path, "?") reqURL := url.URL{Scheme: scheme, Host: CalculateHost(t, gwAddr, scheme), Path: path, RawQuery: query} - tlog.Logf(t, "Making %s request to %s", expected.Request.Method, reqURL.String()) + tlog.Logf(t, "Making %s request to host %s via %s", expected.Request.Method, expected.Request.Host, reqURL.String()) req := roundtripper.Request{ T: t, @@ -172,7 +177,10 @@ func CalculateHost(t *testing.T, gwAddr, scheme string) string { host, port, err = net.SplitHostPort(gwAddr) } if err != nil { - tlog.Logf(t, "Failed to parse host %q: %v", gwAddr, err) + // An address without a port causes an error, but it's fine for some cases. + if !strings.Contains(err.Error(), "missing port in address") { + tlog.Logf(t, "Failed to parse host %q: %v", gwAddr, err) + } return gwAddr } if strings.ToLower(scheme) == "http" && port == "80" { @@ -243,7 +251,7 @@ func WaitForConsistentResponse(t *testing.T, r roundtripper.RoundTripper, req ro return false } - if err := CompareRequest(t, &req, cReq, cRes, expected); err != nil { + if err := CompareRoundTrip(t, &req, cReq, cRes, expected); err != nil { tlog.Logf(t, "Response expectation failed for request: %+v not ready yet: %v (after %v)", req, err, elapsed) return false } @@ -253,14 +261,14 @@ func WaitForConsistentResponse(t *testing.T, r roundtripper.RoundTripper, req ro tlog.Logf(t, "Request passed") } -func CompareRequest(t *testing.T, req *roundtripper.Request, cReq *roundtripper.CapturedRequest, cRes *roundtripper.CapturedResponse, expected ExpectedResponse) error { +func CompareRoundTrip(t *testing.T, req *roundtripper.Request, cReq *roundtripper.CapturedRequest, cRes *roundtripper.CapturedResponse, expected ExpectedResponse) error { if roundtripper.IsTimeoutError(cRes.StatusCode) { if roundtripper.IsTimeoutError(expected.Response.StatusCode) { return nil } } if expected.Response.StatusCode != cRes.StatusCode { - return fmt.Errorf("expected status code to be %d, got %d", expected.Response.StatusCode, cRes.StatusCode) + return fmt.Errorf("expected status code to be %d, got %d. CRes: %v", expected.Response.StatusCode, cRes.StatusCode, cRes) } if cRes.StatusCode == 200 { // The request expected to arrive at the backend is @@ -353,6 +361,10 @@ func CompareRequest(t *testing.T, req *roundtripper.Request, cReq *roundtripper. if !strings.HasPrefix(cReq.Pod, expected.Backend) { return fmt.Errorf("expected pod name to start with %s, got %s", expected.Backend, cReq.Pod) } + + if expected.ExpectedRequest.SNI != "" && expected.ExpectedRequest.SNI != cReq.TLS.ServerName { + return fmt.Errorf("expected SNI %q to be equal to %q", cReq.TLS.ServerName, expected.ExpectedRequest.SNI) + } } else if roundtripper.IsRedirect(cRes.StatusCode) { if expected.RedirectRequest == nil { return nil diff --git a/conformance/utils/kubernetes/certificate.go b/conformance/utils/kubernetes/certificate.go index a0f70ddd14..07c3c80787 100644 --- a/conformance/utils/kubernetes/certificate.go +++ b/conformance/utils/kubernetes/certificate.go @@ -27,12 +27,14 @@ import ( "io" "math/big" "net" + "strings" "testing" "time" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kvalidation "k8s.io/apimachinery/pkg/util/validation" ) const ( @@ -46,8 +48,25 @@ func MustCreateSelfSignedCertSecret(t *testing.T, namespace, secretName string, var serverKey, serverCert bytes.Buffer - require.NoError(t, generateRSACert(hosts, &serverKey, &serverCert), "failed to generate RSA certificate") + require.NoError(t, generateRSACert(hosts, &serverKey, &serverCert, nil, nil), "failed to generate RSA certificate") + return formatSecret(serverCert, serverKey, namespace, secretName) +} + +// MustCreateCASignedCertSecret creates a CA-signed SSL certificate and stores it in a secret +func MustCreateCASignedCertSecret(t *testing.T, namespace, secretName string, hosts []string, ca *x509.Certificate, caPrivKey *rsa.PrivateKey) *corev1.Secret { + require.NotEmpty(t, hosts, "require a non-empty hosts for Subject Alternate Name values") + + var serverCert, serverKey bytes.Buffer + + require.NoError(t, generateRSACert(hosts, &serverKey, &serverCert, ca, caPrivKey), "failed to generate CA signed RSA certificate") + + return formatSecret(serverCert, serverKey, namespace, secretName) +} + +// formatSecret formats the server certificate, key, namespace, and secretName +// and converts it to a Kubernetes Secret object. +func formatSecret(serverCert bytes.Buffer, serverKey bytes.Buffer, namespace string, secretName string) *corev1.Secret { data := map[string][]byte{ corev1.TLSCertKey: serverCert.Bytes(), corev1.TLSPrivateKeyKey: serverKey.Bytes(), @@ -65,8 +84,9 @@ func MustCreateSelfSignedCertSecret(t *testing.T, namespace, secretName string, return newSecret } -// generateRSACert generates a basic self-signed certificate valid for a year -func generateRSACert(hosts []string, keyOut, certOut io.Writer) error { +// generateRSACert generates a basic self-signed certificate if ca and caPrivKey are nil, +// otherwise it creates CA-signed cert with ca and caPrivkey input. Certs are valid for a year. +func generateRSACert(hosts []string, keyOut, certOut io.Writer, ca *x509.Certificate, caPrivKey *rsa.PrivateKey) error { priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return fmt.Errorf("failed to generate key: %w", err) @@ -97,12 +117,20 @@ func generateRSACert(hosts []string, keyOut, certOut io.Writer) error { for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) - } else { + } else if err = validateHost(h); err == nil { template.DNSNames = append(template.DNSNames, h) } } - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + if caPrivKey == nil { + caPrivKey = priv + } + // If ca is nil, we create a self-signed certificate, e.g. template is the parent. + if ca == nil { + ca = &template + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, ca, &priv.PublicKey, caPrivKey) if err != nil { return fmt.Errorf("failed to create certificate: %w", err) } @@ -117,3 +145,117 @@ func generateRSACert(hosts []string, keyOut, certOut io.Writer) error { return nil } + +// MustCreateCACertConfigMap will create a ConfigMap containing a CA Certificate, given a TLS Secret +// for that CA certificate. Also returns the CA certificate. +func MustCreateCACertConfigMap(t *testing.T, namespace, configMapName string, hosts []string) (*corev1.ConfigMap, *x509.Certificate, *rsa.PrivateKey) { + require.NotEmpty(t, hosts, "require a non-empty hosts for Subject Alternate Name values") + + var certData, keyData bytes.Buffer + + ca, caBytes, caPrivKey, err := generateCACert(hosts) + if err != nil { + t.Errorf("failed to generate CA certificate and key: %v", err) + return nil, nil, nil + } + + if err := pem.Encode(&certData, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil { + t.Errorf("failed creating cert: %v", err) + return nil, nil, nil + } + + if err := pem.Encode(&keyData, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey)}); err != nil { + t.Errorf("failed creating key: %v", err) + return nil, nil, nil + } + + // Store the certificate in a ConfigMap. + caConfigMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: configMapName, + }, + Data: map[string]string{ + "ca.crt": certData.String(), + // Don't do this in production, this is just for conformance testing. + "key.crt": keyData.String(), + }, + } + return caConfigMap, ca, caPrivKey +} + +// generateCACert generates a CA and a CA-signed certificate valid for a year. +func generateCACert(hosts []string) (*x509.Certificate, []byte, *rsa.PrivateKey, error) { + var caBytes []byte + + // Create the CA certificate template. + ca := &x509.Certificate{ + SerialNumber: big.NewInt(2024), + Subject: pkix.Name{ + Organization: []string{"Kubernetes Gateway API"}, + Country: []string{"US"}, + CommonName: "gatewayapi", + }, + Issuer: pkix.Name{ + Organization: []string{"Kubernetes Gateway API"}, + Country: []string{"US"}, + CommonName: "kubernetes", + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(1, 0, 0), + IsCA: true, // Indicates this is a CA Certificate. + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + BasicConstraintsValid: true, + } + + // Ensure only valid hosts make it into the CA cert. + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + ca.IPAddresses = append(ca.IPAddresses, ip) + } else if err := validateHost(h); err == nil { + ca.DNSNames = append(ca.DNSNames, h) + } + } + + // Generate the private key to sign certificates. + caPrivKey, err := rsa.GenerateKey(rand.Reader, rsaBits) + if err != nil { + return nil, caBytes, caPrivKey, fmt.Errorf("error generating key for CA: %v", err) + } + + // Create the self-signed certificate using the CA certificate. + caBytes, err = x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey) + if err != nil { + return nil, caBytes, caPrivKey, fmt.Errorf("error creating CA: %v", err) + } + + return ca, caBytes, caPrivKey, nil +} + +// validateHost ensures that the host name length is no more than 253 characters. +// The only characters allowed in host name are alphanumeric characters, '-' or '.', +// and it must start and end with an alphanumeric character. A trailing dot is NOT allowed. +// The host name must in addition consist of one or more labels, with each label no more +// than 63 characters from the character set described above, and each label must start and +// end with an alphanumeric character. Wildcards are handled specially. +// DO NOT USE for general validation purposes, this is just for the hostnames set up for +// conformance testing. +func validateHost(host string) error { + // Remove wildcard if present. + host, _ = strings.CutPrefix(host, "*.") + + errs := kvalidation.IsDNS1123Subdomain(host) + if len(errs) != 0 { + return fmt.Errorf("host %s must conform to DNS naming conventions: %v", host, errs) + } + + labels := strings.Split(host, ".") + for _, l := range labels { + errs := kvalidation.IsDNS1123Label(l) + if len(errs) != 0 { + return fmt.Errorf("label %s in host %s must conform to DNS naming conventions: %v", l, host, errs) + } + } + return nil +} diff --git a/conformance/utils/kubernetes/certificate_test.go b/conformance/utils/kubernetes/certificate_test.go new file mode 100644 index 0000000000..f6c78048a9 --- /dev/null +++ b/conformance/utils/kubernetes/certificate_test.go @@ -0,0 +1,101 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubernetes + +import ( + "bytes" + "crypto/x509" + "encoding/pem" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_generateCACert(t *testing.T) { + tests := []struct { + name string + hosts []string + expectedErr []string + }{ + { + name: "one host generates cert with no host", + hosts: []string{}, + }, + { + name: "one host generates cert for same host", + hosts: []string{"abc.example.com"}, + }, + { + name: "wildcard generates cert for same host", + hosts: []string{"*.example.com"}, + }, + { + name: "two hosts generates cert for both hosts", + hosts: []string{"abc.example.com", "def.example.com"}, + }, + { + name: "bad host generates cert for no host", + hosts: []string{"--abc.example.com"}, + expectedErr: []string{"x509: certificate is not valid for any names, but wanted to match --abc.example.com"}, + }, + { + name: "one good host and one bad host generates cert for only good host", + hosts: []string{"---.example.com", "def.example.com"}, + expectedErr: []string{"x509: certificate is valid xxx for def.example.com, not ---.example.com", ""}, + }, + } + + var serverKey, serverCert bytes.Buffer + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + serverCert.Reset() + serverKey.Reset() + // Test the function generateCACert. We can only test normative function + // and hostnames, everything else is hardcoded. + _, caBytes, caPrivKey, err := generateCACert(tc.hosts) + require.NoError(t, err, "unexpected error generating RSA certificate") + + var certData bytes.Buffer + if err := pem.Encode(&certData, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil { + require.NoError(t, err, "failed to create certificater") + } + + var keyData bytes.Buffer + if err := pem.Encode(&keyData, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey)}); err != nil { + require.NoError(t, err, "failed to create key") + } + + // Test that the CA certificate is decodable, parseable, and has the configured hostname/s. + block, _ := pem.Decode(certData.Bytes()) + if block == nil { + require.FailNow(t, "failed to decode PEM block containing cert") + } else if block.Type == "CERTIFICATE" { + cert, err := x509.ParseCertificate(block.Bytes) + require.NoError(t, err, "failed to parse certificate") + for idx, h := range tc.hosts { + err = cert.VerifyHostname(h) + if err != nil && len(tc.expectedErr) > 0 && tc.expectedErr[idx] == "" { + require.EqualValues(t, tc.expectedErr[idx], err.Error(), "certificate verification failed") + } else if err == nil && len(tc.expectedErr) > 0 && tc.expectedErr[idx] != "" { + require.EqualValues(t, tc.expectedErr[idx], err, "expected an error but certification verification succeeded") + } + } + } + }) + } +} diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 2b43828c09..9e385b4caa 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -331,14 +331,22 @@ func MeshNamespacesMustBeReady(t *testing.T, c client.Client, timeoutConfig conf // - ListenerConditionProgrammed // // The test will fail if these conditions are not met before the timeouts. -func GatewayAndRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeType any, routeNNs ...types.NamespacedName) string { +// Note that this also returns a Gateway address to use, but it takes the port +// from the first listener it finds. Set parameter `usePort` to false if there +// are multiple listeners, and true if there is only one listener. +func GatewayAndRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeType any, usePort bool, routeNNs ...types.NamespacedName) string { t.Helper() RouteTypeMustHaveParentsField(t, routeType) gwAddr, err := WaitForGatewayAddress(t, c, timeoutConfig, gw) - require.NoErrorf(t, err, "timed out waiting for Gateway address to be assigned") + // If the Gateway has multiple listeners, get a portless gwAddr. + // Otherwise, you get the first listener's port, which might not be the one you want. + if !usePort { + gwAddr, _, _ = strings.Cut(gwAddr, ":") + } + ns := gatewayv1.Namespace(gw.Namespace) kind := gatewayv1.Kind("Gateway") @@ -401,7 +409,7 @@ func GatewayAndRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig // // The test will fail if these conditions are not met before the timeouts. func GatewayAndHTTPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeNNs ...types.NamespacedName) string { - return GatewayAndRoutesMustBeAccepted(t, c, timeoutConfig, controllerName, gw, &gatewayv1.HTTPRoute{}, routeNNs...) + return GatewayAndRoutesMustBeAccepted(t, c, timeoutConfig, controllerName, gw, &gatewayv1.HTTPRoute{}, true, routeNNs...) } // GatewayAndUDPRoutesMustBeAccepted waits until the specified Gateway has an IP @@ -409,7 +417,7 @@ func GatewayAndHTTPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCo // Gateway. The test will fail if these conditions are not met before the // timeouts. func GatewayAndUDPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutConfig config.TimeoutConfig, controllerName string, gw GatewayRef, routeNNs ...types.NamespacedName) string { - return GatewayAndRoutesMustBeAccepted(t, c, timeoutConfig, controllerName, gw, &v1alpha2.UDPRoute{}, routeNNs...) + return GatewayAndRoutesMustBeAccepted(t, c, timeoutConfig, controllerName, gw, &v1alpha2.UDPRoute{}, true, routeNNs...) } // WaitForGatewayAddress waits until at least one IP Address has been set in the @@ -419,16 +427,10 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, timeoutConfig con var ipAddr, port string waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.GatewayMustHaveAddress, true, func(ctx context.Context) (bool, error) { - gw := &gatewayv1.Gateway{} - err := client.Get(ctx, gwRef.NamespacedName, gw) - if err != nil { - tlog.Logf(t, "error fetching Gateway: %v", err) - return false, fmt.Errorf("error fetching Gateway: %w", err) - } - - if err := ConditionsHaveLatestObservedGeneration(gw, gw.Status.Conditions); err != nil { - tlog.Log(t, "Gateway", err) - return false, nil + gw, err := getGatewayStatus(ctx, t, client, gwRef) + if gw == nil { + // The returned error is nil if the Gateway conditions don't have the latest observed generation. + return false, err } listener := gw.Spec.Listeners[0] @@ -442,20 +444,34 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, timeoutConfig con } } port = strconv.FormatInt(int64(listener.Port), 10) - for _, address := range gw.Status.Addresses { if address.Type != nil && (*address.Type == gatewayv1.IPAddressType || *address.Type == v1alpha2.HostnameAddressType) { ipAddr = address.Value return true, nil } } - return false, nil }) require.NoErrorf(t, waitErr, "error waiting for Gateway to have at least one IP address in status") return net.JoinHostPort(ipAddr, port), waitErr } +func getGatewayStatus(ctx context.Context, t *testing.T, client client.Client, gwRef GatewayRef) (*gatewayv1.Gateway, error) { + gw := &gatewayv1.Gateway{} + err := client.Get(ctx, gwRef.NamespacedName, gw) + if err != nil { + tlog.Logf(t, "error fetching Gateway: %v", err) + return nil, fmt.Errorf("error fetching Gateway: %w", err) + } + + if err := ConditionsHaveLatestObservedGeneration(gw, gw.Status.Conditions); err != nil { + tlog.Log(t, "Gateway", err) + return nil, nil + } + + return gw, nil +} + // GatewayListenersMustHaveConditions checks if every listener of the specified gateway has all // the specified conditions. func GatewayListenersMustHaveConditions(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, gwName types.NamespacedName, conditions []metav1.Condition) { diff --git a/conformance/utils/roundtripper/roundtripper.go b/conformance/utils/roundtripper/roundtripper.go index f79508784f..9490b648e2 100644 --- a/conformance/utils/roundtripper/roundtripper.go +++ b/conformance/utils/roundtripper/roundtripper.go @@ -88,6 +88,14 @@ type CapturedRequest struct { Namespace string `json:"namespace"` Pod string `json:"pod"` + TLS TLS `json:"tls"` +} + +type TLS struct { + Version string `json:"version"` + ServerName string `json:"serverName"` + NegotiatedProtocol string `json:"negotiatedProtocol"` + CipherSuite string `json:"cipherSuite"` } // RedirectRequest contains a follow up request metadata captured from a redirect @@ -228,6 +236,18 @@ func (d *DefaultRoundTripper) defaultRoundTrip(request Request, transport http.R resp, err := client.Do(req) if err != nil { + if d.Debug { + var dump []byte + if resp != nil { + dump, err = httputil.DumpResponse(resp, true) + if err != nil { + return nil, nil, err + } + tlog.Logf(request.T, "Error sending request:\n%s\n\n", formatDump(dump, "< ")) + } else { + tlog.Logf(request.T, "Error sending request: %v (no response)\n", err) + } + } return nil, nil, err } defer resp.Body.Close() diff --git a/conformance/utils/suite/conformance.go b/conformance/utils/suite/conformance.go index 12db14d6df..436b3ed2ce 100644 --- a/conformance/utils/suite/conformance.go +++ b/conformance/utils/suite/conformance.go @@ -68,7 +68,7 @@ func (test *ConformanceTest) Run(t *testing.T, suite *ConformanceTestSuite) { for _, manifestLocation := range test.Manifests { tlog.Logf(t, "Applying %s", manifestLocation) - suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, manifestLocation, true) + suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, manifestLocation, suite.Cleanup) } if featuresInfo != "" { diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 5b30598886..63a6b93a16 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -383,6 +383,10 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) secret = kubernetes.MustCreateSelfSignedCertSecret(t, "gateway-conformance-app-backend", "tls-passthrough-checks-certificate", []string{"abc.example.com"}) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) + caConfigMap, ca, caPrivKey := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-checks-certificate", []string{"abc.example.com"}) + suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) + secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey) + suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) tlog.Logf(t, "Test Setup: Ensuring Gateways and Pods from base manifests are ready") namespaces := []string{ diff --git a/conformance/utils/tls/tls.go b/conformance/utils/tls/tls.go index e27fab839b..809a4938a8 100644 --- a/conformance/utils/tls/tls.go +++ b/conformance/utils/tls/tls.go @@ -54,8 +54,9 @@ func WaitForConsistentTLSResponse(t *testing.T, r roundtripper.RoundTripper, req return false } - if err := http.CompareRequest(t, &req, cReq, cRes, expected); err != nil { + if err := http.CompareRoundTrip(t, &req, cReq, cRes, expected); err != nil { tlog.Logf(t, "Response expectation failed for request: %+v not ready yet: %v (after %v)", req, err, elapsed) + tlog.Logf(t, "Full response: %+v", cReq) return false } diff --git a/docker/Dockerfile.echo-basic b/docker/Dockerfile.echo-basic index ed6081fb33..55d9b47055 100644 --- a/docker/Dockerfile.echo-basic +++ b/docker/Dockerfile.echo-basic @@ -13,7 +13,7 @@ # limitations under the License. # Build -FROM golang:1.22.2 as builder +FROM golang:1.22.2 AS builder ENV CGO_ENABLED=0 @@ -23,9 +23,10 @@ COPY ./conformance/echo-basic ./ # If left as go.mod and go.sum in the external repo, these files would # interfere with the ability to use reuse the protobuf/gRPC generated code -# for the test client in the conformance tests. -RUN mv .go.mod go.mod -RUN mv .go.sum go.sum +# for the test client in the conformance tests. Add -f in case previous run +# is aborted and not cleaned up. +RUN mv -f .go.mod go.mod +RUN mv -f .go.sum go.sum RUN go build -trimpath -ldflags="-buildid= -s -w" -o echo-basic . diff --git a/pkg/features/backendtlspolicy.go b/pkg/features/backendtlspolicy.go new file mode 100644 index 0000000000..8763b32dd1 --- /dev/null +++ b/pkg/features/backendtlspolicy.go @@ -0,0 +1,40 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package features + +import "k8s.io/apimachinery/pkg/util/sets" + +// ----------------------------------------------------------------------------- +// Features - BackendTLSPolicy Conformance (Core) +// ----------------------------------------------------------------------------- + +const ( + // This option indicates support for BackendTLSPolicy. + SupportBackendTLSPolicy FeatureName = "BackendTLSPolicy" +) + +// TLSRouteFeature contains metadata for the TLSRoute feature. +var BackendTLSPolicyFeature = Feature{ + Name: SupportBackendTLSPolicy, + Channel: FeatureChannelExperimental, +} + +// BackendTLSPolicyCoreFeatures includes all the supported features for the +// BackendTLSPolicy API at a Core level of support. +var BackendTLSPolicyCoreFeatures = sets.New( + BackendTLSPolicyFeature, +) diff --git a/pkg/features/features.go b/pkg/features/features.go index 8406c4b891..2a67d0065f 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -60,7 +60,8 @@ var ( Insert(TLSRouteCoreFeatures.UnsortedList()...). Insert(MeshCoreFeatures.UnsortedList()...). Insert(MeshExtendedFeatures.UnsortedList()...). - Insert(GRPCRouteCoreFeatures.UnsortedList()...) + Insert(GRPCRouteCoreFeatures.UnsortedList()...). + Insert(BackendTLSPolicyCoreFeatures.UnsortedList()...) featureMap = map[FeatureName]Feature{} ) From f0ae2ccbd1605d095398d0f18c0cfb487a5e18b6 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Wed, 23 Jul 2025 11:44:27 +1000 Subject: [PATCH 095/224] Update Auth GEP with Implementable details (#3884) This commit adds the design rationale and API design for phase 1 of the Auth GEP, adding a Filter to HTTPRoute. Signed-off-by: Nick Young --- geps/gep-1494/index.md | 382 +++++++++++++++++++++++++++++++++++- geps/gep-1494/metadata.yaml | 12 +- 2 files changed, 383 insertions(+), 11 deletions(-) diff --git a/geps/gep-1494/index.md b/geps/gep-1494/index.md index 5d5991052f..0fc115292f 100644 --- a/geps/gep-1494/index.md +++ b/geps/gep-1494/index.md @@ -1,7 +1,7 @@ # GEP-1494: HTTP Auth in Gateway API * Issue: [#1494](https://github.com/kubernetes-sigs/gateway-api/issues/1494) -* Status: Provisional +* Status: Implementable (See [status definitions](../overview.md#gep-states).) @@ -115,7 +115,7 @@ This section lays out some examples (updates with extra examples we've missed ar |[traefik](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)|[Custom(ForwardAuth middleware)](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)|[Basic](https://doc.traefik.io/traefik/middlewares/http/basicauth/), [Digest Auth](https://doc.traefik.io/traefik/middlewares/http/digestauth/)| |[Ambassador](https://www.getambassador.io/docs/edge-stack/latest/howtos/ext-filters)|[Envoy](https://github.com/emissary-ingress/emissary) ([Basic](https://www.getambassador.io/docs/edge-stack/latest/howtos/ext-filters#2-configure-aesambassador-edge-stack-authentication))|[SSO(OAuth, OIDC)](https://www.getambassador.io/docs/edge-stack/latest/howtos/oauth-oidc-auth) | |[ingress-nginx](https://kubernetes.github.io/ingress-nginx/examples/customization/external-auth-headers/)|[httpbin](https://httpbin.org) ([Basic](https://kubernetes.github.io/ingress-nginx/examples/auth/external-auth/), [OAuth](https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/))|[Basic](https://kubernetes.github.io/ingress-nginx/examples/auth/basic/), [Client Certificate](https://kubernetes.github.io/ingress-nginx/examples/auth/client-certs/)| -|[Envoy](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto)|[External Authorization server (ext_authz filter)](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto) |[JWT](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto)| +|[Envoy](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authzz/v3/ext_authzz.proto)|[External Authorization server (ext_authzz filter)](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authzz/v3/ext_authzz.proto) |[JWT](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto)| |[Contour](https://projectcontour.io/docs/1.24/config/client-authorization/)|[Envoy](https://projectcontour.io/docs/1.24/config/client-authorization/)|[Envoy(JWT)](https://projectcontour.io/docs/1.24/config/jwt-verification/)| |[Istio](https://istio.io/latest/docs/tasks/security/authorization/)|[mutual TLS ingress gateway](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway), [External Authorization](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/)|[JWT (RequestAuthentication)](https://istio.io/latest/docs/reference/config/security/request_authentication/)| |[Envoy Gateway](https://gateway.envoyproxy.io/docs/tasks/security/ext-auth/)| [Envoy](https://gateway.envoyproxy.io/docs/tasks/security/ext-auth/#http-external-authorization-service) | [Envoy(JWT)](https://gateway.envoyproxy.io/docs/tasks/security/jwt-authentication/), [Basic](https://gateway.envoyproxy.io/docs/tasks/security/basic-auth/) | @@ -130,7 +130,363 @@ From @ongy, some additional goals to keep in mind: ## API -(... details, can point to PR with changes) +This GEP proposes a two-part solution to this problem: + +* We introduce a new HTTPRoute Filter, `ExternalAuth`, that allows the + specification of an external source to connect to using Envoy's `ext_authz` protocol. +* We introduce a new Policy object that can be targeted at either the + Gateway or HTTPRoute levels. In either of these cases, it _defaults_ the settings + for the HTTPRoute Filter across all HTTPRoute matches that roll up to the object. + +These two parts will be done in two separate changes - Filter first, then +Policy after. + +Both of these additions use the same underlying struct for the config, so that +changes or additions in one place add them in the other as well. + +This plan has some big things that need explaining before we get to the API details: + +* Why a Filter plus Policy approach? +* Why two changes? +* Why Envoy's `ext_authz`? + +### Why a Filter plus Policy approach? + +We have two main requirements: Ana needs to be able to configure auth at least at +the smallest possible scope, and Ana, Ian and Chihiro need to be able to configure +defaults at larger scopes. + +The smallest possible scope for this config is the HTTPRoute Rule level, where +you can match a single set of matchers - like a path, or a path and header +combination. + +At this level, the inline tool we have available to perform changes is the HTTPRoute +Filter, which also has the property that it's designed to _filter_ requests. This +matches the overall pattern here, which is to _filter_ some requests, allowing +or denying them based on the presence of Authentication and the passing of +Authorization checks. + +A Policy _can_ be targeted at this level, using the Route rule as a `sectionName`, +but that leaves aside that Filters are exactly designed to handle this use case. + +Policy attachment includes defaulting fields like Filters in its scope already, +so we are allowed to use a combination in this way. + +Using a Filter also has the advantage that, at the tightest possible scope (the +object being defaulted) you can _explicitly_ override any configured defaults. + +Using a Filter also includes ordering (because Filters are an ordered list), +although this exact behavior is currently underspecified. This change will also +need to clarify. Ordering is particularly important for Auth use cases, because +sometimes Auth will expect certain properties that may need to be introduced +by things like header modification. + +Lastly, using a Filter means that, for the simplest possible case, where Ana +wants to enable Auth* for a single path, then there is only a single object to +edit, and a single place to configure. + +Using a Policy for the simplest case immediately brings in all the discovery +problems that Policy entails. + +There are two important caveats here that must be addressed, however: +* Firstly, whatever is in the filter either must be accepted, or the rule + is not accepted. Overrides from anywhere else, including if we add an Override + Policy later, must not override explicit config - that would + violate one of the key declarative principles, that what is requested in the + spec is either what ends up in the state, or that config is rejected. +* Secondly, filter ordering is particularly important for Auth use cases, so we + must ensure that when we add Policy defaulting we have a way to indicate at + what position in a filter list the Auth policy should fit. + +### Why two phases? + +In short: In the interest of getting something, even if incomplete, into our +user's hands as quickly as possible. + +Policy design is complex, and needs to be done carefully. Doing a first +pass using only a Filter to get the basic config correct while we discuss +how to make the Policy handling work means that we can get some work out to the +community without needing to complete the whole design. + +In particular, the design for the Filter plus Policy will need to answer at +least the following questions: + +* How to set where in a list of Filters a defaulted Auth filter sits; + and what happens if no Filters are specified in a HTTPRoute? Does it go first, + last, or should there be a way to specify the order? +* What Policy types are possible? Defaults? (Definitely useful for setting a + baseline expectation for a cluster, which is desirable for security constructs + like Auth) Overrides? (Also very useful for ensuring that exceptions meet + certain requirements - like only allowing the disabling of Auth on `/healthz` + endpoints or similar use cases.) +* Should Policy have a way to describe rules around when it should take effect? + That's in addition to the usual hierarchical rules, should the Policy have ways + to include or exclude specific matches? This would require agreement in the + Policy Attachment spec as well. + +All of these changes have costs in complexity and troubleshooting difficulty, so +it's important to ensure that the design consciously makes these tradeoffs. + +In particular, the last two items in the above list seem likely to require a fair +amount of discussion, and including a Policy in the initial release of this +seems likely to make this change miss its current release window. + + +### Why Envoy's ext_authz? + +#### What is ext_authz? + +Envoy's External Authorization filter is a filter that calls out to an authorization +service to check if the incoming request is authorized or not. Note that, in +order to check _authorization_, it must also be able to determine _authentication_ - +this is one of the reasons why we've chosen this approach. + +Envoy's implementation of this filter allows both a +[gRPC, protobuf API](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authzz/v3/ext_authzz.proto) +and configuration of a HTTP based API (which, as it's not defined using a +specification like protobuf, requires more configuration). + +The important thing to remember here is that the actual authorization process +is delegated to the authorization service, and the authentication process _may +optionally_ also be delegated there - which is why the ext_authz approach allows +handling many Auth methods - most of the work is performed by external services +which implement various methods (like Basic Auth, OAuth, JWT validation, etc). + +#### Why use it over other options? + +The community discussed Auth extensively in-person at Kubecon London in early 2025, +and got broad agreement from multiple dataplanes that: + +* something like ext_authz was a good idea, because it's flexible and allows the + implementation of many types of Auth without specific protocol implementation + in upstream +* Envoy's ext_authz protocol has no major problems that would stop us using it +* Envoy-based implementations mostly already have support for it + +At that meeting, those present agreed that ext_authz was a good place to start. + +Most non-Envoy dataplanes also already have similar methods, so the maintainers +of projects using other dataplanes were okay with this idea. + +The alternative here would be to add a Filter type _per auth method_, which, given +the large number of options, could quickly become very complex. + +This GEP is, however, explicitly _not_ ruling out the possibility of adding +specific Filters for specific Auth methods in the future, if users of this API +find the overhead of running a compatible implementation to be too much. + +### API Design + +#### Phase 1: Adding a Filter + +This config mainly takes inspiration from Envoy's ext_authz filter config, while +also trying to maintain compatibility with other HTTP methods. + +This design is also trying to start with a minimum feature set, and add things +as required, rather than adding everything configurable in all implementations +immediately. + +There is some difference between data planes, based on the links above, but +these fields should be broadly supportable across all the listed implementations. + +Some design comments are included inline. + +The intent for Phase 2 is that this struct will be included in an eventual Policy +so that additions only need to be made in one place. + +Additionally, as per other added Filters, the config is included in HTTPRoute, +and is not an additional CRD. + +##### Go Structs + +```go + +// HTTPRouteExtAuthProtcol specifies what protocol should be used +// for communicating with an external authorization server. +// +// Valid values are supplied as constants below. +type HTTPRouteExtAuthProtocol string + +const ( + HTTPRouteExtAuthGRPCProtocol HTTPRouteExtAuthProtocol = "GRPC" + HTTPRouteExtAuthHTTPProtocol HTTPRouteExtAuthProtocol = "HTTP" +) +// HTTPExtAuthFilter defines a filter that modifies requests by sending +// request details to an external authorization server. +// +// Support: Extended +// Feature Name: HTTPRouteExtAuth +type HTTPExtAuthFilter struct { + + // ExtAuthProtocol describes which protocol to use when communicating with an + // ext_authz authorization server. + // + // When this is set to GRPC, each backend must use the Envoy ext_authz protocol + // on the port specified in `backendRefs`. Requests and responses are defined + // in the protobufs explained at: + // https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + // + // When this is set to HTTP, each backend must respond with a `200` status + // code in on a successful authorization. Any other code is considered + // an authorization failure. + // + // Feature Names: + // GRPC Support - HTTPRouteExtAuthGRPC + // HTTP Support - HTTPRouteExtAuthHTTP + // + // +unionDiscriminator + // +kubebuilder:validation:Enum=HTTP;GRPC + ExtAuthProtocol HTTPRouteExtAuthProtocol `json:"protocol"` + + // BackendRefs is a reference to a backend to send authorization + // requests to. + // + // The backend must speak the selected protocol (GRPC or HTTP) on the + // referenced port. + // + // If the backend service requires TLS, use BackendTLSPolicy to tell the + // implementation to supply the TLS details to be used to connect to that + // backend. + // + BackendRef BackendObjectReference `json:"backendRef"` + + // GRPCAuthConfig contains configuration for communication with ext_authz + // protocol-speaking backends. + // + // If unset, implementations must assume the default behavior for each + // included field is intended. + // + // +optional + GRPCAuthConfig *GRPCAuthConfig `json:"grpc,omitempty"` + + // HTTPAuthConfig contains configuration for communication with HTTP-speaking + // backends. + // + // If unset, implementations must assume the default behavior for each + // included field is intended. + // + // +optional + HTTPAuthConfig *HTTPAuthConfig `json:"http,omitempty"` + + // ForwardBody controls if requests to the authorization server should include + // the body of the client request; and if so, how big that body is allowed + // to be. + // + // It is expected that implementations will buffer the request body up to + // `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + // 4xx series error (413 or 403 are common examples), and fail processing + // of the filter. + // + // If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + // be forwarded. + // + // Feature Name: HTTPRouteExtAuthForwardBody + // + // GEP Review Notes: + // Both Envoy and Traefik show support for this feature, but HAProxy and + // ingress-nginx do not. So this has a separate feature flag for it. + // + // +optional + ForwardBody *ForwardBodyConfig `json:"forwardBody,omitempty"` +} + +// GRPCAuthConfig contains configuration for communication with ext_authz +// protocol-speaking backends. +type GRPCAuthConfig struct { + + // AllowedRequestHeaders specifies what headers from the client request + // will be sent to the authorization server. + // + // If this list is empty, then the following headers must be sent: + // + // - `Authorization` + // - `Location` + // - `Proxy-Authenticate` + // - `Set-Cookie` + // - `WWW-Authenticate` + // + // If the list has entries, only those entries must be sent. + // + // +optional + // +kubebuilder:validation:MaxLength=64 + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` +} + +// HTTPAuthConfig contains configuration for communication with HTTP-speaking +// backends. +type HTTPAuthConfig struct { + // Path sets the prefix that paths from the client request will have added + // when forwarded to the authorization server. + // + // When empty or unspecified, no prefix is added. + // +optional + Path string `json:"path,omitempty"` + + // AllowedRequestHeaders specifies what additional headers from the client request + // will be sent to the authorization server. + // + // The following headers must always be sent to the authorization server, + // regardless of this setting: + // + // * `Host` + // * `Method` + // * `Path` + // * `Content-Length` + // * `Authorization` + // + // If this list is empty, then only those headers must be sent. + // + // Note that `Content-Length` has a special behavior, in that the length + // sent must be correct for the actual request to the external authorization + // server - that is, it must reflect the actual number of bytes sent in the + // body of the request to the authorization server. + // + // So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + // to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + // to anything other than `0`, then the `Content-Length` of the authorization + // request must be set to the actual number of bytes forwarded. + // + // +optional + // +kubebuilder:validation:MaxLength=64 + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` + + // AllowedResponseHeaders specifies what headers from the authorization response + // will be copied into the request to the backend. + // + // If this list is empty, then all headers from the authorization server + // except Authority or Host must be copied. + // + // +optional + // +kubebuilder:validation:MaxLength=64 + AllowedResponseHeaders []string `json:"allowedResponseHeaders,omitempty"` + +} + +// ForwardBody configures if requests to the authorization server should include +// the body of the client request; and if so, how big that body is allowed +// to be. +// +// If empty or unset, do not forward the body. +type ForwardBodyConfig struct { + + // MaxSize specifies how large in bytes the largest body that will be buffered + // and sent to the authorization server. If the body size is larger than + // `maxSize`, then the body sent to the authorization server must be + // truncated to `maxSize` bytes. + // + // If 0, the body will not be sent to the authorization server. + MaxSize uint16 `json:"maxSize,omitempty"` +} + +``` +#### YAML Examples + +Coming soon. + +#### Phase 2: Adding more complex configuration with Policy + +This phase is currently undefined until we reach agreement on the Filter + Policy +approach. ## Conformance Details @@ -138,12 +494,22 @@ From @ongy, some additional goals to keep in mind: #### Feature Names -Every feature should: +For this feature as a base: + +`HTTPRouteExtAuth` + +For supporting talking to ext_authz servers using the gRPC ext_authz protocol: + +`HTTPRouteExtAuthGRPC` + +For supporting talking to ext_authz servers using HTTP: + +`HTTPRouteExtAuthHTTP` + +For forwarding the body of the client request to the authorization server + +`HTTPRouteExtAuthForwardBody` -1. Start with the resource name. i.e HTTPRouteXXX -2. Follow the PascalCase convention. Note that the resource name in the string should come as is and not be converted to PascalCase, i.e HTTPRoutePortRedirect and not HttpRoutePortRedirect. -3. Not exceed 128 characters. -4. Contain only letters and numbers ### Conformance tests diff --git a/geps/gep-1494/metadata.yaml b/geps/gep-1494/metadata.yaml index 14161d8cb4..600aed9a6a 100644 --- a/geps/gep-1494/metadata.yaml +++ b/geps/gep-1494/metadata.yaml @@ -2,7 +2,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 1494 name: HTTP Auth in Gateway API -status: Provisional +status: Implementable # Any authors who contribute to the GEP in any way should be listed here using # their GitHub handle. authors: @@ -13,7 +13,13 @@ authors: references: {} # featureNames is a list of the feature names introduced by the GEP, if there # are any. This will allow us to track which feature was introduced by which GEP. -featureNames: {} +featureNames: + - HTTPRouteExtAuth + - HTTPRouteExtAuthGRPC + - HTTPRouteExtAuthHTTP + - HTTPRouteExtAuthForwardBody # changelog is a list of hyperlinks to PRs that make changes to the GEP, in # ascending date order. -changelog: {} +changelog: + - https://github.com/kubernetes-sigs/gateway-api/pull/3500 + - https://github.com/kubernetes-sigs/gateway-api/pull/3884 From a48921a745f5b9367c7cc96106137ea480d54052 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 23 Jul 2025 02:14:28 -0400 Subject: [PATCH 096/224] Update RELEASE_MANAGEMENT.md (#3943) --- RELEASE_MANAGEMENT.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/RELEASE_MANAGEMENT.md b/RELEASE_MANAGEMENT.md index 94e2c724de..78d0020843 100644 --- a/RELEASE_MANAGEMENT.md +++ b/RELEASE_MANAGEMENT.md @@ -113,3 +113,19 @@ final release when it is cut. [Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ [Milestone]:#github-milestone + +## Time Extensions + +Extensions to timelines may be requested by contributors. Our guidelines for +this are based on the Kubernetes process: + +* Extensions can be granted on a per-GEP basis + * The owners of the GEP have to ask and provide a timeline (measured in + days) as to when they believe the GEP will be ready for merge. +* The request and approval for a GEP extension needs to be in public. +* Extensions can only be granted with a majority agreement by maintainers + / release-managers + +For our purposes we use GitHub discussions as the public place for +requesting/approving extensions. Contributors should use an existing +discussion for the release when feasible, otherwise create a discussion. From 18bd80558884697be5aaeaa75e5091af3553176f Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 24 Jul 2025 00:20:28 -0400 Subject: [PATCH 097/224] docs: move GEP-3798 to Deferred for now (#3947) Signed-off-by: Shane Utt --- geps/gep-3798/index.md | 17 +++++++++++++++-- geps/gep-3798/metadata.yaml | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/geps/gep-3798/index.md b/geps/gep-3798/index.md index 84b4a603c8..16080b1e8e 100644 --- a/geps/gep-3798/index.md +++ b/geps/gep-3798/index.md @@ -1,13 +1,26 @@ # GEP-3798: Client IP-Based Session Persistence * Issue: [#3798](https://github.com/kubernetes-sigs/gateway-api/issues/3798) -* Status: Provisional +* Status: Deferred (See [status definitions](../overview.md#gep-states).) ## Notes and Disclaimers -* This is currently targeting release as `Experimental` in [v1.4.0](https://github.com/kubernetes-sigs/gateway-api/milestone/22). However there was notable concern in [PR#3844](https://github.com/kubernetes-sigs/gateway-api/pull/3844) that it may be difficult to get multiple implementations who will be ready to implement this and move it forward. As such, the primary focus at this point should be finding representatives of implementations who may be interested in implementing this. Otherwise, this GEP may need to be `Deferred` and revisited as part of a later release. +* **DEFERRED**: This originally targeted release as `Experimental` in [v1.4.0]. + Notably (in [PR#3844]) there was concern that it may be difficult to get + multiple implementations to support this. During the release cycle, this GEP + was not able to meet the timeline requirements to progress, so it is now + considered deferred. If anyone is interested in picking this back up, it will + need to be re-submitted for consideration in a future release with a written + plan about how it will achieve implementation from multiple implementations. + If this remains in deferred state for a prolonged period, it may eventually + be moved to `Withdrawn`, or moved into the alternatives considered for + [GEP-1619]. + +[v1.4.0]:https://github.com/kubernetes-sigs/gateway-api/milestone/22 +[PR#3844]:https://github.com/kubernetes-sigs/gateway-api/pull/3844 +[GEP-1619]:https://gateway-api.sigs.k8s.io/geps/gep-1619/ ## TLDR diff --git a/geps/gep-3798/metadata.yaml b/geps/gep-3798/metadata.yaml index e7d33a7c8b..85a47289c0 100644 --- a/geps/gep-3798/metadata.yaml +++ b/geps/gep-3798/metadata.yaml @@ -2,7 +2,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 3798 name: Client IP-Based Session Persistence -status: Provisional +status: Deferred # Any authors who contribute to the GEP in any way should be listed here using # their GitHub handle. authors: From 222a1f8afcefe673505db18bba05f45b1619eb73 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Thu, 24 Jul 2025 02:04:28 -0300 Subject: [PATCH 098/224] Mark grpcroutes.spec as required (#3937) --- apis/v1/grpcroute_types.go | 1 + .../crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml | 2 ++ config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml | 2 ++ pkg/generated/openapi/zz_generated.openapi.go | 2 ++ 4 files changed, 7 insertions(+) diff --git a/apis/v1/grpcroute_types.go b/apis/v1/grpcroute_types.go index c6eeb0f3ea..5e77a897c1 100644 --- a/apis/v1/grpcroute_types.go +++ b/apis/v1/grpcroute_types.go @@ -60,6 +60,7 @@ type GRPCRoute struct { metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of GRPCRoute. + // +required Spec GRPCRouteSpec `json:"spec,omitempty"` // Status defines the current state of GRPCRoute. diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 9e8dd64201..f04363ab31 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -2204,6 +2204,8 @@ spec: required: - parents type: object + required: + - spec type: object served: true storage: true diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 4f7d8f1323..4982ec8453 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -2047,6 +2047,8 @@ spec: required: - parents type: object + required: + - spec type: object served: true storage: true diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index cc919c61da..92162b5a1b 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3286,6 +3286,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRoute(ref common.ReferenceCallback }, }, }, + Required: []string{"spec"}, }, }, Dependencies: []string{ @@ -5927,6 +5928,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_GRPCRoute(ref common.ReferenceCa }, }, }, + Required: []string{"spec"}, }, }, Dependencies: []string{ From ff47627990d2e8845c6728077ee7a414f648bc0b Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:18:27 +0200 Subject: [PATCH 099/224] Gep-91: Address connection coalescing security issue (#3942) * GEP 91: Update API Relates to https://github.com/kubernetes-sigs/gateway-api/discussions/3760#discussioncomment-12997389 Signed-off-by: Arko Dasgupta * GEP-91: Address connection coalescing security issue * remove changes in API --------- Signed-off-by: Arko Dasgupta Co-authored-by: Arko Dasgupta --- geps/gep-91/index.md | 215 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 175 insertions(+), 40 deletions(-) diff --git a/geps/gep-91/index.md b/geps/gep-91/index.md index 5d28c9a117..8eedb7bd62 100644 --- a/geps/gep-91/index.md +++ b/geps/gep-91/index.md @@ -10,24 +10,37 @@ This GEP proposes a way to validate the TLS certificate presented by the frontend client to the server (Gateway in this case) during a [TLS Handshake Protocol][]. +## Connection coalescing security issue + +Gateway API standard defines a `Listener` as "the concept of a logical endpoint where a Gateway accepts network connections." This statement is incorrect because once the connection is established (this applies to both HTTP and TLS traffic) it can be reused across multiple listeners sharing the same port. This might lead to bypassing client certificate validation configuration for a given `Listener`. Those concerns were raised in [GEP-3567](). To provide the best experience for gateway users and secure their applications, client certificate configuration needs to be introduced with finer granularity per-port (binding to TCP connection). + ## Goals * Define an API field to specify the CA Certificate within the Gateway configuration that can be used as a trust anchor to validate the certificates presented by the client. This use case has been highlighted in the [TLS Configuration GEP][] under segment 1 and in the [Gateway API TLS Use Cases][] document under point 7. +* Introduce explicit client certificate validation modes that reflect common TLS behaviors (e.g., optional vs. required client certs) * Ensure the configuration mitigates the authentication bypass risks associated with HTTP/2 connection coalesing as described in [GEP-3567](https://gateway-api.sigs.k8s.io/geps/gep-3567/#interaction-with-client-cert-validation). -* Supporting a mode where validating client certificates is optional, useful for debugging and migrating to strict TLS. ## Non-Goals * Define other fields that can be used to verify the client certificate such as the Certificate Hash. ### API -* Introduce a `FrontendValidation` field of type `FrontendTLSValidation` within [GatewayTLSConfig][] that can be used to validate the peer (frontend) with which the TLS connection is being made. +* Introduce two new structs `TLSConfig` and `FrontendTLSValidation` allowing for the definition of certificate validation used to authenticate the peer (frontend) in a TLS connection. A new `tls` field, storing an array of `TLSConfigs`, will be added to the gateway object. +* This new field is separate from the existing [BackendTLSPolicy][] configuration. [BackendTLSPolicy][] controls TLS certificate validation for connections *from* the Gateway to the backend service. +This proposal adds the ability to validate the TLS certificate presented by the *client* connecting to the Gateway (the frontend). +These two validation mechanisms operate independently and can be used simultaneously. * Introduce a `caCertificateRefs` field within `FrontendTLSValidation` that can be used to specify a list of CA Certificates that can be used as a trust anchor to validate the certificates presented by the client. -* This new field is separate from the existing [BackendTLSPolicy][] configuration. [BackendTLSPolicy][] controls TLS certificate validation for connections *from* the - Gateway to the backend service. This proposal adds the ability to validate the TLS certificate presented by the *client* connecting to the Gateway (the - frontend). These two validation mechanisms operate independently and can be used simultaneously. -* Also introduce a `ObjectReference` structure that can be used to specify `caCertificateRefs` references. +* Add a new `FrontendValidationModeType` enum within `FrontendTLSValidation` indicating how gateway should validate client certificates. As for now we support following values but it might change in the future: + 1) `AllowValidOnly` + 2) `AllowInvalidOrMissingCert` +* Introduce a `ObjectReference` structure that can be used to specify `caCertificateRefs` references. +* Introduce a `tls` field within the Gateway Spec to allow for a common TLS configuration to apply across all listeners. + +### Impact on listeners + +This proposal removes frontendTLSValidation from Listener's TLS configuration and introduces gateways level per port configuration. This is a breaking change for exisitng implementation which uses this feature from Experimental API. + Once gateway level TLS is configured (either by default or for a specific port), the TLS settings will apply to all existing and newly created Listeners that match the configuration. #### GO @@ -65,50 +78,118 @@ type ObjectReference struct { Namespace *Namespace `json:"namespace,omitempty"` } -type GatewayTLSConfig struct { - ...... - // FrontendValidation holds configuration information for validating the frontend (client). - // Setting this field will require clients to send a client certificate - // required for validation during the TLS handshake. In browsers this may result in a dialog appearing - // that requests a user to specify the client certificate. - // The maximum depth of a certificate chain accepted in verification is Implementation specific. - FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` +// GatewayTLSConfigs stores TLS configurations for a Gateway. +// +// * If the `port` field in `TLSConfig` is not set, the TLS configuration applies +// to all listeners in the gateway. We call this `default` configuration. +// * If the `port` field in `TLSConfig` is set, the TLS configuration applies +// only to listeners with a matching port. Each port requires a unique TLS configuration. +// * Per-port configurations can override the `default` configuration. +// * The `default` configuration is optional. Clients can apply TLS configuration +// to a subset of listeners by creating only per-port configurations. Listeners +// with a port that does not match any TLS configuration will not have +// `frontendValidation` set. +type GatewayTLSConfigs = []TLSConfig + +// TLSConfig describes a TLS configuration that can be applied to all Gateway +// Listeners or to all Listeners matching the Port if set. +type TLSConfig struct { + // The Port indicates the Port Number to which the TLS configuration will be + // applied. If the field is not set the TLS Configuration will be applied to + // all Listeners. + // + // Support: Extended + // + // +optional + // + Port *PortNumber + // FrontendValidation holds configuration information for validating the frontend (client). + // Setting this field will result in mutual authentication when connecting to the gateway. In browsers this may result in a dialog appearing + // that requests a user to specify the client certificate. + // The maximum depth of a certificate chain accepted in verification is Implementation specific. + // + // Each field may be overidden by an equivalent setting applied at the Listener level. + // + // Support: Extended + // + // +optional + // + FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` } // FrontendTLSValidation holds configuration information that can be used to validate // the frontend initiating the TLS connection type FrontendTLSValidation struct { - // CACertificateRefs contains one or more references to - // Kubernetes objects that contain TLS certificates of - // the Certificate Authorities that can be used - // as a trust anchor to validate the certificates presented by the client. - // - // A single CA certificate reference to a Kubernetes ConfigMap - // has "Core" support. - // Implementations MAY choose to support attaching multiple CA certificates to - // a Listener, but this behavior is implementation-specific. - // - // Support: Core - A single reference to a Kubernetes ConfigMap - // with the CA certificate in a key named `ca.crt`. - // - // Support: Implementation-specific (More than one reference, or other kinds - // of resources). - // - // References to a resource in a different namespace are invalid UNLESS there - // is a ReferenceGrant in the target namespace that allows the certificate - // to be attached. If a ReferenceGrant does not allow this reference, the - // "ResolvedRefs" condition MUST be set to False for this listener with the - // "RefNotPermitted" reason. - // - // +kubebuilder:validation:MaxItems=8 - // +kubebuilder:validation:MinItems=1 - CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` + // CACertificateRefs contains one or more references to + // Kubernetes objects that contain TLS certificates of + // the Certificate Authorities that can be used + // as a trust anchor to validate the certificates presented by the client. + // + // A single CA certificate reference to a Kubernetes ConfigMap + // has "Core" support. + // Implementations MAY choose to support attaching multiple CA certificates to + // a Listener, but this behavior is implementation-specific. + // + // Support: Core - A single reference to a Kubernetes ConfigMap + // with the CA certificate in a key named `ca.crt`. + // + // Support: Implementation-specific (More than one certificate in a ConfigMap with different keys or more than one reference, or other kinds of resources). + // + // References to a resource in a different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "RefNotPermitted" reason. + // + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:validation:MinItems=1 + CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` + + // FrontendValidationMode defines the mode for validating the client certificate. + // There are two possible modes: + // + // - AllowValidOnly: In this mode, the gateway will accept connections only if + // the client presents a valid certificate. This certificate must successfully + // pass validation against the CA certificates specified in `CACertificateRefs`. + // - AllowInvalidOrMissingCert: In this mode, the gateway will accept + // connections even if the client certificate is not presented or fails verification. + // + // Defaults to AllowValidOnly. + // + // Support: Extended + // + // +optional + // +kubebuilder:default=AllowValidOnly + Mode *FrontendValidationModeType `json:"mode,omitempty"` +} + +// FrontendValidationModeType type defines how a Gateway or Listener validates client certificates. +// +// +kubebuilder:validation:Enum=AllowValidOnly;AllowInvalidOrMissingCert +type FrontendValidationModeType string + +const ( + // AllowValidOnly indicates that a client certificate is required + // during the TLS handshake and MUST pass validation. + AllowValidOnly FrontendValidationModeType = "AllowValidOnly" + + // AllowInvalidOrMissingCert indicates that a client certificate may not be + // presented during the handshake or the validation against CA certificates may fail. + AllowInvalidOrMissingCert FrontendValidationModeType = "AllowInvalidOrMissingCert" +) + +type GatewaySpec struct { + ... + // TLSConfigs stores TLS configurations for a Gateway. + TLSConfigs GatewayTLSConfigs } ``` #### YAML +1. Setting default `frontendValidation` config. + ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway @@ -116,6 +197,12 @@ metadata: name: client-validation-basic spec: gatewayClassName: acme-lb + tls: + - frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: default-cert listeners: - name: foo-https protocol: HTTPS @@ -126,11 +213,58 @@ spec: - kind: Secret group: "" name: foo-example-com-cert + - name: bar-https + protocol: HTTPS + port: 8443 + hostname: bar.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: bar-example-com-cert +``` + +2. Setting default and per port `frontendValidation` configs. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: client-validation-basic +spec: + gatewayClassName: acme-lb + tls: + - port: 443 frontendValidation: caCertificateRefs: - kind: ConfigMap group: "" name: foo-example-com-ca-cert + - frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: default-cert + mode: AllowInvalidOrMissingCert + listeners: + - name: foo-https + protocol: HTTPS + port: 443 + hostname: foo.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: foo-example-com-cert + - name: bar-https + protocol: HTTPS + port: 8443 + hostname: bar.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: bar-example-com-cert ``` ## Deferred @@ -143,7 +277,7 @@ This section highlights use cases that may be covered in a future iteration of t ## Existing support in Implementations -This feature is already widely supported by implementations that conform to the Gateway API. +This feature is already widely supported by implementations that conform to the Gateway API. The table below summarizes current support. Please feel free to add any implementations that are missing. This GEP aims to standardize this behavior as an official part of the upstream specification. @@ -191,3 +325,4 @@ This GEP aims to standardize this behavior as an official part of the upstream s [BackendTLSPolicy]: ../../api-types/backendtlspolicy.md [TLS Configuration GEP]: ../gep-2907/index.md [Gateway API TLS Use Cases]: https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit?pli=1#heading=h.cxuq8vo8pcxm +[GEP-3567]: https://gateway-api.sigs.k8s.io/geps/gep-3567/ From cb2d8f1413b4624b4851cc3319de2b5c27375788 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Thu, 24 Jul 2025 17:44:28 -0300 Subject: [PATCH 100/224] Use envtest for CRD validation tests (#3948) * Use envtest for cel validation instead of a KinD cluster * Add CRD validation tests to gh actions * Move manifest test to use envtest * Remove the crd testing shell script * Fix boilerplate of test file --- .github/workflows/crd-validation.yml | 32 +++++ Makefile | 7 +- go.mod | 1 + go.sum | 14 +++ hack/test-crds-validation.sh | 152 ----------------------- pkg/test/cel/main_test.go | 78 +++++++++--- pkg/test/crd/crd_test.go | 177 +++++++++++++++++++++++++++ 7 files changed, 294 insertions(+), 167 deletions(-) create mode 100644 .github/workflows/crd-validation.yml delete mode 100755 hack/test-crds-validation.sh create mode 100644 pkg/test/crd/crd_test.go diff --git a/.github/workflows/crd-validation.yml b/.github/workflows/crd-validation.yml new file mode 100644 index 0000000000..4aa88c5a99 --- /dev/null +++ b/.github/workflows/crd-validation.yml @@ -0,0 +1,32 @@ +name: CRD Validation + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +# Remove all permissions from GITHUB_TOKEN except metadata. +permissions: {} + +jobs: + crd-validation: + name: CEL + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Available versions at https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/HEAD/envtest-releases.yaml + k8s_version: [v1.33.0, v1.32.0, v1.31.0, v1.30.3, v1.29.5] + crd_channel: [standard, experimental] + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + with: + persist-credentials: false + - name: Set up Go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 + - name: Run CRD Validation tests + env: + K8S_VERSION: ${{ matrix.k8s_version }} + CRD_CHANNEL: ${{ matrix.crd_channel }} + run: | + make CEL_TEST_K8S_VERSION="${K8S_VERSION}" CEL_TEST_CRD_CHANNEL="${CRD_CHANNEL}" test.crds-validation diff --git a/Makefile b/Makefile index 8328ea218b..3f2fee4146 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,10 @@ ROOT := $(abspath $(TOP)) CONFORMANCE_FLAGS ?= GO_TEST_FLAGS ?= +# Flags for CRD validation tests +CEL_TEST_K8S_VERSION ?= +CEL_TEST_CRD_CHANNEL ?= standard + all: generate vet fmt verify test # Run generators for protos, Deepcopy funcs, CRDs, and docs. @@ -85,7 +89,8 @@ test: # Run tests for CRDs validation .PHONY: test.crds-validation test.crds-validation: - ./hack/test-crds-validation.sh $(VERSION) + K8S_VERSION=$(CEL_TEST_K8S_VERSION) CRD_CHANNEL=$(CEL_TEST_CRD_CHANNEL) go test ${GO_TEST_FLAGS} -count=1 -timeout=120s --tags=$(CEL_TEST_CRD_CHANNEL) -v ./pkg/test/cel + K8S_VERSION=$(CEL_TEST_K8S_VERSION) CRD_CHANNEL=$(CEL_TEST_CRD_CHANNEL) go test ${GO_TEST_FLAGS} -count=1 -timeout=120s -v ./pkg/test/crd # Run conformance tests against controller implementation .PHONY: conformance diff --git a/go.mod b/go.mod index 82f05190d0..f0828e05cc 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect diff --git a/go.sum b/go.sum index 85b14c3ac1..85aff8e13d 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,12 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -120,6 +124,14 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -209,6 +221,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= diff --git a/hack/test-crds-validation.sh b/hack/test-crds-validation.sh deleted file mode 100755 index 8f3da81db0..0000000000 --- a/hack/test-crds-validation.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash - -# Copyright 2020 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o nounset -set -o pipefail - -readonly GO111MODULE="on" -readonly GOFLAGS="-mod=readonly" -readonly GOPATH="$(mktemp -d)" -readonly CLUSTER_NAME="verify-gateway-api" - -export KUBECONFIG="${GOPATH}/.kubeconfig" -export GOFLAGS GO111MODULE GOPATH -export PATH="${GOPATH}/bin:${PATH}" - -# Cleanup logic for cleanup on exit -CLEANED_UP=false -cleanup() { - if [ "$CLEANED_UP" = "true" ]; then - return - fi - - if [ "${KIND_CREATE_ATTEMPTED:-}" = true ]; then - kind delete cluster --name "${CLUSTER_NAME}" || true - fi - CLEANED_UP=true -} - -trap cleanup INT TERM EXIT - -# TODO(mlavacca): find a good way to keep this dependency up to date. -KIND_VERSION="v0.26.0" - -# list of kind images taken from https://github.com/kubernetes-sigs/kind/releases/tag/v0.26.0. -# they need to be updated when kind is updated. -KIND_IMAGES=( - "kindest/node:v1.28.15@sha256:a7c05c7ae043a0b8c818f5a06188bc2c4098f6cb59ca7d1856df00375d839251" - "kindest/node:v1.29.12@sha256:62c0672ba99a4afd7396512848d6fc382906b8f33349ae68fb1dbfe549f70dec" - "kindest/node:v1.30.8@sha256:17cd608b3971338d9180b00776cb766c50d0a0b6b904ab4ff52fd3fc5c6369bf" - "kindest/node:v1.31.4@sha256:2cb39f7295fe7eafee0842b1052a599a4fb0f8bcf3f83d96c7f4864c357c6c30" - "kindest/node:v1.32.0@sha256:2458b423d635d7b01637cac2d6de7e1c1dca1148a2ba2e90975e214ca849e7cb" -) - -if [ "$#" -gt 1 ]; then - echo "Error: Too many arguments provided. Only 1 argument is allowed." - exit 1 -fi - -DEFAULT_INDEX=$((1)) - -if [ "$#" -eq 1 ]; then - # Check if the argument is a valid number between 1 and 5 - if ! [[ "$1" =~ ^[1-5] ]]; then - echo "Error: Argument is not a valid integer between 1 and 5." - exit 1 - fi - INDEX=$(($1)) -else - INDEX=$((DEFAULT_INDEX)) -fi - -K8S_IMAGE=${KIND_IMAGES[$((INDEX-1))]} -echo "Using Kubernetes image: ${K8S_IMAGE}" - -# For exit code -res=0 - -# Install kind -(cd "${GOPATH}" && go install sigs.k8s.io/kind@${KIND_VERSION}) || res=$? - -# Create cluster -KIND_CREATE_ATTEMPTED=true -kind create cluster --name "${CLUSTER_NAME}" --image "${K8S_IMAGE}" || res=$? - -# Verify CEL validation -for CHANNEL in experimental standard; do - # Install CRDs. - kubectl apply -f "config/crd/${CHANNEL}/gateway*.yaml" - - # Run tests. - go test -v -timeout=120s -count=1 --tags ${CHANNEL} sigs.k8s.io/gateway-api/pkg/test/cel || res=$? - - # Delete CRDs to reset environment. - kubectl delete -f "config/crd/${CHANNEL}/gateway*.yaml" -done - -# Temporary workaround for https://github.com/kubernetes/kubernetes/issues/104090 -sleep 8 - -## Validate example YAMLs for each channel - -for CHANNEL in experimental standard; do - ##### Test valid CRD apply and that invalid examples are invalid. - # Install CRDs - kubectl apply -f "config/crd/${CHANNEL}/gateway*.yaml" || res=$? - - # Temporary workaround for https://github.com/kubernetes/kubernetes/issues/104090 - sleep 8 - - kubectl apply --recursive -f examples/standard || res=$? - - # Install all experimental example gateway-api resources when experimental mode is enabled - if [[ "${CHANNEL}" == "experimental" ]]; then - echo "Experimental mode enabled: deploying experimental examples" - kubectl apply --recursive -f examples/experimental || res=$? - fi - - # Find all our invalid examples and check them one by one. - # This lets us check the output in a cleaner way than a grep pipeline. - for file in $(find hack/invalid-examples -name "*.yaml"); do - # Don't check alpha resources in Standard checks - if [[ "$file" =~ "experimental" && "$CHANNEL" == "standard" ]]; then - continue - fi - - KUBECTL_OUTPUT=$(kubectl apply -f "$file" 2>&1) - - if [[ \ - ! ("$KUBECTL_OUTPUT" =~ "is invalid") && \ - ! ("$KUBECTL_OUTPUT" =~ "missing required field") && \ - ! ("$KUBECTL_OUTPUT" =~ "denied the request") && \ - ! ("$KUBECTL_OUTPUT" =~ "Invalid value") \ - ]]; then - res=2 - cat< Date: Thu, 24 Jul 2025 19:56:26 -0700 Subject: [PATCH 101/224] build(deps): bump sigs.k8s.io/yaml from 1.4.0 to 1.5.0 (#3904) Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/kubernetes-sigs/yaml/releases) - [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/yaml dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f0828e05cc..b2fd9f7a0d 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/controller-tools v0.18.0 sigs.k8s.io/structured-merge-diff/v4 v4.7.0 - sigs.k8s.io/yaml v1.4.0 + sigs.k8s.io/yaml v1.5.0 ) require ( @@ -67,6 +67,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect diff --git a/go.sum b/go.sum index 85aff8e13d..560828c789 100644 --- a/go.sum +++ b/go.sum @@ -172,6 +172,10 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -275,5 +279,6 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= From f00522647bafdd4c3d40d396b6360726f469f923 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 19:56:33 -0700 Subject: [PATCH 102/224] build(deps): bump the k8s-io group with 5 updates (#3931) Bumps the k8s-io group with 5 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.33.2` | `0.33.3` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.33.2` | `0.33.3` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.33.2` | `0.33.3` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.33.2` | `0.33.3` | | [k8s.io/code-generator](https://github.com/kubernetes/code-generator) | `0.33.2` | `0.33.3` | Updates `k8s.io/api` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/api/compare/v0.33.2...v0.33.3) Updates `k8s.io/apiextensions-apiserver` from 0.33.2 to 0.33.3 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.2...v0.33.3) Updates `k8s.io/apimachinery` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.2...v0.33.3) Updates `k8s.io/client-go` from 0.33.2 to 0.33.3 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.33.2...v0.33.3) Updates `k8s.io/code-generator` from 0.33.2 to 0.33.3 - [Commits](https://github.com/kubernetes/code-generator/compare/v0.33.2...v0.33.3) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/code-generator dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index b2fd9f7a0d..e02beb946a 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( google.golang.org/grpc v1.73.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 - k8s.io/api v0.33.2 - k8s.io/apiextensions-apiserver v0.33.2 - k8s.io/apimachinery v0.33.2 - k8s.io/client-go v0.33.2 - k8s.io/code-generator v0.33.2 + k8s.io/api v0.33.3 + k8s.io/apiextensions-apiserver v0.33.3 + k8s.io/apimachinery v0.33.3 + k8s.io/client-go v0.33.3 + k8s.io/code-generator v0.33.3 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.21.0 diff --git a/go.sum b/go.sum index 560828c789..60714d401a 100644 --- a/go.sum +++ b/go.sum @@ -250,16 +250,16 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= -k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= -k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= -k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= -k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= -k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= -k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= -k8s.io/code-generator v0.33.2 h1:PCJ0Y6viTCxxJHMOyGqYwWEteM4q6y1Hqo2rNpl6jF4= -k8s.io/code-generator v0.33.2/go.mod h1:hBjCA9kPMpjLWwxcr75ReaQfFXY8u+9bEJJ7kRw3J8c= +k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= +k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= +k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= +k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= +k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= +k8s.io/code-generator v0.33.3 h1:6+34LhYkIuQ/yn/E3qlpVqjQaP8smzCu4NE1A8b0LWs= +k8s.io/code-generator v0.33.3/go.mod h1:6Y02+HQJYgNphv9z3wJB5w+sjYDIEBQW7sh62PkufvA= k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= From c60a5e0352b80badc442e884d3a9cc6878e1c856 Mon Sep 17 00:00:00 2001 From: Saylor Berman Date: Fri, 25 Jul 2025 11:58:28 -0600 Subject: [PATCH 103/224] NGINX v2.0.2 conformance report for 1.2.1 (#3954) Adding conformance report for NGINX Gateway Fabric v2.0.2 for Gateway API version v1.2.1. --- .../nginx-nginx-gateway-fabric/README.md | 1 + .../experimental-2.0.2-default-report.yaml | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/experimental-2.0.2-default-report.yaml diff --git a/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/README.md b/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/README.md index 75cbb4c14b..ab4c83009e 100644 --- a/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/README.md +++ b/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/README.md @@ -5,6 +5,7 @@ | API channel | Implementation version | Mode | Report | |--------------|-----------------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v1.6.0](https://github.com/nginx/nginx-gateway-fabric/releases/tag/v1.6.0) | default | [v1.6.0 report](./experimental-1.6.0-default-report.yaml) | +| experimental | [v2.0.2](https://github.com/nginx/nginx-gateway-fabric/releases/tag/v2.0.2) | default | [v2.0.2 report](./experimental-2.0.2-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/experimental-2.0.2-default-report.yaml b/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/experimental-2.0.2-default-report.yaml new file mode 100644 index 0000000000..6f42f47e4a --- /dev/null +++ b/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric/experimental-2.0.2-default-report.yaml @@ -0,0 +1,93 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-07-25T15:36:44Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.2.1 +implementation: + contact: + - https://github.com/nginx/nginx-gateway-fabric/discussions/new/choose + organization: nginx + project: nginx-gateway-fabric + url: https://github.com/nginx/nginx-gateway-fabric + version: v2.0.2 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 14 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteParentRefPort + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure From 040c2a04b9da6c0f7d0eb394cf0ba9c28495e2ec Mon Sep 17 00:00:00 2001 From: Flynn Date: Fri, 25 Jul 2025 20:22:27 -0400 Subject: [PATCH 104/224] API for Default Gateways (#3887) * Add API to GEP-3793. Signed-off-by: Flynn * Minor fixes in text, more important fixes in list formatting. Signed-off-by: Flynn * Major update for multiple default Gateways, including clarification of goals and non-goals as needed and acknowledgment that a defaulted Route gives up some control. Signed-off-by: Flynn * Rearrange Prior Art based on feedback; also split the explicit/implicit bit into its own paragraph. Signed-off-by: Flynn * :man_facepalming: I can count, really. Signed-off-by: Flynn * Massive update for `defaultOK: true` instead of "no parentRefs". Signed-off-by: Flynn * Use `spec.defaultOK` to parallel `spec.isDefault`. Signed-off-by: Flynn * Minor tweaks for feedback. Signed-off-by: Flynn * Mark as implementable Signed-off-by: Flynn * Change `defaultOK` to `useDefaultGateway`. Signed-off-by: Flynn * Move 3793 to Implementable in mkdocs.yml Signed-off-by: Flynn * Define default "scopes", with the only currently-defined scope being All. Update isDefault to defaultScope; switch both it and useDefaultGateway to scopes instead of bools. Signed-off-by: Flynn * Add RFC8174 definitions Signed-off-by: Flynn --------- Signed-off-by: Flynn --- geps/gep-3793/index.md | 577 +++++++++++++++++++++++++++++++----- geps/gep-3793/metadata.yaml | 2 +- mkdocs.yml | 2 +- 3 files changed, 510 insertions(+), 71 deletions(-) diff --git a/geps/gep-3793/index.md b/geps/gep-3793/index.md index 9f15ead87d..f0cad9a72d 100644 --- a/geps/gep-3793/index.md +++ b/geps/gep-3793/index.md @@ -1,10 +1,17 @@ # GEP-3793: Default Gateways * Issue: [#3793](https://github.com/kubernetes-sigs/gateway-api/issues/3793) -* Status: Provisional +* Status: Implementable (See [status definitions](../overview.md#gep-states).) +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14 ([RFC8174]) when, and +only when, they appear in all capitals, as shown here. + +[RFC8174]: https://www.rfc-editor.org/rfc/rfc8174 + ## User Story **[Ana] wants a concept of a default Gateway.** @@ -17,44 +24,73 @@ just wants to create a Route that "works from the outside world" and she really doesn't care what the Gateway is called. Therefore, Ana would like a way to be able to rely on a default Gateway that -she doesn't have to explicitly name, and can simply trust to exist. +she doesn't have to explicitly name, and can simply trust to exist. Ana +recognizes that this will involve **giving up** a certain amount of control +over how requests reach her workloads. She's OK with that, and she understands +that it means that relying on a default Gateway is not always appropriate: for +example, if she needs to be sure that her Route is protected by specific +authorization policies, she should confer with Chihiro to make sure that she +explicitly specifies a Gateway that meets those requirements. -[Ana]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana +In the future, it may also be important to distinguish different kinds of +default Gateways -- for example, a default ingress Gateway or a default egress +Gateway. This GEP deliberately defines only a single _scope_ of default +Gateway (`All`) but recognizes the need to at least consider the possibility +of multiple scopes in the future. + +## Definitions + +- **defaulted Route**: a Route that Ana creates without explicitly specifying + a Gateway + +- **default Gateway**: a Gateway that Chihiro has configured to accept + defaulted Routes + +- **default Gateway scope**: the scope within which a default Gateway is + applicable ## Goals - Give Ana a way to use Gateway API without having to explicitly specify a - Gateway for every Route, ideally without mutating Routes. + Gateway for every Route, ideally without mutating Routes. (In other words, + give Ana an easy way to create a defaulted Route.) + +- Give Ana an easy way to define the scope for a defaulted Route. -- Give Ana an easy way to determine which Gateway is the default, and which of - her Routes are bound to it. +- Give Ana an easy way to determine which default Gateways are present in the + cluster, if any, and which of her Routes are currently bound to these + Gateways. -- Continue supporting multiple Gateways in a cluster, while allowing exactly - one of them to be the default Gateway. +- Continue supporting multiple Gateways in a cluster, while allowing zero or + more of them to be configured as default Gateways. -- Allow [Chihiro] to retain control over which Gateway is the default, so that - they can ensure that it meets their requirements for security, performance, - and other operational concerns. +- Allow [Chihiro] to retain control over which Gateways accept defaulted + Routes, so that they can ensure that all Gateways meet their requirements + for security, performance, and other operational concerns. -- Allow Chihiro to choose not to provide a default Gateway. +- Allow Chihiro to choose not to provide any default Gateways at all. -- Allow Chihiro to rename, reconfigure, or replace the default Gateway at +- Allow Chihiro to define the scope of a default Gateway. + +- Allow Chihiro to rename, reconfigure, or replace any default Gateway at runtime. - - If Chihiro renames the default Gateway, Routes using the default Gateway - MUST remain bound to the new default Gateway. Ana shouldn't need to go - recreate all her Routes just because Chihiro is being indecisive. + - While Kubernetes does not allow renaming a resource, Chihiro MUST be able + to duplicate a default Gateway under a new name, then remove the old + default Gateway, without disrupting routing. Ana MUST NOT need to go + update all her Routes just because Chihiro is being indecisive about + naming. - - Determine how (or if) to signal changes in functionality if the default - Gateway implementation is changed. For example, suppose that Chihiro - switches the default Gateway from an implementation that supports the + - Determine how (or if) to signal changes in functionality if a default + Gateway's implementation is changed. For example, suppose that Chihiro + switches a default Gateway from an implementation that supports the `HTTPRoutePhaseOfTheMoon` filter to an implementation that does not. (Note that this problem is not unique to default Gateways; it affects explicitly-named Gateways as well.) -- Allow Chihiro to control which Routes may bind to the default Gateway, and - to enumerate which Routes are currently bound to the default Gateway. +- Allow Chihiro to control which Routes may bind to a default Gateway, and to + enumerate which Routes are currently bound to a default Gateway. - Support easy interoperation with common CI/CD and GitOps workflows. @@ -63,20 +99,11 @@ she doesn't have to explicitly name, and can simply trust to exist. ## Non-Goals -- Support multiple "default" Gateways in a single cluster. If Ana has to make - a choice about which Gateway she wants to use, she'll need to be explicit - about that. - - Loosening this restriction later is a possibility. For example, we may later - want to consider allowing a default Gateway per namespace, or a default - Gateway per implementation running in a cluster. However, these examples are - not in scope for this GEP, in order to have a fighting chance of getting - functionality into Gateway API 1.4. +- Allow Ana to override Chihiro's choices for default Gateways for a given + Route without explicitly specifying the Gateway: a Route can either be + defaulted, or it MUST specify a Gateway explicitly. -- Allow Ana to override Chihiro's choice for the default Gateway for a given - Route without explicitly specifying the Gateway. - -- Require that every possible routing use case be met by a Route using the +- Require that every possible routing use case be met by a Route using a default Gateway. There will be a great many situations that require Ana to explicitly choose a Gateway; the existence of a default Gateway is not a guarantee that it will be correct for any given use case. @@ -112,37 +139,70 @@ Ian, the Gateway is a first-class thing that they think about regularly, while to Ana, it's an implementation detail that she doesn't care about. Neither point of view is wrong, but they are in tension with each other. +In practice, the trick is to find a usable balance between explicitness and +simplicity, while managing ambiguity. A good example is the humble URL, where +the port number is not always explicit, but it _is_ always unambiguous. +Requiring everyone to type `:80` or `:443` at the end of the host portion of +every URL wouldn't actually help anyone, though allowing it to be specified +explicitly when needed definitely does help people. + ### Prior Art -This is very much not a new problem: there are many other systems out there -where being unambiguous is crucial, but where being completely explicit is a -burden. One of the simplest examples is the humble URL, where the port number -is not always explicit, but it _is_ always unambiguous. Requiring everyone to -type `:80` or `:443` at the end of the host portion of every URL wouldn't -actually help anyone, though allowing it to be specified explicitly when -needed definitely does help people. +- **Ingress** + + The Ingress resource is the most obvious example of prior art: it permitted + specifying a default IngressClass, allowing users to create Ingress + resources that didn't specify the IngressClass explicitly. As with a great + many things in the Ingress API, this caused problems: + + 1. Ingress never defined how conflicts between multiple Ingress resources + should be handled. Many (most?) implementations merged conflicting + resources, which is arguably the worst possible choice. + + 2. Ingress also never defined a way to allow users to see which IngressClass + was being used by a given Ingress resource, which made it difficult for + users to understand what was going on if they were using the default + IngressClass. -The Ingress resource, of course, is another example of prior art: it permitted -specifying a default IngressClass, allowing users to create Ingress resources -that didn't specify the IngressClass explicitly. As with a great many things -in the Ingress API, this caused problems: + (Oddly enough, Ingress' general lack of attention to separation of concerns + wasn't really one of the problems here, since IngressClass was a separate + resource.) -1. Ingress never defined how conflicts between multiple Ingress resources - should be handled. Many (most?) implementations merged conflicting - resources, which is arguably the worst possible choice. +- **Emissary Mapping** -2. Ingress also never defined a way to allow users to see which IngressClass - was being used by a given Ingress resource, which made it difficult for - users to understand what was going on if they were using the default - IngressClass. + Emissary-ingress turns this idea on its head: it assumes that app developers + will almost never care about which specific Emissary they're using, and will + instead only care about the hostnames and ports involved. -(Oddly enough, Ingress' general lack of attention to separation of concerns -wasn't really one of the problems here, since IngressClass was a separate -resource.) + In Emissary: -It's rare to find systems that are completely explicit or completely implicit: -in practice, the trick is to find a usable balance between explicitness and -simplicity, while managing ambiguity. + - a Listener resource defines which ports and protocols are in play; + - a Host resource defines hostnames, TLS certificates, etc.; + - a Mapping resource is roughly analogous to a Route. + + The Listener resource has selectors to control which Hosts it will claim; + Mappings, though, are claimed by Hosts based on the hostname that the + Mapping specifies. In other words, Mappings are not bound to a Listener + explicitly, but rather are bound to a Listener implicitly based on the + hostname that the Mapping specifies. There is no way to _explicitly_ specify + which Listener a Mapping wants to be claimed by. + + This is obviously a very different model from Gateway API, shifting almost + all the work of controlling route binding away from the application + developer onto the cluster operator. + +- **Service** + + We could also consider a Service of `type: LoadBalancer` as a kind of prior + art: in many cases, Ana can directly create these Services and use them to + provide direct, completely unmediated access to a workload, without + worrying about the specifics of how her cluster provider implements them. + + Service's major disadvantages here are that it doesn't support Layer 7 + functionality, and that each Service of type `LoadBalancer` has direct + costs in many cases. In other words, Service allows Ana to rely on the + cluster provider to create the load balancer, while forcing Ana to shoulder + the burden of basically everything else. ### Debugging and Visibility @@ -156,15 +216,16 @@ Ana has easy access to this information, and that it's clear enough for her to understand, is clearly important for many more reasons than just default Gateways. +[Ana]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana [Chihiro]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro [Ian]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian ## API -Most of the API work for this GEP is TBD at this point. The challenge is to -find a way to allow Ana to use Routes without requiring her to specify the -Gateway explicitly, while still allowing Chihiro and Ian to retain control -over the Gateway and its configuration. +The main challenge in the API design is to find a way to allow Ana to use +Routes without requiring her to specify the Gateway explicitly, while still +allowing Chihiro and Ian to retain control over Gateways and their +configurations. An additional concern is CD tools and GitOps workflows. In very broad terms, these tools function by applying manifests from a Git repository to a @@ -184,15 +245,371 @@ Gateway controller write a new `parentRefs` stanza to the resource. There has been (much!) [discussion] about whether the ideal API for this feature will mutate the `parentRefs` of a Route using a default Gateway to reflect the Gateway chosen, or whether it should not, relying instead on the -`status` stanza to carry this information. This is obviously a key point that -will need resolution before this GEP can graduate. +`status` stanza to carry this information. Ultimately, mutating the `spec` of +a Kubernetes resource introduces complexity which we should avoid if it's not +required. Since we can gracefully provide default-Gateway functionality +without mutating `parentRefs`, we will rely on `status` instead of mutating +`parentRefs`. [discussion]: https://github.com/kubernetes-sigs/gateway-api/pull/3852#discussion_r2140117567 ### Gateway for Ingress (North/South) +There are three main aspects to the API design for default Gateways: + +1. Giving Ana a way to indicate that a Route should be defaulted. + +2. Giving Chihiro a way to control which Gateways (if any) will accept + defaulted Routes. + +3. Give anyone with read access to Routes (Ana, Chihiro, or Ian) a way to + enumerate which Routes are bound to the default Gateways. + +We will describe each of these aspects in turn, laying out changes to Gateway +API behaviors and resources that are necessary to support them. **Any behavior +not explicitly discussed in this GEP is intended to remain unchanged;** the +GEP covers **all** intended changes to Gateway API behavior. + +#### 1. Creating a Defaulted Route + +Since Ana must be able to choose whether a Route is defaulted or not, marking +a Route as defaulted must be an active configuration step she takes, rather +than any kind of implicit behavior. To that end, the `CommonRouteSpec` +resource will gain a new field, `useDefaultGateway`, which defines the +_scope_ for the defaulted Route: + +```go +// GatewayDefaultScope defines the set of default scopes that a Gateway +// can claim. At present the only supported scope is "All". +type GatewayDefaultScope string + +const ( + // GatewayDefaultScopeAll indicates that a Gateway can claim absolutely + // any Route asking for a default Gateway. + GatewayDefaultScopeAll GatewayDefaultScope = "All" +) + +type CommonRouteSpec struct { + // ... other fields ... + useDefaultGateway GatewayDefaultScope `json:"useDefaultGateway,omitempty"` +} +``` + +For Ana to indicate that a Route should use a default Gateway, she MUST set +the Route's `spec.useDefaultGateway` to the desired scope: + +```yaml +... +spec: + useDefaultGateway: All +``` + +A defaulted Route MUST be accepted only by Gateways that have been configured +with a matching `spec.useDefaultGateway` scope. + +A Route MAY include explicit `parentRefs` in addition to setting +`spec.useDefaultGateway`. In this case, the Route will be a candidate for +being bound to default Gateways, but it will also be bound to its +explicitly-specified `parentRefs`. This allows Ana to create a single Route +that handles N/S traffic via the default Gateways and also handles E/W traffic +via a Service, for example. + +All other characteristics of a defaulted Route MUST behave the same as if all +default Gateways were explicitly specified in `parentRefs`. + +##### Examples + +**Simple N/S Route**: The following HTTPRoute would route _all_ HTTP traffic +arriving at any default Gateway to `my-service` on port 80: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: my-route +spec: + useDefaultGateway: All + rules: + - backendRefs: + - name: my-service + port: 80 +``` + +**N/S and E/W Route**: The following HTTPRoute would be bound to both any +default Gateways and to a Service named `face` in the `faces` namespace, +permitting a single Route to handle both N/S traffic (via the default Gateway) +and E/W traffic (via the Service): + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: ns-ew-route +spec: + useDefaultGateway: All + parentRefs: + - kind: Service + name: face + namespace: faces + rules: + - backendRefs: + - name: face + port: 80 +``` + +**Multiple Gateways**: A defaulted Route MAY both set `useDefaultGateway` and +name other Gateways in `parentRefs`, although this is not expected to be +common in practice: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: multi-gateway-route +spec: + useDefaultGateway: All + parentRefs: + - kind: Gateway + name: my-gateway + namespace: default + rules: + - backendRefs: + - name: my-service + port: 80 +``` + +##### `status` for a Defaulted Route + +When a defaulted Route is claimed by a default Gateway, the Gateway MUST use +`status.parents` to announce that it has claimed the Route, for example: + +```yaml +status: + parents: + - name: my-default-gateway + namespace: default + controllerName: gateway.networking.k8s.io/some-gateway-controller + conditions: + - type: Accepted + status: "True" + lastTransitionTime: "2025-10-01T12:00:00Z" + message: "Route is bound to default Gateway" +``` + +##### Other Considerations + +A default Gateway MUST NOT modify the `parentRefs` of a defaulted Route to +indicate that the Route has been claimed by a default Gateway. This becomes +important if the set of default Gateways changes, or (in some situations) if +GitOps tools are in play. + +If there are no default Gateways in the cluster, `spec.useDefaultGateway` MUST +be treated as if it were set to `false` in all Routes, parallel to the +situation where a Route specifies a Gateway by name, but no Gateway of that +name exists in the cluster. + +#### 2. Controlling which Gateways accept Defaulted Routes + +Since Chihiro must be able to control which Gateways accept defaulted Routes, +configuring a Gateway to accept defaulted Routes must be an active +configuration step taken by Chihiro, rather than any kind of implicit +behavior. To that end, the Gateway resource will gain a new field, +`spec.defaultScope`: + +```go +type GatewaySpec struct { + // ... other fields ... + DefaultScope GatewayDefaultScope `json:"defaultScope,omitempty"` +} +``` + +Again, the only currently-defined scope is `All`. + +If `spec.defaultScope` is set, the Gateway MUST claim Routes that have set +`spec.useDefaultGateway` to a matching value (subject to the usual Gateway API +rules about which Routes may be bound to a Gateway), and it MUST update its +own `status` with a `condition` of type `DefaultGateway` and `status` true to +indicate that it is a default Gateway and what its scope is, for example: + +```yaml +status: + conditions: + - type: DefaultGateway + status: "True" + lastTransitionTime: "2025-10-01T12:00:00Z" + message: "Gateway has default scope All" +``` + +If `spec.defaultScope` is not present, the Gateway MUST NOT claim Routes that +do not name it specifically in `parentRefs`, and it MUST NOT set the +`DefaultGateway` condition in its `status`. + +##### Access to a Default Gateway + +The rules for which Routes may bind to a Gateway do not change for a default +Gateway. In particular, if a default Gateway should accept Routes from other +namespaces, then it MUST include the appropriate `AllowedRoutes` definition, +and without such an `AllowedRoutes`, a default Gateway MUST accept only Routes +from its own namespace. + +##### Behavior with No Default Gateway + +If no Gateway has `spec.defaultScope` set, then all Gateways MUST ignore +`spec.useDefaultGateway` in all Routes. A Route will be bound to only those Gateways that it specifically names in `parentRefs` entries. + +##### Deleting a Default Gateway + +Deleting a default Gateway MUST behave the same as deleting any other Gateway: +all Routes that were bound to that Gateway MUST be unbound, and the `Accepted` +conditions in the `status` of those Routes SHOULD be removed. + +##### Multiple Default Gateways + +Support for multiple default Gateways in a cluster was not one of the original +goals of this GEP. However, allowing Chihiro full control over which Gateways +accept defaulted Routes - including being able to change the set of default +Gateways at runtime, without requiring downtime - has always been a goal, and +this turns out to require support for multiple default Gateways. + +Kubernetes itself will not prevent setting `spec.defaultScope` on multiple +Gateways in a cluster, and it also doesn't support any atomic swap mechanisms. +If we want to enforce only a single default Gateway, the Gateway controllers +will have to implement that enforcement logic. There are three possible +options here. + +1. Don't bother with any enforcement logic. + + In this case, a Route that sets `spec.useDefaultGateway` would be bound to + _all_ Gateways that have `spec.defaultScope` set a matching scope. Since + Gateway API already allows a Route to be bound to multiple Gateways, and + the Route `status` is already designed for it, this should function + without difficulty. + +2. Treat multiple Gateways with `spec.defaultScope` set as if no Gateway has + `spec.defaultScope` set. + + If we assume that all Gateway controllers in a cluster can see all the + Gateways in the cluster, then detecting that multiple Gateways have + `spec.defaultScope` set is relatively straightforward. + + In this case, every Gateway with `spec.defaultScope` set would ignore it, + with the final effect being the same as if no Gateway had + `spec.defaultScope` set: all Gateways would ignore + `spec.useDefaultGateway` in all Routes, and each Gateway would only accept + Routes that explicitly named it in `parentRefs`. + + Each Gateway with `spec.defaultScope` set would also update its `status` + with a `condition` of type `DefaultGateway` and `status` false to indicate + that it is not the default Gateway, for example: + + ```yaml + status: + conditions: + - type: DefaultGateway + status: "False" + lastTransitionTime: "2025-10-01T12:00:00Z" + message: "Multiple Gateways are marked as default" + ``` + +3. Perform conflict resolution as with Routes. + + In this case, the oldest Gateway with `spec.defaultScope` set would be + considered the only default Gateway. That oldest Gateway would be the only + one that honors `spec.useDefaultGateway` in Routes, and all other Gateways + with `spec.defaultScope` set would ignore `spec.useDefaultGateway` in + every Route. + + The oldest default Gateway would update its `status` to reflect that it + the default Gateway; all other Gateways with `spec.defaultScope` set to + `true` will update their `status` as in Option 2. + +Unfortunately, option 2 will almost certainly cause downtime in any case where +Chihiro wants to change the implementation behind a default Gateway: + +- If Chihiro deletes the old Gateway resource before creating the new one, + then all routes using that Gateway will be unbound during the time between + deletion and recreation, resulting in errors for any requests using those + Routes. + +- If Chihiro creates the new Gateway resource before deleting the old one, + then all Routes using the old default Gateway will still be unbound during + the time that both Gateways exist. + +Option 3 gives Chihiro a way to change the default Gateway without downtime: +when they create the new default Gateway resource, it will not take effect +until the old default Gateway resource is deleted. However, it doesn't give +Chihiro any way to test the Routes through the new default Gateway before +deleting the old Gateway. + +Reluctantly, we must therefore conclude that option 1 is the only viable +choice. Therefore: Gateways MUST NOT attempt to enforce a single default +Gateway, and MUST allow Routes that set `spec.useDefaultGateway` to bind to +_all_ Gateways that have `spec.defaultScope` set a matching scope. This is +simplest to implement, it permits zero-downtime changes to the default +Gateway, it allows for testing of the new default Gateway before the old one +is deleted, and it doesn't cause trouble with respect to security posture +(since Ana already accepts that she's giving up some control over how her +Routes are handled when she's using default Gateways). + +##### Changes in Functionality + +If Chihiro changes a default Gateway to a different implementation that does +not support all the functionality of the previous default Gateway, then the +Routes that were bound to the previous default Gateway will no longer function +as expected. This is not a new problem: it already exists when Ana changes a +Route's `parentRefs`, or when Chihiro changes the implementation of a Gateway +that is explicitly specified in a Route's `parentRefs`. + +At present, we do not propose any solution to this problem, other than to note +that `gwctl` or similar tools SHOULD be able to show Ana not just the Gateways +to which a Route is bound, but also the features supported by those Gateways. +This will at least give Ana some visibility into whether she's trying to use +Gateways that don't support a feature that she needs. This is a definitely an +area for future work, and it is complicated by the fact that Ana may not have +access to read Gateway resources in the cluster at all. + +##### Listeners, ListenerSets, and Merging + +Setting `spec.defaultScope` on a Gateway affects which Routes will bind to the +Gateway, not where the Gateway listens for traffic. As such, setting +`spec.defaultScope` MUST NOT alter a Gateway's behavior with respect to +Listeners, ListenerSets, or merging. + +In the future, we may want to consider allowing default ListenerSets rather +than only default Gateways, but that is not in scope for this GEP. Even if it +is considered later, the guiding principle SHOULD be that `spec.defaultScope` +SHOULD NOT affect where a Gateway listens for traffic or whether it can be +merged with other Gateways. + +#### 4. Enumerating Routes Bound to Default Gateways + +To enumerate Routes bound to the default Gateways, any of Ana, Chihiro, or Ian +can look for Routes that set `spec.useDefaultGateway` to `true`, and then +check the `status.parents` of those Routes to see if the Route has been +claimed. Since this will also show _which_ Gateways have claimed a given +defaulted Route, it neatly solves the problem of allowing Ana to determine +which default Gateway(s) her Route is using even if she doesn't have RBAC to +query Gateway resources directly. + +While this is possible with `kubectl get -o yaml`, it's not exactly a friendly +user experience, so adding this functionality to a tool like `gwctl` would be +a dramatic improvement. In fact, looking at the `status` of a Route is very +much something that we should expect any user of Gateway API to do often, +whether or not default Gateways are in play; `gwctl` or something similar +SHOULD be able to show her which Routes are bound to which Gateways in every +case, not just with default Gateways. + ### Gateway For Mesh (East/West) +Mesh traffic is defined by using a Service as a `parentRef` rather than a +Gateway. As such, there is no case where a default Gateway would be used for +mesh traffic. + +As noted above, a Route MAY both set `spec.useDefaultGateway` _and_ include a +`Service` `parentRef` entry, allowing a single Route to handle both N/S and +E/W traffic. In this case, the Route will be bound to both the default Gateway +and the mesh, and the `status` will show both parents. + ## Conformance Details #### Feature Names @@ -204,14 +621,36 @@ not seem like a good choice. ### Conformance tests +TBD. + ## Alternatives -A possible alternative API design is to modify the behavior of Listeners or -ListenerSets; rather than having a "default Gateway", perhaps we would have -"[default Listeners]". One challenge here is that the Route `status` doesn't -currently expose information about which Listener is being used, though it -does show which Gateway is being used. +- A possible alternative API design is to modify the behavior of Listeners or + ListenerSets; rather than having a "default Gateway", perhaps we would have + "[default Listeners]". One challenge here is that the Route `status` doesn't + currently expose information about which Listener is being used, though it + does show which Gateway is being used. [default Listeners]: https://github.com/kubernetes-sigs/gateway-api/pull/3852#discussion_r2149056246 +- We could define the default Gateway as a Gateway with a magic name, e.g. + "default". This doesn't actually make things that much simpler for Ana + (she'd still have to specify `parentRefs`), and it raises questions about + Chihiro's ability to control which Routes can bind to the default Gateway, + as well as how namespacing would work -- it's especially unhelpful for Ana + if she has to know the namespace of the default Gateway in order to use it. + + (Also, this is a breaking change if Chihiro has already created a + non-default Gateway with whatever name we choose to use for the convention.) + +- A default Gateway could overwrite a defaulted Route's `parentRefs` to point + to the default Gateway. The main challenge with this approach is that once + the `parentRefs` are overwritten, it's no longer possible to know what Ana + originally intended. Using the `status` to indicate that the Route is bound + to the default Gateway instead both preserves Ana's original intent and also + makes it possible to change the default Gateway without requiring Ana to + recreate all her Routes. + ## References + +TBD. diff --git a/geps/gep-3793/metadata.yaml b/geps/gep-3793/metadata.yaml index 060426f033..db611f5988 100644 --- a/geps/gep-3793/metadata.yaml +++ b/geps/gep-3793/metadata.yaml @@ -2,7 +2,7 @@ apiVersion: internal.gateway.networking.k8s.io/v1alpha1 kind: GEPDetails number: 3793 name: Default Gateways -status: Provisional +status: Implementable # Any authors who contribute to the GEP in any way should be listed here using # their GitHub handle. authors: diff --git a/mkdocs.yml b/mkdocs.yml index 7765e320d3..d29e212746 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -132,10 +132,10 @@ nav: - geps/gep-2648/index.md - geps/gep-3779/index.md - geps/gep-3792/index.md - - geps/gep-3793/index.md - Implementable: - geps/gep-91/index.md - geps/gep-3567/index.md + - geps/gep-3793/index.md - Experimental: - geps/gep-1619/index.md - geps/gep-1713/index.md From d3b3a089087ac7767dd54bf79eda24870045f324 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:18:30 -0700 Subject: [PATCH 105/224] build(deps): bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#3957) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.2. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.74.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index e02beb946a..2ef20f67d1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/stretchr/testify v1.10.0 golang.org/x/net v0.41.0 golang.org/x/sync v0.16.0 - google.golang.org/grpc v1.73.0 + google.golang.org/grpc v1.74.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.6 k8s.io/api v0.33.3 @@ -34,7 +34,7 @@ require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect 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 @@ -70,14 +70,14 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/mod v0.25.0 // indirect - golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.26.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.33.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 60714d401a..7050b8ff32 100644 --- a/go.sum +++ b/go.sum @@ -29,8 +29,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -156,16 +156,16 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -191,8 +191,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -227,10 +227,10 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From 08b0c9b36376db6b26c928e0e08d187e83f64f89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:36:29 -0700 Subject: [PATCH 106/224] build(deps): bump mkdocs-material in /hack/mkdocs/image (#3959) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.15 to 9.6.16. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.15...9.6.16) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.16 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index a075a43182..7a5fc4adde 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -10,7 +10,7 @@ MarkupSafe==3.0.2 mkdocs==1.6.1 mkdocs-awesome-pages-plugin==2.10.1 mkdocs-macros-plugin==1.3.7 -mkdocs-material==9.6.15 +mkdocs-material==9.6.16 mkdocs-redirects==1.2.2 mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 From 0f6f9a35677b86ced94e1ebf5060471fd8e75e75 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 30 Jul 2025 12:42:29 -0400 Subject: [PATCH 107/224] Mesh resource definition (#3950) * GEP-3949, Mesh resource Signed-off-by: Flynn * Tweak punctuation Signed-off-by: Flynn * Update to experimental API group and resource name Signed-off-by: Flynn * More tweak Signed-off-by: Flynn * Indentation fix Signed-off-by: Flynn * Note that changing GAMMA's position on multiple meshes is a non-goal Signed-off-by: Flynn * Review feedback Signed-off-by: Flynn * Fix list-element indentation Signed-off-by: Flynn * Add a mkdocs.yml entry. :man_facepalming: Signed-off-by: Flynn * Review feedback Signed-off-by: Flynn * Initial type definition Signed-off-by: Flynn * Drop comment that was breaking rendering? Signed-off-by: Flynn * Tabs -> spaces Signed-off-by: Flynn * Implementable, not Provisional Signed-off-by: Flynn * Fix the other place a kubebuilder default was breaking rendering Signed-off-by: Flynn * Tweak Signed-off-by: Flynn * Formatting fixes Signed-off-by: Flynn * Review feedback. Signed-off-by: Flynn * Review feedback Signed-off-by: Flynn * :man_facepalming: Cluster-scoped resources don't have namespaces. Signed-off-by: Flynn --------- Signed-off-by: Flynn --- geps/gep-3792/index.md | 32 +-- geps/gep-3949/index.md | 539 ++++++++++++++++++++++++++++++++++++ geps/gep-3949/metadata.yaml | 34 +++ mkdocs.yml | 2 +- 4 files changed, 590 insertions(+), 17 deletions(-) create mode 100644 geps/gep-3949/index.md create mode 100644 geps/gep-3949/metadata.yaml diff --git a/geps/gep-3792/index.md b/geps/gep-3792/index.md index 802d729c97..2441074466 100644 --- a/geps/gep-3792/index.md +++ b/geps/gep-3792/index.md @@ -42,10 +42,10 @@ In this GEP: wrangling the mTLS meshes! Supporting non-mTLS meshes will be a separate GEP. - **Note:** It's important to separate mTLS and HTTPS here. Saying that the - mTLS meshes use mTLS for secure communication does not preclude them from - using custom protocols on top of mTLS, and certainly does not mean that - they must use only HTTPS. + **Note:** It's important to separate mTLS and HTTPS here. Saying that the + mTLS meshes use mTLS for secure communication does not preclude them from + using custom protocols on top of mTLS, and certainly does not mean that + they must use only HTTPS. 3. _Authentication_ is the act of verifying the identity of some _principal_; what the principal actually is depends on context. For this GEP we will @@ -56,21 +56,21 @@ In this GEP: can't trust what the OCG says about the user unless the OCG successfully authenticates itself as a workload. - **Note:** A single workload will have only one identity, but in practice we - often see a single identity being used for multiple workloads (both because - multiple replicas of a single workload need to share the same identity, and - because some low-security workloads may be grouped together under a single - identity). + **Note:** A single workload will have only one identity, but in practice we + often see a single identity being used for multiple workloads (both because + multiple replicas of a single workload need to share the same identity, and + because some low-security workloads may be grouped together under a single + identity). 4. Finally, we'll distinguish between _inbound_ and _outbound_ behaviors. - Inbound behaviors are those that are applied to a request _arriving_ at a - given workload. Authorization and rate limiting are canonical examples - of inbound behaviors. + Inbound behaviors are those that are applied to a request _arriving_ at a + given workload. Authorization and rate limiting are canonical examples + of inbound behaviors. - Outbound behaviors are those that are applied to a request _leaving_ a - given workload. Load balancing, retries, and circuit breakers are canonical - examples of outbound behaviors. + Outbound behaviors are those that are applied to a request _leaving_ a + given workload. Load balancing, retries, and circuit breakers are canonical + examples of outbound behaviors. ## Goals @@ -197,7 +197,7 @@ is sent. (For example, Linkerd requires the originating proxy to send transport metadata right after the TLS handshake, and it will reject a connection which doesn't do that correctly.) -#### 4. The Discovery Problem +#### 3. The Discovery Problem When using a mesh, not every workload in the cluster is required to be meshed (for example, it's fairly common to have some namespaces meshed and other diff --git a/geps/gep-3949/index.md b/geps/gep-3949/index.md new file mode 100644 index 0000000000..26f5f2056c --- /dev/null +++ b/geps/gep-3949/index.md @@ -0,0 +1,539 @@ +# GEP-3949: Mesh Resource + +* Issue: [#3949](https://github.com/kubernetes-sigs/gateway-api/issues/3949) +* Status: Implementable + +(See [status definitions](../overview.md#gep-states).) + +[Chihiro]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#chihiro +[Ian]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ian +[Ana]: https//gateway-api.sigs.k8s.io/concepts/roles-and-personas/#ana + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14 ([RFC8174]) when, and +only when, they appear in all capitals, as shown here. + +[RFC8174]: https://www.rfc-editor.org/rfc/rfc8174 + +## User Story + +**[Chihiro] and [Ian] would like a Mesh resource, +parallel to the Gateway resource, +that allows them to +supply mesh-wide configuration +and +shows what features +a given mesh implementation supports.** + +## Background + +Gateway API has long had a GatewayClass resource +that represents a class of Gateways +that can be instantiated in a cluster. +GatewayClass both +allows configuring the class as a whole +and provides a way for [Chihiro] and [Ian] to see +what features Gateways in that class support. +We have, +to date, +avoided such a resource for meshes, +but as we work on +improving mesh conformance tests and reports +and start work on +supporting Out-of-Cluster Gateways (OCGs), +we will need ways to +show what features a given mesh implementation supports +and represent mesh-wide configuration. + +This GEP therefore defines a Mesh resource +which represents a running instance of a service mesh, +allowing [Chihiro] and [Ian] to +supply mesh-wide configuration, +and allowing the mesh implementation +to indicate what features it supports. + +Unlike Gateways, we do not expect +multiple instances of meshes to be instantiated +in a single cluster. +This implies that a MeshClass resource is not needed; +instead, we will simply define a Mesh resource. + +## Goals + +- Define a Mesh resource + that allows for + mesh-wide configuration + and feature discovery. + +- Avoid making it more difficult for [Chihiro] and [Ian] + to adopt a mesh + (or to experiment with adopting a mesh). + +## Non-Goals + +- Support meshes interoperating with each other. + + As always, + we will not rule out future work + in this area, + but it is out of scope + for this GEP. + +- Support off-cluster gateways. + + This is covered in a separate GEP + and will not be discussed here. + +- Change GAMMA's position on + multiple meshes running simultaneously + in a single cluster. + + GAMMA has always taken the position + that multiple meshes running simultaneously + in a single cluster + is not an explicit goal, but neither is it forbidden. + This GEP does not change that position. + +## API + +The purpose +of the Mesh resource +is to support both +mesh-wide configuration +as well as feature discovery. +However, +as of the writing of this GEP, +there is +no mesh-wide configuration +that is portable across implementations. +Therefore, +the Mesh resource +is currently pretty simple: + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XMesh +metadata: + name: one-mesh-to-mesh-them-all +spec: + # required, must be domain-prefixed + controllerName: one-mesh.example.com/one-mesh + parametersRef: + # optional ParametersReference + ... +``` + +- The Mesh resource is cluster-scoped, + so there is no `metadata.namespace` field. + +- Although we call this the Mesh resource, + as an experimental API + it must be named XMesh + in the `gateway.networking.x-k8s.io` API group. + + When the API graduates to standard, + it will be renamed to `Mesh` + in the `gateway.networking.k8s.io` API group. + +- The `controllerName` field + is analogous to + the `controllerName` field + in the GatewayClass resource: + it defines the name + of the mesh implementation + that is responsible for + this Mesh resource. + + A given mesh implementation will define its controller name + at build time. + It MUST be a domain-prefixed path, + for example `linkerd.io/linkerd` or `istio.io/istio`. + It MUST NOT be empty. + It MAY be configurable at runtime, + although this is not expected to be common. + + Although we expect + that there will be + only one mesh + in a given cluster, the + `controllerName` field + MUST be supplied, + and a given mesh implementation + MUST ignore + a Mesh resource + that does not have + a `controllerName` field + that matches its own name. + +- The `parametersRef` field + is analogous to + the `parametersRef` field + in the GatewayClass resource: + it allows optionally specifying + a reference to a resource + that contains configuration + specific to the mesh + implementation. + +### `status` + +The `status` stanza +of the Mesh resource +is used to indicate +whether the Mesh resource +has been accepted by +a mesh implementation, +whether the mesh is +ready to use, +and +what features +the mesh supports. + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: XMesh +metadata: + name: one-mesh-to-mesh-them-all +spec: + controllerName: one-mesh.example.com/one-mesh +status: + conditions: + # MUST include Accepted condition if the Mesh resource is active. + - type: Accepted # Becomes true when the controller accepts the Mesh resource + status: "True" + reason: Accepted + lastTransitionTime: "2023-10-01T12:00:00Z" + message: Mesh resource accepted by one-mesh v1.2.3 in namespace one-mesh + ... + supportedFeatures: + # List of SupportedFeature + - name: MeshHTTPRoute + - name: MeshConsumerRoute + - name: OffClusterGateway + ... +``` + +Although GAMMA does not fully support multiple meshes +running in the same cluster at the same time, +meshes still MUST provide +human-readable information +in the `Accepted` condition +about which mesh instance +has claimed a given Mesh resource. +This information is meant to be used +by [Chihiro] and [Ian] as confirmation +that the mesh instance +is doing what they expect it to do. + +Mesh implementations MUST +reject Mesh resources in which `spec.parametersRef` +references a resource that does not exist +or is not supported by the mesh implementation, +setting the `Reason` to `InvalidParameters`. + +The mesh implementation +MUST set `status.SupportedFeatures` +to indicate which features +the mesh supports. + +### Life Cycle + +One of the explicit goals of this GEP +is to avoid making it more difficult for [Chihiro] and [Ian] +to adopt a mesh. +In turn, this implies that we MUST NOT require [Chihiro] or [Ian] +to manually create a Mesh resource in order to use a mesh. + +The simplest way to achieve this is +for the mesh implementation to create a Mesh resource +when it starts up, +if one does not already exist +with a matching `controllerName` field. +This raises questions around +what the Mesh resource should be named, +and how the mesh implementation can avoid overwriting +any modifications [Chihiro] or [Ian] make +to the Mesh resource after it is created. + +To manage these concerns +while still minimizing added friction, +mesh implementations MUST define a default `metadata.name` +for the Mesh resource they will look for, +and SHOULD allow overriding this name at install time. +This default name SHOULD be +an obvious derivative of the mesh implementation name, +such as "linkerd" or "istio"; +its purpose is to make it easy for [Chihiro] and [Ian] +to find the Mesh resource +while also allowing for the possibility +that there will need to be more than one +Mesh resource in a cluster. + +At startup, then: + +- The mesh implementation MUST look for a Mesh resource + with the expected `metadata.name` field. + +- If no Mesh resource exists with the expected `metadata.name`, + the implementation MUST create a Mesh resource + with the expected `metadata.name` + and `spec.controllerName` fields. + + - The mesh MUST NOT set any other fields + in the `spec` of the Mesh resource + that it creates. + + In particular, the mesh MUST NOT set `parametersRef` + when it creates the Mesh resource. + +- Otherwise + (a Mesh resource already exists with the expected `metadata.name`), + the implementation MUST NOT modify the `spec` + of that Mesh resource + in **any way**. + Instead, it MUST check the `spec.controllerName` field: + + - If the Mesh resource has a matching `spec.controllerName` field: + + - The implementation MUST set the `status` stanza + of the Mesh resource + to indicate whether or not it has accepted the Mesh resource + and, if accepted, what features the mesh supports. + + - Otherwise + (the Mesh resource does not have + a matching `spec.controllerName` field): + + - The implementation MUST NOT modify the Mesh resource + in any way, + and it SHOULD warn the user + (in whatever way is appropriate for the mesh) + that there is a mismatch in the Mesh resource + +```mermaid +flowchart TD + Start{Does a Mesh resource with a matching name exist?} + Start -->|Yes| Match + Start -->|No| NoMatch + Match{Does the controllerName also match?} + Match -->|No| WarnNoModify + Match -->|Yes| UpdateStat + NoMatch[Create a new Mesh resource] --> CheckCreate + CheckCreate{Did creation succeed?} + CheckCreate -->|Yes| UpdateStat + CheckCreate -->|No| Warn + UpdateStat[Update status] + Warn[Warn] + WarnNoModify[Warn and don't modify] +``` + +If, at the end of this process, +there is no Mesh resource with both +a matching `metadata.name` and +a matching `spec.controllerName`, +the implementation MUST act as if +a Mesh resource was found with a empty `spec` +(other than the `controllerName` field). +Optional configuration MUST remain in its default state, +and features that require a Mesh resource +(such as OCG support) +MUST NOT be enabled. + +Obviously, if no matching Mesh resource exists, +the mesh will not be able to publish support features, +which may lead to assumptions +that the mesh does not support any features. + +The mesh implementation MUST NOT, +under any circumstances, +modify the `spec` of a Mesh resource +other than by creating a new Mesh resource +when one does not exist. + +Mesh implementations SHOULD +respond to changes in the Mesh resource +without requiring the mesh to be restarted. + +### API Type Definitions + +```go +// Mesh is a Cluster level resource. +type Mesh struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of Mesh. + Spec MeshSpec `json:"spec"` + + // Status defines the current state of Mesh. + // + // Implementations MUST populate status on all Mesh resources which + // specify their controller name. + // + // Defaults to Accepted condition with status Unknown and reason Pending. + Status MeshStatus `json:"status,omitempty"` +} + +// MeshSpec defines the desired state of a Mesh. +type MeshSpec struct { + // ControllerName is the name of the controller that is managing this + // Mesh. The value of this field MUST be a domain prefixed path. + // + // Example: "example.com/awesome-mesh". + // + // This field is not mutable and cannot be empty. + // + // Support: Core + // + // +kubebuilder:validation:XValidation:message="Value is immutable",rule="self == oldSelf" + ControllerName string `json:"controllerName"` + + // ParametersRef is an optional reference to a resource that contains + // implementation-specific for this Mesh. If no implementation-specific + // parameters are needed, this field MUST be omitted. + // + // ParametersRef can reference a standard Kubernetes resource, i.e. + // ConfigMap, or an implementation-specific custom resource. The resource + // can be cluster-scoped or namespace-scoped. + // + // If the referent cannot be found, refers to an unsupported kind, or when + // the data within that resource is malformed, the Mesh MUST be rejected + // with the "Accepted" status condition set to "False" and an + // "InvalidParameters" reason. + // + // Support: Implementation-specific + // + // +optional + ParametersRef *ParametersReference `json:"parametersRef,omitempty"` +} + +// MeshConditionType is the type for status conditions on Mesh resources. +// This type should be used with the MeshStatus.Conditions field. +type MeshConditionType string + +// MeshConditionReason defines the set of reasons that explain why a +// particular Mesh condition type has been raised. +type MeshConditionReason string + +const ( + // This condition indicates whether the Mesh has been accepted by the + // controller requested in the `spec.controller` field. + // + // This condition defaults to Unknown, and MUST be set by a controller + // when it sees a Mesh using its controller string. The status of this + // condition MUST be set to True if the controller will accept the Mesh + // resource. Otherwise, this status MUST be set to False. If the status + // is set to False, the controller MUST set a Message and Reason as an + // explanation. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidParameters" + // + // Controllers should prefer to use the values of MeshConditionReason + // for the corresponding Reason, where appropriate. + MeshConditionStatusAccepted MeshConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // true. + MeshConditionReasonAccepted MeshConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the Mesh + // was not accepted because the parametersRef field refers to + // * a namespaced resource but the Namespace field is not set, or + // * a cluster-scoped resource but the Namespace field is set, or + // * a nonexistent object, or + // * an unsupported resource or kind, or + // * an existing resource but the data within that resource is malformed. + MeshConditionReasonInvalidParameters MeshConditionReason = "InvalidParameters" + + // This reason is used with the "Accepted" condition when the + // requested controller has not yet made a decision about whether + // to accept the Mesh. It is the default Reason on a new Mesh. + MeshConditionReasonPending MeshConditionReason = "Pending" +) + +// MeshStatus is the current status for the Mesh. +type MeshStatus struct { + // Conditions is the current status from the controller for + // this Mesh. + // + // Controllers should prefer to publish conditions using values + // of MeshConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // Defaults to Accepted condition with status Unknown and reason Pending. + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // SupportedFeatures is the set of features the Mesh support. + // It MUST be sorted in ascending alphabetical order by the Name key. + // +optional + // +listType=map + // +listMapKey=name + // + // +kubebuilder:validation:MaxItems=64 + SupportedFeatures []SupportedFeature `json:"supportedFeatures,omitempty"` +} + +// +kubebuilder:object:root=true + +// MeshList contains a list of Mesh +type MeshList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Mesh `json:"items"` +} +``` + +## Conformance Details + +TBA. + +#### Feature Names + +No feature name is defined +for the Mesh resource itself; +filling out the `status` stanza +of the Mesh resource +is a conformance requirement, +and is sufficient indication +that the Mesh resource is supported. + +### Conformance tests + +TBA. + +## Alternatives + +We did not find any +particularly compelling alternatives +to having a Mesh resource +to meet these needs. +We considered having both +MeshClass and Mesh resources, +but decided that +there was no clear need for both, +and that a Mesh resource +better served the use cases. + +If a MeshClass resource +is later defined, +the Mesh resource +will need to be updated. +One potential approach to such an update might be: + +- Add a `meshClassName` field to the Mesh resource; +- Deprecate the `controllerName` field; and +- Define that a Mesh resource with both fields set is invalid. + +## References + +TBA. diff --git a/geps/gep-3949/metadata.yaml b/geps/gep-3949/metadata.yaml new file mode 100644 index 0000000000..de9c3639e7 --- /dev/null +++ b/geps/gep-3949/metadata.yaml @@ -0,0 +1,34 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3949 +name: Mesh Resource +status: Implementable +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - kflynn + - karthikbox +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/mkdocs.yml b/mkdocs.yml index d29e212746..18393ce4c6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -135,7 +135,7 @@ nav: - Implementable: - geps/gep-91/index.md - geps/gep-3567/index.md - - geps/gep-3793/index.md + - geps/gep-3949/index.md - Experimental: - geps/gep-1619/index.md - geps/gep-1713/index.md From 657b26558bc495d7c35a7a4a2bf5cbd5d0ca6fba Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Thu, 31 Jul 2025 20:27:15 -0300 Subject: [PATCH 108/224] Lint required optional (#3929) * Add missing required markers on gateway types * Add missing required markers on grpcroute types * Add missing required markers on httproute types * Add missing required markers on obj_reference types * Add missing required markers on shared types * Add missing required markers on experimental types * Add missing required markers on v1beta1 types * Add missing required markers on v1alpha3 types * Add missing required markers on v1alpha2 types * Enable optionalorrequired linter * Revert objectmeta field doc * Revert minItems changes --- .github/workflows/kal.yml | 3 +++ .golangci-kal.yml | 1 + apis/v1/gateway_types.go | 20 ++++++++++++++++++- apis/v1/gatewayclass_types.go | 10 +++++++++- apis/v1/gatewayclass_types_overrides.go | 1 + apis/v1/grpcroute_types.go | 7 ++++++- apis/v1/httproute_types.go | 17 +++++++++++++++- apis/v1/object_reference_types.go | 8 ++++++++ apis/v1/shared_types.go | 6 ++++++ apis/v1alpha2/policy_types.go | 10 ++++++++++ apis/v1alpha2/tcproute_types.go | 7 ++++++- apis/v1alpha2/tlsroute_types.go | 7 ++++++- apis/v1alpha2/udproute_types.go | 7 ++++++- apis/v1alpha3/backendtlspolicy_types.go | 11 +++++++++- apis/v1alpha3/tlsroute_types.go | 6 +++++- apis/v1beta1/referencegrant_types.go | 15 +++++++++++++- apisx/v1alpha1/shared_types.go | 3 +++ apisx/v1alpha1/xbackendtrafficpolicy_types.go | 6 +++++- apisx/v1alpha1/xlistenerset_types.go | 15 +++++++++++++- ....networking.k8s.io_backendtlspolicies.yaml | 1 + .../gateway.networking.k8s.io_gateways.yaml | 4 ++++ .../gateway.networking.k8s.io_grpcroutes.yaml | 1 + .../gateway.networking.k8s.io_httproutes.yaml | 2 ++ .../gateway.networking.k8s.io_tcproutes.yaml | 3 +++ .../gateway.networking.k8s.io_tlsroutes.yaml | 6 ++++++ .../gateway.networking.k8s.io_udproutes.yaml | 3 +++ ...king.x-k8s.io_xbackendtrafficpolicies.yaml | 1 + ...way.networking.x-k8s.io_xlistenersets.yaml | 2 ++ .../gateway.networking.k8s.io_grpcroutes.yaml | 1 + .../gateway.networking.k8s.io_httproutes.yaml | 2 ++ pkg/generated/openapi/zz_generated.openapi.go | 8 ++++++-- 31 files changed, 180 insertions(+), 14 deletions(-) diff --git a/.github/workflows/kal.yml b/.github/workflows/kal.yml index d657969f5d..618256e886 100644 --- a/.github/workflows/kal.yml +++ b/.github/workflows/kal.yml @@ -15,6 +15,9 @@ jobs: fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + name: Checkout code + with: + persist-credentials: false - name: Set up Go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0 - name: Install Golang CI Lint diff --git a/.golangci-kal.yml b/.golangci-kal.yml index aad23ab40d..d2b764e868 100644 --- a/.golangci-kal.yml +++ b/.golangci-kal.yml @@ -16,6 +16,7 @@ linters: - "nofloats" # Ensure floats are not used. - "nomaps" # Ensure maps are not used. - "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead. + - "optionalorrequired" # Every field should be marked as `+optional` or `+required`. - "statussubresource" # All root objects that have a `status` field should have a status subresource. - "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once. disable: diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index f54e5d10ce..ea8667af61 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -33,15 +33,18 @@ import ( // Gateway represents an instance of a service-traffic handling infrastructure // by binding Listeners to a set of IP addresses. type Gateway struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of Gateway. + // +required Spec GatewaySpec `json:"spec"` // Status defines the current state of Gateway. // // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +optional Status GatewayStatus `json:"status,omitempty"` } @@ -63,6 +66,7 @@ type GatewayList struct { type GatewaySpec struct { // GatewayClassName used for this Gateway. This is the name of a // GatewayClass resource. + // +required GatewayClassName ObjectName `json:"gatewayClassName"` // Listeners associated with this Gateway. Listeners define @@ -236,6 +240,7 @@ type GatewaySpec struct { // +kubebuilder:validation:XValidation:message="hostname must not be specified for protocols ['TCP', 'UDP']",rule="self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" // +kubebuilder:validation:XValidation:message="Listener name must be unique within the Gateway",rule="self.all(l1, self.exists_one(l2, l1.name == l2.name))" // +kubebuilder:validation:XValidation:message="Combination of port, protocol and hostname must be unique for each listener",rule="self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" + // +required Listeners []Listener `json:"listeners"` // Addresses requested for this Gateway. This is optional and behavior can @@ -333,6 +338,7 @@ type Listener struct { // Gateway. // // Support: Core + // +required Name SectionName `json:"name"` // Hostname specifies the virtual hostname to match for protocol types that @@ -390,11 +396,13 @@ type Listener struct { // same port, subject to the Listener compatibility rules. // // Support: Core + // +required Port PortNumber `json:"port"` // Protocol specifies the network protocol this listener expects to receive. // // Support: Core + // +required Protocol ProtocolType `json:"protocol"` // TLS is the TLS configuration for the Listener. This field is required if @@ -637,6 +645,7 @@ type FrontendTLSValidation struct { // // +kubebuilder:validation:MaxItems=8 // +kubebuilder:validation:MinItems=1 + // +required CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` } @@ -721,6 +730,7 @@ type RouteGroupKind struct { Group *Group `json:"group,omitempty"` // Kind is the kind of the Route. + // +required Kind Kind `json:"kind"` } @@ -764,6 +774,7 @@ type GatewayStatusAddress struct { // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 + // +required Value string `json:"value"` } @@ -873,15 +884,18 @@ type GatewayInfrastructure struct { // configuration resource within the namespace. type LocalParametersReference struct { // Group is the group of the referent. + // +required Group Group `json:"group"` // Kind is kind of the referent. + // +required Kind Kind `json:"kind"` // Name is the name of the referent. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 + // +required Name string `json:"name"` } @@ -1096,6 +1110,7 @@ const ( // ListenerStatus is the status associated with a Listener. type ListenerStatus struct { // Name is the name of the Listener that this status corresponds to. + // +required Name SectionName `json:"name"` // SupportedKinds is the list indicating the Kinds supported by this @@ -1109,6 +1124,7 @@ type ListenerStatus struct { // reference the valid Route kinds that have been specified. // // +kubebuilder:validation:MaxItems=8 + // +required SupportedKinds []RouteGroupKind `json:"supportedKinds"` // AttachedRoutes represents the total number of Routes that have been @@ -1128,6 +1144,7 @@ type ListenerStatus struct { // // Uses for this field include troubleshooting Route attachment and // measuring blast radius/impact of changes to a Listener. + // +required AttachedRoutes int32 `json:"attachedRoutes"` // Conditions describe the current condition of this listener. @@ -1135,6 +1152,7 @@ type ListenerStatus struct { // +listType=map // +listMapKey=type // +kubebuilder:validation:MaxItems=8 + // +required Conditions []metav1.Condition `json:"conditions"` } diff --git a/apis/v1/gatewayclass_types.go b/apis/v1/gatewayclass_types.go index 6699e7a18f..655195ce6d 100644 --- a/apis/v1/gatewayclass_types.go +++ b/apis/v1/gatewayclass_types.go @@ -49,10 +49,12 @@ import ( // // GatewayClass is a Cluster level resource. type GatewayClass struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of GatewayClass. + // +required Spec GatewayClassSpec `json:"spec"` // Status defines the current state of GatewayClass. @@ -61,6 +63,7 @@ type GatewayClass struct { // specify their controller name. // // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Pending", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +optional Status GatewayClassStatus `json:"status,omitempty"` } @@ -83,6 +86,7 @@ type GatewayClassSpec struct { // Support: Core // // +kubebuilder:validation:XValidation:message="Value is immutable",rule="self == oldSelf" + // +required ControllerName GatewayController `json:"controllerName"` // ParametersRef is a reference to a resource that contains the configuration @@ -118,15 +122,18 @@ type GatewayClassSpec struct { // configuration resource within the cluster. type ParametersReference struct { // Group is the group of the referent. + // +required Group Group `json:"group"` // Kind is kind of the referent. + // +required Kind Kind `json:"kind"` // Name is the name of the referent. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 + // +required Name string `json:"name"` // Namespace is the namespace of the referent. @@ -287,5 +294,6 @@ type GatewayClassList struct { type FeatureName string type SupportedFeature struct { + // +required Name FeatureName `json:"name"` } diff --git a/apis/v1/gatewayclass_types_overrides.go b/apis/v1/gatewayclass_types_overrides.go index f635084782..8d768fdea0 100644 --- a/apis/v1/gatewayclass_types_overrides.go +++ b/apis/v1/gatewayclass_types_overrides.go @@ -51,6 +51,7 @@ func (s *SupportedFeature) UnmarshalJSON(data []byte) error { // This is solely for the purpose of ensuring backward compatibility and // SHOULD NOT be used elsewhere. type supportedFeatureInternal struct { + // +required Name FeatureName `json:"name"` } diff --git a/apis/v1/grpcroute_types.go b/apis/v1/grpcroute_types.go index 5e77a897c1..c6480c3857 100644 --- a/apis/v1/grpcroute_types.go +++ b/apis/v1/grpcroute_types.go @@ -56,7 +56,8 @@ import ( // Implementations MAY also accept HTTP/2 connections with an upgrade from // HTTP/1, i.e. without prior knowledge. type GRPCRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of GRPCRoute. @@ -64,6 +65,7 @@ type GRPCRoute struct { Spec GRPCRouteSpec `json:"spec,omitempty"` // Status defines the current state of GRPCRoute. + // +optional Status GRPCRouteStatus `json:"status,omitempty"` } @@ -405,12 +407,14 @@ type GRPCHeaderMatch struct { // entries with an equivalent header name MUST be ignored. Due to the // case-insensitivity of header names, "foo" and "Foo" are considered // equivalent. + // +required Name GRPCHeaderName `json:"name"` // Value is the value of the gRPC Header to be matched. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 + // +required Value string `json:"value"` } @@ -521,6 +525,7 @@ type GRPCRouteFilter struct { // +unionDiscriminator // +kubebuilder:validation:Enum=ResponseHeaderModifier;RequestHeaderModifier;RequestMirror;ExtensionRef // + // +required Type GRPCRouteFilterType `json:"type"` // RequestHeaderModifier defines a schema for a filter that modifies request diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 157932e971..96e245c386 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -33,13 +33,16 @@ import ( // used to specify additional processing steps. Backends specify where matching // requests should be routed. type HTTPRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of HTTPRoute. + // +required Spec HTTPRouteSpec `json:"spec"` // Status defines the current state of HTTPRoute. + // +optional Status HTTPRouteStatus `json:"status,omitempty"` } @@ -608,12 +611,14 @@ type HTTPHeaderMatch struct { // Generally, proxies should follow the guidance from the RFC: // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding // processing a repeated header, with special handling for "Set-Cookie". + // +required Name HTTPHeaderName `json:"name"` // Value is the value of HTTP Header to be matched. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 + // +required Value string `json:"value"` } @@ -675,12 +680,14 @@ type HTTPQueryParamMatch struct { // // Users SHOULD NOT route traffic based on repeated query params to guard // themselves against potential differences in the implementations. + // +required Name HTTPHeaderName `json:"name"` // Value is the value of HTTP query param to be matched. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=1024 + // +required Value string `json:"value"` } @@ -830,6 +837,7 @@ type HTTPRouteFilter struct { // +unionDiscriminator // +kubebuilder:validation:Enum=RequestHeaderModifier;ResponseHeaderModifier;RequestMirror;RequestRedirect;URLRewrite;ExtensionRef // + // +required Type HTTPRouteFilterType `json:"type"` // RequestHeaderModifier defines a schema for a filter that modifies request @@ -977,12 +985,14 @@ type HTTPHeader struct { // with an equivalent header name MUST be ignored. Due to the // case-insensitivity of header names, "foo" and "Foo" are considered // equivalent. + // +required Name HTTPHeaderName `json:"name"` // Value is the value of HTTP Header to be matched. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 + // +required Value string `json:"value"` } @@ -1101,6 +1111,7 @@ type HTTPPathModifier struct { // Reason of `UnsupportedValue`. // // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch + // +required Type HTTPPathModifierType `json:"type"` // ReplaceFullPath specifies the value with which to replace the full path @@ -1274,6 +1285,7 @@ type HTTPRequestMirrorFilter struct { // Support: Extended for Kubernetes Service // // Support: Implementation-specific for any other resource + // +required BackendRef BackendObjectReference `json:"backendRef"` // Percent represents the percentage of requests that should be @@ -1356,6 +1368,7 @@ type HTTPCORSFilter struct { // Support: Extended // +listType=set // +kubebuilder:validation:MaxItems=64 + // +optional AllowOrigins []AbsoluteURI `json:"allowOrigins,omitempty"` // AllowCredentials indicates whether the actual cross-origin request allows @@ -1417,6 +1430,7 @@ type HTTPCORSFilter struct { // +listType=set // +kubebuilder:validation:MaxItems=9 // +kubebuilder:validation:XValidation:message="AllowMethods cannot contain '*' alongside other methods",rule="!('*' in self && self.size() > 1)" + // +optional AllowMethods []HTTPMethodWithWildcard `json:"allowMethods,omitempty"` // AllowHeaders indicates which HTTP request headers are supported for @@ -1458,6 +1472,7 @@ type HTTPCORSFilter struct { // // +listType=set // +kubebuilder:validation:MaxItems=64 + // +optional AllowHeaders []HTTPHeaderName `json:"allowHeaders,omitempty"` // ExposeHeaders indicates which HTTP response headers can be exposed diff --git a/apis/v1/object_reference_types.go b/apis/v1/object_reference_types.go index dd507b2136..54e34fa2ed 100644 --- a/apis/v1/object_reference_types.go +++ b/apis/v1/object_reference_types.go @@ -27,12 +27,15 @@ package v1 type LocalObjectReference struct { // Group is the group of the referent. For example, "gateway.networking.k8s.io". // When unspecified or empty string, core API group is inferred. + // +required Group Group `json:"group"` // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // +required Kind Kind `json:"kind"` // Name is the name of the referent. + // +required Name ObjectName `json:"name"` } @@ -60,6 +63,7 @@ type SecretObjectReference struct { Kind *Kind `json:"kind"` // Name is the name of the referent. + // +required Name ObjectName `json:"name"` // Namespace is the namespace of the referenced object. When unspecified, the local @@ -121,6 +125,7 @@ type BackendObjectReference struct { Kind *Kind `json:"kind,omitempty"` // Name is the name of the referent. + // +required Name ObjectName `json:"name"` // Namespace is the namespace of the backend. When unspecified, the local @@ -157,12 +162,15 @@ type BackendObjectReference struct { type ObjectReference struct { // Group is the group of the referent. For example, "gateway.networking.k8s.io". // When set to the empty string, core API group is inferred. + // +required Group Group `json:"group"` // Kind is kind of the referent. For example "ConfigMap" or "Service". + // +required Kind Kind `json:"kind"` // Name is the name of the referent. + // +required Name ObjectName `json:"name"` // Namespace is the namespace of the referenced object. When unspecified, the local diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 226c776372..e874c2f905 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -86,6 +86,7 @@ type ParentReference struct { // Name is the name of the referent. // // Support: Core + // +required Name ObjectName `json:"name"` // SectionName is the name of a section within the target resource. In the @@ -436,6 +437,7 @@ const ( type RouteParentStatus struct { // ParentRef corresponds with a ParentRef in the spec that this // RouteParentStatus struct describes the status of. + // +required ParentRef ParentReference `json:"parentRef"` // ControllerName is a domain/path string that indicates the name of the @@ -451,6 +453,7 @@ type RouteParentStatus struct { // Controllers MUST populate this field when writing status. Controllers should ensure that // entries to status populated with their ControllerName are cleaned up when they are no // longer necessary. + // +required ControllerName GatewayController `json:"controllerName"` // Conditions describes the status of the route with respect to the Gateway. @@ -477,6 +480,7 @@ type RouteParentStatus struct { // +listMapKey=type // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=8 + // +required Conditions []metav1.Condition `json:"conditions,omitempty"` } @@ -499,6 +503,7 @@ type RouteStatus struct { // means the route has not been attached to any Gateway. // // +kubebuilder:validation:MaxItems=32 + // +required Parents []RouteParentStatus `json:"parents"` } @@ -913,6 +918,7 @@ const ( // +kubebuilder:validation:XValidation:message="numerator must be less than or equal to denominator",rule="self.numerator <= self.denominator" type Fraction struct { // +kubebuilder:validation:Minimum=0 + // +required Numerator int32 `json:"numerator"` // +optional diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index bc2ef766a9..b38ff00327 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -38,12 +38,15 @@ const ( // the policy attachment documentation for Gateway API. type LocalPolicyTargetReference struct { // Group is the group of the target resource. + // +required Group Group `json:"group"` // Kind is kind of the target resource. + // +required Kind Kind `json:"kind"` // Name is the name of the target resource. + // +required Name ObjectName `json:"name"` } @@ -55,12 +58,15 @@ type LocalPolicyTargetReference struct { // documentation for Gateway API. type NamespacedPolicyTargetReference struct { // Group is the group of the target resource. + // +required Group Group `json:"group"` // Kind is kind of the target resource. + // +required Kind Kind `json:"kind"` // Name is the name of the target resource. + // +required Name ObjectName `json:"name"` // Namespace is the namespace of the referent. When unspecified, the local @@ -174,6 +180,7 @@ const ( type PolicyAncestorStatus struct { // AncestorRef corresponds with a ParentRef in the spec that this // PolicyAncestorStatus struct describes the status of. + // +required AncestorRef ParentReference `json:"ancestorRef"` // ControllerName is a domain/path string that indicates the name of the @@ -189,10 +196,12 @@ type PolicyAncestorStatus struct { // Controllers MUST populate this field when writing status. Controllers should ensure that // entries to status populated with their ControllerName are cleaned up when they are no // longer necessary. + // +required ControllerName GatewayController `json:"controllerName"` // Conditions describes the status of the Policy with respect to the given Ancestor. // + // +required // +listType=map // +listMapKey=type // +kubebuilder:validation:MinItems=1 @@ -234,5 +243,6 @@ type PolicyStatus struct { // the BackendTLSPolicy. // // +kubebuilder:validation:MaxItems=16 + // +required Ancestors []PolicyAncestorStatus `json:"ancestors"` } diff --git a/apis/v1alpha2/tcproute_types.go b/apis/v1alpha2/tcproute_types.go index e383af495d..99446bedcb 100644 --- a/apis/v1alpha2/tcproute_types.go +++ b/apis/v1alpha2/tcproute_types.go @@ -31,13 +31,16 @@ import ( // listener, it can be used to forward connections on the port specified by the // listener to a set of backends specified by the TCPRoute. type TCPRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of TCPRoute. + // +required Spec TCPRouteSpec `json:"spec"` // Status defines the current state of TCPRoute. + // +optional Status TCPRouteStatus `json:"status,omitempty"` } @@ -47,6 +50,7 @@ type TCPRouteSpec struct { // Rules are a list of TCP matchers and actions. // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -81,6 +85,7 @@ type TCPRouteRule struct { // // Support for weight: Extended // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha2/tlsroute_types.go b/apis/v1alpha2/tlsroute_types.go index f1b3814cf7..5cd56ca201 100644 --- a/apis/v1alpha2/tlsroute_types.go +++ b/apis/v1alpha2/tlsroute_types.go @@ -33,13 +33,16 @@ import ( // If you need to forward traffic to a single target for a TLS listener, you // could choose to use a TCPRoute with a TLS listener. type TLSRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of TLSRoute. + // +required Spec TLSRouteSpec `json:"spec"` // Status defines the current state of TLSRoute. + // +optional Status TLSRouteStatus `json:"status,omitempty"` } @@ -87,6 +90,7 @@ type TLSRouteSpec struct { // Rules are a list of TLS matchers and actions. // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -124,6 +128,7 @@ type TLSRouteRule struct { // // Support for weight: Extended // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha2/udproute_types.go b/apis/v1alpha2/udproute_types.go index c7e92b92b4..82afedc6bb 100644 --- a/apis/v1alpha2/udproute_types.go +++ b/apis/v1alpha2/udproute_types.go @@ -31,13 +31,16 @@ import ( // listener, it can be used to forward traffic on the port specified by the // listener to a set of backends specified by the UDPRoute. type UDPRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of UDPRoute. + // +required Spec UDPRouteSpec `json:"spec"` // Status defines the current state of UDPRoute. + // +optional Status UDPRouteStatus `json:"status,omitempty"` } @@ -47,6 +50,7 @@ type UDPRouteSpec struct { // Rules are a list of UDP matchers and actions. // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -81,6 +85,7 @@ type UDPRouteRule struct { // // Support for weight: Extended // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index 75655f5d63..93c47d72bb 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -36,13 +36,16 @@ import ( // BackendTLSPolicy provides a way to configure how a Gateway // connects to a Backend via TLS. type BackendTLSPolicy struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of BackendTLSPolicy. + // +required Spec BackendTLSPolicySpec `json:"spec"` // Status defines the current state of BackendTLSPolicy. + // +optional Status v1alpha2.PolicyStatus `json:"status,omitempty"` } @@ -79,11 +82,13 @@ type BackendTLSPolicySpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 + // +required // +kubebuilder:validation:XValidation:message="sectionName must be specified when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" // +kubebuilder:validation:XValidation:message="sectionName must be unique when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName))))" TargetRefs []v1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"` // Validation contains backend TLS validation configuration. + // +required Validation BackendTLSPolicyValidation `json:"validation"` // Options are a list of key/value pairs to enable extended TLS @@ -154,6 +159,8 @@ type BackendTLSPolicyValidation struct { // 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. // // Support: Core + // + // +required Hostname v1.PreciseHostname `json:"hostname"` // SubjectAltNames contains one or more Subject Alternative Names. @@ -176,6 +183,8 @@ type SubjectAltName struct { // Type determines the format of the Subject Alternative Name. Always required. // // Support: Core + // + // +required Type SubjectAltNameType `json:"type"` // Hostname contains Subject Alternative Name specified in DNS name format. diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go index 82345f9080..5d2f9c5879 100644 --- a/apis/v1alpha3/tlsroute_types.go +++ b/apis/v1alpha3/tlsroute_types.go @@ -36,13 +36,16 @@ import ( // If you need to forward traffic to a single target for a TLS listener, you // could choose to use a TCPRoute with a TLS listener. type TLSRoute struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of TLSRoute. + // +required Spec TLSRouteSpec `json:"spec"` // Status defines the current state of TLSRoute. + // +optional Status v1alpha2.TLSRouteStatus `json:"status,omitempty"` } @@ -91,6 +94,7 @@ type TLSRouteSpec struct { // Rules are a list of TLS matchers and actions. // + // +required // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // diff --git a/apis/v1beta1/referencegrant_types.go b/apis/v1beta1/referencegrant_types.go index 0b0caf7088..6321515238 100644 --- a/apis/v1beta1/referencegrant_types.go +++ b/apis/v1beta1/referencegrant_types.go @@ -41,10 +41,12 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // no grant, and MUST respond to the removal of a grant by revoking the access // that the grant allowed. type ReferenceGrant struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of ReferenceGrant. + // +optional Spec ReferenceGrantSpec `json:"spec,omitempty"` // Note that `Status` sub-resource has been excluded at the @@ -72,6 +74,7 @@ type ReferenceGrantSpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 + // +required From []ReferenceGrantFrom `json:"from"` // To describes the resources that may be referenced by the resources @@ -83,6 +86,7 @@ type ReferenceGrantSpec struct { // // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 + // +required To []ReferenceGrantTo `json:"to"` } @@ -92,6 +96,8 @@ type ReferenceGrantFrom struct { // When empty, the Kubernetes core API group is inferred. // // Support: Core + // + // +required Group Group `json:"group"` // Kind is the kind of the referent. Although implementations may support @@ -109,11 +115,14 @@ type ReferenceGrantFrom struct { // * TCPRoute // * TLSRoute // * UDPRoute + // +required Kind Kind `json:"kind"` // Namespace is the namespace of the referent. // // Support: Core + // + // +required Namespace Namespace `json:"namespace"` } @@ -124,6 +133,8 @@ type ReferenceGrantTo struct { // When empty, the Kubernetes core API group is inferred. // // Support: Core + // + // +required Group Group `json:"group"` // Kind is the kind of the referent. Although implementations may support @@ -132,6 +143,8 @@ type ReferenceGrantTo struct { // // * Secret when used to permit a SecretObjectReference // * Service when used to permit a BackendObjectReference + // + // +required Kind Kind `json:"kind"` // Name is the name of the referent. When unspecified, this policy diff --git a/apisx/v1alpha1/shared_types.go b/apisx/v1alpha1/shared_types.go index f811ace877..441d4758c1 100644 --- a/apisx/v1alpha1/shared_types.go +++ b/apisx/v1alpha1/shared_types.go @@ -70,6 +70,7 @@ type ParentGatewayReference struct { Kind *Kind `json:"kind"` // Name is the name of the referent. + // +required Name ObjectName `json:"name"` // Namespace is the namespace of the referent. If not present, @@ -87,6 +88,7 @@ type RequestRate struct { // Support: Extended // +kubebuilder:validation:Minimum=1 // +kubebuilder:validation:Maximum=1000000 + // +optional Count *int `json:"count,omitempty"` // Interval specifies the divisor of the rate of requests, the amount of @@ -94,5 +96,6 @@ type RequestRate struct { // // Support: Extended // +kubebuilder:validation:XValidation:message="interval can not be greater than one hour",rule="!(duration(self) == duration('0s') || duration(self) > duration('1h'))" + // +optional Interval *Duration `json:"interval,omitempty"` } diff --git a/apisx/v1alpha1/xbackendtrafficpolicy_types.go b/apisx/v1alpha1/xbackendtrafficpolicy_types.go index b2dcba6985..3ac5163693 100644 --- a/apisx/v1alpha1/xbackendtrafficpolicy_types.go +++ b/apisx/v1alpha1/xbackendtrafficpolicy_types.go @@ -37,13 +37,16 @@ type XBackendTrafficPolicy struct { // // +optional - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of BackendTrafficPolicy. + // +required Spec BackendTrafficPolicySpec `json:"spec"` // Status defines the current state of BackendTrafficPolicy. + // +optional Status PolicyStatus `json:"status,omitempty"` } @@ -72,6 +75,7 @@ type BackendTrafficPolicySpec struct { // +listMapKey=name // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 + // +required TargetRefs []LocalPolicyTargetReference `json:"targetRefs"` // RetryConstraint defines the configuration for when to allow or prevent diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index 92cca1b735..5eb6942b1b 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -57,21 +57,25 @@ import ( // - False: when AllowedListeners is set but no valid listeners are attached, or when AllowedListeners is not set or false // - Unknown: when no AllowedListeners config is present type XListenerSet struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` + // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of ListenerSet. + // +required Spec ListenerSetSpec `json:"spec"` // Status defines the current state of ListenerSet. // // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + // +optional Status ListenerSetStatus `json:"status,omitempty"` } // ListenerSetSpec defines the desired state of a ListenerSet. type ListenerSetSpec struct { // ParentRef references the Gateway that the listeners are attached to. + // +required ParentRef ParentGatewayReference `json:"parentRef"` // Listeners associated with this ListenerSet. Listeners define @@ -110,6 +114,7 @@ type ListenerSetSpec struct { // +kubebuilder:validation:XValidation:message="hostname must not be specified for protocols ['TCP', 'UDP']",rule="self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" // +kubebuilder:validation:XValidation:message="Listener name must be unique within the Gateway",rule="self.all(l1, self.exists_one(l2, l1.name == l2.name))" // +kubebuilder:validation:XValidation:message="Combination of port, protocol and hostname must be unique for each listener",rule="self.all(l1, !has(l1.port) || self.exists_one(l2, has(l2.port) && l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" + // +required Listeners []ListenerEntry `json:"listeners"` } @@ -120,6 +125,7 @@ type ListenerEntry struct { // Name is not required to be unique across a Gateway and ListenerSets. // Routes can attach to a Listener by having a ListenerSet as a parentRef // and setting the SectionName + // +required Name SectionName `json:"name"` // Hostname specifies the virtual hostname to match for protocol types that @@ -152,9 +158,11 @@ type ListenerEntry struct { // Port is the network port. Multiple listeners may use the // same port, subject to the Listener compatibility rules. + // +required Port PortNumber `json:"port"` // Protocol specifies the network protocol this listener expects to receive. + // +required Protocol ProtocolType `json:"protocol"` // TLS is the TLS configuration for the Listener. This field is required if @@ -230,9 +238,11 @@ type ListenerSetStatus struct { // ListenerStatus is the status associated with a Listener. type ListenerEntryStatus struct { // Name is the name of the Listener that this status corresponds to. + // +required Name SectionName `json:"name"` // Port is the network port the listener is configured to listen on. + // +required Port PortNumber `json:"port"` // SupportedKinds is the list indicating the Kinds supported by this @@ -246,6 +256,7 @@ type ListenerEntryStatus struct { // reference the valid Route kinds that have been specified. // // +kubebuilder:validation:MaxItems=8 + // +required SupportedKinds []RouteGroupKind `json:"supportedKinds"` // AttachedRoutes represents the total number of Routes that have been @@ -265,6 +276,7 @@ type ListenerEntryStatus struct { // // Uses for this field include troubleshooting Route attachment and // measuring blast radius/impact of changes to a Listener. + // +required AttachedRoutes int32 `json:"attachedRoutes"` // Conditions describe the current condition of this listener. @@ -272,6 +284,7 @@ type ListenerEntryStatus struct { // +listType=map // +listMapKey=type // +kubebuilder:validation:MaxItems=8 + // +required Conditions []metav1.Condition `json:"conditions"` } diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index a2a5506c17..f431e98faf 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -623,6 +623,7 @@ spec: type: string required: - ancestorRef + - conditions - controllerName type: object maxItems: 16 diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 328999eee9..6ad00cb433 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -973,6 +973,8 @@ spec: maxItems: 8 minItems: 1 type: array + required: + - caCertificateRefs type: object mode: default: Terminate @@ -2311,6 +2313,8 @@ spec: maxItems: 8 minItems: 1 type: array + required: + - caCertificateRefs type: object mode: default: Terminate diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index f04363ab31..25575f3150 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -2196,6 +2196,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index fe5b7f0330..dc198cf154 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -3619,6 +3619,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object @@ -7235,6 +7236,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 7365304e2a..8d094e012d 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -435,6 +435,8 @@ spec: minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + required: + - backendRefs type: object maxItems: 16 minItems: 1 @@ -709,6 +711,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 8843c2f0d3..597a3178c1 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -498,6 +498,8 @@ spec: minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + required: + - backendRefs type: object maxItems: 16 minItems: 1 @@ -772,6 +774,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object @@ -1268,6 +1271,8 @@ spec: minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + required: + - backendRefs type: object maxItems: 16 minItems: 1 @@ -1543,6 +1548,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 5ef205c1d2..6c5cd46b0b 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -435,6 +435,8 @@ spec: minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + required: + - backendRefs type: object maxItems: 16 minItems: 1 @@ -709,6 +711,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index a4674dec56..6c69c96b40 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -583,6 +583,7 @@ spec: type: string required: - ancestorRef + - conditions - controllerName type: object maxItems: 16 diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 2454521c2e..637a9ed365 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -487,6 +487,8 @@ spec: maxItems: 8 minItems: 1 type: array + required: + - caCertificateRefs type: object mode: default: Terminate diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 4982ec8453..989e24e844 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -2039,6 +2039,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 1824bd5e19..12c0639a2f 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -2803,6 +2803,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object @@ -5603,6 +5604,7 @@ spec: - name type: object required: + - conditions - controllerName - parentRef type: object diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 92162b5a1b..4c70dd18b1 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3093,6 +3093,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.Refer }, }, }, + Required: []string{"caCertificateRefs"}, }, }, Dependencies: []string{ @@ -5717,7 +5718,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_RouteParentStatus(ref common.Reference }, }, }, - Required: []string{"parentRef", "controllerName"}, + Required: []string{"parentRef", "controllerName", "conditions"}, }, }, Dependencies: []string{ @@ -6156,7 +6157,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyAncestorStatus(ref common. }, }, }, - Required: []string{"ancestorRef", "controllerName"}, + Required: []string{"ancestorRef", "controllerName", "conditions"}, }, }, Dependencies: []string{ @@ -6412,6 +6413,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteRule(ref common.Referenc }, }, }, + Required: []string{"backendRefs"}, }, }, Dependencies: []string{ @@ -6621,6 +6623,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteRule(ref common.Referenc }, }, }, + Required: []string{"backendRefs"}, }, }, Dependencies: []string{ @@ -6845,6 +6848,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteRule(ref common.Referenc }, }, }, + Required: []string{"backendRefs"}, }, }, Dependencies: []string{ From 7cf2dab3557f04a645b91608acb701855f6421e6 Mon Sep 17 00:00:00 2001 From: Zhen Zhang Date: Fri, 1 Aug 2025 22:33:38 +0800 Subject: [PATCH 109/224] add OpenKruise Rollouts as one of the integration solution (#3968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 守辰 --- site-src/implementations.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/site-src/implementations.md b/site-src/implementations.md index 93f6dc2c89..791f5450d3 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -130,6 +130,7 @@ other functions (like managing DNS or creating certificates). - [argo-rollouts][22] (alpha) - [Knative][24] (alpha) - [Kuadrant][26] (GA) +- [kruise-rollouts][41] (alpha) [1]:#acnodal-epic [2]:#apisix @@ -170,6 +171,7 @@ other functions (like managing DNS or creating certificates). [38]:#google-cloud-service-mesh [39]:#kubvernor [40]:#agentgateway-with-kgateway +[41]:#kruise-rollouts [gamma]:mesh/index.md @@ -685,6 +687,10 @@ For help and support with Kuadrant's implementation please feel free to [create [kuadrant-issue-new]:https://github.com/Kuadrant/kuadrant-operator/issues/new [kuadrant-slack]:https://kubernetes.slack.com/archives/C05J0D0V525 +### OpenKruise Rollouts +[OpenKruise Rollouts][kruise-rollouts] is a plugin-n-play progressive delivery controller for Kubernetes. It supports several advanced deployment methods such as blue/green and canaries. OpenKruise Rollouts has built-in support for the Gateway API. + +[kruise-rollouts]:https://openkruise.io/rollouts/introduction ## Adding new entries From 30a0767956c5063b48e56744476885156ae1aaa8 Mon Sep 17 00:00:00 2001 From: Sneha Chhabria <59101963+snehachhabria@users.noreply.github.com> Date: Fri, 1 Aug 2025 08:51:38 -0700 Subject: [PATCH 110/224] add conformance report for AGC (#3939) --- .../README.md | 13 ++++ .../standard-v1.2.1-default-report.yaml | 59 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 conformance/reports/v1.2.1/azure-application-gateway-for-containers/README.md create mode 100644 conformance/reports/v1.2.1/azure-application-gateway-for-containers/standard-v1.2.1-default-report.yaml diff --git a/conformance/reports/v1.2.1/azure-application-gateway-for-containers/README.md b/conformance/reports/v1.2.1/azure-application-gateway-for-containers/README.md new file mode 100644 index 0000000000..22b7f94910 --- /dev/null +++ b/conformance/reports/v1.2.1/azure-application-gateway-for-containers/README.md @@ -0,0 +1,13 @@ +# Azure Application Gateway for Containers + +[Application Gateway for Containers][azure-application-gateway-for-containers] is a managed application (layer 7) load balancing solution, providing dynamic traffic management capabilities for workloads running in a Kubernetes cluster in Azure. Follow the [quickstart guide][azure-application-gateway-for-containers-quickstart-controller] to deploy the ALB controller and get started with Gateway API. + +## Table of Contents + +|API channel|Implementation version|Mode|Report| +|-----------|----------------------|----|------| +|standard|[v1.2.1](https://learn.microsoft.com/azure/application-gateway/for-containers/alb-controller-release-notes#latest-release-recommended)|default|[v1.2.1 report](./standard-v1.2.1-default-report.yaml)| + + +[azure-application-gateway-for-containers]:https://aka.ms/appgwcontainers/docs +[azure-application-gateway-for-containers-quickstart-controller]:https://aka.ms/appgwcontainers/docs diff --git a/conformance/reports/v1.2.1/azure-application-gateway-for-containers/standard-v1.2.1-default-report.yaml b/conformance/reports/v1.2.1/azure-application-gateway-for-containers/standard-v1.2.1-default-report.yaml new file mode 100644 index 0000000000..b15b81ef39 --- /dev/null +++ b/conformance/reports/v1.2.1/azure-application-gateway-for-containers/standard-v1.2.1-default-report.yaml @@ -0,0 +1,59 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-07-18T23:02:29Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.1 +implementation: + organization: Microsoft Azure + project: Application Gateway for Containers + url: https://aka.ms/appgwcontainers/docs + version: "1.7.9" + contact: + - agcfeedback@microsoft.com +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + name: GATEWAY-GRPC + summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 9 + Skipped: 0 + supportedFeatures: + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteParentRefPort + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. From eaaf985df500b39c14836f068673446998e7b4d9 Mon Sep 17 00:00:00 2001 From: Bob Tian Date: Fri, 1 Aug 2025 15:55:37 -0700 Subject: [PATCH 111/224] Skip test in report if RunTest is configured. (#3966) --- conformance/utils/suite/suite.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 63a6b93a16..b34a1ea3ff 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -461,6 +461,9 @@ func (suite *ConformanceTestSuite) Run(t *testing.T, tests []ConformanceTest) er sleepForTestIsolation := false for _, test := range tests { res := testSucceeded + if suite.RunTest != "" && test.ShortName != suite.RunTest { + res = testSkipped + } if suite.SkipTests.Has(test.ShortName) { res = testSkipped } From b6b242839ebd353b25ee41f83d2ce69dd177ea56 Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Mon, 4 Aug 2025 05:57:37 +0200 Subject: [PATCH 112/224] TLSRoute: Set MaxItems=1 for rules[] in v1alpha3 (#3971) * TLSRoute: Set Rules MaxItems to 1 * TLSRoute: Add omitempty to Rules * TLSRoute: Rules godoc --- apis/v1alpha3/tlsroute_types.go | 6 +++--- .../experimental/gateway.networking.k8s.io_tlsroutes.yaml | 4 ++-- pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go index 5d2f9c5879..68900b3c9a 100644 --- a/apis/v1alpha3/tlsroute_types.go +++ b/apis/v1alpha3/tlsroute_types.go @@ -92,13 +92,13 @@ type TLSRouteSpec struct { // +required Hostnames []Hostname `json:"hostnames,omitempty"` - // Rules are a list of TLS matchers and actions. + // Rules are a list of actions. // // +required // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:MaxItems=1 // - Rules []v1alpha2.TLSRouteRule `json:"rules"` + Rules []v1alpha2.TLSRouteRule `json:"rules,omitempty"` } // +kubebuilder:object:root=true diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index 597a3178c1..cdeecdd31c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -1119,7 +1119,7 @@ spec: || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) rules: - description: Rules are a list of TLS matchers and actions. + description: Rules are a list of actions. items: description: TLSRouteRule is the configuration for a given rule. properties: @@ -1274,7 +1274,7 @@ spec: required: - backendRefs type: object - maxItems: 16 + maxItems: 1 minItems: 1 type: array x-kubernetes-validations: diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 4c70dd18b1..cf47507b1f 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7314,7 +7314,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, "rules": { SchemaProps: spec.SchemaProps{ - Description: "Rules are a list of TLS matchers and actions.\n\n", + Description: "Rules are a list of actions.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From c011e670b155414f9ab52c6ecb697edd807c9f64 Mon Sep 17 00:00:00 2001 From: jgreeer Date: Mon, 4 Aug 2025 16:31:39 -0400 Subject: [PATCH 113/224] Fix Gateway API community meeting schedule documentation (#3975) Update meeting schedule to reflect the correct alternating weekly pattern: - Week A: Mondays at 3pm Pacific Time (23:00 UTC) - Week B: Tuesdays at 8am Pacific Time (16:00 UTC) This replaces the incorrect information about first Tuesday monthly + weekly Monday meetings. --- site-src/contributing/index.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/site-src/contributing/index.md b/site-src/contributing/index.md index 05798beb42..323fda8992 100644 --- a/site-src/contributing/index.md +++ b/site-src/contributing/index.md @@ -37,10 +37,9 @@ questions, discussions. ## Meetings -Gateway API community meetings happen on the first Tuesday of each month at -8am Pacific Time (15:00 UTC, [convert to your timezone][8am-pst-convert]) and -weekly on all subsequent weeks each month on Mondays at 3pm Pacific Time -(23:00 UTC, [convert to your timezone][3pm-pst-convert]): +Gateway API community meetings happen on alternating weeks: +- **Week A**: Mondays at 3pm Pacific Time (23:00 UTC, [convert to your timezone][3pm-pst-convert]) +- **Week B**: Tuesdays at 8am Pacific Time (16:00 UTC, [convert to your timezone][8am-pst-convert]) Being the main meeting for Gateway API, the topics can vary here and often this is where new topics and ideas are discussed, including both ingress and service From 5836f6fad0953d2ef1778627471e575ace55a92e Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 5 Aug 2025 16:41:27 -0400 Subject: [PATCH 114/224] ListenerSet adjust PortNumber kubebuilder validations (#3750) * use a custom min/max marker controller-tools only allows this to work on object types and not ref types * update GEP with optional port * adjust markers * make generate --- apis/v1/gateway_types.go | 4 ++ apis/v1/httproute_types.go | 3 + apis/v1/object_reference_types.go | 2 + apis/v1/shared_types.go | 6 +- apis/v1alpha2/shared_types.go | 3 - apis/v1beta1/shared_types.go | 3 - apisx/v1alpha1/xlistenerset_types.go | 18 ++++- applyconfiguration/internal/internal.go | 1 - ...way.networking.x-k8s.io_xlistenersets.yaml | 9 ++- geps/gep-1713/index.md | 17 ++++- pkg/generated/openapi/zz_generated.openapi.go | 5 +- pkg/generator/main.go | 2 + pkg/generator/markers.go | 66 +++++++++++++++++++ 13 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 pkg/generator/markers.go diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index ea8667af61..8425231530 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -396,6 +396,10 @@ type Listener struct { // same port, subject to the Listener compatibility rules. // // Support: Core + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // // +required Port PortNumber `json:"port"` diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 96e245c386..d051df1046 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1219,6 +1219,9 @@ type HTTPRequestRedirectFilter struct { // Support: Extended // // +optional + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` // StatusCode is the HTTP status code to be used in response. diff --git a/apis/v1/object_reference_types.go b/apis/v1/object_reference_types.go index 54e34fa2ed..414e39b947 100644 --- a/apis/v1/object_reference_types.go +++ b/apis/v1/object_reference_types.go @@ -148,6 +148,8 @@ type BackendObjectReference struct { // resource or this field. // // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` } diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index e874c2f905..231a22a746 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -149,6 +149,9 @@ type ParentReference struct { // Support: Extended // // +optional + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 Port *PortNumber `json:"port,omitempty"` } @@ -228,9 +231,6 @@ type CommonRouteSpec struct { } // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber int32 // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 2fb84d5f3b..3d2f787909 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -40,9 +40,6 @@ type ParentReference = v1.ParentReference type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index 3dbcc280fc..ce1c430649 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -40,9 +40,6 @@ type ParentReference = v1.ParentReference type CommonRouteSpec = v1.CommonRouteSpec // PortNumber defines a network port. -// -// +kubebuilder:validation:Minimum=1 -// +kubebuilder:validation:Maximum=65535 type PortNumber = v1.PortNumber // BackendRef defines how a Route should forward a request to a Kubernetes diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index 5eb6942b1b..a4cedc6949 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -158,8 +158,18 @@ type ListenerEntry struct { // Port is the network port. Multiple listeners may use the // same port, subject to the Listener compatibility rules. - // +required - Port PortNumber `json:"port"` + // + // If the port is not set or specified as zero, the implementation will assign + // a unique port. If the implementation does not support dynamic port + // assignment, it MUST set `Accepted` condition to `False` with the + // `UnsupportedPort` reason. + // + // +optional + // + // +kubebuilder:default=0 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 + Port PortNumber `json:"port,omitempty"` // Protocol specifies the network protocol this listener expects to receive. // +required @@ -242,6 +252,10 @@ type ListenerEntryStatus struct { Name SectionName `json:"name"` // Port is the network port the listener is configured to listen on. + // + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // // +required Port PortNumber `json:"port"` diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 0403df0d63..92508d3a05 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -1795,7 +1795,6 @@ var schemaYAML = typed.YAMLObject(`types: - name: port type: scalar: numeric - default: 0 - name: protocol type: scalar: string diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 637a9ed365..9a21d52e81 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -296,12 +296,18 @@ spec: pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string port: + default: 0 description: |- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. + + If the port is not set or specified as zero, the implementation will assign + a unique port. If the implementation does not support dynamic port + assignment, it MUST set `Accepted` condition to `False` with the + `UnsupportedPort` reason. format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer protocol: description: Protocol specifies the network protocol this listener @@ -541,7 +547,6 @@ spec: > 0 || size(self.options) > 0 : true' required: - name - - port - protocol type: object maxItems: 64 diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 4cad39fde1..c720b35794 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -163,8 +163,19 @@ type ListenerEntry struct { // Port is the network port. Multiple listeners may use the // same port, subject to the Listener compatibility rules. - // + // + // If the port is not set or specified as zero, the implementation will assign + // a unique port. If the implementation does not support dynamic port + // assignment, it MUST set `Accepted` condition to `False` with the + // `UnsupportedPort` reason. + // // Support: Core + // + // +optional + // + // +kubebuilder:default=0 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=65535 Port PortNumber `json:"port,omitempty"` // Protocol specifies the network protocol this listener expects to receive. @@ -380,6 +391,10 @@ spec: `ListenerEntry` is currently a copy of the `Listener` struct with some changes noted in the below sections +#### Port + +`Port` is now optional to allow for dynamic port assignment. If the port is unspecified or set to zero, the implementation will assign a unique port. If the implementation does not support dynamic port assignment, it MUST set `Accepted` condition to `False` with the `UnsupportedPort` reason. + ## Semantics ### Gateway Changes diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index cf47507b1f..62c65b8e74 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7944,8 +7944,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere }, "port": { SchemaProps: spec.SchemaProps{ - Description: "Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules.", - Default: 0, + Description: "Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules.\n\nIf the port is not set or specified as zero, the implementation will assign a unique port. If the implementation does not support dynamic port assignment, it MUST set `Accepted` condition to `False` with the `UnsupportedPort` reason.", Type: []string{"integer"}, Format: "int32", }, @@ -7971,7 +7970,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere }, }, }, - Required: []string{"name", "port", "protocol"}, + Required: []string{"name", "protocol"}, }, }, Dependencies: []string{ diff --git a/pkg/generator/main.go b/pkg/generator/main.go index dc170b8823..1149e1a902 100644 --- a/pkg/generator/main.go +++ b/pkg/generator/main.go @@ -69,6 +69,8 @@ func main() { log.Fatalf("failed to register markers: %s", err) } + registerMarkerOverrides(parser.Collector.Registry) + crd.AddKnownTypes(parser) for _, r := range roots { parser.NeedPackage(r) diff --git a/pkg/generator/markers.go b/pkg/generator/markers.go new file mode 100644 index 0000000000..ab5f625aae --- /dev/null +++ b/pkg/generator/markers.go @@ -0,0 +1,66 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/controller-tools/pkg/markers" +) + +type Minimum float64 + +func (m Minimum) Value() float64 { + return float64(m) +} + +//nolint:unparam +func (m Minimum) ApplyToSchema(schema *apiext.JSONSchemaProps) error { + val := m.Value() + schema.Minimum = &val + return nil +} + +type Maximum float64 + +func (m Maximum) Value() float64 { + return float64(m) +} + +//nolint:unparam +func (m Maximum) ApplyToSchema(schema *apiext.JSONSchemaProps) error { + val := m.Value() + schema.Maximum = &val + return nil +} + +// kubebuilder Min Max markers are broken with type aliases +func registerMarkerOverrides(into *markers.Registry) { + minMarker, _ := markers.MakeDefinition( + "kubebuilder:validation:Minimum", + markers.DescribesField, + Minimum(0), + ) + + maxMarker, _ := markers.MakeDefinition( + "kubebuilder:validation:Maximum", + markers.DescribesField, + Maximum(0), + ) + + into.Register(minMarker) //nolint:errcheck + into.Register(maxMarker) //nolint:errcheck +} From 78496d8f897031a5335fb1fbcdfe422721646f4b Mon Sep 17 00:00:00 2001 From: Erik Godding Boye Date: Wed, 6 Aug 2025 06:37:26 +0200 Subject: [PATCH 115/224] Fix OpenAPI validations by adding API list markers (#3964) --- .golangci-kal.yml | 1 + apis/v1/gateway_types.go | 11 +- apis/v1/grpcroute_types.go | 6 + apis/v1/httproute_types.go | 7 + apis/v1/shared_types.go | 4 +- apis/v1alpha2/policy_types.go | 3 +- apis/v1alpha2/tcproute_types.go | 2 + apis/v1alpha2/tlsroute_types.go | 3 + apis/v1alpha2/udproute_types.go | 2 + apis/v1alpha3/backendtlspolicy_types.go | 8 +- apis/v1alpha3/tlsroute_types.go | 4 +- apis/v1beta1/referencegrant_types.go | 6 +- apisx/v1alpha1/xlistenerset_types.go | 3 +- ....networking.k8s.io_backendtlspolicies.yaml | 4 + .../gateway.networking.k8s.io_gateways.yaml | 12 + .../gateway.networking.k8s.io_grpcroutes.yaml | 8 + .../gateway.networking.k8s.io_httproutes.yaml | 18 ++ ...way.networking.k8s.io_referencegrants.yaml | 2 + .../gateway.networking.k8s.io_tcproutes.yaml | 4 + .../gateway.networking.k8s.io_tlsroutes.yaml | 10 + .../gateway.networking.k8s.io_udproutes.yaml | 4 + ...king.x-k8s.io_xbackendtrafficpolicies.yaml | 1 + ...way.networking.x-k8s.io_xlistenersets.yaml | 4 + .../gateway.networking.k8s.io_gateways.yaml | 10 + .../gateway.networking.k8s.io_grpcroutes.yaml | 8 + .../gateway.networking.k8s.io_httproutes.yaml | 16 ++ ...way.networking.k8s.io_referencegrants.yaml | 2 + pkg/generated/openapi/zz_generated.openapi.go | 250 ++++++++++++++++++ 28 files changed, 403 insertions(+), 10 deletions(-) diff --git a/.golangci-kal.yml b/.golangci-kal.yml index d2b764e868..27fdabbef1 100644 --- a/.golangci-kal.yml +++ b/.golangci-kal.yml @@ -17,6 +17,7 @@ linters: - "nomaps" # Ensure maps are not used. - "nophase" # Phase fields are discouraged by the Kube API conventions, use conditions instead. - "optionalorrequired" # Every field should be marked as `+optional` or `+required`. + - "ssatags" # Ensure proper Server-Side Apply (SSA) tags on array fields. - "statussubresource" # All root objects that have a `status` field should have a status subresource. - "uniquemarkers" # Ensure that types and fields do not contain more than a single definition of a marker that should only be present once. disable: diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 8425231530..86de1bad59 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -265,6 +265,7 @@ type GatewaySpec struct { // Support: Extended // // +optional + // +listType=atomic // // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="IPAddress values must be unique",rule="self.all(a1, a1.type == 'IPAddress' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )" @@ -573,6 +574,7 @@ type GatewayTLSConfig struct { // Support: Implementation-specific (More than one reference or other resource types) // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=64 CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` @@ -647,9 +649,10 @@ type FrontendTLSValidation struct { // "ResolvedRefs" condition MUST be set to False for this listener with the // "RefNotPermitted" reason. // + // +required + // +listType=atomic // +kubebuilder:validation:MaxItems=8 // +kubebuilder:validation:MinItems=1 - // +required CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` } @@ -661,6 +664,7 @@ type AllowedRoutes struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:default={from: Same} Namespaces *RouteNamespaces `json:"namespaces,omitempty"` @@ -677,6 +681,7 @@ type AllowedRoutes struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=8 Kinds []RouteGroupKind `json:"kinds,omitempty"` } @@ -795,6 +800,7 @@ type GatewayStatus struct { // * a specified address was unusable (e.g. already in use) // // +optional + // +listType=atomic // // +kubebuilder:validation:MaxItems=16 Addresses []GatewayStatusAddress `json:"addresses,omitempty"` @@ -1127,8 +1133,9 @@ type ListenerStatus struct { // and invalid Route kinds are specified, the implementation MUST // reference the valid Route kinds that have been specified. // - // +kubebuilder:validation:MaxItems=8 // +required + // +listType=atomic + // +kubebuilder:validation:MaxItems=8 SupportedKinds []RouteGroupKind `json:"supportedKinds"` // AttachedRoutes represents the total number of Routes that have been diff --git a/apis/v1/grpcroute_types.go b/apis/v1/grpcroute_types.go index c6480c3857..5f9bde7a8e 100644 --- a/apis/v1/grpcroute_types.go +++ b/apis/v1/grpcroute_types.go @@ -139,12 +139,14 @@ type GRPCRouteSpec struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 Hostnames []Hostname `json:"hostnames,omitempty"` // Rules are a list of GRPC matchers, filters and actions. // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128",rule="(self.size() > 0 ? (has(self[0].matches) ? self[0].matches.size() : 0) : 0) + (self.size() > 1 ? (has(self[1].matches) ? self[1].matches.size() : 0) : 0) + (self.size() > 2 ? (has(self[2].matches) ? self[2].matches.size() : 0) : 0) + (self.size() > 3 ? (has(self[3].matches) ? self[3].matches.size() : 0) : 0) + (self.size() > 4 ? (has(self[4].matches) ? self[4].matches.size() : 0) : 0) + (self.size() > 5 ? (has(self[5].matches) ? self[5].matches.size() : 0) : 0) + (self.size() > 6 ? (has(self[6].matches) ? self[6].matches.size() : 0) : 0) + (self.size() > 7 ? (has(self[7].matches) ? self[7].matches.size() : 0) : 0) + (self.size() > 8 ? (has(self[8].matches) ? self[8].matches.size() : 0) : 0) + (self.size() > 9 ? (has(self[9].matches) ? self[9].matches.size() : 0) : 0) + (self.size() > 10 ? (has(self[10].matches) ? self[10].matches.size() : 0) : 0) + (self.size() > 11 ? (has(self[11].matches) ? self[11].matches.size() : 0) : 0) + (self.size() > 12 ? (has(self[12].matches) ? self[12].matches.size() : 0) : 0) + (self.size() > 13 ? (has(self[13].matches) ? self[13].matches.size() : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128" // @@ -212,6 +214,7 @@ type GRPCRouteRule struct { // the above criteria. // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=64 Matches []GRPCRouteMatch `json:"matches,omitempty"` @@ -241,6 +244,7 @@ type GRPCRouteRule struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" @@ -276,6 +280,7 @@ type GRPCRouteRule struct { // Support for weight: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 BackendRefs []GRPCBackendRef `json:"backendRefs,omitempty"` @@ -636,6 +641,7 @@ type GRPCBackendRef struct { // Filters field in GRPCRouteRule.) // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" // +kubebuilder:validation:XValidation:message="ResponseHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1" diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index d051df1046..39a01f27f1 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -114,12 +114,14 @@ type HTTPRouteSpec struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 Hostnames []Hostname `json:"hostnames,omitempty"` // Rules are a list of HTTP matchers, filters and actions. // // +optional + // +listType=atomic // // +kubebuilder:validation:MaxItems=16 // +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}} @@ -201,6 +203,7 @@ type HTTPRouteRule struct { // parent a request is coming from, a HTTP 404 status code MUST be returned. // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=64 // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} Matches []HTTPRouteMatch `json:"matches,omitempty"` @@ -243,6 +246,7 @@ type HTTPRouteRule struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" @@ -288,6 +292,7 @@ type HTTPRouteRule struct { // Support for weight: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` @@ -382,6 +387,7 @@ type HTTPRouteRetry struct { // Support: Extended // // +optional + // +listType=atomic Codes []HTTPRouteRetryStatusCode `json:"codes,omitempty"` // Attempts specifies the maximum number of times an individual request @@ -1606,6 +1612,7 @@ type HTTPBackendRef struct { // Filters field in HTTPRouteRule.) // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 // +kubebuilder:validation:XValidation:message="May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both",rule="!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" // +kubebuilder:validation:XValidation:message="RequestHeaderModifier filter cannot be repeated",rule="self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1" diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 231a22a746..b98a9e812f 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -222,6 +222,7 @@ type CommonRouteSpec struct { // // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=32 // // @@ -502,8 +503,9 @@ type RouteStatus struct { // A maximum of 32 Gateways will be represented in this list. An empty list // means the route has not been attached to any Gateway. // - // +kubebuilder:validation:MaxItems=32 // +required + // +listType=atomic + // +kubebuilder:validation:MaxItems=32 Parents []RouteParentStatus `json:"parents"` } diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index b38ff00327..dc2f8f7f09 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -242,7 +242,8 @@ type PolicyStatus struct { // additional Gateways would be able to reference the Service targeted by // the BackendTLSPolicy. // - // +kubebuilder:validation:MaxItems=16 // +required + // +listType=atomic + // +kubebuilder:validation:MaxItems=16 Ancestors []PolicyAncestorStatus `json:"ancestors"` } diff --git a/apis/v1alpha2/tcproute_types.go b/apis/v1alpha2/tcproute_types.go index 99446bedcb..e545e6fdab 100644 --- a/apis/v1alpha2/tcproute_types.go +++ b/apis/v1alpha2/tcproute_types.go @@ -51,6 +51,7 @@ type TCPRouteSpec struct { // Rules are a list of TCP matchers and actions. // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -86,6 +87,7 @@ type TCPRouteRule struct { // Support for weight: Extended // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha2/tlsroute_types.go b/apis/v1alpha2/tlsroute_types.go index 5cd56ca201..8ca02d370d 100644 --- a/apis/v1alpha2/tlsroute_types.go +++ b/apis/v1alpha2/tlsroute_types.go @@ -85,12 +85,14 @@ type TLSRouteSpec struct { // Support: Core // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=16 Hostnames []Hostname `json:"hostnames,omitempty"` // Rules are a list of TLS matchers and actions. // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -129,6 +131,7 @@ type TLSRouteRule struct { // Support for weight: Extended // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha2/udproute_types.go b/apis/v1alpha2/udproute_types.go index 82afedc6bb..f5f8feff77 100644 --- a/apis/v1alpha2/udproute_types.go +++ b/apis/v1alpha2/udproute_types.go @@ -51,6 +51,7 @@ type UDPRouteSpec struct { // Rules are a list of UDP matchers and actions. // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 // @@ -86,6 +87,7 @@ type UDPRouteRule struct { // Support for weight: Extended // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 BackendRefs []BackendRef `json:"backendRefs,omitempty"` diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index 93c47d72bb..e00491908c 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -80,9 +80,10 @@ type BackendTLSPolicySpec struct { // // Support: Implementation-specific for any other resource // + // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - // +required // +kubebuilder:validation:XValidation:message="sectionName must be specified when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" // +kubebuilder:validation:XValidation:message="sectionName must be unique when targetRefs includes 2 or more references to the same target",rule="self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName))))" TargetRefs []v1alpha2.LocalPolicyTargetReferenceWithSectionName `json:"targetRefs"` @@ -133,8 +134,9 @@ type BackendTLSPolicyValidation struct { // Support: Implementation-specific (More than one reference, or other kinds // of resources). // - // +kubebuilder:validation:MaxItems=8 // +optional + // +listType=atomic + // +kubebuilder:validation:MaxItems=8 CACertificateRefs []v1.LocalObjectReference `json:"caCertificateRefs,omitempty"` // WellKnownCACertificates specifies whether system CA certificates may be used in @@ -150,6 +152,7 @@ type BackendTLSPolicyValidation struct { // Support: Implementation-specific // // +optional + // +listType=atomic WellKnownCACertificates *WellKnownCACertificatesType `json:"wellKnownCACertificates,omitempty"` // Hostname is used for two purposes in the connection between Gateways and @@ -170,6 +173,7 @@ type BackendTLSPolicyValidation struct { // Support: Extended // // +optional + // +listType=atomic // +kubebuilder:validation:MaxItems=5 SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` } diff --git a/apis/v1alpha3/tlsroute_types.go b/apis/v1alpha3/tlsroute_types.go index 68900b3c9a..8ae5b51866 100644 --- a/apis/v1alpha3/tlsroute_types.go +++ b/apis/v1alpha3/tlsroute_types.go @@ -87,14 +87,16 @@ type TLSRouteSpec struct { // // Support: Core // + // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - // +required Hostnames []Hostname `json:"hostnames,omitempty"` // Rules are a list of actions. // // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=1 // diff --git a/apis/v1beta1/referencegrant_types.go b/apis/v1beta1/referencegrant_types.go index 6321515238..bed43bc957 100644 --- a/apis/v1beta1/referencegrant_types.go +++ b/apis/v1beta1/referencegrant_types.go @@ -72,9 +72,10 @@ type ReferenceGrantSpec struct { // // Support: Core // + // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - // +required From []ReferenceGrantFrom `json:"from"` // To describes the resources that may be referenced by the resources @@ -84,9 +85,10 @@ type ReferenceGrantSpec struct { // // Support: Core // + // +required + // +listType=atomic // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - // +required To []ReferenceGrantTo `json:"to"` } diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index a4cedc6949..fd108e2bed 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -269,8 +269,9 @@ type ListenerEntryStatus struct { // and invalid Route kinds are specified, the implementation MUST // reference the valid Route kinds that have been specified. // - // +kubebuilder:validation:MaxItems=8 // +required + // +listType=atomic + // +kubebuilder:validation:MaxItems=8 SupportedKinds []RouteGroupKind `json:"supportedKinds"` // AttachedRoutes represents the total number of Routes that have been diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index f431e98faf..8622def679 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -149,6 +149,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when targetRefs includes 2 or more references to the same target @@ -226,6 +227,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic hostname: description: |- Hostname is used for two purposes in the connection between Gateways and @@ -302,6 +304,7 @@ spec: "")' maxItems: 5 type: array + x-kubernetes-list-type: atomic wellKnownCACertificates: description: |- WellKnownCACertificates specifies whether system CA certificates may be used in @@ -628,6 +631,7 @@ spec: type: object maxItems: 16 type: array + x-kubernetes-list-type: atomic required: - ancestors type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 6ad00cb433..2e2462a087 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -126,6 +126,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, @@ -633,6 +634,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic namespaces: default: from: Same @@ -887,6 +889,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic frontendValidation: description: |- FrontendValidation holds configuration information for validating the frontend (client). @@ -973,6 +976,7 @@ spec: maxItems: 8 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - caCertificateRefs type: object @@ -1128,6 +1132,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" @@ -1341,6 +1346,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic required: - attachedRoutes - conditions @@ -1466,6 +1472,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, @@ -1973,6 +1980,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic namespaces: default: from: Same @@ -2227,6 +2235,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic frontendValidation: description: |- FrontendValidation holds configuration information for validating the frontend (client). @@ -2313,6 +2322,7 @@ spec: maxItems: 8 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - caCertificateRefs type: object @@ -2468,6 +2478,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" @@ -2681,6 +2692,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic required: - attachedRoutes - conditions diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 25575f3150..3a40ee2314 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -151,6 +151,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -363,6 +364,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -984,6 +986,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() @@ -1080,6 +1083,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -1630,6 +1634,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() @@ -1807,6 +1812,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -1908,6 +1914,7 @@ spec: type: object maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -2202,6 +2209,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index dc198cf154..65515a4e22 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -131,6 +131,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -343,6 +344,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -1523,6 +1525,7 @@ spec: rule: '!(!has(self.cors) && self.type == ''CORS'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -1629,6 +1632,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -2736,6 +2740,7 @@ spec: rule: '!(!has(self.cors) && self.type == ''CORS'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -3047,6 +3052,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -3142,6 +3148,7 @@ spec: minimum: 400 type: integer type: array + x-kubernetes-list-type: atomic type: object sessionPersistence: description: |- @@ -3337,6 +3344,7 @@ spec: != ''PathPrefix'') ? false : true) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -3625,6 +3633,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object @@ -3748,6 +3757,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -3960,6 +3970,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -5140,6 +5151,7 @@ spec: rule: '!(!has(self.cors) && self.type == ''CORS'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -5246,6 +5258,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -6353,6 +6366,7 @@ spec: rule: '!(!has(self.cors) && self.type == ''CORS'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -6664,6 +6678,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -6759,6 +6774,7 @@ spec: minimum: 400 type: integer type: array + x-kubernetes-list-type: atomic type: object sessionPersistence: description: |- @@ -6954,6 +6970,7 @@ spec: != ''PathPrefix'') ? false : true) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -7242,6 +7259,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index a4952e39a6..ac146b270c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -124,6 +124,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic to: description: |- To describes the resources that may be referenced by the resources @@ -173,6 +174,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - from - to diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 8d094e012d..9de083257d 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -262,6 +262,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -426,6 +427,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -441,6 +443,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) @@ -717,6 +720,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index cdeecdd31c..dce65f876b 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -110,6 +110,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -322,6 +323,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -489,6 +491,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -504,6 +507,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) @@ -780,6 +784,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object @@ -883,6 +888,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -1095,6 +1101,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -1262,6 +1269,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -1277,6 +1285,7 @@ spec: maxItems: 1 minItems: 1 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) @@ -1554,6 +1563,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 6c5cd46b0b..1f7be3d34c 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -262,6 +262,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent @@ -426,6 +427,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -441,6 +443,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: Rule name must be unique within the route rule: self.all(l1, !has(l1.name) || self.exists_one(l2, has(l2.name) @@ -717,6 +720,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 6c69c96b40..3e6d06b210 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -588,6 +588,7 @@ spec: type: object maxItems: 16 type: array + x-kubernetes-list-type: atomic required: - ancestors type: object diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 9a21d52e81..1a266cca60 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -174,6 +174,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic namespaces: default: from: Same @@ -407,6 +408,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic frontendValidation: description: |- FrontendValidation holds configuration information for validating the frontend (client). @@ -493,6 +495,7 @@ spec: maxItems: 8 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - caCertificateRefs type: object @@ -846,6 +849,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic required: - attachedRoutes - conditions diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 2952481bdb..bcb648812d 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -126,6 +126,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, @@ -488,6 +489,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic namespaces: default: from: Same @@ -742,6 +744,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic mode: default: Terminate description: |- @@ -894,6 +897,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" @@ -1107,6 +1111,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic required: - attachedRoutes - conditions @@ -1232,6 +1237,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, @@ -1594,6 +1600,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic namespaces: default: from: Same @@ -1848,6 +1855,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic mode: default: Terminate description: |- @@ -2000,6 +2008,7 @@ spec: true' maxItems: 16 type: array + x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" @@ -2213,6 +2222,7 @@ spec: type: object maxItems: 8 type: array + x-kubernetes-list-type: atomic required: - attachedRoutes - conditions diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 989e24e844..4e81b08878 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -151,6 +151,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -334,6 +335,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent @@ -937,6 +939,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() @@ -1033,6 +1036,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -1583,6 +1587,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() @@ -1760,6 +1765,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -1772,6 +1778,7 @@ spec: type: object maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -2045,6 +2052,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index 12c0639a2f..dfa6af4c77 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -131,6 +131,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -314,6 +315,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent @@ -1190,6 +1192,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -1296,6 +1299,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -2117,6 +2121,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -2428,6 +2433,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -2542,6 +2548,7 @@ spec: != ''PathPrefix'') ? false : true) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -2809,6 +2816,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object @@ -2932,6 +2940,7 @@ spec: type: string maxItems: 16 type: array + x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants @@ -3115,6 +3124,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent @@ -3991,6 +4001,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -4097,6 +4108,7 @@ spec: ? has(self.port) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match @@ -4918,6 +4930,7 @@ spec: rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both @@ -5229,6 +5242,7 @@ spec: type: object maxItems: 64 type: array + x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. @@ -5343,6 +5357,7 @@ spec: != ''PathPrefix'') ? false : true) : true' maxItems: 16 type: array + x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less @@ -5610,6 +5625,7 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-list-type: atomic required: - parents type: object diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index da71ceaac4..6a2d368971 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -124,6 +124,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic to: description: |- To describes the resources that may be referenced by the resources @@ -173,6 +174,7 @@ spec: maxItems: 16 minItems: 1 type: array + x-kubernetes-list-type: atomic required: - from - to diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 62c65b8e74..9885f10471 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -2862,12 +2862,22 @@ func schema_sigsk8sio_gateway_api_apis_v1_AllowedRoutes(ref common.ReferenceCall Type: []string{"object"}, Properties: map[string]spec.Schema{ "namespaces": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Namespaces indicates namespaces from which Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default.\n\nSupport: Core", Ref: ref("sigs.k8s.io/gateway-api/apis/v1.RouteNamespaces"), }, }, "kinds": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Kinds specifies the groups and kinds of Routes that are allowed to bind to this Gateway Listener. When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol.\n\nA RouteGroupKind MUST correspond to kinds of Routes that are compatible with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the \"ResolvedRefs\" condition to False for this Listener with the \"InvalidRouteKinds\" reason.\n\nSupport: Core", Type: []string{"array"}, @@ -3004,6 +3014,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref common.ReferenceCa Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -3079,6 +3094,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.Refer Type: []string{"object"}, Properties: map[string]spec.Schema{ "caCertificateRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain TLS certificates of the Certificate Authorities that can be used as a trust anchor to validate the certificates presented by the client.\n\nA single CA certificate reference to a Kubernetes ConfigMap has \"Core\" support. Implementations MAY choose to support attaching multiple CA certificates to a Listener, but this behavior is implementation-specific.\n\nSupport: Core - A single reference to a Kubernetes ConfigMap with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific (More than one reference, or other kinds of resources).\n\nReferences to a resource in a different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.", Type: []string{"array"}, @@ -3152,6 +3172,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCBackendRef(ref common.ReferenceCal }, }, "filters": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Filters defined at this level MUST be executed if and only if the request is being forwarded to the backend defined here.\n\nSupport: Implementation-specific (For broader support of filters, use the Filters field in GRPCRouteRule.)", Type: []string{"array"}, @@ -3450,6 +3475,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteRule(ref common.ReferenceCall }, }, "matches": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Matches define conditions used for matching the rule against incoming gRPC requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied.\n\nFor example, take the following matches configuration:\n\n``` matches: - method:\n service: foo.bar\n headers:\n values:\n version: 2\n- method:\n service: foo.bar.v2\n```\n\nFor a request to match against this rule, it MUST satisfy EITHER of the two conditions:\n\n- service of foo.bar AND contains the header `version: 2` - service of foo.bar.v2\n\nSee the documentation for GRPCRouteMatch on how to specify multiple match conditions to be ANDed together.\n\nIf no matches are specified, the implementation MUST match every gRPC request.\n\nProxy or Load Balancer routing configuration generated from GRPCRoutes MUST prioritize rules based on the following criteria, continuing on ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. Precedence MUST be given to the rule with the largest number of:\n\n* Characters in a matching non-wildcard hostname. * Characters in a matching hostname. * Characters in a matching service. * Characters in a matching method. * Header matches.\n\nIf ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties:\n\n* The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by\n \"{namespace}/{name}\".\n\nIf ties still exist within the Route that has been given precedence, matching precedence MUST be granted to the first matching rule meeting the above criteria.", Type: []string{"array"}, @@ -3464,6 +3494,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteRule(ref common.ReferenceCall }, }, "filters": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Filters define the filters that are applied to requests that match this rule.\n\nThe effects of ordering of multiple behaviors are currently unspecified. This can change in the future based on feedback during the alpha stage.\n\nConformance-levels at this level are defined based on the type of filter:\n\n- ALL core filters MUST be supported by all implementations that support\n GRPCRoute.\n- Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across\n implementations.\n\nSpecifying the same filter multiple times is not supported unless explicitly indicated in the filter.\n\nIf an implementation cannot support a combination of filters, it must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error.\n\nSupport: Core", Type: []string{"array"}, @@ -3478,6 +3513,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteRule(ref common.ReferenceCall }, }, "backendRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "BackendRefs defines the backend(s) where matching requests should be sent.\n\nFailure behavior here depends on how many BackendRefs are specified and how many are invalid.\n\nIf *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive an `UNAVAILABLE` status.\n\nSee the GRPCBackendRef definition for the rules about what makes a single GRPCBackendRef invalid.\n\nWhen a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive an `UNAVAILABLE` status.\n\nFor example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. Implementations may choose how that 50 percent is determined.\n\nSupport: Core for Kubernetes Service\n\nSupport: Implementation-specific for any other resource\n\nSupport for weight: Core", Type: []string{"array"}, @@ -3513,6 +3553,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -3527,6 +3572,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, }, "hostnames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Hostnames defines a set of hostnames to match against the GRPC Host header to select a GRPCRoute to process the request. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label MUST appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and GRPCRoute, there MUST be at least one intersecting hostname for the GRPCRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches GRPCRoutes\n that have either not specified any hostnames, or have specified at\n least one of `test.example.com` or `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches GRPCRoutes\n that have either not specified any hostnames or have specified at least\n one hostname that matches the Listener hostname. For example,\n `test.example.com` and `*.example.com` would both match. On the other\n hand, `example.com` and `test.example.net` would not match.\n\nHostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`.\n\nIf both the Listener and GRPCRoute have specified hostnames, any GRPCRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the GRPCRoute specified `test.example.com` and `test.example.net`, `test.example.net` MUST NOT be considered for a match.\n\nIf both the Listener and GRPCRoute have specified hostnames, and none match with the criteria above, then the GRPCRoute MUST NOT be accepted by the implementation. The implementation MUST raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nIf a Route (A) of type HTTPRoute or GRPCRoute is attached to a Listener and that listener already has another Route (B) of the other type attached and the intersection of the hostnames of A and B is non-empty, then the implementation MUST accept exactly one of these two routes, determined by the following criteria, in order:\n\n* The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by\n \"{namespace}/{name}\".\n\nThe rejected Route MUST raise an 'Accepted' condition with a status of 'False' in the corresponding RouteParentStatus.\n\nSupport: Core", Type: []string{"array"}, @@ -3542,6 +3592,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteSpec(ref common.ReferenceCall }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of GRPC matchers, filters and actions.\n\n", Type: []string{"array"}, @@ -3571,6 +3626,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteStatus(ref common.ReferenceCa Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -3998,6 +4058,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, }, "addresses": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in the associated entry in GatewayStatus.Addresses.\n\nThe Addresses field represents a request for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to.\n\nIf no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses.\n\nThe implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses.\n\nSupport: Extended\n\n", Type: []string{"array"}, @@ -4073,6 +4138,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayStatus(ref common.ReferenceCall Type: []string{"object"}, Properties: map[string]spec.Schema{ "addresses": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Addresses lists the network addresses that have been bound to the Gateway.\n\nThis list may differ from the addresses provided in the spec under some conditions:\n\n * no addresses are specified, all addresses are dynamically assigned\n * a combination of specified and dynamic addresses are assigned\n * a specified address was unusable (e.g. already in use)\n\n", Type: []string{"array"}, @@ -4181,6 +4251,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayTLSConfig(ref common.ReferenceC }, }, "certificateRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener.\n\nA single CertificateRef to a Kubernetes Secret has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific.\n\nReferences to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.\n\nThis field is required to have at least one element when the mode is set to \"Terminate\" (default) and is optional otherwise.\n\nCertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources.\n\nSupport: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls\n\nSupport: Implementation-specific (More than one reference or other resource types)", Type: []string{"array"}, @@ -4275,6 +4350,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPBackendRef(ref common.ReferenceCal }, }, "filters": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Filters defined at this level should be executed if and only if the request is being forwarded to the backend defined here.\n\nSupport: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.)", Type: []string{"array"}, @@ -4980,6 +5060,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteRetry(ref common.ReferenceCal Type: []string{"object"}, Properties: map[string]spec.Schema{ "codes": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Codes defines the HTTP response status codes for which a backend request should be retried.\n\nSupport: Extended", Type: []string{"array"}, @@ -5029,6 +5114,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteRule(ref common.ReferenceCall }, }, "matches": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Matches define conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied.\n\nFor example, take the following matches configuration:\n\n``` matches: - path:\n value: \"/foo\"\n headers:\n - name: \"version\"\n value: \"v2\"\n- path:\n value: \"/v2/foo\"\n```\n\nFor a request to match against this rule, a request must satisfy EITHER of the two conditions:\n\n- path prefixed with `/foo` AND contains the header `version: v2` - path prefix of `/v2/foo`\n\nSee the documentation for HTTPRouteMatch on how to specify multiple match conditions that should be ANDed together.\n\nIf no matches are specified, the default is a prefix path match on \"/\", which has the effect of matching every HTTP request.\n\nProxy or Load Balancer routing configuration generated from HTTPRoutes MUST prioritize matches based on the following criteria, continuing on ties. Across all rules specified on applicable Routes, precedence must be given to the match having:\n\n* \"Exact\" path match. * \"Prefix\" path match with largest number of characters. * Method match. * Largest number of header matches. * Largest number of query param matches.\n\nNote: The precedence of RegularExpression path matches are implementation-specific.\n\nIf ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties:\n\n* The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by\n \"{namespace}/{name}\".\n\nIf ties still exist within an HTTPRoute, matching precedence MUST be granted to the FIRST matching rule (in list order) with a match meeting the above criteria.\n\nWhen no rules matching a request have been successfully attached to the parent a request is coming from, a HTTP 404 status code MUST be returned.", Type: []string{"array"}, @@ -5043,6 +5133,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteRule(ref common.ReferenceCall }, }, "filters": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Filters define the filters that are applied to requests that match this rule.\n\nWherever possible, implementations SHOULD implement filters in the order they are specified.\n\nImplementations MAY choose to implement this ordering strictly, rejecting any combination or order of filters that cannot be supported. If implementations choose a strict interpretation of filter ordering, they MUST clearly document that behavior.\n\nTo reject an invalid combination or order of filters, implementations SHOULD consider the Route Rules with this configuration invalid. If all Route Rules in a Route are invalid, the entire Route would be considered invalid. If only a portion of Route Rules are invalid, implementations MUST set the \"PartiallyInvalid\" condition for the Route.\n\nConformance-levels at this level are defined based on the type of filter:\n\n- ALL core filters MUST be supported by all implementations. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across\n implementations.\n\nSpecifying the same filter multiple times is not supported unless explicitly indicated in the filter.\n\nAll filters are expected to be compatible with each other except for the URLRewrite and RequestRedirect filters, which may not be combined. If an implementation cannot support other combinations of filters, they must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error.\n\nSupport: Core", Type: []string{"array"}, @@ -5057,6 +5152,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteRule(ref common.ReferenceCall }, }, "backendRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "BackendRefs defines the backend(s) where matching requests should be sent.\n\nFailure behavior here depends on how many BackendRefs are specified and how many are invalid.\n\nIf *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive a 500 status code.\n\nSee the HTTPBackendRef definition for the rules about what makes a single HTTPBackendRef invalid.\n\nWhen a HTTPBackendRef is invalid, 500 status codes MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive a 500 status code.\n\nFor example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic must receive a 500. Implementations may choose how that 50 percent is determined.\n\nWhen a HTTPBackendRef refers to a Service that has no ready endpoints, implementations SHOULD return a 503 for requests to that backend instead. If an implementation chooses to do this, all of the above rules for 500 responses MUST also apply for responses that return a 503.\n\nSupport: Core for Kubernetes Service\n\nSupport: Extended for Kubernetes ServiceImport\n\nSupport: Implementation-specific for any other resource\n\nSupport for weight: Core", Type: []string{"array"}, @@ -5104,6 +5204,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -5118,6 +5223,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, }, "hostnames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Hostnames defines a set of hostnames that should match against the HTTP Host header to select a HTTPRoute used to process the request. Implementations MUST ignore any port value specified in the HTTP Host header while performing a match and (absent of any applicable header modification configuration) MUST forward this header unmodified to the backend.\n\nValid values for Hostnames are determined by RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and HTTPRoute, there must be at least one intersecting hostname for the HTTPRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches HTTPRoutes\n that have either not specified any hostnames, or have specified at\n least one of `test.example.com` or `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches HTTPRoutes\n that have either not specified any hostnames or have specified at least\n one hostname that matches the Listener hostname. For example,\n `*.example.com`, `test.example.com`, and `foo.test.example.com` would\n all match. On the other hand, `example.com` and `test.example.net` would\n not match.\n\nHostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`.\n\nIf both the Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the HTTPRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and HTTPRoute have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nIn the event that multiple HTTPRoutes specify intersecting hostnames (e.g. overlapping wildcard matching and exact matching hostnames), precedence must be given to rules from the HTTPRoute with the largest number of:\n\n* Characters in a matching non-wildcard hostname. * Characters in a matching hostname.\n\nIf ties exist across multiple Routes, the matching precedence rules for HTTPRouteMatches takes over.\n\nSupport: Core", Type: []string{"array"}, @@ -5133,6 +5243,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteSpec(ref common.ReferenceCall }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of HTTP matchers, filters and actions.\n\n", Type: []string{"array"}, @@ -5162,6 +5277,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteStatus(ref common.ReferenceCa Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -5342,6 +5462,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_ListenerStatus(ref common.ReferenceCal }, }, "supportedKinds": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration.\n\nIf kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified.", Type: []string{"array"}, @@ -5734,6 +5859,11 @@ func schema_sigsk8sio_gateway_api_apis_v1_RouteStatus(ref common.ReferenceCallba Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -6172,6 +6302,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyStatus(ref common.Referenc Type: []string{"object"}, Properties: map[string]spec.Schema{ "ancestors": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Ancestors is a list of ancestor resources (usually Gateways) that are associated with the policy, and the status of the policy with respect to each ancestor. When this policy attaches to a parent, the controller that manages the parent and the ancestors MUST add an entry to this list when the controller first sees the policy and SHOULD update the entry as appropriate when the relevant ancestor is modified.\n\nNote that choosing the relevant ancestor is left to the Policy designers; an important part of Policy design is designing the right object level at which to namespace this status.\n\nNote also that implementations MUST ONLY populate ancestor status for the Ancestor resources they are responsible for. Implementations MUST use the ControllerName field to uniquely identify the entries in this list that they are responsible for.\n\nNote that to achieve this, the list of PolicyAncestorStatus structs MUST be treated as a map with a composite key, made up of the AncestorRef and ControllerName fields combined.\n\nA maximum of 16 ancestors will be represented in this list. An empty list means the Policy is not relevant for any ancestors.\n\nIf this slice is full, implementations MUST NOT add further entries. Instead they MUST consider the policy unimplementable and signal that on any related resources such as the ancestor that would be referenced here. For example, if this list was full on BackendTLSPolicy, no additional Gateways would be able to reference the Service targeted by the BackendTLSPolicy.", Type: []string{"array"}, @@ -6399,6 +6534,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteRule(ref common.Referenc }, }, "backendRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a nonexistent resource or a Service with no endpoints), the underlying implementation MUST actively reject connection attempts to this backend. Connection rejections must respect weight; if an invalid backend is requested to have 80% of connections, then 80% of connections must be rejected instead.\n\nSupport: Core for Kubernetes Service\n\nSupport: Extended for Kubernetes ServiceImport\n\nSupport: Implementation-specific for any other resource\n\nSupport for weight: Extended", Type: []string{"array"}, @@ -6429,6 +6569,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -6443,6 +6588,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteSpec(ref common.Referenc }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of TCP matchers and actions.\n\n", Type: []string{"array"}, @@ -6473,6 +6623,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteStatus(ref common.Refere Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -6609,6 +6764,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteRule(ref common.Referenc }, }, "backendRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a nonexistent resource or a Service with no endpoints), the rule performs no forwarding; if no filters are specified that would result in a response being sent, the underlying implementation must actively reject request attempts to this backend, by rejecting the connection or returning a 500 status code. Request rejections must respect weight; if an invalid backend is requested to have 80% of requests, then 80% of requests must be rejected instead.\n\nSupport: Core for Kubernetes Service\n\nSupport: Extended for Kubernetes ServiceImport\n\nSupport: Implementation-specific for any other resource\n\nSupport for weight: Extended", Type: []string{"array"}, @@ -6639,6 +6799,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -6653,6 +6818,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, }, "hostnames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Hostnames defines a set of SNI names that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed in SNI names per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames, or have specified at\n least one of `test.example.com` or `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches TLSRoutes\n that have either not specified any hostnames or have specified at least\n one hostname that matches the Listener hostname. For example,\n `test.example.com` and `*.example.com` would both match. On the other\n hand, `example.com` and `test.example.net` would not match.\n\nIf both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nSupport: Core", Type: []string{"array"}, @@ -6668,6 +6838,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteSpec(ref common.Referenc }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of TLS matchers and actions.\n\n", Type: []string{"array"}, @@ -6698,6 +6873,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteStatus(ref common.Refere Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -6834,6 +7014,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteRule(ref common.Referenc }, }, "backendRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a nonexistent resource or a Service with no endpoints), the underlying implementation MUST actively reject connection attempts to this backend. Packet drops must respect weight; if an invalid backend is requested to have 80% of the packets, then 80% of packets must be dropped instead.\n\nSupport: Core for Kubernetes Service\n\nSupport: Extended for Kubernetes ServiceImport\n\nSupport: Implementation-specific for any other resource\n\nSupport for weight: Extended", Type: []string{"array"}, @@ -6864,6 +7049,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -6878,6 +7068,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteSpec(ref common.Referenc }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of UDP matchers and actions.\n\n", Type: []string{"array"}, @@ -6908,6 +7103,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteStatus(ref common.Refere Type: []string{"object"}, Properties: map[string]spec.Schema{ "parents": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", Type: []string{"array"}, @@ -7037,6 +7237,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicySpec(ref common. Type: []string{"object"}, Properties: map[string]spec.Schema{ "targetRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy.\n\nTargetRefs must be _distinct_. This means either that:\n\n* They select different targets. If this is the case, then targetRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, and `name` must\n be unique across all targetRef entries in the BackendTLSPolicy.\n* They select different sectionNames in the same target.\n\nSupport: Extended for Kubernetes Service\n\nSupport: Implementation-specific for any other resource", Type: []string{"array"}, @@ -7090,6 +7295,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c Type: []string{"object"}, Properties: map[string]spec.Schema{ "caCertificateRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod.\n\nIf CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation.\n\nReferences to a resource in a different namespace are invalid for the moment, although we will revisit this in the future.\n\nA single CACertificateRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific.\n\nSupport: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific (More than one reference, or other kinds of resources).", Type: []string{"array"}, @@ -7104,6 +7314,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, }, "wellKnownCACertificates": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod.\n\nIf WellKnownCACertificates is unspecified or empty (\"\"), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field or the value supplied is not supported, the Status Conditions on the Policy MUST be updated to include an Accepted: False Condition with Reason: Invalid.\n\nSupport: Implementation-specific", Type: []string{"string"}, @@ -7119,6 +7334,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, }, "subjectAltNames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "SubjectAltNames contains one or more Subject Alternative Names. When specified the certificate served from the backend MUST have at least one Subject Alternate Name matching one of the specified SubjectAltNames.\n\nSupport: Extended", Type: []string{"array"}, @@ -7284,6 +7504,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc Type: []string{"object"}, Properties: map[string]spec.Schema{ "parentRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route.\n\nThere are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nParentRefs must be _distinct_. This means either that:\n\n* They select different objects. If this is the case, then parentRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, `namespace`, and `name` must\n be unique across all parentRef entries in the Route.\n* They do not select different objects, but for each optional field used,\n each ParentRef that selects the same object must set the same set of\n optional fields to different values. If one ParentRef sets a\n combination of optional fields, all must set the same combination.\n\nSome examples:\n\n* If one ParentRef sets `sectionName`, all ParentRefs referencing the\n same object must also set `sectionName`.\n* If one ParentRef sets `port`, all ParentRefs referencing the same\n object must also set `port`.\n* If one ParentRef sets `sectionName` and `port`, all ParentRefs\n referencing the same object must also set `sectionName` and `port`.\n\nIt is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged.\n\nNote that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference.\n\n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service.\n\nParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n\n ", Type: []string{"array"}, @@ -7298,6 +7523,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, }, "hostnames": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Hostnames defines a set of SNI hostnames that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions:\n\n1. IPs are not allowed in SNI hostnames per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard\n label must appear by itself as the first label.\n\nIf a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example:\n\n* A Listener with `test.example.com` as the hostname matches TLSRoutes\n that have specified at least one of `test.example.com` or\n `*.example.com`.\n* A Listener with `*.example.com` as the hostname matches TLSRoutes\n that have specified at least one hostname that matches the Listener\n hostname. For example, `test.example.com` and `*.example.com` would both\n match. On the other hand, `example.com` and `test.example.net` would not\n match.\n\nIf both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match.\n\nIf both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus.\n\nSupport: Core", Type: []string{"array"}, @@ -7313,6 +7543,11 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_TLSRouteSpec(ref common.Referenc }, }, "rules": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Rules are a list of actions.\n\n", Type: []string{"array"}, @@ -7769,6 +8004,11 @@ func schema_sigsk8sio_gateway_api_apis_v1beta1_ReferenceGrantSpec(ref common.Ref Type: []string{"object"}, Properties: map[string]spec.Schema{ "from": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "From describes the trusted namespaces and kinds that can reference the resources described in \"To\". Each entry in this list MUST be considered to be an additional place that references can be valid from, or to put this another way, entries MUST be combined using OR.\n\nSupport: Core", Type: []string{"array"}, @@ -7783,6 +8023,11 @@ func schema_sigsk8sio_gateway_api_apis_v1beta1_ReferenceGrantSpec(ref common.Ref }, }, "to": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "To describes the resources that may be referenced by the resources described in \"From\". Each entry in this list MUST be considered to be an additional place that references can be valid to, or to put this another way, entries MUST be combined using OR.\n\nSupport: Core", Type: []string{"array"}, @@ -8002,6 +8247,11 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntryStatus(ref common. }, }, "supportedKinds": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, SchemaProps: spec.SchemaProps{ Description: "SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration.\n\nIf kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified.", Type: []string{"array"}, From bee090d4eaab79948f05b15f17bf6c5824cf01bf Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Thu, 7 Aug 2025 16:01:43 +0200 Subject: [PATCH 116/224] Invalid BackendTLSPolicy conformance test (#3930) --- conformance/tests/backendtlspolicy.go | 56 +++++++++-- conformance/tests/backendtlspolicy.yaml | 124 ++++++++++++++++++++---- conformance/utils/http/http.go | 34 +++++++ conformance/utils/kubernetes/helpers.go | 33 +++++++ conformance/utils/suite/suite.go | 2 + pkg/features/backendtlspolicy.go | 2 +- 6 files changed, 225 insertions(+), 26 deletions(-) diff --git a/conformance/tests/backendtlspolicy.go b/conformance/tests/backendtlspolicy.go index 1d55627816..fc6c6576eb 100644 --- a/conformance/tests/backendtlspolicy.go +++ b/conformance/tests/backendtlspolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2024 The Kubernetes Authors. +Copyright 2025 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,9 +19,12 @@ package tests import ( "testing" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -35,7 +38,7 @@ func init() { var BackendTLSPolicy = suite.ConformanceTest{ ShortName: "BackendTLSPolicy", - Description: "A single service that is targeted by a BackendTLSPolicy must successfully complete TLS termination", + Description: "BackendTLSPolicy must be used to configure TLS connection between gateway and backend", Features: []features.FeatureName{ features.SupportGateway, features.SupportHTTPRoute, @@ -51,10 +54,25 @@ var BackendTLSPolicy = suite.ConformanceTest{ gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + policyCond := metav1.Condition{ + Type: string(v1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(v1alpha2.PolicyReasonAccepted), + } + + validPolicyNN := types.NamespacedName{Name: "normative-test-backendtlspolicy", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, policyCond) + + invalidPolicyNN := types.NamespacedName{Name: "backendtlspolicy-host-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, policyCond) + + invalidCertPolicyNN := types.NamespacedName{Name: "backendtlspolicy-cert-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, policyCond) + serverStr := "abc.example.com" - // Verify that the response to a backend-tls-only call to /backendTLS will return the matching SNI. - t.Run("Simple HTTP request targeting BackendTLSPolicy should reach infra-backend", func(t *testing.T) { + // Verify that the request sent to Service with valid BackendTLSPolicy should succeed. + t.Run("HTTP request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, h.ExpectedResponse{ Namespace: ns, @@ -73,8 +91,8 @@ var BackendTLSPolicy = suite.ConformanceTest{ if err != nil { t.Fatalf("unexpected error finding TLS secret: %v", err) } - // Verify that the response to a re-encrypted call to /backendTLS will return the matching SNI. - t.Run("Re-encrypt HTTPS request targeting BackendTLSPolicy should reach infra-backend", func(t *testing.T) { + // Verify that the request to a re-encrypted call to /backendTLS should succeed. + t.Run("Re-encrypt HTTPS request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, keyPem, serverStr, h.ExpectedResponse{ Namespace: ns, @@ -86,5 +104,31 @@ var BackendTLSPolicy = suite.ConformanceTest{ Response: h.Response{StatusCode: 200}, }) }) + + // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched host will fail. + t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched hostname should return an HTTP error", func(t *testing.T) { + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSHostMismatch", + SNI: serverStr, + }, + }) + }) + + // Verify that request sent to Service targeted by BackendTLSPolicy with mismatched cert should failed. + t.Run("HTTP request send to Service targeted by BackendTLSPolicy with mismatched cert should return HTTP error", func(t *testing.T) { + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSCertMismatch", + SNI: serverStr, + }, + }) + }) }, } diff --git a/conformance/tests/backendtlspolicy.yaml b/conformance/tests/backendtlspolicy.yaml index 91f6a590f9..e048cc2e7b 100644 --- a/conformance/tests/backendtlspolicy.yaml +++ b/conformance/tests/backendtlspolicy.yaml @@ -31,25 +31,6 @@ spec: kinds: - kind: HTTPRoute --- -apiVersion: gateway.networking.k8s.io/v1alpha3 -kind: BackendTLSPolicy -metadata: - name: normative-test-backendtlspolicy - namespace: gateway-conformance-infra -spec: - targetRefs: - - group: "" - kind: Service - name: "backendtlspolicy-test" - sectionName: "btls" - validation: - caCertificateRefs: - - group: "" - kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-checks-certificate" - hostname: "abc.example.com" ---- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: @@ -71,6 +52,24 @@ spec: - path: type: Exact value: /backendTLS + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-host-mismatch-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSHostMismatch + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-cert-mismatch-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSCertMismatch --- apiVersion: v1 kind: Service @@ -86,6 +85,36 @@ spec: port: 443 targetPort: 8443 --- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-host-mismatch-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-cert-mismatch-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- # Deployment must not be applied until after the secret is generated. apiVersion: apps/v1 kind: Deployment @@ -151,3 +180,60 @@ spec: path: crt - key: tls.key path: key +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: normative-test-backendtlspolicy + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-test" + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-checks-certificate" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-host-mismatch + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-host-mismatch-test" + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-checks-certificate" + hostname: "mismatch.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-cert-mismatch + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-cert-mismatch-test" + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-mismatch-certificate" + hostname: "abc.example.com" diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index e1aca27d54..91ebf2254e 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -117,6 +117,17 @@ func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, r roundtripp WaitForConsistentResponse(t, r, req, expected, timeoutConfig.RequiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency) } +// MakeRequestAndExpectFailure makes a request with the given parameters. +// This function needs to ensure that after the system is stable the Request is +// not returning http 200 StatusCode. +func MakeRequestAndExpectFailure(t *testing.T, r roundtripper.RoundTripper, timeoutConfig config.TimeoutConfig, gwAddr string, expected ExpectedResponse) { + t.Helper() + + req := MakeRequest(t, &expected, gwAddr, "HTTP", "http") + + WaitForConsistentFailureResponse(t, r, req, 5, timeoutConfig.MaxTimeToConsistency) +} + func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, scheme string) roundtripper.Request { t.Helper() @@ -261,6 +272,29 @@ func WaitForConsistentResponse(t *testing.T, r roundtripper.RoundTripper, req ro tlog.Logf(t, "Request passed") } +// WaitForConsistentFailureResponse repeats the provided request for the given +// period of time and ensures an error is returned each time. This function fails +// when HTTP Status OK (200) is returned. +func WaitForConsistentFailureResponse(t *testing.T, r roundtripper.RoundTripper, req roundtripper.Request, threshold int, maxTimeToConsistency time.Duration) { + AwaitConvergence(t, threshold, maxTimeToConsistency, func(elapsed time.Duration) bool { + _, cRes, err := r.CaptureRoundTrip(req) + if err != nil { + tlog.Logf(t, "Request failed, not ready yet: %v (after %v)", err.Error(), elapsed) + return false + } + if roundtripper.IsTimeoutError(cRes.StatusCode) { + tlog.Logf(t, "Response expectation failed for request: %+v not ready yet: %v (after %v)", req, cRes.StatusCode, elapsed) + return false + } + if cRes.StatusCode == 200 { // http:StatusCode OK + t.Fatalf("Request %+v should failed, returned HTTP Status OK (200) instead", req) + return false + } + return true + }) + tlog.Logf(t, "Expectation for failing Request are met") +} + func CompareRoundTrip(t *testing.T, req *roundtripper.Request, cReq *roundtripper.CapturedRequest, cRes *roundtripper.CapturedResponse, expected ExpectedResponse) error { if roundtripper.IsTimeoutError(cRes.StatusCode) { if roundtripper.IsTimeoutError(expected.Response.StatusCode) { diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 9e385b4caa..8075132da1 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -37,6 +37,7 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1alpha3" "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/tlog" ) @@ -993,3 +994,35 @@ func findPodConditionInList(t *testing.T, conditions []v1.PodCondition, condName tlog.Logf(t, "%s was not in conditions list", condName) return false } + +// BackendTLSPolicyMustHaveCondition checks that the created BackentTLSPolicy has the Condition, +// halting after the specified timeout is exceeded. +func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeoutConfig config.TimeoutConfig, policyNN, gwNN types.NamespacedName, condition metav1.Condition) { + t.Helper() + waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, timeoutConfig.HTTPRouteMustHaveCondition, true, func(ctx context.Context) (bool, error) { + policy := &v1alpha3.BackendTLSPolicy{} + err := client.Get(ctx, policyNN, policy) + if err != nil { + return false, fmt.Errorf("error fetching BackendTLSPolicy: %w", err) + } + + for _, parent := range policy.Status.Ancestors { + if err := ConditionsHaveLatestObservedGeneration(policy, parent.Conditions); err != nil { + tlog.Logf(t, "BackendTLSPolicy %s (parentRef=%v) %v", + policyNN, parentRefToString(parent.AncestorRef), err, + ) + return false, nil + } + + if parent.AncestorRef.Name == gatewayv1.ObjectName(gwNN.Name) && (parent.AncestorRef.Namespace == nil || string(*parent.AncestorRef.Namespace) == gwNN.Namespace) { + if findConditionInList(t, parent.Conditions, condition.Type, string(condition.Status), condition.Reason) { + return true, nil + } + } + } + + return false, nil + }) + + require.NoErrorf(t, waitErr, "error waiting for BackendTLSPolicy status to have a Condition %v", condition) +} diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index b34a1ea3ff..858fea2ed1 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -383,6 +383,8 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) secret = kubernetes.MustCreateSelfSignedCertSecret(t, "gateway-conformance-app-backend", "tls-passthrough-checks-certificate", []string{"abc.example.com"}) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) + caConfigMapBST, _, _ := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-mismatch-certificate", []string{"nex.example.com"}) + suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMapBST}, suite.Cleanup) caConfigMap, ca, caPrivKey := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-checks-certificate", []string{"abc.example.com"}) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey) diff --git a/pkg/features/backendtlspolicy.go b/pkg/features/backendtlspolicy.go index 8763b32dd1..95d5017164 100644 --- a/pkg/features/backendtlspolicy.go +++ b/pkg/features/backendtlspolicy.go @@ -1,5 +1,5 @@ /* -Copyright 2024 The Kubernetes Authors. +Copyright 2025 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From fb75360bd54bb7e380b8fa56c725cbec4d492ce5 Mon Sep 17 00:00:00 2001 From: Mahesh Rijal <62394512+maheshrijal@users.noreply.github.com> Date: Thu, 7 Aug 2025 21:43:42 +0530 Subject: [PATCH 117/224] fix typo (#3976) --- site-src/implementations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index 791f5450d3..46335451c9 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -271,7 +271,7 @@ performance, and avoid the operational complexity of sidecars. Cilium also supports the sidecar proxy model, offering choice to users. As of [Cilium 1.14][cilium114blog], Cilium supports Gateway API, passing conformance for v0.7.1. -Cilium is open source and is a CNCF Graduates project. +Cilium is open source and is a CNCF Graduated project. If you have questions about Cilium Service Mesh the #service-mesh channel on [Cilium Slack][cilium-slack] is a good place to start. For contributing to the development From b167eedffc15a90ad1a3926a1b9066a70791a2bb Mon Sep 17 00:00:00 2001 From: John Howard Date: Thu, 7 Aug 2025 17:21:43 -0700 Subject: [PATCH 118/224] Add gateway class label to generated objects (#3955) This proposes adding an optional new label to generated objects. This is useful for general querying, such as "find the total CPU usage of all pods created by ". --- geps/gep-1762/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/geps/gep-1762/index.md b/geps/gep-1762/index.md index e5f4ebf395..eb25e53859 100644 --- a/geps/gep-1762/index.md +++ b/geps/gep-1762/index.md @@ -59,6 +59,7 @@ With this configuration, an implementation: * MUST mark the Gateway as `Programmed` and provide an address in `Status.Addresses` where the Gateway can be reached on each configured port. * MUST label all generated resources (Service, Deployment, etc) with `gateway.networking.k8s.io/gateway-name: my-gateway` (where `my-gateway` is the name of the Gateway resource). +* SHOULD label all generated resources (Service, Deployment, etc) with `gateway.networking.k8s.io/gateway-class-name: my-gateway-class` (where `my-gateway-class` is the name of the GatewayClass resource). * MUST provision generated resources in the same namespace as the Gateway if they are namespace scoped resources. * Cluster scoped resources are not recommended. * SHOULD name all generated resources `my-gateway-example` (`-`). From 372a5b06624cff12117f41dcd26c08cb1def22e7 Mon Sep 17 00:00:00 2001 From: carson <127476216+carsontham@users.noreply.github.com> Date: Tue, 12 Aug 2025 00:05:13 +0800 Subject: [PATCH 119/224] added entropy to HTTPRoute-weight (#3880) Signed-off-by: carsontham --- conformance/tests/httproute-weight.go | 6 ++- conformance/tests/mesh/httproute-weight.go | 56 +--------------------- conformance/utils/http/http.go | 53 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/conformance/tests/httproute-weight.go b/conformance/tests/httproute-weight.go index 2c1a520dc0..fa85deb9bf 100644 --- a/conformance/tests/httproute-weight.go +++ b/conformance/tests/httproute-weight.go @@ -91,7 +91,6 @@ func testDistribution(t *testing.T, suite *suite.ConformanceTestSuite, gwAddr st g errgroup.Group seenMutex sync.Mutex seen = make(map[string]float64, 3 /* number of backends */) - req = http.MakeRequest(t, &expected, gwAddr, "HTTP", "http") expectedWeights = map[string]float64{ "infra-backend-v1": 0.7, "infra-backend-v2": 0.3, @@ -101,6 +100,11 @@ func testDistribution(t *testing.T, suite *suite.ConformanceTestSuite, gwAddr st g.SetLimit(concurrentRequests) for i := 0.0; i < totalRequests; i++ { g.Go(func() error { + uniqueExpected := expected + if err := http.AddEntropy(&uniqueExpected); err != nil { + return fmt.Errorf("error adding entropy: %w", err) + } + req := http.MakeRequest(t, &uniqueExpected, gwAddr, "HTTP", "http") cReq, cRes, err := roundTripper.CaptureRoundTrip(req) if err != nil { return fmt.Errorf("failed to roundtrip request: %w", err) diff --git a/conformance/tests/mesh/httproute-weight.go b/conformance/tests/mesh/httproute-weight.go index cc296d92d5..844d5471e7 100644 --- a/conformance/tests/mesh/httproute-weight.go +++ b/conformance/tests/mesh/httproute-weight.go @@ -18,16 +18,13 @@ package meshtests import ( "cmp" - "crypto/rand" "errors" "fmt" "math" - "math/big" "slices" "strings" "sync" "testing" - "time" "golang.org/x/sync/errgroup" @@ -93,7 +90,7 @@ func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedR for i := 0.0; i < totalRequests; i++ { g.Go(func() error { uniqueExpected := expected - if err := addEntropy(&uniqueExpected); err != nil { + if err := http.AddEntropy(&uniqueExpected); err != nil { return fmt.Errorf("error adding entropy: %w", err) } _, cRes, err := client.CaptureRequestResponseAndCompare(t, uniqueExpected) @@ -148,54 +145,3 @@ func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedR }) return errors.Join(errs...) } - -// addEntropy adds jitter to the request by adding either a delay up to 1 second, or a random header value, or both. -func addEntropy(exp *http.ExpectedResponse) error { - randomNumber := func(limit int64) (*int64, error) { - number, err := rand.Int(rand.Reader, big.NewInt(limit)) - if err != nil { - return nil, err - } - n := number.Int64() - return &n, nil - } - - // adds a delay - delay := func(limit int64) error { - randomSleepDuration, err := randomNumber(limit) - if err != nil { - return err - } - time.Sleep(time.Duration(*randomSleepDuration) * time.Millisecond) - return nil - } - // adds random header value - randomHeader := func(limit int64) error { - randomHeaderValue, err := randomNumber(limit) - if err != nil { - return err - } - exp.Request.Headers = make(map[string]string) - exp.Request.Headers["X-Jitter"] = fmt.Sprintf("%d", *randomHeaderValue) - return nil - } - - random, err := randomNumber(3) - if err != nil { - return err - } - - switch *random { - case 0: - return delay(1000) - case 1: - return randomHeader(10000) - case 2: - if err := delay(1000); err != nil { - return err - } - return randomHeader(10000) - default: - return fmt.Errorf("invalid random value: %d", *random) - } -} diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index 91ebf2254e..da7036daf6 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -17,7 +17,9 @@ limitations under the License. package http import ( + "crypto/rand" "fmt" + "math/big" "net" "net/url" "strings" @@ -478,3 +480,54 @@ func setRedirectRequestDefaults(req *roundtripper.Request, cRes *roundtripper.Ca expected.RedirectRequest.Path = req.URL.Path } } + +// addEntropy adds jitter to the request by adding either a delay up to 1 second, or a random header value, or both. +func AddEntropy(exp *ExpectedResponse) error { + randomNumber := func(limit int64) (*int64, error) { + number, err := rand.Int(rand.Reader, big.NewInt(limit)) + if err != nil { + return nil, err + } + n := number.Int64() + return &n, nil + } + + // adds a delay + delay := func(limit int64) error { + randomSleepDuration, err := randomNumber(limit) + if err != nil { + return err + } + time.Sleep(time.Duration(*randomSleepDuration) * time.Millisecond) + return nil + } + // adds random header value + randomHeader := func(limit int64) error { + randomHeaderValue, err := randomNumber(limit) + if err != nil { + return err + } + exp.Request.Headers = make(map[string]string) + exp.Request.Headers["X-Jitter"] = fmt.Sprintf("%d", *randomHeaderValue) + return nil + } + + random, err := randomNumber(3) + if err != nil { + return err + } + + switch *random { + case 0: + return delay(1000) + case 1: + return randomHeader(10000) + case 2: + if err := delay(1000); err != nil { + return err + } + return randomHeader(10000) + default: + return fmt.Errorf("invalid random value: %d", *random) + } +} From 51488fae6b89900326939784f4bfb1a15de579a7 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:35:07 -0700 Subject: [PATCH 120/224] Change to ignore Mesh features in GWC instead of erroring out. (#3938) * Change to ignore Mesh features in GWC instead of erroring out. * Added comment on what new code does. * Punctuation. * Added extended mesh feture for test suite unit test. --- conformance/utils/suite/suite.go | 13 +++++++------ conformance/utils/suite/suite_test.go | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 858fea2ed1..23c936536a 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -211,8 +211,13 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite, return nil, fmt.Errorf("cannot infer supported features: %w", err) } - if hasMeshFeatures(supportedFeatures) { - return nil, fmt.Errorf("mesh features should not be populated in GatewayClass") + // If Mesh features are populated in the GatewayClass we remove them from the supported features set. + meshFeatureNames := features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures) + for _, f := range supportedFeatures.UnsortedList() { + if meshFeatureNames.Has(f) { + supportedFeatures.Delete(f) + fmt.Printf("WARNING: Mesh feature %q should not be populated in GatewayClass, skipping...", f) + } } source = supportedFeaturesSourceInferred } @@ -660,7 +665,3 @@ func getAPIVersionAndChannel(crds []apiextensionsv1.CustomResourceDefinition) (v return version, channel, nil } - -func hasMeshFeatures(f FeaturesSet) bool { - return f.HasAny(features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures).UnsortedList()...) -} diff --git a/conformance/utils/suite/suite_test.go b/conformance/utils/suite/suite_test.go index 311da616a2..778afa7180 100644 --- a/conformance/utils/suite/suite_test.go +++ b/conformance/utils/suite/suite_test.go @@ -22,7 +22,6 @@ import ( "github.com/stretchr/testify/assert" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" @@ -545,9 +544,8 @@ func TestGWCPublishedMeshFeatures(t *testing.T) { }, SupportedFeatures: featureNamesToSet([]string{ string(features.SupportGateway), - string(features.SupportGatewayStaticAddresses), + string(features.SupportMesh), string(features.SupportMeshClusterIPMatching), - string(features.SupportMeshConsumerRoute), }), }, } @@ -568,9 +566,12 @@ func TestGWCPublishedMeshFeatures(t *testing.T) { Client: fakeClient, } - _, err := NewConformanceTestSuite(options) - if err == nil { - t.Fatalf("expected an error but got nil") + suite, err := NewConformanceTestSuite(options) + if err != nil { + t.Fatalf("error initializing conformance suite: %v", err) + } + if suite.SupportedFeatures.HasAny(features.SetsToNamesSet(features.MeshCoreFeatures, features.MeshExtendedFeatures).UnsortedList()...) { + t.Errorf("Mesh features should be skipped, got: %v", suite.SupportedFeatures.UnsortedList()) } } From 60cdac35c276fa9a5b9d92da05694c97490041e8 Mon Sep 17 00:00:00 2001 From: EyalPazz <67443108+EyalPazz@users.noreply.github.com> Date: Wed, 13 Aug 2025 14:35:08 +0300 Subject: [PATCH 121/224] fix(docs): remove unnecessary array in incorrect example @ gep-1767 (#3991) --- geps/gep-1767/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geps/gep-1767/index.md b/geps/gep-1767/index.md index c115dbf116..14315e190c 100644 --- a/geps/gep-1767/index.md +++ b/geps/gep-1767/index.md @@ -516,7 +516,7 @@ spec: value: /resource/foo filters: - cors: - - allowOrigins: + allowOrigins: - * allowMethods: - GET @@ -575,7 +575,7 @@ spec: value: /resource/foo filters: - cors: - - allowOrigins: + allowOrigins: - https://foo.example - http://foo.example allowCredentials: true From bb58b0d1a1fa10bc1fedd3ef1b11e664a0a94efd Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Wed, 13 Aug 2025 18:11:11 +0200 Subject: [PATCH 122/224] gep: standardizing behavior for invalid BackendTLSPolicy (#3909) * gep: standardizing behavior for invalid BackendTLSPolicy Signed-off-by: Norwin Schnyder * Apply PR feedback Signed-off-by: Norwin Schnyder * Incorporate feedback from various discussions Signed-off-by: Norwin Schnyder * Introduce ResolvedRefs status condition for BackendTLSPolicy * Apply PR suggestions and feedback Signed-off-by: Norwin Schnyder * Fix typos Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- geps/gep-1897/index.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/geps/gep-1897/index.md b/geps/gep-1897/index.md index 4571c70335..8e24b8bf09 100644 --- a/geps/gep-1897/index.md +++ b/geps/gep-1897/index.md @@ -214,6 +214,13 @@ configuration. CACertificateRefs is an implementation-specific slice of named object references, each containing a single cert. We originally proposed to follow the convention established by the [CertificateRefs field on Gateway](https://github.com/kubernetes-sigs/gateway-api/blob/18e79909f7310aafc625ba7c862dfcc67b385250/apis/v1beta1/gateway_types.go#L340) , but the CertificateRef requires both a tls.key and tls.crt and a certificate reference only requires the tls.crt. +If any of the CACertificateRefs cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured (e.g., ConfigMap does not contain a key named `ca.crt`), the `ResolvedRefs` status condition MUST be set to `False` with `Reason: InvalidCACertificateRef`. Connections using that CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. +References to objects with an unsupported Group and Kind are not valid, and MUST be rejected by the implementation with the `ResolvedRefs` status condition set to `False` and `Reason: UnsupportedFeature`. +Implementations MAY perform further validation of the certificate content (i.e., checking expiry or enforcing specific formats). If they do, they MUST ensure that the `ResolvedRefs` Condition is `False` and use an implementation-specific `Reason`, like `ExpiredCertificate` or similar. +If `ResolvedRefs` Condition is `False` implementations SHOULD include a message specifying which references are invalid and explaining why. + +If all CertificateRefs cannot be resolved, the BackendTLSPolicy is considered invalid and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `NoCACertificates` and a message explaining this. + WellKnownCACertificates is an optional enum that allows users to specify whether to use the set of CA certificates trusted by the Gateway (WellKnownCACertificates specified as "System"), or to use the existing CACertificateRefs (WellKnownCACertificates specified as ""). The use and definition of system certificates is implementation-dependent, and the intent is that @@ -222,8 +229,12 @@ references to Kubernetes objects that contain PEM-encoded TLS certificates, whic between the gateway and backend pod. References to a resource in a different namespace are invalid. If ClientCertificateRefs is unspecified, then WellKnownCACertificates must be set to "System" for a valid configuration. If WellKnownCACertificates is unspecified, then CACertificateRefs must be specified with at least one entry for a valid configuration. -If WellKnownCACertificates is set to "System" and there are no system trusted certificates or the implementation doesn't define system -trusted certificates, then the associated TLS connection must fail. +If an implementation does not support the WellKnownCACertificates, or the provided value is unsupported,the BackendTLSPolicy is considered invalid, and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `UnsupportedFeature` and a message explaining this. + +For an invalid BackendTLSPolicy, implementations MUST NOT fall back to unencrypted (plaintext) connections. +Instead, the corresponding TLS connection MUST fail, and the client MUST receive an HTTP 5xx error response. + +Implementations MUST NOT modify any status other than their own. Ownership of a status is determined by the `controllerName`, which identifies the responsible controller. The `Hostname` field is required and is to be used to configure the SNI the Gateway should use to connect to the backend. Implementations must validate that at least one name in the certificate served by the backend matches this field. From 85839c80afb50239bf442e80503b5deae7501156 Mon Sep 17 00:00:00 2001 From: Beka Modebadze <58038950+bexxmodd@users.noreply.github.com> Date: Wed, 13 Aug 2025 14:21:07 -0700 Subject: [PATCH 123/224] Updated index.md to reflect changes in GEP-2162 (#3898) * Updated index doc and corrected formatting. * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Added details about Mesh and staying compliant. * Wording update. * TODO for what GWC reports. * Added mesh stuff. * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Added summary paragraph for Staying Compliant section. * Update geps/gep-2162/index.md Co-authored-by: Rob Scott * Update geps/gep-2162/index.md Co-authored-by: Rob Scott * Formatting changes. * Added info that suite will throw an error if Mesh features are added to GWC. * Apply suggestions from code review Co-authored-by: Lior Lieberman * Update geps/gep-2162/index.md Co-authored-by: Lior Lieberman * Link issue for populating mesh features in its crd. * Update geps/gep-2162/index.md Co-authored-by: Rob Scott * Update geps/gep-2162/index.md Co-authored-by: Rob Scott --------- Co-authored-by: Lior Lieberman Co-authored-by: Rob Scott --- geps/gep-2162/index.md | 52 +++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/geps/gep-2162/index.md b/geps/gep-2162/index.md index a8959acc8e..25f3371c63 100644 --- a/geps/gep-2162/index.md +++ b/geps/gep-2162/index.md @@ -1,11 +1,11 @@ # GEP-2162: Supported features in GatewayClass Status * Issue: [#2162](https://github.com/kubernetes-sigs/gateway-api/issues/2162) -* Status: Experimental +* Status: Standard ## TLDR -This GEP proposes to enhance the [GatewayClassStatus](https://github.com/kubernetes-sigs/gateway-api/blob/f2cd9bb92b4ff392416c40d6148ff7f76b30e649/apis/v1beta1/gatewayclass_types.go#L185) to include a list of Gateway API features supported by the installed GatewayClass. +This GEP proposes to enhance the [GatewayClassStatus](https://github.com/kubernetes-sigs/gateway-api/blob/f2cd9bb92b4ff392416c40d6148ff7f76b30e649/apis/v1beta1/gatewayclass_types.go#L185) to include a list of Gateway API features supported by the installed GatewayClass. ## Goals @@ -17,16 +17,12 @@ This GEP proposes to enhance the [GatewayClassStatus](https://github.com/kuberne * Provide foundation for tools to block or warn when unsupported features are used. - ## Non-Goals * Validate correctness of supported features published by the implementation. - Meaning we don't intend to verify whether the supported features reported by - the implementation are indeed supported. + Meaning we don't intend to verify whether the supported features reported by the implementation are indeed supported. - However, the supported features in the status of the GatewayClass should - make it very easy for any individual to run conformance tests against the - GatewayClass using our conformance tooling. + However, the supported features in the status of the GatewayClass should make it easy for any individual to run conformance tests against the GatewayClass using our conformance tooling. ## Introduction @@ -45,7 +41,7 @@ Implementations **must** publish the supported features before Accepting the Gat Implementations are free to decide how they manage this information. A common approach could be to maintain static lists of supported features or using predefined sets. -Note: implementations must keep the published list sorted in ascending alphabetical order. +> Note: implementations must keep the published list sorted in ascending alphabetical order. ## API @@ -53,7 +49,6 @@ This GEP proposes API changes describes as follow: * Update the `GatewayClassStatus` struct to include a string-represented list of `SupportedFeatures`. - ```go // GatewayClassStatus is the current status for the GatewayClass. type GatewayClassStatus struct { @@ -106,6 +101,12 @@ status: - HTTPRouteQueryParamMatching ``` + +### SupportedFeatures Guidance in GatewayClass + +Only Gateway related features should be published on GatewayClass. The rest, i.e Mesh features should not be published under GatewayClass, and will likely to be published on the new Mesh resource CRD when it is ready [ref](https://github.com/kubernetes-sigs/gateway-api/pull/3950). +Mesh features published on GatewayClassStatus will be ignored by the conformance test suite along with a warning. + ## Standardize features and conformance tests names Before we add the supported features into our API, it is necessary to establish standardized naming and formatting conventions. @@ -116,7 +117,7 @@ Before we add the supported features into our API, it is necessary to establish Every feature should: -1. Start with the resource name. i.e HTTPRouteXXX +1. Start with the resource name. i.e HTTPRouteXXX. 2. Follow the PascalCase convention. Note that the resource name in the string should come as is and not be converted to PascalCase, i.e HTTPRoutePortRedirect and not HttpRoutePortRedirect. 3. Not exceed 128 characters. 4. Contain only letters and numbers @@ -130,6 +131,26 @@ We should treat this guidance as "best effort" because we might have test files In any case, the conformance tests file names should be meaningful and easy to understand. +#### Conformance report + +In order for to verify that the list of features reported are indeed supported by GatewayClass tests will be run based on the features from the GatewayClassStatus. +If the source of Gateway features are not inferred and manually provided the conformance suite will block the report from being submitted. + +#### Reporting Mesh features + +As Mesh doesn't have a good place (yet) to populate SupportedFeatures, its features can be tested for compliance by using Conformance Profiles, or manually, providing features for test using `--supported-features` flag. +Until mesh features are posted on the Mesh resource CRD, the conformance suite will determine if conformance run is for [Mesh features](https://github.com/kubernetes-sigs/gateway-api/issues/3984) and will NOT block the report if provided manually. + +#### Staying Compliant + +SupportedFeatures will become available starting 1.4 release as a standard feature, which means that all Gateway implementations will be expected to define and populate SupportedFeatures in the GatewayClass' Status. +The conformance test suite will be based on inferring supported features from GatewayClassStatus, +meaning if you want to generate passing report, features should be populated there. +There will be a grace period until the 1.5 release, after which all Gateway Conformance Reports will need to be generated based on the SupportedFeatures field in GatewayClass status (with the exception of Mesh features described above). + +The core purpose of conformance tests for GatewayClass is to verify that reported features are truly supported. +While the community currently operates on a trust-based system for conformance reports, programmatically inferring features from the GatewayClass status field creates a strong, verifiable link between an implementation's claims and the test results. +Having this connection between supported features and conformance tests, helps improve the UX and make it easier for implementers to run the correct conformance tests. ## Followups @@ -137,14 +158,13 @@ Before we make the changes we need to; 1. Change the names of the supported features and conformance tests that don't conform with the formatting rules. - ## Alternatives ### Re-using ConformanceProfiles structs We could use the same structs as we do in conformance profile object, more specifically, the [ProfileReport](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/apis/v1alpha1/profilereport.go#LL24C6-L24C19) struct. -Though it would be nice to have only one place to update, these structs seems to include much more data relevant to the conformance report but not for our use case. +Though it would be nice to have only one place to update, these structs seems to include much more data relevant to the conformance report but not for our use case. That said, conformance profiles are still at experimental stage, we could explore the option to create a shared struct that will be used both for the conformance reports and for the GatewayClass status. @@ -158,8 +178,7 @@ However, having the supported features published in the GatewayClass Status adds * We could build a mechanism or a tool to block or warn when unsupported features are used. * Users will be able to select the GatewayClass that suits their needs without having to refer to documentation or conformance reports. -This does not cover a future piece of work we want to implement which is to warn/block users from applying a Gateway API object if the installed GWC doesn't support it. (originally suggested in [#1804](https://github.com/kubernetes-sigs/gateway-api/issues/1804)). - +This does not cover a future piece of work we want to implement which is to warn/block users from applying a Gateway API object if the installed GWC doesn't support it. (originally suggested in [#1804](https://github.com/kubernetes-sigs/gateway-api/issues/1804)). ## References @@ -169,6 +188,7 @@ This does not cover a future piece of work we want to implement which is to warn ## Future Work ### Research the development of an unsupported feature warning/blocking mechanism + Once the GatewayClass features support are is published into the status we could look into; 1. Using the supported features in the webhook to validate or block attempts to apply manifests with unsupported features. @@ -181,7 +201,7 @@ Once the GatewayClass features support are is published into the status we could We got some feedback that it will be useful to indicate which Gateway API version the implementation supports. So when we have supported features published in the GatewayClass Status, users will also be able to understand that those are the supported features for a specific Gateway API version. -This work is likely to require its own small GEP but ideally what this field would mean is that an implementation supports Max(vX.X). +This work is likely to require its own small GEP but ideally what this field would mean is that an implementation supports Max(vX.X). The value of it is to provide a better user experience and also more foundation for tools to be able to warn for example when a GatewayClass and CRDs have mismatched versions. From da623ce324472b445cb36dfcfeb65bac81c9d74d Mon Sep 17 00:00:00 2001 From: zirain Date: Thu, 14 Aug 2025 06:51:08 +0800 Subject: [PATCH 124/224] update conformance report for EnvoyGateway v1.5.0 (#3987) * update EnvoyGateway conformance report * update * update version --- .../reports/v1.3.0/envoy-gateway/README.md | 21 +++- ...> experimental-v1.5.0-default-report.yaml} | 20 ++-- ...-v1.5.0-gateway-namespace-mode-report.yaml | 98 +++++++++++++++++++ 3 files changed, 125 insertions(+), 14 deletions(-) rename conformance/reports/v1.3.0/envoy-gateway/{experimental-v1.4.0-default-report.yaml => experimental-v1.5.0-default-report.yaml} (97%) create mode 100644 conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-gateway-namespace-mode-report.yaml diff --git a/conformance/reports/v1.3.0/envoy-gateway/README.md b/conformance/reports/v1.3.0/envoy-gateway/README.md index d48c5c9ac0..6baa7b7b2d 100644 --- a/conformance/reports/v1.3.0/envoy-gateway/README.md +++ b/conformance/reports/v1.3.0/envoy-gateway/README.md @@ -2,9 +2,17 @@ ## Table of Contents -|API channel|Implementation version|Mode|Report| -|-----------|----------------------|----|------| -| experimental |[v1.4.0](https://github.com/envoyproxy/gateway/releases/tag/v1.4.0)| default |[link](./experimental-v1.4.0-default-report.yaml)| +| API channel | Implementation version | Mode | Report | +|--------------|---------------------------------------------------------------------|------------------------------|------------------------------------------------------------------| +| experimental | [v1.5.0](https://github.com/envoyproxy/gateway/releases/tag/v1.5.0) | ControllerNamespace(default) | [link](./experimental-v1.5.0-default-report.yaml) | +| experimental | [v1.5.0](https://github.com/envoyproxy/gateway/releases/tag/v1.5.0) | GatewayNamespace | [link](./experimental-v1.5.0-gateway-namespace-mode-report.yaml) | + + +## Overview + +Envoy Gateway supports different deployment [modes](https://gateway.envoyproxy.io/docs/tasks/operations/deployment-mode/#supported-modes), +including a controller namespace mode(the default one) and a [gateway namespace mode](https://gateway.envoyproxy.io/docs/tasks/operations/deployment-mode/#gateway-namespace-mode). +The conformance tests are run against both modes to ensure compatibility and functionality. ## Reproduce @@ -23,8 +31,13 @@ 3. Run the conformance tests + ```bash + KUBE_DEPLOY_PROFILE=default CONFORMANCE_REPORT_PATH=conformance-report-k8s.yaml make experimental-conformance + ``` + or + ```bash - CONFORMANCE_REPORT_PATH=conformance-report-k8s.yaml make experimental-conformance + KUBE_DEPLOY_PROFILE=gateway-namespace-mode CONFORMANCE_REPORT_PATH=conformance-report-k8s.yaml make experimental-conformance ``` 4. Check the produced report diff --git a/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-default-report.yaml similarity index 97% rename from conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml rename to conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-default-report.yaml index 4504a506da..14775c504e 100644 --- a/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.4.0-default-report.yaml +++ b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-default-report.yaml @@ -1,5 +1,5 @@ apiVersion: gateway.networking.k8s.io/v1 -date: "2025-05-14T03:12:24Z" +date: "2025-08-08T05:23:48Z" gatewayAPIChannel: experimental gatewayAPIVersion: v1.3.0 implementation: @@ -8,18 +8,10 @@ implementation: organization: envoyproxy project: envoy-gateway url: https://github.com/envoyproxy/gateway - version: latest + version: v1.5.0 kind: ConformanceReport mode: default profiles: -- core: - result: success - statistics: - Failed: 0 - Passed: 12 - Skipped: 0 - name: GATEWAY-GRPC - summary: Core tests succeeded. - core: result: success statistics: @@ -67,5 +59,13 @@ profiles: Skipped: 0 name: GATEWAY-TLS summary: Core tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + name: GATEWAY-GRPC + summary: Core tests succeeded. succeededProvisionalTests: - HTTPRouteRequestPercentageMirror diff --git a/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-gateway-namespace-mode-report.yaml b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-gateway-namespace-mode-report.yaml new file mode 100644 index 0000000000..0cc86f7694 --- /dev/null +++ b/conformance/reports/v1.3.0/envoy-gateway/experimental-v1.5.0-gateway-namespace-mode-report.yaml @@ -0,0 +1,98 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-08-08T05:25:57Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/envoyproxy/gateway/blob/main/GOVERNANCE.md + organization: envoyproxy + project: envoy-gateway + url: https://github.com/envoyproxy/gateway + version: v1.5.0 +kind: ConformanceReport +mode: GatewayNamespace +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 24 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure +- HTTPRouteRequestPercentageMirror From 3f2b1eee89144073a245404b6055c2d6461715dd Mon Sep 17 00:00:00 2001 From: zirain Date: Thu, 14 Aug 2025 08:45:08 +0800 Subject: [PATCH 125/224] support protocol in ExpectedResponse (#3986) --- conformance/utils/http/http.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index da7036daf6..50f8d1efdd 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -94,6 +94,7 @@ type Response struct { StatusCode int Headers map[string]string AbsentHeaders []string + Protocol string } type BackendRef struct { @@ -306,6 +307,10 @@ func CompareRoundTrip(t *testing.T, req *roundtripper.Request, cReq *roundtrippe if expected.Response.StatusCode != cRes.StatusCode { return fmt.Errorf("expected status code to be %d, got %d. CRes: %v", expected.Response.StatusCode, cRes.StatusCode, cRes) } + if expected.Response.Protocol != "" && expected.Response.Protocol != cRes.Protocol { + return fmt.Errorf("expected protocol to be %s, got %s", expected.Response.Protocol, cRes.Protocol) + } + if cRes.StatusCode == 200 { // The request expected to arrive at the backend is // the same as the request made, unless otherwise From db957baec4f34bf52f68b14e9e1b4b5e69aa66b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 05:55:08 -0700 Subject: [PATCH 126/224] build(deps): bump github.com/elastic/crd-ref-docs from 0.1.0 to 0.2.0 (#3958) Bumps [github.com/elastic/crd-ref-docs](https://github.com/elastic/crd-ref-docs) from 0.1.0 to 0.2.0. - [Release notes](https://github.com/elastic/crd-ref-docs/releases) - [Changelog](https://github.com/elastic/crd-ref-docs/blob/master/.goreleaser.yaml) - [Commits](https://github.com/elastic/crd-ref-docs/compare/v0.1.0...v0.2.0) --- updated-dependencies: - dependency-name: github.com/elastic/crd-ref-docs dependency-version: 0.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 20 ++++++++++---------- go.sum | 50 ++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index 2ef20f67d1..ce0e7cc3e8 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module sigs.k8s.io/gateway-api go 1.24.0 require ( - github.com/elastic/crd-ref-docs v0.1.0 + github.com/elastic/crd-ref-docs v0.2.0 github.com/miekg/dns v1.1.66 github.com/stretchr/testify v1.10.0 - golang.org/x/net v0.41.0 + golang.org/x/net v0.42.0 golang.org/x/sync v0.16.0 google.golang.org/grpc v1.74.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 @@ -39,7 +39,7 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gobuffalo/flect v1.0.3 // indirect - github.com/goccy/go-yaml v1.11.3 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 // indirect @@ -68,15 +68,15 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/crypto v0.39.0 // indirect - golang.org/x/mod v0.25.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/mod v0.26.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.26.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.33.0 // indirect + golang.org/x/text v0.27.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.33.0 // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + golang.org/x/tools v0.35.0 // indirect + golang.org/x/tools/go/expect v0.1.1-deprecated // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 7050b8ff32..e61c8f378d 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/elastic/crd-ref-docs v0.1.0 h1:Cr5kz89QB3Iuuj7dhAfLMApCrChEGAaIBTxGk/xuRKw= -github.com/elastic/crd-ref-docs v0.1.0/go.mod h1:X83mMBdJt05heJUYiS3T0yJ/JkCuliuhSUNav5Gjo/U= +github.com/elastic/crd-ref-docs v0.2.0 h1:U17MyGX71j4qfKTvYxbR4qZGoA1hc2thy7kseGYmP+o= +github.com/elastic/crd-ref-docs v0.2.0/go.mod h1:0bklkJhTG7nC6AVsdDi0wt5bGoqvzdZSzMMQkilZ6XM= github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -41,18 +41,12 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= 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/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= 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/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= -github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I= -github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -85,8 +79,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -179,18 +171,18 @@ go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -203,28 +195,30 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= From 5ecdaaca639e383e52a8f8537120739df0a224de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 06:25:08 -0700 Subject: [PATCH 127/224] build(deps): bump github.com/miekg/dns from 1.1.66 to 1.1.68 (#3973) Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.66 to 1.1.68. - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](https://github.com/miekg/dns/compare/v1.1.66...v1.1.68) --- updated-dependencies: - dependency-name: github.com/miekg/dns dependency-version: 1.1.68 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ce0e7cc3e8..fba26cda4e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.0 require ( github.com/elastic/crd-ref-docs v0.2.0 - github.com/miekg/dns v1.1.66 + github.com/miekg/dns v1.1.68 github.com/stretchr/testify v1.10.0 golang.org/x/net v0.42.0 golang.org/x/sync v0.16.0 diff --git a/go.sum b/go.sum index e61c8f378d..48a569160f 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= -github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA= +github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= From 8af898c0076b0d024634af5932135d4b6f70b414 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 06:43:06 -0700 Subject: [PATCH 128/224] build(deps): bump pymdown-extensions in /hack/mkdocs/image (#3974) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.16 to 10.16.1. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16...10.16.1) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 10.16.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 7a5fc4adde..8cd6c310ff 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -16,7 +16,7 @@ mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 pep562==1.1 Pygments==2.19.2 -pymdown-extensions==10.16 +pymdown-extensions==10.16.1 PyYAML==6.0.2 six==1.17.0 tabulate==0.9.0 From 07f7675de6892434bb7b48f0419e9a051a4406c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 06:43:13 -0700 Subject: [PATCH 129/224] build(deps): bump google.golang.org/protobuf from 1.36.6 to 1.36.7 (#3980) Bumps google.golang.org/protobuf from 1.36.6 to 1.36.7. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.36.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fba26cda4e..8bf6146a56 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( golang.org/x/sync v0.16.0 google.golang.org/grpc v1.74.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 - google.golang.org/protobuf v1.36.6 + google.golang.org/protobuf v1.36.7 k8s.io/api v0.33.3 k8s.io/apiextensions-apiserver v0.33.3 k8s.io/apimachinery v0.33.3 diff --git a/go.sum b/go.sum index 48a569160f..5134a920f2 100644 --- a/go.sum +++ b/go.sum @@ -227,8 +227,8 @@ google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 5244a392eb3f94ca26747faad1424def30e0f24c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 06:43:20 -0700 Subject: [PATCH 130/224] build(deps): bump tornado from 6.5.1 to 6.5.2 in /hack/mkdocs/image (#3982) Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.1 to 6.5.2. - [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst) - [Commits](https://github.com/tornadoweb/tornado/compare/v6.5.1...v6.5.2) --- updated-dependencies: - dependency-name: tornado dependency-version: 6.5.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index 8cd6c310ff..e4d6677b63 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -20,4 +20,4 @@ pymdown-extensions==10.16.1 PyYAML==6.0.2 six==1.17.0 tabulate==0.9.0 -tornado==6.5.1 \ No newline at end of file +tornado==6.5.2 \ No newline at end of file From 02e495200afe41422b3b03f346541d0851ede147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 08:25:08 -0700 Subject: [PATCH 131/224] build(deps): bump golang.org/x/net from 0.41.0 to 0.43.0 (#3981) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.41.0 to 0.43.0. - [Commits](https://github.com/golang/net/compare/v0.41.0...v0.43.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-version: 0.43.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 8bf6146a56..dcb0a21eb6 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/elastic/crd-ref-docs v0.2.0 github.com/miekg/dns v1.1.68 github.com/stretchr/testify v1.10.0 - golang.org/x/net v0.42.0 + golang.org/x/net v0.43.0 golang.org/x/sync v0.16.0 google.golang.org/grpc v1.74.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 @@ -68,12 +68,12 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/crypto v0.40.0 // indirect + golang.org/x/crypto v0.41.0 // indirect golang.org/x/mod v0.26.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.35.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect diff --git a/go.sum b/go.sum index 5134a920f2..67c2a445ef 100644 --- a/go.sum +++ b/go.sum @@ -171,8 +171,8 @@ go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= @@ -181,8 +181,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -195,14 +195,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 804d644e6217377a9694c0df3946681e2d85d1eb Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Mon, 18 Aug 2025 17:45:10 +0200 Subject: [PATCH 132/224] BackendTLSPolicy conformance tests for observedGeneration bump (#3997) * BackendTLSPolicy conformance tests for observedGeneration bump Signed-off-by: Norwin Schnyder * Apply PR feedback Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- ...ckendtlspolicy-observed-generation-bump.go | 88 +++++++++++++++++++ ...endtlspolicy-observed-generation-bump.yaml | 45 ++++++++++ conformance/utils/kubernetes/helpers.go | 12 +++ 3 files changed, 145 insertions(+) create mode 100644 conformance/tests/backendtlspolicy-observed-generation-bump.go create mode 100644 conformance/tests/backendtlspolicy-observed-generation-bump.yaml diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.go b/conformance/tests/backendtlspolicy-observed-generation-bump.go new file mode 100644 index 0000000000..a3cd4000bd --- /dev/null +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.go @@ -0,0 +1,88 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1alpha3" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicyObservedGenerationBump) +} + +var BackendTLSPolicyObservedGenerationBump = suite.ConformanceTest{ + ShortName: "BackendTLSPolicyObservedGenerationBump", + Description: "A BackendTLSPolicy in the gateway-conformance-infra namespace should update the observedGeneration in all of it's Status.Conditions after an update to the spec", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + }, + Manifests: []string{"tests/backendtlspolicy-observed-generation-bump.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + policyNN := types.NamespacedName{Name: "observed-generation-bump", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + + t.Run("observedGeneration should increment", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), suite.TimeoutConfig.LatestObservedGenerationSet) + defer cancel() + + namespaces := []string{"gateway-conformance-infra"} + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, namespaces) + + original := &v1alpha3.BackendTLSPolicy{} + err := suite.Client.Get(ctx, policyNN, original) + require.NoError(t, err, "error getting HTTPRoute") + + // Sanity check + kubernetes.BackendTLSPolicyMustHaveLatestConditions(t, original) + + mutate := original.DeepCopy() + mutate.Spec.Validation.Hostname = "foo.example.com" + err = suite.Client.Patch(ctx, mutate, client.MergeFrom(original)) + require.NoError(t, err, "error patching the BackendTLSPolicy") + + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, metav1.Condition{ + Type: string(v1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionTrue, + Reason: "", // any reason + }) + + updated := &v1alpha3.BackendTLSPolicy{} + err = suite.Client.Get(ctx, policyNN, updated) + require.NoError(t, err, "error getting BackendTLSPolicy") + + // Sanity check + kubernetes.BackendTLSPolicyMustHaveLatestConditions(t, updated) + + require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update") + }) + }, +} diff --git a/conformance/tests/backendtlspolicy-observed-generation-bump.yaml b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml new file mode 100644 index 0000000000..c21bd45bbc --- /dev/null +++ b/conformance/tests/backendtlspolicy-observed-generation-bump.yaml @@ -0,0 +1,45 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backendtlspolicy-observed-generation-bump + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - backendRefs: + - name: observed-generation-bump-test + port: 443 +--- +apiVersion: v1 +kind: Service +metadata: + name: observed-generation-bump-test + namespace: gateway-conformance-infra +spec: + selector: + app: observed-generation-bump-test + ports: + - name: "https" + protocol: TCP + port: 443 + targetPort: 8443 +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: observed-generation-bump + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "observed-generation-bump-test" + sectionName: "https" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + name: "backend-tls-checks-certificate" + hostname: "abc.example.com" diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 8075132da1..1501d93571 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -1026,3 +1026,15 @@ func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeo require.NoErrorf(t, waitErr, "error waiting for BackendTLSPolicy status to have a Condition %v", condition) } + +// BackendTLSPolicyMustHaveLatestConditions will fail the test if there are +// conditions that were not updated +func BackendTLSPolicyMustHaveLatestConditions(t *testing.T, r *v1alpha3.BackendTLSPolicy) { + t.Helper() + + for _, ancestor := range r.Status.Ancestors { + if err := ConditionsHaveLatestObservedGeneration(r, ancestor.Conditions); err != nil { + tlog.Fatalf(t, "BackendTLSPolicy(controller=%v, ancestorRef=%#v) %v", ancestor.ControllerName, parentRefToString(ancestor.AncestorRef), err) + } + } +} From a516fa4097fa4a8396c6bccdedccb31dfd70ea74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:05:12 -0700 Subject: [PATCH 133/224] build(deps): bump the k8s-io group with 5 updates (#4002) Bumps the k8s-io group with 5 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.33.3` | `0.33.4` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.33.3` | `0.33.4` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.33.3` | `0.33.4` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.33.3` | `0.33.4` | | [k8s.io/code-generator](https://github.com/kubernetes/code-generator) | `0.33.3` | `0.33.4` | Updates `k8s.io/api` from 0.33.3 to 0.33.4 - [Commits](https://github.com/kubernetes/api/compare/v0.33.3...v0.33.4) Updates `k8s.io/apiextensions-apiserver` from 0.33.3 to 0.33.4 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.3...v0.33.4) Updates `k8s.io/apimachinery` from 0.33.3 to 0.33.4 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.3...v0.33.4) Updates `k8s.io/client-go` from 0.33.3 to 0.33.4 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.33.3...v0.33.4) Updates `k8s.io/code-generator` from 0.33.3 to 0.33.4 - [Commits](https://github.com/kubernetes/code-generator/compare/v0.33.3...v0.33.4) --- updated-dependencies: - dependency-name: k8s.io/api dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io - dependency-name: k8s.io/code-generator dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-io ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index dcb0a21eb6..c818773daf 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( google.golang.org/grpc v1.74.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.7 - k8s.io/api v0.33.3 - k8s.io/apiextensions-apiserver v0.33.3 - k8s.io/apimachinery v0.33.3 - k8s.io/client-go v0.33.3 - k8s.io/code-generator v0.33.3 + k8s.io/api v0.33.4 + k8s.io/apiextensions-apiserver v0.33.4 + k8s.io/apimachinery v0.33.4 + k8s.io/client-go v0.33.4 + k8s.io/code-generator v0.33.4 k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/controller-runtime v0.21.0 diff --git a/go.sum b/go.sum index 67c2a445ef..b6f7fbce18 100644 --- a/go.sum +++ b/go.sum @@ -244,16 +244,16 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= -k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= -k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= -k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= -k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= -k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= -k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= -k8s.io/code-generator v0.33.3 h1:6+34LhYkIuQ/yn/E3qlpVqjQaP8smzCu4NE1A8b0LWs= -k8s.io/code-generator v0.33.3/go.mod h1:6Y02+HQJYgNphv9z3wJB5w+sjYDIEBQW7sh62PkufvA= +k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk= +k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc= +k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU= +k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs= +k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s= +k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw= +k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY= +k8s.io/code-generator v0.33.4 h1:DiA801QxqApRIBh3OWULasVAUA237XnYvFNMh+E34Y8= +k8s.io/code-generator v0.33.4/go.mod h1:ifWxKWhEl/Z1K7WmWAyOBEf3ex/i546ingCzLC8YVIY= k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= From 7fae5d7139a663667c72372f3ccfbabe749f6751 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Mon, 18 Aug 2025 20:03:08 -0300 Subject: [PATCH 134/224] Enable dark mode switch on docs (#3977) --- mkdocs.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 18393ce4c6..1052a44512 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -27,7 +27,16 @@ theme: - navigation.top - navigation.expand palette: - primary: custom + - scheme: default + primary: custom + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: custom + toggle: + icon: material/brightness-4 + name: Switch to light mode custom_dir: site-src/overrides edit_uri: edit/main/site-src/ plugins: From 4adc82ed2bce7f012aa5217cc996a0689bfef347 Mon Sep 17 00:00:00 2001 From: Pronomita Dey Date: Wed, 20 Aug 2025 10:23:26 +0530 Subject: [PATCH 135/224] Update devguide.md to include docker as a pre-req for verify (#4000) * Update devguide.md * added docker and buildx added docker and buildx to the prereqs section & removed docker as a prereq for make verify specifically * KinD naming change --- site-src/contributing/devguide.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site-src/contributing/devguide.md b/site-src/contributing/devguide.md index 6d3acfdfed..ee5e5bd4c2 100644 --- a/site-src/contributing/devguide.md +++ b/site-src/contributing/devguide.md @@ -36,7 +36,9 @@ command in PR and issue comments][issue-cmds]. For example, Before you start developing with Gateway API, we'd recommend having the following prerequisites installed: -* [Kind](https://kubernetes.io/docs/tasks/tools/#kind): This is a standalone local Kubernetes cluster. At least one container runtime is required. We recommend installing [Docker](https://docs.docker.com/engine/install/). While you can opt for alternatives like [Podman](https://podman.io/docs/installation), please be aware that doing so is at your own risk. +* [KinD](https://kubernetes.io/docs/tasks/tools/#kind): This is a standalone local Kubernetes cluster. At least one container runtime is required. +* [Docker](https://docs.docker.com/engine/install/): This is a prerequisite for running KinD. While you can opt for alternatives like [Podman](https://podman.io/docs/installation), please be aware that doing so is at your own risk. +* [BuildX](https://github.com/docker/buildx): Prerequisite for `make verify` to run. * [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl): This is the Kubernetes command-line tool. * [Go](https://golang.org/doc/install): It is the main programming language in this project. Please check this [file](https://github.com/kubernetes-sigs/gateway-api/blob/main/go.mod#L3) to find out the least `Go` version otherwise you might encounter compilation errors. * [Digest::SHA](https://metacpan.org/pod/Digest::SHA): It is a required dependency. You can obtain it by installing the `perl-Digest-SHA` package. From 43b0cf775513e5caada14384269a6e6cda522bbe Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Wed, 20 Aug 2025 09:09:07 +0200 Subject: [PATCH 136/224] GEP-91: Address connection coalescing security issue - API updates (#3960) --- apis/v1/gateway_types.go | 150 +++- apis/v1/zz_generated.deepcopy.go | 97 ++- apis/v1beta1/gateway_types.go | 4 +- apisx/v1alpha1/shared_types.go | 2 +- apisx/v1alpha1/xlistenerset_types.go | 4 +- apisx/v1alpha1/zz_generated.deepcopy.go | 2 +- .../apis/v1/frontendtlsvalidation.go | 13 + applyconfiguration/apis/v1/gatewayspec.go | 9 + .../apis/v1/gatewaytlsconfig.go | 50 +- applyconfiguration/apis/v1/listener.go | 14 +- .../apis/v1/listenertlsconfig.go | 72 ++ applyconfiguration/apis/v1/tlsconfig.go | 39 + applyconfiguration/apis/v1/tlsportconfig.go | 52 ++ .../apisx/v1alpha1/listenerentry.go | 14 +- applyconfiguration/internal/internal.go | 68 +- applyconfiguration/utils.go | 6 + .../gateway.networking.k8s.io_gateways.yaml | 766 +++++++++++++----- ...way.networking.x-k8s.io_xlistenersets.yaml | 92 +-- .../gateway.networking.k8s.io_gateways.yaml | 4 +- .../frontend-cert-validation.yaml | 12 +- geps/gep-91/index.md | 153 ++-- pkg/generated/openapi/zz_generated.openapi.go | 188 ++++- pkg/test/cel/gateway_test.go | 22 +- 23 files changed, 1327 insertions(+), 506 deletions(-) create mode 100644 applyconfiguration/apis/v1/listenertlsconfig.go create mode 100644 applyconfiguration/apis/v1/tlsconfig.go create mode 100644 applyconfiguration/apis/v1/tlsportconfig.go diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index 86de1bad59..fdb31043cd 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -295,6 +295,14 @@ type GatewaySpec struct { // // +optional AllowedListeners *AllowedListeners `json:"allowedListeners,omitempty"` + // + // GatewayTLSConfig specifies frontend tls configuration for gateway. + // + // Support: Extended + // + // +optional + // + TLS *GatewayTLSConfig `json:"tls,omitempty"` } // AllowedListeners defines which ListenerSets can be attached to this Gateway. @@ -414,7 +422,7 @@ type Listener struct { // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field // if the Protocol field is "HTTP", "TCP", or "UDP". // - // The association of SNIs to Certificate defined in GatewayTLSConfig is + // The association of SNIs to Certificate defined in ListenerTLSConfig is // defined based on the Hostname field for this listener. // // The GatewayClass MUST use the longest matching SNI out of all @@ -423,7 +431,7 @@ type Listener struct { // Support: Core // // +optional - TLS *GatewayTLSConfig `json:"tls,omitempty"` + TLS *ListenerTLSConfig `json:"tls,omitempty"` // AllowedRoutes defines the types of routes that MAY be attached to a // Listener and the trusted namespaces where those Route resources MAY be @@ -526,10 +534,10 @@ type GatewayBackendTLS struct { ClientCertificateRef *SecretObjectReference `json:"clientCertificateRef,omitempty"` } -// GatewayTLSConfig describes a TLS configuration. +// ListenerTLSConfig describes a TLS configuration for a listener. // // +kubebuilder:validation:XValidation:message="certificateRefs or options must be specified when mode is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" -type GatewayTLSConfig struct { +type ListenerTLSConfig struct { // Mode defines the TLS behavior for the TLS session initiated by the client. // There are two possible modes: // @@ -578,18 +586,6 @@ type GatewayTLSConfig struct { // +kubebuilder:validation:MaxItems=64 CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` - // FrontendValidation holds configuration information for validating the frontend (client). - // Setting this field will require clients to send a client certificate - // required for validation during the TLS handshake. In browsers this may result in a dialog appearing - // that requests a user to specify the client certificate. - // The maximum depth of a certificate chain accepted in verification is Implementation specific. - // - // Support: Extended - // - // +optional - // - FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` - // Options are a list of key/value pairs to enable extended TLS // configuration for each implementation. For example, configuring the // minimum TLS version or supported cipher suites. @@ -606,6 +602,35 @@ type GatewayTLSConfig struct { Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` } +// GatewayTLSConfig specifies frontend tls configuration for gateway. +type GatewayTLSConfig struct { + // Default specifies the default client certificate validation configuration + // for all Listeners handling HTTPS traffic, unless a per-port configuration + // is defined. + // + // support: Core + // + // +required + // + Default TLSConfig `json:"default"` + + // PerPort specifies tls configuration assigned per port. + // Per port configuration is optional. Once set this configuration overrides + // the default configuration for all Listeners handling HTTPS traffic + // that match this port. + // Each override port requires a unique TLS configuration. + // + // support: Core + // + // +optional + // +listType=map + // +listMapKey=port + // +kubebuilder:validation:MaxItems=64 + // +kubebuilder:validation:XValidation:message="Port for TLS configuration must be unique within the Gateway",rule="self.all(t1, self.exists_one(t2, t1.port == t2.port))" + // + PerPort []TLSPortConfig `json:"perPort,omitempty"` +} + // TLSModeType type defines how a Gateway handles TLS sessions. // // +kubebuilder:validation:Enum=Terminate;Passthrough @@ -624,6 +649,46 @@ const ( TLSModePassthrough TLSModeType = "Passthrough" ) +// TLSConfig describes TLS configuration that can apply to multiple Listeners +// within this Gateway. Currently, it stores only the client certificate validation +// configuration, but this may be extended in the future. +type TLSConfig struct { + // FrontendValidation holds configuration information for validating the frontend (client). + // Setting this field will result in mutual authentication when connecting to the gateway. + // In browsers this may result in a dialog appearing + // that requests a user to specify the client certificate. + // The maximum depth of a certificate chain accepted in verification is Implementation specific. + // + // Support: Core + // + // +required + // + FrontendValidation FrontendTLSValidation `json:"frontendValidation"` +} + +type TLSPortConfig struct { + // The Port indicates the Port Number to which the TLS configuration will be + // applied. This configuration will be applied to all Listeners handling HTTPS + // traffic that match this port. + // + // Support: Core + // + // +required + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // + Port PortNumber `json:"port"` + + // TLS store the configuration that will be applied to all Listeners handling + // HTTPS traffic and matching given port. + // + // Support: Core + // + // +required + // + TLS TLSConfig `json:"tls"` +} + // FrontendTLSValidation holds configuration information that can be used to validate // the frontend initiating the TLS connection type FrontendTLSValidation struct { @@ -640,8 +705,8 @@ type FrontendTLSValidation struct { // Support: Core - A single reference to a Kubernetes ConfigMap // with the CA certificate in a key named `ca.crt`. // - // Support: Implementation-specific (More than one reference, or other kinds - // of resources). + // Support: Implementation-specific (More than one certificate in a ConfigMap + // with different keys or more than one reference, or other kinds of resources). // // References to a resource in a different namespace are invalid UNLESS there // is a ReferenceGrant in the target namespace that allows the certificate @@ -653,9 +718,49 @@ type FrontendTLSValidation struct { // +listType=atomic // +kubebuilder:validation:MaxItems=8 // +kubebuilder:validation:MinItems=1 - CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` + CACertificateRefs []ObjectReference `json:"caCertificateRefs"` + + // FrontendValidationMode defines the mode for validating the client certificate. + // There are two possible modes: + // + // - AllowValidOnly: In this mode, the gateway will accept connections only if + // the client presents a valid certificate. This certificate must successfully + // pass validation against the CA certificates specified in `CACertificateRefs`. + // - AllowInsecureFallback: In this mode, the gateway will accept connections + // even if the client certificate is not presented or fails verification. + // + // This approach delegates client authorization to the backend and introduce + // a significant security risk. It should be used in testing environments or + // on a temporary basis in non-testing environments. + // + // Defaults to AllowValidOnly. + // + // Support: Core + // + // +optional + // +kubebuilder:default=AllowValidOnly + Mode FrontendValidationModeType `json:"mode,omitempty"` } +// FrontendValidationModeType type defines how a Gateway validates client certificates. +// +// +kubebuilder:validation:Enum=AllowValidOnly;AllowInsecureFallback +type FrontendValidationModeType string + +const ( + // AllowValidOnly indicates that a client certificate is required + // during the TLS handshake and MUST pass validation. + // + // Support: Core + AllowValidOnly FrontendValidationModeType = "AllowValidOnly" + + // AllowInsecureFallback indicates that a client certificate may not be + // presented during the handshake or the validation against CA certificates may fail. + // + // Support: Extended + AllowInsecureFallback FrontendValidationModeType = "AllowInsecureFallback" +) + // AllowedRoutes defines which Routes may be attached to this Listener. type AllowedRoutes struct { // Namespaces indicates namespaces from which Routes may be attached to this @@ -993,6 +1098,13 @@ const ( // information on which address is causing the problem and how to resolve it // in the condition message. GatewayReasonAddressNotUsable GatewayConditionReason = "AddressNotUsable" + // This condition indicates `FrontendValidationModeType` changed from + // `AllowValidOnly` to `AllowInsecureFallback`. + GatewayConditionInsecureFrontendValidationMode GatewayConditionReason = "InsecureFrontendValidationMode" + // This reason MUST be set for GatewayConditionInsecureFrontendValidationMode + // when client change FrontendValidationModeType for a Gateway or per port override + // to `AllowInsecureFallback`. + GatewayReasonConfigurationChanged GatewayConditionReason = "ConfigurationChanged" ) const ( diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index 9bc1c8c53e..d7e4a6c2f4 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -752,6 +752,11 @@ func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { *out = new(AllowedListeners) (*in).DeepCopyInto(*out) } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(GatewayTLSConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec. @@ -843,30 +848,14 @@ func (in *GatewayStatusAddress) DeepCopy() *GatewayStatusAddress { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { *out = *in - if in.Mode != nil { - in, out := &in.Mode, &out.Mode - *out = new(TLSModeType) - **out = **in - } - if in.CertificateRefs != nil { - in, out := &in.CertificateRefs, &out.CertificateRefs - *out = make([]SecretObjectReference, len(*in)) + in.Default.DeepCopyInto(&out.Default) + if in.PerPort != nil { + in, out := &in.PerPort, &out.PerPort + *out = make([]TLSPortConfig, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.FrontendValidation != nil { - in, out := &in.FrontendValidation, &out.FrontendValidation - *out = new(FrontendTLSValidation) - (*in).DeepCopyInto(*out) - } - if in.Options != nil { - in, out := &in.Options, &out.Options - *out = make(map[AnnotationKey]AnnotationValue, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTLSConfig. @@ -1481,7 +1470,7 @@ func (in *Listener) DeepCopyInto(out *Listener) { } if in.TLS != nil { in, out := &in.TLS, &out.TLS - *out = new(GatewayTLSConfig) + *out = new(ListenerTLSConfig) (*in).DeepCopyInto(*out) } if in.AllowedRoutes != nil { @@ -1555,6 +1544,40 @@ func (in *ListenerStatus) DeepCopy() *ListenerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerTLSConfig) DeepCopyInto(out *ListenerTLSConfig) { + *out = *in + if in.Mode != nil { + in, out := &in.Mode, &out.Mode + *out = new(TLSModeType) + **out = **in + } + if in.CertificateRefs != nil { + in, out := &in.CertificateRefs, &out.CertificateRefs + *out = make([]SecretObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Options != nil { + in, out := &in.Options, &out.Options + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerTLSConfig. +func (in *ListenerTLSConfig) DeepCopy() *ListenerTLSConfig { + if in == nil { + return nil + } + out := new(ListenerTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { *out = *in @@ -1839,3 +1862,35 @@ func (in *SupportedFeature) DeepCopy() *SupportedFeature { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { + *out = *in + in.FrontendValidation.DeepCopyInto(&out.FrontendValidation) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig. +func (in *TLSConfig) DeepCopy() *TLSConfig { + if in == nil { + return nil + } + out := new(TLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSPortConfig) DeepCopyInto(out *TLSPortConfig) { + *out = *in + in.TLS.DeepCopyInto(&out.TLS) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSPortConfig. +func (in *TLSPortConfig) DeepCopy() *TLSPortConfig { + if in == nil { + return nil + } + out := new(TLSPortConfig) + in.DeepCopyInto(out) + return out +} diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go index 1998c2ac27..60bac20c94 100644 --- a/apis/v1beta1/gateway_types.go +++ b/apis/v1beta1/gateway_types.go @@ -88,9 +88,9 @@ type Listener = v1.Listener // +k8s:deepcopy-gen=false type ProtocolType = v1.ProtocolType -// GatewayTLSConfig describes a TLS configuration. +// ListenerTLSConfig describes a TLS configuration. // +k8s:deepcopy-gen=false -type GatewayTLSConfig = v1.GatewayTLSConfig +type ListenerTLSConfig = v1.ListenerTLSConfig // TLSModeType type defines how a Gateway handles TLS sessions. // diff --git a/apisx/v1alpha1/shared_types.go b/apisx/v1alpha1/shared_types.go index 441d4758c1..848ff53b18 100644 --- a/apisx/v1alpha1/shared_types.go +++ b/apisx/v1alpha1/shared_types.go @@ -25,7 +25,7 @@ type ( // +k8s:deepcopy-gen=false AllowedRoutes = v1.AllowedRoutes // +k8s:deepcopy-gen=false - GatewayTLSConfig = v1.GatewayTLSConfig + ListenerTLSConfig = v1.ListenerTLSConfig // +k8s:deepcopy-gen=false Group = v1.Group // +k8s:deepcopy-gen=false diff --git a/apisx/v1alpha1/xlistenerset_types.go b/apisx/v1alpha1/xlistenerset_types.go index fd108e2bed..f8198c8659 100644 --- a/apisx/v1alpha1/xlistenerset_types.go +++ b/apisx/v1alpha1/xlistenerset_types.go @@ -179,14 +179,14 @@ type ListenerEntry struct { // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field // if the Protocol field is "HTTP", "TCP", or "UDP". // - // The association of SNIs to Certificate defined in GatewayTLSConfig is + // The association of SNIs to Certificate defined in ListenerTLSConfig is // defined based on the Hostname field for this listener. // // The GatewayClass MUST use the longest matching SNI out of all // available certificates for any TLS handshake. // // +optional - TLS *GatewayTLSConfig `json:"tls,omitempty"` + TLS *ListenerTLSConfig `json:"tls,omitempty"` // AllowedRoutes defines the types of routes that MAY be attached to a // Listener and the trusted namespaces where those Route resources MAY be diff --git a/apisx/v1alpha1/zz_generated.deepcopy.go b/apisx/v1alpha1/zz_generated.deepcopy.go index bd5348692d..802d371927 100644 --- a/apisx/v1alpha1/zz_generated.deepcopy.go +++ b/apisx/v1alpha1/zz_generated.deepcopy.go @@ -92,7 +92,7 @@ func (in *ListenerEntry) DeepCopyInto(out *ListenerEntry) { } if in.TLS != nil { in, out := &in.TLS, &out.TLS - *out = new(GatewayTLSConfig) + *out = new(ListenerTLSConfig) (*in).DeepCopyInto(*out) } if in.AllowedRoutes != nil { diff --git a/applyconfiguration/apis/v1/frontendtlsvalidation.go b/applyconfiguration/apis/v1/frontendtlsvalidation.go index 5342400ccf..fada2ba15e 100644 --- a/applyconfiguration/apis/v1/frontendtlsvalidation.go +++ b/applyconfiguration/apis/v1/frontendtlsvalidation.go @@ -18,10 +18,15 @@ limitations under the License. package v1 +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + // FrontendTLSValidationApplyConfiguration represents a declarative configuration of the FrontendTLSValidation type for use // with apply. type FrontendTLSValidationApplyConfiguration struct { CACertificateRefs []ObjectReferenceApplyConfiguration `json:"caCertificateRefs,omitempty"` + Mode *apisv1.FrontendValidationModeType `json:"mode,omitempty"` } // FrontendTLSValidationApplyConfiguration constructs a declarative configuration of the FrontendTLSValidation type for use with @@ -42,3 +47,11 @@ func (b *FrontendTLSValidationApplyConfiguration) WithCACertificateRefs(values . } return b } + +// WithMode sets the Mode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Mode field is set to the value of the last call. +func (b *FrontendTLSValidationApplyConfiguration) WithMode(value apisv1.FrontendValidationModeType) *FrontendTLSValidationApplyConfiguration { + b.Mode = &value + return b +} diff --git a/applyconfiguration/apis/v1/gatewayspec.go b/applyconfiguration/apis/v1/gatewayspec.go index bdfeba84d4..b123a40f9c 100644 --- a/applyconfiguration/apis/v1/gatewayspec.go +++ b/applyconfiguration/apis/v1/gatewayspec.go @@ -31,6 +31,7 @@ type GatewaySpecApplyConfiguration struct { Infrastructure *GatewayInfrastructureApplyConfiguration `json:"infrastructure,omitempty"` BackendTLS *GatewayBackendTLSApplyConfiguration `json:"backendTLS,omitempty"` AllowedListeners *AllowedListenersApplyConfiguration `json:"allowedListeners,omitempty"` + TLS *GatewayTLSConfigApplyConfiguration `json:"tls,omitempty"` } // GatewaySpecApplyConfiguration constructs a declarative configuration of the GatewaySpec type for use with @@ -96,3 +97,11 @@ func (b *GatewaySpecApplyConfiguration) WithAllowedListeners(value *AllowedListe b.AllowedListeners = value return b } + +// WithTLS sets the TLS field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the TLS field is set to the value of the last call. +func (b *GatewaySpecApplyConfiguration) WithTLS(value *GatewayTLSConfigApplyConfiguration) *GatewaySpecApplyConfiguration { + b.TLS = value + return b +} diff --git a/applyconfiguration/apis/v1/gatewaytlsconfig.go b/applyconfiguration/apis/v1/gatewaytlsconfig.go index 896e3e56b3..dbd3f443b1 100644 --- a/applyconfiguration/apis/v1/gatewaytlsconfig.go +++ b/applyconfiguration/apis/v1/gatewaytlsconfig.go @@ -18,17 +18,11 @@ limitations under the License. package v1 -import ( - apisv1 "sigs.k8s.io/gateway-api/apis/v1" -) - // GatewayTLSConfigApplyConfiguration represents a declarative configuration of the GatewayTLSConfig type for use // with apply. type GatewayTLSConfigApplyConfiguration struct { - Mode *apisv1.TLSModeType `json:"mode,omitempty"` - CertificateRefs []SecretObjectReferenceApplyConfiguration `json:"certificateRefs,omitempty"` - FrontendValidation *FrontendTLSValidationApplyConfiguration `json:"frontendValidation,omitempty"` - Options map[apisv1.AnnotationKey]apisv1.AnnotationValue `json:"options,omitempty"` + Default *TLSConfigApplyConfiguration `json:"default,omitempty"` + PerPort []TLSPortConfigApplyConfiguration `json:"perPort,omitempty"` } // GatewayTLSConfigApplyConfiguration constructs a declarative configuration of the GatewayTLSConfig type for use with @@ -37,45 +31,23 @@ func GatewayTLSConfig() *GatewayTLSConfigApplyConfiguration { return &GatewayTLSConfigApplyConfiguration{} } -// WithMode sets the Mode field in the declarative configuration to the given value +// WithDefault sets the Default field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the Mode field is set to the value of the last call. -func (b *GatewayTLSConfigApplyConfiguration) WithMode(value apisv1.TLSModeType) *GatewayTLSConfigApplyConfiguration { - b.Mode = &value +// If called multiple times, the Default field is set to the value of the last call. +func (b *GatewayTLSConfigApplyConfiguration) WithDefault(value *TLSConfigApplyConfiguration) *GatewayTLSConfigApplyConfiguration { + b.Default = value return b } -// WithCertificateRefs adds the given value to the CertificateRefs field in the declarative configuration +// WithPerPort adds the given value to the PerPort field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. -// If called multiple times, values provided by each call will be appended to the CertificateRefs field. -func (b *GatewayTLSConfigApplyConfiguration) WithCertificateRefs(values ...*SecretObjectReferenceApplyConfiguration) *GatewayTLSConfigApplyConfiguration { +// If called multiple times, values provided by each call will be appended to the PerPort field. +func (b *GatewayTLSConfigApplyConfiguration) WithPerPort(values ...*TLSPortConfigApplyConfiguration) *GatewayTLSConfigApplyConfiguration { for i := range values { if values[i] == nil { - panic("nil value passed to WithCertificateRefs") + panic("nil value passed to WithPerPort") } - b.CertificateRefs = append(b.CertificateRefs, *values[i]) - } - return b -} - -// WithFrontendValidation sets the FrontendValidation field in the declarative configuration to the given value -// and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the FrontendValidation field is set to the value of the last call. -func (b *GatewayTLSConfigApplyConfiguration) WithFrontendValidation(value *FrontendTLSValidationApplyConfiguration) *GatewayTLSConfigApplyConfiguration { - b.FrontendValidation = value - return b -} - -// WithOptions puts the entries into the Options field in the declarative configuration -// and returns the receiver, so that objects can be build by chaining "With" function invocations. -// If called multiple times, the entries provided by each call will be put on the Options field, -// overwriting an existing map entries in Options field with the same key. -func (b *GatewayTLSConfigApplyConfiguration) WithOptions(entries map[apisv1.AnnotationKey]apisv1.AnnotationValue) *GatewayTLSConfigApplyConfiguration { - if b.Options == nil && len(entries) > 0 { - b.Options = make(map[apisv1.AnnotationKey]apisv1.AnnotationValue, len(entries)) - } - for k, v := range entries { - b.Options[k] = v + b.PerPort = append(b.PerPort, *values[i]) } return b } diff --git a/applyconfiguration/apis/v1/listener.go b/applyconfiguration/apis/v1/listener.go index 35be06a768..c7d3b08023 100644 --- a/applyconfiguration/apis/v1/listener.go +++ b/applyconfiguration/apis/v1/listener.go @@ -25,12 +25,12 @@ import ( // ListenerApplyConfiguration represents a declarative configuration of the Listener type for use // with apply. type ListenerApplyConfiguration struct { - Name *apisv1.SectionName `json:"name,omitempty"` - Hostname *apisv1.Hostname `json:"hostname,omitempty"` - Port *apisv1.PortNumber `json:"port,omitempty"` - Protocol *apisv1.ProtocolType `json:"protocol,omitempty"` - TLS *GatewayTLSConfigApplyConfiguration `json:"tls,omitempty"` - AllowedRoutes *AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` + Name *apisv1.SectionName `json:"name,omitempty"` + Hostname *apisv1.Hostname `json:"hostname,omitempty"` + Port *apisv1.PortNumber `json:"port,omitempty"` + Protocol *apisv1.ProtocolType `json:"protocol,omitempty"` + TLS *ListenerTLSConfigApplyConfiguration `json:"tls,omitempty"` + AllowedRoutes *AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` } // ListenerApplyConfiguration constructs a declarative configuration of the Listener type for use with @@ -74,7 +74,7 @@ func (b *ListenerApplyConfiguration) WithProtocol(value apisv1.ProtocolType) *Li // WithTLS sets the TLS field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the TLS field is set to the value of the last call. -func (b *ListenerApplyConfiguration) WithTLS(value *GatewayTLSConfigApplyConfiguration) *ListenerApplyConfiguration { +func (b *ListenerApplyConfiguration) WithTLS(value *ListenerTLSConfigApplyConfiguration) *ListenerApplyConfiguration { b.TLS = value return b } diff --git a/applyconfiguration/apis/v1/listenertlsconfig.go b/applyconfiguration/apis/v1/listenertlsconfig.go new file mode 100644 index 0000000000..6ab72f1526 --- /dev/null +++ b/applyconfiguration/apis/v1/listenertlsconfig.go @@ -0,0 +1,72 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// ListenerTLSConfigApplyConfiguration represents a declarative configuration of the ListenerTLSConfig type for use +// with apply. +type ListenerTLSConfigApplyConfiguration struct { + Mode *apisv1.TLSModeType `json:"mode,omitempty"` + CertificateRefs []SecretObjectReferenceApplyConfiguration `json:"certificateRefs,omitempty"` + Options map[apisv1.AnnotationKey]apisv1.AnnotationValue `json:"options,omitempty"` +} + +// ListenerTLSConfigApplyConfiguration constructs a declarative configuration of the ListenerTLSConfig type for use with +// apply. +func ListenerTLSConfig() *ListenerTLSConfigApplyConfiguration { + return &ListenerTLSConfigApplyConfiguration{} +} + +// WithMode sets the Mode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Mode field is set to the value of the last call. +func (b *ListenerTLSConfigApplyConfiguration) WithMode(value apisv1.TLSModeType) *ListenerTLSConfigApplyConfiguration { + b.Mode = &value + return b +} + +// WithCertificateRefs adds the given value to the CertificateRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the CertificateRefs field. +func (b *ListenerTLSConfigApplyConfiguration) WithCertificateRefs(values ...*SecretObjectReferenceApplyConfiguration) *ListenerTLSConfigApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithCertificateRefs") + } + b.CertificateRefs = append(b.CertificateRefs, *values[i]) + } + return b +} + +// WithOptions puts the entries into the Options field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Options field, +// overwriting an existing map entries in Options field with the same key. +func (b *ListenerTLSConfigApplyConfiguration) WithOptions(entries map[apisv1.AnnotationKey]apisv1.AnnotationValue) *ListenerTLSConfigApplyConfiguration { + if b.Options == nil && len(entries) > 0 { + b.Options = make(map[apisv1.AnnotationKey]apisv1.AnnotationValue, len(entries)) + } + for k, v := range entries { + b.Options[k] = v + } + return b +} diff --git a/applyconfiguration/apis/v1/tlsconfig.go b/applyconfiguration/apis/v1/tlsconfig.go new file mode 100644 index 0000000000..1dfa5e024e --- /dev/null +++ b/applyconfiguration/apis/v1/tlsconfig.go @@ -0,0 +1,39 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// TLSConfigApplyConfiguration represents a declarative configuration of the TLSConfig type for use +// with apply. +type TLSConfigApplyConfiguration struct { + FrontendValidation *FrontendTLSValidationApplyConfiguration `json:"frontendValidation,omitempty"` +} + +// TLSConfigApplyConfiguration constructs a declarative configuration of the TLSConfig type for use with +// apply. +func TLSConfig() *TLSConfigApplyConfiguration { + return &TLSConfigApplyConfiguration{} +} + +// WithFrontendValidation sets the FrontendValidation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FrontendValidation field is set to the value of the last call. +func (b *TLSConfigApplyConfiguration) WithFrontendValidation(value *FrontendTLSValidationApplyConfiguration) *TLSConfigApplyConfiguration { + b.FrontendValidation = value + return b +} diff --git a/applyconfiguration/apis/v1/tlsportconfig.go b/applyconfiguration/apis/v1/tlsportconfig.go new file mode 100644 index 0000000000..bc9043a149 --- /dev/null +++ b/applyconfiguration/apis/v1/tlsportconfig.go @@ -0,0 +1,52 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// TLSPortConfigApplyConfiguration represents a declarative configuration of the TLSPortConfig type for use +// with apply. +type TLSPortConfigApplyConfiguration struct { + Port *apisv1.PortNumber `json:"port,omitempty"` + TLS *TLSConfigApplyConfiguration `json:"tls,omitempty"` +} + +// TLSPortConfigApplyConfiguration constructs a declarative configuration of the TLSPortConfig type for use with +// apply. +func TLSPortConfig() *TLSPortConfigApplyConfiguration { + return &TLSPortConfigApplyConfiguration{} +} + +// WithPort sets the Port field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Port field is set to the value of the last call. +func (b *TLSPortConfigApplyConfiguration) WithPort(value apisv1.PortNumber) *TLSPortConfigApplyConfiguration { + b.Port = &value + return b +} + +// WithTLS sets the TLS field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the TLS field is set to the value of the last call. +func (b *TLSPortConfigApplyConfiguration) WithTLS(value *TLSConfigApplyConfiguration) *TLSPortConfigApplyConfiguration { + b.TLS = value + return b +} diff --git a/applyconfiguration/apisx/v1alpha1/listenerentry.go b/applyconfiguration/apisx/v1alpha1/listenerentry.go index e6396bf199..b72cf4e044 100644 --- a/applyconfiguration/apisx/v1alpha1/listenerentry.go +++ b/applyconfiguration/apisx/v1alpha1/listenerentry.go @@ -26,12 +26,12 @@ import ( // ListenerEntryApplyConfiguration represents a declarative configuration of the ListenerEntry type for use // with apply. type ListenerEntryApplyConfiguration struct { - Name *v1.SectionName `json:"name,omitempty"` - Hostname *v1.Hostname `json:"hostname,omitempty"` - Port *v1.PortNumber `json:"port,omitempty"` - Protocol *v1.ProtocolType `json:"protocol,omitempty"` - TLS *apisv1.GatewayTLSConfigApplyConfiguration `json:"tls,omitempty"` - AllowedRoutes *apisv1.AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` + Name *v1.SectionName `json:"name,omitempty"` + Hostname *v1.Hostname `json:"hostname,omitempty"` + Port *v1.PortNumber `json:"port,omitempty"` + Protocol *v1.ProtocolType `json:"protocol,omitempty"` + TLS *apisv1.ListenerTLSConfigApplyConfiguration `json:"tls,omitempty"` + AllowedRoutes *apisv1.AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` } // ListenerEntryApplyConfiguration constructs a declarative configuration of the ListenerEntry type for use with @@ -75,7 +75,7 @@ func (b *ListenerEntryApplyConfiguration) WithProtocol(value v1.ProtocolType) *L // WithTLS sets the TLS field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the TLS field is set to the value of the last call. -func (b *ListenerEntryApplyConfiguration) WithTLS(value *apisv1.GatewayTLSConfigApplyConfiguration) *ListenerEntryApplyConfiguration { +func (b *ListenerEntryApplyConfiguration) WithTLS(value *apisv1.ListenerTLSConfigApplyConfiguration) *ListenerEntryApplyConfiguration { b.TLS = value return b } diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 92508d3a05..f71080402f 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -307,6 +307,9 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.ObjectReference elementRelationship: atomic + - name: mode + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.GRPCBackendRef map: fields: @@ -598,6 +601,9 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - name + - name: tls + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.GatewayTLSConfig - name: io.k8s.sigs.gateway-api.apis.v1.GatewaySpecAddress map: fields: @@ -645,23 +651,18 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.sigs.gateway-api.apis.v1.GatewayTLSConfig map: fields: - - name: certificateRefs + - name: default type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1.SecretObjectReference - elementRelationship: atomic - - name: frontendValidation - type: - namedType: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSValidation - - name: mode - type: - scalar: string - - name: options + namedType: io.k8s.sigs.gateway-api.apis.v1.TLSConfig + default: {} + - name: perPort type: - map: + list: elementType: - scalar: string + namedType: io.k8s.sigs.gateway-api.apis.v1.TLSPortConfig + elementRelationship: associative + keys: + - port - name: io.k8s.sigs.gateway-api.apis.v1.HTTPBackendRef map: fields: @@ -1033,7 +1034,7 @@ var schemaYAML = typed.YAMLObject(`types: default: "" - name: tls type: - namedType: io.k8s.sigs.gateway-api.apis.v1.GatewayTLSConfig + namedType: io.k8s.sigs.gateway-api.apis.v1.ListenerTLSConfig - name: io.k8s.sigs.gateway-api.apis.v1.ListenerNamespaces map: fields: @@ -1068,6 +1069,23 @@ var schemaYAML = typed.YAMLObject(`types: elementType: namedType: io.k8s.sigs.gateway-api.apis.v1.RouteGroupKind elementRelationship: atomic +- name: io.k8s.sigs.gateway-api.apis.v1.ListenerTLSConfig + map: + fields: + - name: certificateRefs + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.SecretObjectReference + elementRelationship: atomic + - name: mode + type: + scalar: string + - name: options + type: + map: + elementType: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.LocalObjectReference map: fields: @@ -1235,6 +1253,24 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: string default: "" +- name: io.k8s.sigs.gateway-api.apis.v1.TLSConfig + map: + fields: + - name: frontendValidation + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSValidation + default: {} +- name: io.k8s.sigs.gateway-api.apis.v1.TLSPortConfig + map: + fields: + - name: port + type: + scalar: numeric + default: 0 + - name: tls + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.TLSConfig + default: {} - name: io.k8s.sigs.gateway-api.apis.v1alpha2.GRPCRoute map: fields: @@ -1801,7 +1837,7 @@ var schemaYAML = typed.YAMLObject(`types: default: "" - name: tls type: - namedType: io.k8s.sigs.gateway-api.apis.v1.GatewayTLSConfig + namedType: io.k8s.sigs.gateway-api.apis.v1.ListenerTLSConfig - name: io.k8s.sigs.gateway-api.apisx.v1alpha1.ListenerEntryStatus map: fields: diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 8014f68c7c..71851d893d 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -140,6 +140,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.ListenerNamespacesApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ListenerStatus"): return &apisv1.ListenerStatusApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ListenerTLSConfig"): + return &apisv1.ListenerTLSConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("LocalObjectReference"): return &apisv1.LocalObjectReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("LocalParametersReference"): @@ -164,6 +166,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.SessionPersistenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("SupportedFeature"): return &apisv1.SupportedFeatureApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("TLSConfig"): + return &apisv1.TLSConfigApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("TLSPortConfig"): + return &apisv1.TLSPortConfigApplyConfiguration{} // Group=gateway.networking.k8s.io, Version=v1alpha2 case v1alpha2.SchemeGroupVersion.WithKind("GRPCRoute"): diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 2e2462a087..f04f7b978a 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -802,7 +802,7 @@ spec: the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". - The association of SNIs to Certificate defined in GatewayTLSConfig is + The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all @@ -890,96 +890,6 @@ spec: maxItems: 64 type: array x-kubernetes-list-type: atomic - frontendValidation: - description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will require clients to send a client certificate - required for validation during the TLS handshake. In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. - - Support: Extended - properties: - caCertificateRefs: - description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one reference, or other kinds - of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For - example "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - required: - - caCertificateRefs - type: object mode: default: Terminate description: |- @@ -1058,6 +968,297 @@ spec: rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + tls: + description: |- + GatewayTLSConfig specifies frontend tls configuration for gateway. + + Support: Extended + properties: + default: + description: |- + Default specifies the default client certificate validation configuration + for all Listeners handling HTTPS traffic, unless a per-port configuration + is defined. + + support: Core + properties: + frontendValidation: + description: |- + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + required: + - frontendValidation + type: object + perPort: + description: |- + PerPort specifies tls configuration assigned per port. + Per port configuration is optional. Once set this configuration overrides + the default configuration for all Listeners handling HTTPS traffic + that match this port. + Each override port requires a unique TLS configuration. + + support: Core + items: + properties: + port: + description: |- + The Port indicates the Port Number to which the TLS configuration will be + applied. This configuration will be applied to all Listeners handling HTTPS + traffic that match this port. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + tls: + description: |- + TLS store the configuration that will be applied to all Listeners handling + HTTPS traffic and matching given port. + + Support: Core + properties: + frontendValidation: + description: |- + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + For example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + required: + - frontendValidation + type: object + required: + - port + - tls + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: Port for TLS configuration must be unique within the + Gateway + rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) + required: + - default + type: object required: - gatewayClassName - listeners @@ -2148,7 +2349,7 @@ spec: the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". - The association of SNIs to Certificate defined in GatewayTLSConfig is + The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all @@ -2236,96 +2437,6 @@ spec: maxItems: 64 type: array x-kubernetes-list-type: atomic - frontendValidation: - description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will require clients to send a client certificate - required for validation during the TLS handshake. In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. - - Support: Extended - properties: - caCertificateRefs: - description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one reference, or other kinds - of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For - example "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - required: - - caCertificateRefs - type: object mode: default: Terminate description: |- @@ -2404,6 +2515,297 @@ spec: rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + tls: + description: |- + GatewayTLSConfig specifies frontend tls configuration for gateway. + + Support: Extended + properties: + default: + description: |- + Default specifies the default client certificate validation configuration + for all Listeners handling HTTPS traffic, unless a per-port configuration + is defined. + + support: Core + properties: + frontendValidation: + description: |- + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + required: + - frontendValidation + type: object + perPort: + description: |- + PerPort specifies tls configuration assigned per port. + Per port configuration is optional. Once set this configuration overrides + the default configuration for all Listeners handling HTTPS traffic + that match this port. + Each override port requires a unique TLS configuration. + + support: Core + items: + properties: + port: + description: |- + The Port indicates the Port Number to which the TLS configuration will be + applied. This configuration will be applied to all Listeners handling HTTPS + traffic that match this port. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + tls: + description: |- + TLS store the configuration that will be applied to all Listeners handling + HTTPS traffic and matching given port. + + Support: Core + properties: + frontendValidation: + description: |- + FrontendValidation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. + + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + For example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + required: + - frontendValidation + type: object + required: + - port + - tls + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: Port for TLS configuration must be unique within the + Gateway + rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) + required: + - default + type: object required: - gatewayClassName - listeners diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 1a266cca60..6d5a5bd5f9 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -323,7 +323,7 @@ spec: the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". - The association of SNIs to Certificate defined in GatewayTLSConfig is + The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all @@ -409,96 +409,6 @@ spec: maxItems: 64 type: array x-kubernetes-list-type: atomic - frontendValidation: - description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will require clients to send a client certificate - required for validation during the TLS handshake. In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. - - Support: Extended - properties: - caCertificateRefs: - description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one reference, or other kinds - of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For - example "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - required: - - caCertificateRefs - type: object mode: default: Terminate description: |- diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index bcb648812d..8b7b0a02e5 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -657,7 +657,7 @@ spec: the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". - The association of SNIs to Certificate defined in GatewayTLSConfig is + The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all @@ -1768,7 +1768,7 @@ spec: the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". - The association of SNIs to Certificate defined in GatewayTLSConfig is + The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all diff --git a/examples/experimental/frontend-cert-validation.yaml b/examples/experimental/frontend-cert-validation.yaml index 7f103aed8e..a7a9d4a14d 100644 --- a/examples/experimental/frontend-cert-validation.yaml +++ b/examples/experimental/frontend-cert-validation.yaml @@ -4,6 +4,13 @@ metadata: name: client-validation-basic spec: gatewayClassName: acme-lb + tls: + default: + frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: foo-example-com-ca-cert listeners: - name: foo-https protocol: HTTPS @@ -14,10 +21,5 @@ spec: - kind: Secret group: "" name: foo-example-com-cert - frontendValidation: - caCertificateRefs: - - kind: ConfigMap - group: "" - name: foo-example-com-ca-cert --- diff --git a/geps/gep-91/index.md b/geps/gep-91/index.md index 8eedb7bd62..d71aef7650 100644 --- a/geps/gep-91/index.md +++ b/geps/gep-91/index.md @@ -26,21 +26,28 @@ This use case has been highlighted in the [TLS Configuration GEP][] under segmen ### API -* Introduce two new structs `TLSConfig` and `FrontendTLSValidation` allowing for the definition of certificate validation used to authenticate the peer (frontend) in a TLS connection. A new `tls` field, storing an array of `TLSConfigs`, will be added to the gateway object. +* Introduce new structs: `GatewayTLSConfig`, `TLSConfig`, `TLSPortConfig`, `FrontendTLSValidation` allowing for the definition of certificate validation used to authenticate the peer (frontend) in a TLS connection. A new `tls` field with gateway tls configuration will be added to the gateway object. +* `TLSConfig` will allow defining client certificate validation per port which will be applied to all Listeners matching this port. We might want to extend this struct with other tls configurations. +* `TLSPortConfig` will allow defining client certificate validation per port which will be applied to all Listeners matching this port. +* `GatewayTLSConfig` struct contains default and (optional) per port configuration. Default configuration will apply to all Listeners which are not matching per port override. * This new field is separate from the existing [BackendTLSPolicy][] configuration. [BackendTLSPolicy][] controls TLS certificate validation for connections *from* the Gateway to the backend service. This proposal adds the ability to validate the TLS certificate presented by the *client* connecting to the Gateway (the frontend). These two validation mechanisms operate independently and can be used simultaneously. * Introduce a `caCertificateRefs` field within `FrontendTLSValidation` that can be used to specify a list of CA Certificates that can be used as a trust anchor to validate the certificates presented by the client. * Add a new `FrontendValidationModeType` enum within `FrontendTLSValidation` indicating how gateway should validate client certificates. As for now we support following values but it might change in the future: - 1) `AllowValidOnly` - 2) `AllowInvalidOrMissingCert` + 1) `AllowValidOnly` (Core Support) + 2) `AllowInsecureFallback` (Extended Support) + + `AllowInsecureFallback` mode indicates the gateway will accept connections even if the client certificate is not presented or fails verification. + This approach delegates client authorization to the backend and introduce a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + When `FrontendValidationModeType` is changed from `AllowValidOnly` to `AllowInsecureFallback` the `InsecureFrontendValidationMode` condition MUST be set to `True` with Reason `ConfigurationChanged` on gateway. * Introduce a `ObjectReference` structure that can be used to specify `caCertificateRefs` references. -* Introduce a `tls` field within the Gateway Spec to allow for a common TLS configuration to apply across all listeners. ### Impact on listeners This proposal removes frontendTLSValidation from Listener's TLS configuration and introduces gateways level per port configuration. This is a breaking change for exisitng implementation which uses this feature from Experimental API. - Once gateway level TLS is configured (either by default or for a specific port), the TLS settings will apply to all existing and newly created Listeners that match the configuration. + Once gateway level TLS is configured (either by default or for a specific port), the TLS settings will apply to all existing and newly created Listeners serving HTTPS that match the configuration. #### GO @@ -78,43 +85,58 @@ type ObjectReference struct { Namespace *Namespace `json:"namespace,omitempty"` } -// GatewayTLSConfigs stores TLS configurations for a Gateway. -// -// * If the `port` field in `TLSConfig` is not set, the TLS configuration applies -// to all listeners in the gateway. We call this `default` configuration. -// * If the `port` field in `TLSConfig` is set, the TLS configuration applies -// only to listeners with a matching port. Each port requires a unique TLS configuration. -// * Per-port configurations can override the `default` configuration. -// * The `default` configuration is optional. Clients can apply TLS configuration -// to a subset of listeners by creating only per-port configurations. Listeners -// with a port that does not match any TLS configuration will not have -// `frontendValidation` set. -type GatewayTLSConfigs = []TLSConfig - -// TLSConfig describes a TLS configuration that can be applied to all Gateway -// Listeners or to all Listeners matching the Port if set. +// GatewayTLSConfig specifies frontend tls configuration for gateway. +type GatewayTLSConfig struct { + // default specifies the default client certificate validation configuration + // for all Listeners handling HTTPS traffic, unless a per-port configuration + // is defined. + // + // support: Core + // + // +required + // + Default FrontendTLSValidation `json:"default"` + + // PerPort specifies tls configuration assigned per port. + // Per port configuration is optional. Once set this configuration overrides + // the default configuration for all Listeners handling HTTPS traffic + // that match this port. + // Each override port requires a unique TLS configuration. + // + // support: Core + // + PerPort []TLSConfig `json:"PerPort,omitempty"` +} + +// TLSConfig describes a TLS configuration. Currently, it stores only the client +// certificate validation configuration, but this may be extended in the future. type TLSConfig struct { - // The Port indicates the Port Number to which the TLS configuration will be - // applied. If the field is not set the TLS Configuration will be applied to - // all Listeners. - // - // Support: Extended - // - // +optional - // - Port *PortNumber // FrontendValidation holds configuration information for validating the frontend (client). - // Setting this field will result in mutual authentication when connecting to the gateway. In browsers this may result in a dialog appearing + // Setting this field will result in mutual authentication when connecting to the gateway. + // In browsers this may result in a dialog appearing // that requests a user to specify the client certificate. // The maximum depth of a certificate chain accepted in verification is Implementation specific. // - // Each field may be overidden by an equivalent setting applied at the Listener level. - // // Support: Extended // - // +optional + // +required + // + FrontendValidation FrontendTLSValidation `json:"frontendValidation"` +} + +type TLSPortConfig struct { + // The Port indicates the Port Number to which the TLS configuration will be + // applied. This configuration will be applied to all Listeners handling HTTPS + // traffic that match this port. + // + // Support: Core + // + // +required // - FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` + Port PortNumber `json:"port"` + // TLS store the configuration that will be applied to all Listeners handling + // HTTPS traffic and matching given port. + TLS TLSConfig `json:"tls"` } // FrontendTLSValidation holds configuration information that can be used to validate @@ -151,21 +173,25 @@ type FrontendTLSValidation struct { // - AllowValidOnly: In this mode, the gateway will accept connections only if // the client presents a valid certificate. This certificate must successfully // pass validation against the CA certificates specified in `CACertificateRefs`. - // - AllowInvalidOrMissingCert: In this mode, the gateway will accept - // connections even if the client certificate is not presented or fails verification. + // - AllowInsecureFallback: In this mode, the gateway will accept connections + // even if the client certificate is not presented or fails verification. + // + // This approach delegates client authorization to the backend and introduce + // a significant security risk. It should be used in testing environments or + // on a temporary basis in non-testing environments. // // Defaults to AllowValidOnly. // - // Support: Extended + // Support: Core // // +optional // +kubebuilder:default=AllowValidOnly - Mode *FrontendValidationModeType `json:"mode,omitempty"` + Mode FrontendValidationModeType `json:"mode,omitempty"` } -// FrontendValidationModeType type defines how a Gateway or Listener validates client certificates. +// FrontendValidationModeType type defines how a Gateway validates client certificates. // -// +kubebuilder:validation:Enum=AllowValidOnly;AllowInvalidOrMissingCert +// +kubebuilder:validation:Enum=AllowValidOnly;AllowInsecureFallback type FrontendValidationModeType string const ( @@ -173,15 +199,20 @@ const ( // during the TLS handshake and MUST pass validation. AllowValidOnly FrontendValidationModeType = "AllowValidOnly" - // AllowInvalidOrMissingCert indicates that a client certificate may not be + // AllowInsecureFallback indicates that a client certificate may not be // presented during the handshake or the validation against CA certificates may fail. - AllowInvalidOrMissingCert FrontendValidationModeType = "AllowInvalidOrMissingCert" + AllowInsecureFallback FrontendValidationModeType = "AllowInsecureFallback" ) type GatewaySpec struct { ... - // TLSConfigs stores TLS configurations for a Gateway. - TLSConfigs GatewayTLSConfigs + // GatewayTLSConfig specifies frontend tls configuration for gateway. + // + // Support: Core + // + // +optional + // + TLS *GatewayTLSConfig `json:"tls,omitempty"` } ``` @@ -198,11 +229,12 @@ metadata: spec: gatewayClassName: acme-lb tls: - - frontendValidation: - caCertificateRefs: - - kind: ConfigMap - group: "" - name: default-cert + default: + frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: default-cert listeners: - name: foo-https protocol: HTTPS @@ -234,18 +266,20 @@ metadata: spec: gatewayClassName: acme-lb tls: - - port: 443 + default: frontendValidation: caCertificateRefs: - - kind: ConfigMap - group: "" - name: foo-example-com-ca-cert - - frontendValidation: - caCertificateRefs: - - kind: ConfigMap - group: "" - name: default-cert - mode: AllowInvalidOrMissingCert + - kind: ConfigMap + group: "" + name: default-cert + mode: AllowInsecureFallback + perPort: + - port: 443 + frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: foo-example-com-ca-cert listeners: - name: foo-https protocol: HTTPS @@ -321,7 +355,6 @@ This GEP aims to standardize this behavior as an official part of the upstream s [TLS Handshake Protocol]: https://www.rfc-editor.org/rfc/rfc5246#section-7.4 [Certificate Path Validation]: https://www.rfc-editor.org/rfc/rfc5280#section-6 -[GatewayTLSConfig]: ../../reference/spec.md#gateway.networking.k8s.io/v1.GatewayTLSConfig [BackendTLSPolicy]: ../../api-types/backendtlspolicy.md [TLS Configuration GEP]: ../gep-2907/index.md [Gateway API TLS Use Cases]: https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit?pli=1#heading=h.cxuq8vo8pcxm diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 9885f10471..d412463a01 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -136,6 +136,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.Listener": schema_sigsk8sio_gateway_api_apis_v1_Listener(ref), "sigs.k8s.io/gateway-api/apis/v1.ListenerNamespaces": schema_sigsk8sio_gateway_api_apis_v1_ListenerNamespaces(ref), "sigs.k8s.io/gateway-api/apis/v1.ListenerStatus": schema_sigsk8sio_gateway_api_apis_v1_ListenerStatus(ref), + "sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig": schema_sigsk8sio_gateway_api_apis_v1_ListenerTLSConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference": schema_sigsk8sio_gateway_api_apis_v1_LocalObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.LocalParametersReference": schema_sigsk8sio_gateway_api_apis_v1_LocalParametersReference(ref), "sigs.k8s.io/gateway-api/apis/v1.ObjectReference": schema_sigsk8sio_gateway_api_apis_v1_ObjectReference(ref), @@ -148,6 +149,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference": schema_sigsk8sio_gateway_api_apis_v1_SecretObjectReference(ref), "sigs.k8s.io/gateway-api/apis/v1.SessionPersistence": schema_sigsk8sio_gateway_api_apis_v1_SessionPersistence(ref), "sigs.k8s.io/gateway-api/apis/v1.SupportedFeature": schema_sigsk8sio_gateway_api_apis_v1_SupportedFeature(ref), + "sigs.k8s.io/gateway-api/apis/v1.TLSConfig": schema_sigsk8sio_gateway_api_apis_v1_TLSConfig(ref), + "sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig": schema_sigsk8sio_gateway_api_apis_v1_TLSPortConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.supportedFeatureInternal": schema_sigsk8sio_gateway_api_apis_v1_supportedFeatureInternal(ref), "sigs.k8s.io/gateway-api/apis/v1alpha2.GRPCRoute": schema_sigsk8sio_gateway_api_apis_v1alpha2_GRPCRoute(ref), "sigs.k8s.io/gateway-api/apis/v1alpha2.GRPCRouteList": schema_sigsk8sio_gateway_api_apis_v1alpha2_GRPCRouteList(ref), @@ -3100,7 +3103,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.Refer }, }, SchemaProps: spec.SchemaProps{ - Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain TLS certificates of the Certificate Authorities that can be used as a trust anchor to validate the certificates presented by the client.\n\nA single CA certificate reference to a Kubernetes ConfigMap has \"Core\" support. Implementations MAY choose to support attaching multiple CA certificates to a Listener, but this behavior is implementation-specific.\n\nSupport: Core - A single reference to a Kubernetes ConfigMap with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific (More than one reference, or other kinds of resources).\n\nReferences to a resource in a different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.", + Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain TLS certificates of the Certificate Authorities that can be used as a trust anchor to validate the certificates presented by the client.\n\nA single CA certificate reference to a Kubernetes ConfigMap has \"Core\" support. Implementations MAY choose to support attaching multiple CA certificates to a Listener, but this behavior is implementation-specific.\n\nSupport: Core - A single reference to a Kubernetes ConfigMap with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific (More than one certificate in a ConfigMap with different keys or more than one reference, or other kinds of resources).\n\nReferences to a resource in a different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -3112,6 +3115,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.Refer }, }, }, + "mode": { + SchemaProps: spec.SchemaProps{ + Description: "FrontendValidationMode defines the mode for validating the client certificate. There are two possible modes:\n\n- AllowValidOnly: In this mode, the gateway will accept connections only if\n the client presents a valid certificate. This certificate must successfully\n pass validation against the CA certificates specified in `CACertificateRefs`.\n- AllowInsecureFallback: In this mode, the gateway will accept connections\n even if the client certificate is not presented or fails verification.\n\n This approach delegates client authorization to the backend and introduce\n a significant security risk. It should be used in testing environments or\n on a temporary basis in non-testing environments.\n\nDefaults to AllowValidOnly.\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, }, Required: []string{"caCertificateRefs"}, }, @@ -4094,12 +4104,18 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba Ref: ref("sigs.k8s.io/gateway-api/apis/v1.AllowedListeners"), }, }, + "tls": { + SchemaProps: spec.SchemaProps{ + Description: "GatewayTLSConfig specifies frontend tls configuration for gateway.\n\nSupport: Extended\n\n", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"), + }, + }, }, Required: []string{"gatewayClassName", "listeners"}, }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.AllowedListeners", "sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS", "sigs.k8s.io/gateway-api/apis/v1.GatewayInfrastructure", "sigs.k8s.io/gateway-api/apis/v1.GatewaySpecAddress", "sigs.k8s.io/gateway-api/apis/v1.Listener"}, + "sigs.k8s.io/gateway-api/apis/v1.AllowedListeners", "sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS", "sigs.k8s.io/gateway-api/apis/v1.GatewayInfrastructure", "sigs.k8s.io/gateway-api/apis/v1.GatewaySpecAddress", "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig", "sigs.k8s.io/gateway-api/apis/v1.Listener"}, } } @@ -4241,61 +4257,44 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayTLSConfig(ref common.ReferenceC return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "GatewayTLSConfig specifies frontend tls configuration for gateway.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ - "mode": { + "default": { SchemaProps: spec.SchemaProps{ - Description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes:\n\n- Terminate: The TLS session between the downstream client and the\n Gateway is terminated at the Gateway. This mode requires certificates\n to be specified in some way, such as populating the certificateRefs\n field.\n- Passthrough: The TLS session is NOT terminated by the Gateway. This\n implies that the Gateway can't decipher the TLS stream except for\n the ClientHello message of the TLS protocol. The certificateRefs field\n is ignored in this mode.\n\nSupport: Core", - Type: []string{"string"}, - Format: "", + Description: "Default specifies the default client certificate validation configuration for all Listeners handling HTTPS traffic, unless a per-port configuration is defined.\n\nsupport: Core\n\n", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSConfig"), }, }, - "certificateRefs": { + "perPort": { VendorExtensible: spec.VendorExtensible{ Extensions: spec.Extensions{ - "x-kubernetes-list-type": "atomic", + "x-kubernetes-list-map-keys": []interface{}{ + "port", + }, + "x-kubernetes-list-type": "map", }, }, SchemaProps: spec.SchemaProps{ - Description: "CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener.\n\nA single CertificateRef to a Kubernetes Secret has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific.\n\nReferences to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.\n\nThis field is required to have at least one element when the mode is set to \"Terminate\" (default) and is optional otherwise.\n\nCertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources.\n\nSupport: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls\n\nSupport: Implementation-specific (More than one reference or other resource types)", + Description: "PerPort specifies tls configuration assigned per port. Per port configuration is optional. Once set this configuration overrides the default configuration for all Listeners handling HTTPS traffic that match this port. Each override port requires a unique TLS configuration.\n\nsupport: Core\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference"), - }, - }, - }, - }, - }, - "frontendValidation": { - SchemaProps: spec.SchemaProps{ - Description: "FrontendValidation holds configuration information for validating the frontend (client). Setting this field will require clients to send a client certificate required for validation during the TLS handshake. In browsers this may result in a dialog appearing that requests a user to specify the client certificate. The maximum depth of a certificate chain accepted in verification is Implementation specific.\n\nSupport: Extended\n\n", - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation"), - }, - }, - "options": { - SchemaProps: spec.SchemaProps{ - Description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites.\n\nA set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API.\n\nSupport: Implementation-specific", - Type: []string{"object"}, - AdditionalProperties: &spec.SchemaOrBool{ - Allows: true, - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"), }, }, }, }, }, }, + Required: []string{"default"}, }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation", "sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference"}, + "sigs.k8s.io/gateway-api/apis/v1.TLSConfig", "sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"}, } } @@ -5399,8 +5398,8 @@ func schema_sigsk8sio_gateway_api_apis_v1_Listener(ref common.ReferenceCallback) }, "tls": { SchemaProps: spec.SchemaProps{ - Description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\".\n\nThe association of SNIs to Certificate defined in GatewayTLSConfig is defined based on the Hostname field for this listener.\n\nThe GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake.\n\nSupport: Core", - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"), + Description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\".\n\nThe association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener.\n\nThe GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake.\n\nSupport: Core", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig"), }, }, "allowedRoutes": { @@ -5414,7 +5413,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_Listener(ref common.ReferenceCallback) }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.AllowedRoutes", "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"}, + "sigs.k8s.io/gateway-api/apis/v1.AllowedRoutes", "sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig"}, } } @@ -5519,6 +5518,62 @@ func schema_sigsk8sio_gateway_api_apis_v1_ListenerStatus(ref common.ReferenceCal } } +func schema_sigsk8sio_gateway_api_apis_v1_ListenerTLSConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "mode": { + SchemaProps: spec.SchemaProps{ + Description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes:\n\n- Terminate: The TLS session between the downstream client and the\n Gateway is terminated at the Gateway. This mode requires certificates\n to be specified in some way, such as populating the certificateRefs\n field.\n- Passthrough: The TLS session is NOT terminated by the Gateway. This\n implies that the Gateway can't decipher the TLS stream except for\n the ClientHello message of the TLS protocol. The certificateRefs field\n is ignored in this mode.\n\nSupport: Core", + Type: []string{"string"}, + Format: "", + }, + }, + "certificateRefs": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener.\n\nA single CertificateRef to a Kubernetes Secret has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific.\n\nReferences to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.\n\nThis field is required to have at least one element when the mode is set to \"Terminate\" (default) and is optional otherwise.\n\nCertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources.\n\nSupport: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls\n\nSupport: Implementation-specific (More than one reference or other resource types)", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference"), + }, + }, + }, + }, + }, + "options": { + SchemaProps: spec.SchemaProps{ + Description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites.\n\nA set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API.\n\nSupport: Implementation-specific", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Allows: true, + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_LocalObjectReference(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -5997,6 +6052,59 @@ func schema_sigsk8sio_gateway_api_apis_v1_SupportedFeature(ref common.ReferenceC } } +func schema_sigsk8sio_gateway_api_apis_v1_TLSConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "TLSConfig describes TLS configuration that can apply to multiple Listeners within this Gateway. Currently, it stores only the client certificate validation configuration, but this may be extended in the future.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "frontendValidation": { + SchemaProps: spec.SchemaProps{ + Description: "FrontendValidation holds configuration information for validating the frontend (client). Setting this field will result in mutual authentication when connecting to the gateway. In browsers this may result in a dialog appearing that requests a user to specify the client certificate. The maximum depth of a certificate chain accepted in verification is Implementation specific.\n\nSupport: Core\n\n", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation"), + }, + }, + }, + Required: []string{"frontendValidation"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation"}, + } +} + +func schema_sigsk8sio_gateway_api_apis_v1_TLSPortConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "port": { + SchemaProps: spec.SchemaProps{ + Description: "The Port indicates the Port Number to which the TLS configuration will be applied. This configuration will be applied to all Listeners handling HTTPS traffic that match this port.\n\nSupport: Core\n\n", + Default: 0, + Type: []string{"integer"}, + Format: "int32", + }, + }, + "tls": { + SchemaProps: spec.SchemaProps{ + Description: "TLS store the configuration that will be applied to all Listeners handling HTTPS traffic and matching given port.\n\nSupport: Core\n\n", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSConfig"), + }, + }, + }, + Required: []string{"port", "tls"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.TLSConfig"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_supportedFeatureInternal(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -8204,8 +8312,8 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere }, "tls": { SchemaProps: spec.SchemaProps{ - Description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\".\n\nThe association of SNIs to Certificate defined in GatewayTLSConfig is defined based on the Hostname field for this listener.\n\nThe GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake.", - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"), + Description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\".\n\nThe association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener.\n\nThe GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake.", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig"), }, }, "allowedRoutes": { @@ -8219,7 +8327,7 @@ func schema_sigsk8sio_gateway_api_apisx_v1alpha1_ListenerEntry(ref common.Refere }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.AllowedRoutes", "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"}, + "sigs.k8s.io/gateway-api/apis/v1.AllowedRoutes", "sigs.k8s.io/gateway-api/apis/v1.ListenerTLSConfig"}, } } diff --git a/pkg/test/cel/gateway_test.go b/pkg/test/cel/gateway_test.go index 7f8d867642..ba85b50f2e 100644 --- a/pkg/test/cel/gateway_test.go +++ b/pkg/test/cel/gateway_test.go @@ -60,7 +60,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("http"), Protocol: gatewayv1.HTTPProtocolType, Port: gatewayv1.PortNumber(8080), - TLS: &gatewayv1.GatewayTLSConfig{}, + TLS: &gatewayv1.ListenerTLSConfig{}, }, } }, @@ -74,7 +74,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("https"), Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8080), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: ptrTo(gatewayv1.TLSModeType("Passthrough")), }, }, @@ -90,7 +90,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("https"), Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8080), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ CertificateRefs: []gatewayv1.SecretObjectReference{ {Name: gatewayv1.ObjectName("foo")}, }, @@ -107,7 +107,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("tcp"), Protocol: gatewayv1.TCPProtocolType, Port: gatewayv1.PortNumber(8080), - TLS: &gatewayv1.GatewayTLSConfig{}, + TLS: &gatewayv1.ListenerTLSConfig{}, }, } }, @@ -212,7 +212,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("https"), Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, }, }, @@ -229,7 +229,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("tls"), Protocol: gatewayv1.TLSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, }, }, @@ -246,7 +246,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("https"), Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, CertificateRefs: []gatewayv1.SecretObjectReference{ {Name: gatewayv1.ObjectName("foo")}, @@ -265,7 +265,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("tls"), Protocol: gatewayv1.TLSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, CertificateRefs: []gatewayv1.SecretObjectReference{ {Name: gatewayv1.ObjectName("foo")}, @@ -284,7 +284,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("https"), Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, Options: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ "networking.example.com/tls-version": "1.2", @@ -303,7 +303,7 @@ func TestValidateGateway(t *testing.T) { Name: gatewayv1.SectionName("tls"), Protocol: gatewayv1.TLSProtocolType, Port: gatewayv1.PortNumber(8443), - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ Mode: &tlsMode, Options: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ "networking.example.com/tls-version": "1.2", @@ -473,7 +473,7 @@ func TestValidateGateway(t *testing.T) { Protocol: gatewayv1.HTTPSProtocolType, Port: gatewayv1.PortNumber(8000), Hostname: &hostnameFoo, - TLS: &gatewayv1.GatewayTLSConfig{ + TLS: &gatewayv1.ListenerTLSConfig{ CertificateRefs: []gatewayv1.SecretObjectReference{ {Name: gatewayv1.ObjectName("foo")}, }, From c703df92906dff5a95e2644f17799093f81dff34 Mon Sep 17 00:00:00 2001 From: bjee19 <139261241+bjee19@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:03:05 -0700 Subject: [PATCH 137/224] Add NGINX Gateway Fabric v2.1.0 conformance report (#4005) * Add NGINX v2.1.0 conformance report * Remove backtick * Add end of file new line --- .../nginx-nginx-gateway-fabric/README.md | 1 + .../experimental-2.1.0-default-report.yaml | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.1.0-default-report.yaml diff --git a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md index ae54954fae..6074dc7bf6 100644 --- a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md +++ b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/README.md @@ -5,6 +5,7 @@ | API channel | Implementation version | Mode | Report | |--------------|-----------------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v2.0.0](https://github.com/nginx/nginx-gateway-fabric/releases/tag/v2.0.0) | default | [v2.0.0 report](./experimental-2.0.0-default-report.yaml) | +| experimental | [v2.1.0](https://github.com/nginx/nginx-gateway-fabric/releases/tag/v2.1.0) | default | [v2.1.0 report](./experimental-2.1.0-default-report.yaml) | ## Reproduce diff --git a/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.1.0-default-report.yaml b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.1.0-default-report.yaml new file mode 100644 index 0000000000..b9f14ea8bf --- /dev/null +++ b/conformance/reports/v1.3.0/nginx-nginx-gateway-fabric/experimental-2.1.0-default-report.yaml @@ -0,0 +1,98 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-08-18T20:07:45Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://github.com/nginx/nginx-gateway-fabric/discussions/new/choose + organization: nginx + project: nginx-gateway-fabric + url: https://github.com/nginx/nginx-gateway-fabric + version: v2.1.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-GRPC + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 16 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayStaticAddresses + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteParentRefPort + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +- core: + result: success + statistics: + Failed: 0 + Passed: 11 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 1 + Skipped: 0 + supportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayInfrastructurePropagation + - GatewayPort8080 + unsupportedFeatures: + - GatewayStaticAddresses + name: GATEWAY-TLS + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure +- HTTPRouteRequestPercentageMirror From 8fe8316f5792a7830a49c800f89fe689e0df042e Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Wed, 20 Aug 2025 21:37:07 +0200 Subject: [PATCH 138/224] Add ResolvedRefs condition for BackendTLSPolicy (#3994) * Add ResolvedRefs condition for BackendTLSPolicy Signed-off-by: Norwin Schnyder * Apply PR feedback Signed-off-by: Norwin Schnyder * Refined implementation-specific behavior of CACertificateRefs Signed-off-by: Norwin Schnyder * Apply PR suggestions Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- apis/v1alpha3/backendtlspolicy_types.go | 81 +++++++++++++++++-- ....networking.k8s.io_backendtlspolicies.yaml | 40 +++++++-- geps/gep-1897/index.md | 6 +- pkg/generated/openapi/zz_generated.openapi.go | 4 +- 4 files changed, 110 insertions(+), 21 deletions(-) diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index e00491908c..9c5c019d46 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -121,8 +121,32 @@ type BackendTLSPolicyValidation struct { // not both. If CACertificateRefs is empty or unspecified, the configuration for // WellKnownCACertificates MUST be honored instead if supported by the implementation. // - // References to a resource in a different namespace are invalid for the - // moment, although we will revisit this in the future. + // A CACertificateRef is invalid if: + // + // * It refers to a resource that cannot be resolved (e.g., the referenced resource + // does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + // named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + // and the Message of the Condition must indicate which reference is invalid and why. + // + // * It refers to an unknown or unsupported kind of resource. In this case, the Reason + // must be set to `InvalidKind` and the Message of the Condition must explain which + // kind of resource is unknown or unsupported. + // + // * It refers to a resource in another namespace. This may change in future + // spec updates. + // + // Implementations MAY choose to perform further validation of the certificate + // content (e.g., checking expiry or enforcing specific formats). In such cases, + // an implementation-specific Reason and Message must be set for the invalid reference. + // + // In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + // the BackendTLSPolicy is set to `status: False`, with a Reason and Message + // that indicate the cause of the error. Connections using an invalid + // CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + // response. If ALL CACertificateRefs are invalid, the implementation MUST also + // ensure the `Accepted` Condition on the BackendTLSPolicy is set to + // `status: False`, with a Reason `NoValidCACertificate`. + // // // A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. // Implementations MAY choose to support attaching multiple certificates to @@ -131,8 +155,8 @@ type BackendTLSPolicyValidation struct { // Support: Core - An optional single reference to a Kubernetes ConfigMap, // with the CA certificate in a key named `ca.crt`. // - // Support: Implementation-specific (More than one reference, or other kinds - // of resources). + // Support: Implementation-specific - More than one reference, other kinds + // of resources, or a single reference that includes multiple certificates. // // +optional // +listType=atomic @@ -144,10 +168,11 @@ type BackendTLSPolicyValidation struct { // // If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs // must be specified with at least one entry for a valid configuration. Only one of - // CACertificateRefs or WellKnownCACertificates may be specified, not both. If an - // implementation does not support the WellKnownCACertificates field or the value - // supplied is not supported, the Status Conditions on the Policy MUST be - // updated to include an Accepted: False Condition with Reason: Invalid. + // CACertificateRefs or WellKnownCACertificates may be specified, not both. + // If an implementation does not support the WellKnownCACertificates field, or + // the supplied value is not recognized, the implementation MUST ensure the + // `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + // a Reason `Invalid`. // // Support: Implementation-specific // @@ -235,3 +260,43 @@ const ( // Support: Core URISubjectAltNameType SubjectAltNameType = "URI" ) + +const ( + // This reason is used with the "Accepted" condition when it is + // set to false because all CACertificateRefs of the + // BackendTLSPolicy are invalid. + BackendTLSPolicyReasonNoValidCACertificate v1alpha2.PolicyConditionReason = "NoValidCACertificate" +) + +const ( + // This condition indicates whether the controller was able to resolve all + // object references for the BackendTLSPolicy. + // + // Possible reasons for this condition to be True are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCACertificateRef" + // * "InvalidKind" + // + // Controllers may raise this condition with other reasons, but should + // prefer to use the reasons listed above to improve interoperability. + BackendTLSPolicyConditionResolvedRefs v1alpha2.PolicyConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + BackendTLSPolicyReasonResolvedRefs v1alpha2.PolicyConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs is invalid. + // A CACertificateRef is considered invalid when it refers to a nonexistent + // resource or when the data within that resource is malformed. + BackendTLSPolicyReasonInvalidCACertificateRef v1alpha2.PolicyConditionReason = "InvalidCACertificateRef" + + // This reason is used with the "ResolvedRefs" condition when one of the + // BackendTLSPolicy's CACertificateRefs references an unknown or unsupported + // Group and/or Kind. + BackendTLSPolicyReasonInvalidKind v1alpha2.PolicyConditionReason = "InvalidKind" +) diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index 8622def679..b5a05f1be6 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -178,8 +178,31 @@ spec: not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation. - References to a resource in a different namespace are invalid for the - moment, although we will revisit this in the future. + A CACertificateRef is invalid if: + + * It refers to a resource that cannot be resolved (e.g., the referenced resource + does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key + named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` + and the Message of the Condition must indicate which reference is invalid and why. + + * It refers to an unknown or unsupported kind of resource. In this case, the Reason + must be set to `InvalidKind` and the Message of the Condition must explain which + kind of resource is unknown or unsupported. + + * It refers to a resource in another namespace. This may change in future + spec updates. + + Implementations MAY choose to perform further validation of the certificate + content (e.g., checking expiry or enforcing specific formats). In such cases, + an implementation-specific Reason and Message must be set for the invalid reference. + + In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on + the BackendTLSPolicy is set to `status: False`, with a Reason and Message + that indicate the cause of the error. Connections using an invalid + CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error + response. If ALL CACertificateRefs are invalid, the implementation MUST also + ensure the `Accepted` Condition on the BackendTLSPolicy is set to + `status: False`, with a Reason `NoValidCACertificate`. A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. Implementations MAY choose to support attaching multiple certificates to @@ -188,8 +211,8 @@ spec: Support: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`. - Support: Implementation-specific (More than one reference, or other kinds - of resources). + Support: Implementation-specific - More than one reference, other kinds + of resources, or a single reference that includes multiple certificates. items: description: |- LocalObjectReference identifies an API object within the namespace of the @@ -312,10 +335,11 @@ spec: If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of - CACertificateRefs or WellKnownCACertificates may be specified, not both. If an - implementation does not support the WellKnownCACertificates field or the value - supplied is not supported, the Status Conditions on the Policy MUST be - updated to include an Accepted: False Condition with Reason: Invalid. + CACertificateRefs or WellKnownCACertificates may be specified, not both. + If an implementation does not support the WellKnownCACertificates field, or + the supplied value is not recognized, the implementation MUST ensure the + `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with + a Reason `Invalid`. Support: Implementation-specific enum: diff --git a/geps/gep-1897/index.md b/geps/gep-1897/index.md index 8e24b8bf09..149d6c649e 100644 --- a/geps/gep-1897/index.md +++ b/geps/gep-1897/index.md @@ -215,11 +215,11 @@ named object references, each containing a single cert. We originally proposed t [CertificateRefs field on Gateway](https://github.com/kubernetes-sigs/gateway-api/blob/18e79909f7310aafc625ba7c862dfcc67b385250/apis/v1beta1/gateway_types.go#L340) , but the CertificateRef requires both a tls.key and tls.crt and a certificate reference only requires the tls.crt. If any of the CACertificateRefs cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured (e.g., ConfigMap does not contain a key named `ca.crt`), the `ResolvedRefs` status condition MUST be set to `False` with `Reason: InvalidCACertificateRef`. Connections using that CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. -References to objects with an unsupported Group and Kind are not valid, and MUST be rejected by the implementation with the `ResolvedRefs` status condition set to `False` and `Reason: UnsupportedFeature`. +References to objects with an unsupported Group and Kind are not valid, and MUST be rejected by the implementation with the `ResolvedRefs` status condition set to `False` and `Reason: InvalidKind`. Implementations MAY perform further validation of the certificate content (i.e., checking expiry or enforcing specific formats). If they do, they MUST ensure that the `ResolvedRefs` Condition is `False` and use an implementation-specific `Reason`, like `ExpiredCertificate` or similar. If `ResolvedRefs` Condition is `False` implementations SHOULD include a message specifying which references are invalid and explaining why. -If all CertificateRefs cannot be resolved, the BackendTLSPolicy is considered invalid and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `NoCACertificates` and a message explaining this. +If all CertificateRefs cannot be resolved, the BackendTLSPolicy is considered invalid and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `NoValidCACertificate` and a message explaining this. WellKnownCACertificates is an optional enum that allows users to specify whether to use the set of CA certificates trusted by the Gateway (WellKnownCACertificates specified as "System"), or to use the existing CACertificateRefs (WellKnownCACertificates @@ -229,7 +229,7 @@ references to Kubernetes objects that contain PEM-encoded TLS certificates, whic between the gateway and backend pod. References to a resource in a different namespace are invalid. If ClientCertificateRefs is unspecified, then WellKnownCACertificates must be set to "System" for a valid configuration. If WellKnownCACertificates is unspecified, then CACertificateRefs must be specified with at least one entry for a valid configuration. -If an implementation does not support the WellKnownCACertificates, or the provided value is unsupported,the BackendTLSPolicy is considered invalid, and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `UnsupportedFeature` and a message explaining this. +If an implementation does not support the WellKnownCACertificates, or the provided value is unsupported,the BackendTLSPolicy is considered invalid, and the implementation MUST set the `Accepted` Condition to `False`, with a reason of `Invalid` and a message explaining this. For an invalid BackendTLSPolicy, implementations MUST NOT fall back to unencrypted (plaintext) connections. Instead, the corresponding TLS connection MUST fail, and the client MUST receive an HTTP 5xx error response. diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index d412463a01..6774709847 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7409,7 +7409,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, }, SchemaProps: spec.SchemaProps{ - Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod.\n\nIf CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation.\n\nReferences to a resource in a different namespace are invalid for the moment, although we will revisit this in the future.\n\nA single CACertificateRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific.\n\nSupport: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific (More than one reference, or other kinds of resources).", + Description: "CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod.\n\nIf CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation.\n\nA CACertificateRef is invalid if:\n\n* It refers to a resource that cannot be resolved (e.g., the referenced resource\n does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key\n named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef`\n and the Message of the Condition must indicate which reference is invalid and why.\n\n* It refers to an unknown or unsupported kind of resource. In this case, the Reason\n must be set to `InvalidKind` and the Message of the Condition must explain which\n kind of resource is unknown or unsupported.\n\n* It refers to a resource in another namespace. This may change in future\n spec updates.\n\nImplementations MAY choose to perform further validation of the certificate content (e.g., checking expiry or enforcing specific formats). In such cases, an implementation-specific Reason and Message must be set for the invalid reference.\n\nIn all cases, the implementation MUST ensure the `ResolvedRefs` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason and Message that indicate the cause of the error. Connections using an invalid CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. If ALL CACertificateRefs are invalid, the implementation MUST also ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `NoValidCACertificate`.\n\nA single CACertificateRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific.\n\nSupport: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`.\n\nSupport: Implementation-specific - More than one reference, other kinds of resources, or a single reference that includes multiple certificates.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -7428,7 +7428,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, }, SchemaProps: spec.SchemaProps{ - Description: "WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod.\n\nIf WellKnownCACertificates is unspecified or empty (\"\"), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field or the value supplied is not supported, the Status Conditions on the Policy MUST be updated to include an Accepted: False Condition with Reason: Invalid.\n\nSupport: Implementation-specific", + Description: "WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod.\n\nIf WellKnownCACertificates is unspecified or empty (\"\"), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field, or the supplied value is not recognized, the implementation MUST ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `Invalid`.\n\nSupport: Implementation-specific", Type: []string{"string"}, Format: "", }, From 99599108220e5f32a07022343b6b2c93fec19ab6 Mon Sep 17 00:00:00 2001 From: Nick Young Date: Mon, 25 Aug 2025 21:49:10 +1000 Subject: [PATCH 139/224] Update status fields with clearer definitions (#4008) Signed-off-by: Nick Young --- apis/v1/gateway_types.go | 58 +++++++++++++++++++ apis/v1/gatewayclass_types.go | 29 ++++++++++ apis/v1/shared_types.go | 53 +++++++++++++++++ apis/v1alpha2/policy_types.go | 30 ++++++++++ pkg/generated/openapi/zz_generated.openapi.go | 22 +++---- 5 files changed, 181 insertions(+), 11 deletions(-) diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index fdb31043cd..e85e81ba48 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -923,6 +923,34 @@ type GatewayStatus struct { // * "Programmed" // * "Ready" // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // // +optional // +listType=map // +listMapKey=type @@ -1272,6 +1300,36 @@ type ListenerStatus struct { // Conditions describe the current condition of this listener. // + // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // + // // +listType=map // +listMapKey=type // +kubebuilder:validation:MaxItems=8 diff --git a/apis/v1/gatewayclass_types.go b/apis/v1/gatewayclass_types.go index 655195ce6d..f9b779c7b3 100644 --- a/apis/v1/gatewayclass_types.go +++ b/apis/v1/gatewayclass_types.go @@ -263,6 +263,35 @@ type GatewayClassStatus struct { // Controllers should prefer to publish conditions using values // of GatewayClassConditionType for the type of each Condition. // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // + // // +optional // +listType=map // +listMapKey=type diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index b98a9e812f..5b5ed4cfed 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -477,6 +477,36 @@ type RouteParentStatus struct { // * The Route is of a type that the controller does not support. // * The Route is in a namespace the controller does not have access to. // + // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // + // // +listType=map // +listMapKey=type // +kubebuilder:validation:MinItems=1 @@ -503,6 +533,29 @@ type RouteStatus struct { // A maximum of 32 Gateways will be represented in this list. An empty list // means the route has not been attached to any Gateway. // + // + // Notes for implementors: + // + // While parents is not a listType `map`, this is due to the fact that the + // list key is not scalar, and Kubernetes is unable to represent this. + // + // Parent status MUST be considered to be namespaced by the combination of + // the parentRef and controllerName fields, and implementations should keep + // the following rules in mind when updating this status: + // + // * Implementations MUST update only entries that have a matching value of + // `controllerName` for that implementation. + // * Implementations MUST NOT update entries with non-matching `controllerName` + // fields. + // * Implementations MUST treat each `parentRef`` in the Route separately and + // update its status based on the relationship with that parent. + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // + // + // // +required // +listType=atomic // +kubebuilder:validation:MaxItems=32 diff --git a/apis/v1alpha2/policy_types.go b/apis/v1alpha2/policy_types.go index dc2f8f7f09..d24bb2ee74 100644 --- a/apis/v1alpha2/policy_types.go +++ b/apis/v1alpha2/policy_types.go @@ -201,6 +201,36 @@ type PolicyAncestorStatus struct { // Conditions describes the status of the Policy with respect to the given Ancestor. // + // + // + // Notes for implementors: + // + // Conditions are a listType `map`, which means that they function like a + // map with a key of the `type` field _in the k8s apiserver_. + // + // This means that implementations must obey some rules when updating this + // section. + // + // * Implementations MUST perform a read-modify-write cycle on this field + // before modifying it. That is, when modifying this field, implementations + // must be confident they have fetched the most recent version of this field, + // and ensure that changes they make are on that recent version. + // * Implementations MUST NOT remove or reorder Conditions that they are not + // directly responsible for. For example, if an implementation sees a Condition + // with type `special.io/SomeField`, it MUST NOT remove, change or update that + // Condition. + // * Implementations MUST always _merge_ changes into Conditions of the same Type, + // rather than creating more than one Condition of the same Type. + // * Implementations MUST always update the `observedGeneration` field of the + // Condition to the `metadata.generation` of the Gateway at the time of update creation. + // * If the `observedGeneration` of a Condition is _greater than_ the value the + // implementation knows about, then it MUST NOT perform the update on that Condition, + // but must wait for a future reconciliation and status update. (The assumption is that + // the implementation's copy of the object is stale and an update will be re-triggered + // if relevant.) + // + // + // // +required // +listType=map // +listMapKey=type diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 6774709847..e674ba5140 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -3642,7 +3642,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GRPCRouteStatus(ref common.ReferenceCa }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -3887,7 +3887,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayClassStatus(ref common.Referenc }, }, SchemaProps: spec.SchemaProps{ - Description: "Conditions is the current status from the controller for this GatewayClass.\n\nControllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition.", + Description: "Conditions is the current status from the controller for this GatewayClass.\n\nControllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition.\n\n Notes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -4182,7 +4182,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayStatus(ref common.ReferenceCall }, }, SchemaProps: spec.SchemaProps{ - Description: "Conditions describe the current conditions of the Gateway.\n\nImplementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state.\n\nKnown condition types are:\n\n* \"Accepted\" * \"Programmed\" * \"Ready\"", + Description: "Conditions describe the current conditions of the Gateway.\n\nImplementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state.\n\nKnown condition types are:\n\n* \"Accepted\" * \"Programmed\" * \"Ready\"\n\n Notes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -5282,7 +5282,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteStatus(ref common.ReferenceCa }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -5497,7 +5497,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_ListenerStatus(ref common.ReferenceCal }, }, SchemaProps: spec.SchemaProps{ - Description: "Conditions describe the current condition of this listener.", + Description: "Conditions describe the current condition of this listener.\n\n Notes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -5885,7 +5885,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_RouteParentStatus(ref common.Reference }, }, SchemaProps: spec.SchemaProps{ - Description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status.\n\nIf the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why.\n\nA Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway.\n\nThere are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when:\n\n* The Route refers to a nonexistent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to.", + Description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status.\n\nIf the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why.\n\nA Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway.\n\nThere are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when:\n\n* The Route refers to a nonexistent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to.\n\n\n\nNotes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -5920,7 +5920,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_RouteStatus(ref common.ReferenceCallba }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -6382,7 +6382,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyAncestorStatus(ref common. }, }, SchemaProps: spec.SchemaProps{ - Description: "Conditions describes the status of the Policy with respect to the given Ancestor.", + Description: "Conditions describes the status of the Policy with respect to the given Ancestor.\n\n\n\nNotes for implementors:\n\nConditions are a listType `map`, which means that they function like a map with a key of the `type` field _in the k8s apiserver_.\n\nThis means that implementations must obey some rules when updating this section.\n\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n* Implementations MUST NOT remove or reorder Conditions that they are not\n directly responsible for. For example, if an implementation sees a Condition\n with type `special.io/SomeField`, it MUST NOT remove, change or update that\n Condition.\n* Implementations MUST always _merge_ changes into Conditions of the same Type,\n rather than creating more than one Condition of the same Type.\n* Implementations MUST always update the `observedGeneration` field of the\n Condition to the `metadata.generation` of the Gateway at the time of update creation.\n* If the `observedGeneration` of a Condition is _greater than_ the value the\n implementation knows about, then it MUST NOT perform the update on that Condition,\n but must wait for a future reconciliation and status update. (The assumption is that\n the implementation's copy of the object is stale and an update will be re-triggered\n if relevant.)\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -6737,7 +6737,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TCPRouteStatus(ref common.Refere }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -6987,7 +6987,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_TLSRouteStatus(ref common.Refere }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -7217,7 +7217,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_UDPRouteStatus(ref common.Refere }, }, SchemaProps: spec.SchemaProps{ - Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.", + Description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified.\n\nNote that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for.\n\nA maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway.\n\n Notes for implementors:\n\nWhile parents is not a listType `map`, this is due to the fact that the list key is not scalar, and Kubernetes is unable to represent this.\n\nParent status MUST be considered to be namespaced by the combination of the parentRef and controllerName fields, and implementations should keep the following rules in mind when updating this status:\n\n* Implementations MUST update only entries that have a matching value of\n `controllerName` for that implementation.\n* Implementations MUST NOT update entries with non-matching `controllerName`\n fields.\n* Implementations MUST treat each `parentRef`` in the Route separately and\n update its status based on the relationship with that parent.\n* Implementations MUST perform a read-modify-write cycle on this field\n before modifying it. That is, when modifying this field, implementations\n must be confident they have fetched the most recent version of this field,\n and ensure that changes they make are on that recent version.\n\n", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From 230b20454c19302684ebcbab5b72023b8f5bbd7e Mon Sep 17 00:00:00 2001 From: idb <71566757+idebeijer@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:35:07 +0200 Subject: [PATCH 140/224] docs: update cilium impl docs for gateway-api v1.3.0 conformance (#4018) --- site-src/implementations.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site-src/implementations.md b/site-src/implementations.md index 46335451c9..0d97e76468 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -261,15 +261,15 @@ Documentation to deploy and use AKO Gateway API can be found at [Avi Kubernetes ### Cilium -[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-Cilium-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/cilium) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Cilium-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/cilium-cilium) [Cilium][cilium] is an eBPF-based networking, observability and security solution for Kubernetes and other networking environments. It includes [Cilium Service Mesh][cilium-service-mesh], a highly efficient mesh data plane that can be run in [sidecarless mode][cilium-sidecarless] to dramatically improve performance, and avoid the operational complexity of sidecars. Cilium also -supports the sidecar proxy model, offering choice to users. As of [Cilium 1.14][cilium114blog], -Cilium supports Gateway API, passing conformance for v0.7.1. +supports the sidecar proxy model, offering choice to users. +Cilium supports Gateway API, passing conformance for v1.3.0 as of [Cilium 1.18][cilium118blog]. Cilium is open source and is a CNCF Graduated project. @@ -280,7 +280,7 @@ effort, check out the #development channel or join our [weekly developer meeting [cilium]:https://cilium.io [cilium-service-mesh]:https://docs.cilium.io/en/stable/gettingstarted/#service-mesh [cilium-sidecarless]:https://isovalent.com/blog/post/cilium-service-mesh/ -[cilium114blog]:https://isovalent.com/blog/post/cilium-release-114/ +[cilium118blog]:https://isovalent.com/blog/post/cilium-1-18/#service-mesh-gateway-api [cilium-slack]:https://cilium.io/slack [cilium-meeting]:https://github.com/cilium/cilium#weekly-developer-meeting From 110bcaf60d1178b18af7588feddcc1f22474dd4a Mon Sep 17 00:00:00 2001 From: Nick Young Date: Tue, 26 Aug 2025 04:51:07 +1000 Subject: [PATCH 141/224] Add API changes for HTTP External Auth (#4001) Updates #1494. Signed-off-by: Nick Young --- apis/v1/httproute_types.go | 226 +++- apis/v1/zz_generated.deepcopy.go | 96 ++ .../apis/v1/forwardbodyconfig.go | 39 + applyconfiguration/apis/v1/grpcauthconfig.go | 41 + applyconfiguration/apis/v1/httpauthconfig.go | 61 + .../apis/v1/httpexternalauthfilter.go | 79 ++ applyconfiguration/apis/v1/httproutefilter.go | 9 + applyconfiguration/internal/internal.go | 55 + applyconfiguration/utils.go | 8 + .../gateway.networking.k8s.io_httproutes.yaml | 1036 +++++++++++++++++ ...lid-filter-externalauth-bad-http-path.yaml | 12 + .../invalid-filter-externalauth-empty.yaml | 8 + ...valid-filter-externalauth-no-protocol.yaml | 9 + pkg/generated/openapi/zz_generated.openapi.go | 175 ++- pkg/test/cel/httproute_experimental_test.go | 46 + 15 files changed, 1897 insertions(+), 3 deletions(-) create mode 100644 applyconfiguration/apis/v1/forwardbodyconfig.go create mode 100644 applyconfiguration/apis/v1/grpcauthconfig.go create mode 100644 applyconfiguration/apis/v1/httpauthconfig.go create mode 100644 applyconfiguration/apis/v1/httpexternalauthfilter.go create mode 100644 hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-bad-http-path.yaml create mode 100644 hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-empty.yaml create mode 100644 hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-no-protocol.yaml diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 39a01f27f1..53fae56716 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -804,6 +804,8 @@ type HTTPRouteMatch struct { // +kubebuilder:validation:XValidation:message="filter.urlRewrite must be specified for URLRewrite filter.type",rule="!(!has(self.urlRewrite) && self.type == 'URLRewrite')" // // +// +// // +kubebuilder:validation:XValidation:message="filter.extensionRef must be nil if the filter.type is not ExtensionRef",rule="!(has(self.extensionRef) && self.type != 'ExtensionRef')" // +kubebuilder:validation:XValidation:message="filter.extensionRef must be specified for ExtensionRef filter.type",rule="!(!has(self.extensionRef) && self.type == 'ExtensionRef')" type HTTPRouteFilter struct { @@ -842,7 +844,7 @@ type HTTPRouteFilter struct { // // +unionDiscriminator // +kubebuilder:validation:Enum=RequestHeaderModifier;ResponseHeaderModifier;RequestMirror;RequestRedirect;URLRewrite;ExtensionRef - // + // // +required Type HTTPRouteFilterType `json:"type"` @@ -901,6 +903,19 @@ type HTTPRouteFilter struct { // CORS *HTTPCORSFilter `json:"cors,omitempty"` + // ExternalAuth configures settings related to sending request details + // to an external auth service. The external service MUST authenticate + // the request, and MAY authorize the request as well. + // + // If there is any problem communicating with the external service, + // this filter MUST fail closed. + // + // Support: Extended + // + // +optional + // + ExternalAuth *HTTPExternalAuthFilter `json:"externalAuth,omitempty"` + // ExtensionRef is an optional, implementation-specific extension to the // "filter" behavior. For example, resource "myroutefilter" in group // "networking.example.net"). ExtensionRef MUST NOT be used for core and @@ -972,6 +987,18 @@ const ( // HTTPRouteFilterCORS HTTPRouteFilterType = "CORS" + // HTTPRouteFilterExternalAuth can be used to configure a Gateway implementation + // to call out to an external Auth server, which MUST perform Authentication + // and MAY perform Authorization on the matched request before the request + // is forwarded to the backend. + // + // Support in HTTPRouteRule: Extended + // + // Feature Name: HTTPRouteExternalAuth + // + // + HTTPRouteFilterExternalAuth HTTPRouteFilterType = "ExternalAuth" + // HTTPRouteFilterExtensionRef should be used for configuring custom // HTTP filters. // @@ -1536,6 +1563,203 @@ type HTTPCORSFilter struct { MaxAge int32 `json:"maxAge,omitempty"` } +// HTTPRouteExternalAuthProtcol specifies what protocol should be used +// for communicating with an external authorization server. +// +// Valid values are supplied as constants below. +type HTTPRouteExternalAuthProtocol string + +const ( + HTTPRouteExternalAuthGRPCProtocol HTTPRouteExternalAuthProtocol = "GRPC" + HTTPRouteExternalAuthHTTPProtocol HTTPRouteExternalAuthProtocol = "HTTP" +) + +// HTTPExternalAuthFilter defines a filter that modifies requests by sending +// request details to an external authorization server. +// +// Support: Extended +// Feature Name: HTTPRouteExternalAuth +// +kubebuilder:validation:XValidation:message="grpc must be specified when protocol is set to 'GRPC'",rule="self.protocol == 'GRPC' ? has(self.grpc) : true" +// +kubebuilder:validation:XValidation:message="protocol must be 'GRPC' when grpc is set",rule="has(self.grpc) ? self.protocol == 'GRPC' : true" +// +kubebuilder:validation:XValidation:message="http must be specified when protocol is set to 'HTTP'",rule="self.protocol == 'HTTP' ? has(self.http) : true" +// +kubebuilder:validation:XValidation:message="protocol must be 'HTTP' when http is set",rule="has(self.http) ? self.protocol == 'HTTP' : true" +type HTTPExternalAuthFilter struct { + // ExternalAuthProtocol describes which protocol to use when communicating with an + // ext_authz authorization server. + // + // When this is set to GRPC, each backend must use the Envoy ext_authz protocol + // on the port specified in `backendRefs`. Requests and responses are defined + // in the protobufs explained at: + // https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + // + // When this is set to HTTP, each backend must respond with a `200` status + // code in on a successful authorization. Any other code is considered + // an authorization failure. + // + // Feature Names: + // GRPC Support - HTTPRouteExternalAuthGRPC + // HTTP Support - HTTPRouteExternalAuthHTTP + // + // +unionDiscriminator + // +required + // +kubebuilder:validation:Enum=HTTP;GRPC + ExternalAuthProtocol HTTPRouteExternalAuthProtocol `json:"protocol,omitempty"` + + // BackendRef is a reference to a backend to send authorization + // requests to. + // + // The backend must speak the selected protocol (GRPC or HTTP) on the + // referenced port. + // + // If the backend service requires TLS, use BackendTLSPolicy to tell the + // implementation to supply the TLS details to be used to connect to that + // backend. + // + // +required + BackendRef BackendObjectReference `json:"backendRef,omitempty"` + + // GRPCAuthConfig contains configuration for communication with ext_authz + // protocol-speaking backends. + // + // If unset, implementations must assume the default behavior for each + // included field is intended. + // + // +optional + GRPCAuthConfig *GRPCAuthConfig `json:"grpc,omitempty"` + + // HTTPAuthConfig contains configuration for communication with HTTP-speaking + // backends. + // + // If unset, implementations must assume the default behavior for each + // included field is intended. + // + // +optional + HTTPAuthConfig *HTTPAuthConfig `json:"http,omitempty"` + + // ForwardBody controls if requests to the authorization server should include + // the body of the client request; and if so, how big that body is allowed + // to be. + // + // It is expected that implementations will buffer the request body up to + // `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + // 4xx series error (413 or 403 are common examples), and fail processing + // of the filter. + // + // If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + // be forwarded. + // + // Feature Name: HTTPRouteExternalAuthForwardBody + // + // + // +optional + ForwardBody *ForwardBodyConfig `json:"forwardBody,omitempty"` +} + +// GRPCAuthConfig contains configuration for communication with Auth server +// backends that speak Envoy's ext_authz gRPC protocol. +// +// Requests and responses are defined in the protobufs explained at: +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto +type GRPCAuthConfig struct { + // AllowedRequestHeaders specifies what headers from the client request + // will be sent to the authorization server. + // + // If this list is empty, then the following headers must be sent: + // + // - `Authorization` + // - `Location` + // - `Proxy-Authenticate` + // - `Set-Cookie` + // - `WWW-Authenticate` + // + // If the list has entries, only those entries must be sent. + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxLength=64 + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` +} + +// HTTPAuthConfig contains configuration for communication with HTTP-speaking +// backends. +type HTTPAuthConfig struct { + // Path sets the prefix that paths from the client request will have added + // when forwarded to the authorization server. + // + // When empty or unspecified, no prefix is added. + // + // Valid values are the same as the "value" regex for path values in the `match` + // stanza, and the validation regex will screen out invalid paths in the same way. + // Even with the validation, implementations MUST sanitize this input before using it + // directly. + // + // +optional + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:Pattern="^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$" + Path string `json:"path,omitempty"` + + // AllowedRequestHeaders specifies what additional headers from the client request + // will be sent to the authorization server. + // + // The following headers must always be sent to the authorization server, + // regardless of this setting: + // + // * `Host` + // * `Method` + // * `Path` + // * `Content-Length` + // * `Authorization` + // + // If this list is empty, then only those headers must be sent. + // + // Note that `Content-Length` has a special behavior, in that the length + // sent must be correct for the actual request to the external authorization + // server - that is, it must reflect the actual number of bytes sent in the + // body of the request to the authorization server. + // + // So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + // to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + // to anything other than `0`, then the `Content-Length` of the authorization + // request must be set to the actual number of bytes forwarded. + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxLength=64 + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` + + // AllowedResponseHeaders specifies what headers from the authorization response + // will be copied into the request to the backend. + // + // If this list is empty, then all headers from the authorization server + // except Authority or Host must be copied. + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxLength=64 + AllowedResponseHeaders []string `json:"allowedResponseHeaders,omitempty"` +} + +// ForwardBody configures if requests to the authorization server should include +// the body of the client request; and if so, how big that body is allowed +// to be. +// +// If empty or unset, do not forward the body. +type ForwardBodyConfig struct { + // MaxSize specifies how large in bytes the largest body that will be buffered + // and sent to the authorization server. If the body size is larger than + // `maxSize`, then the body sent to the authorization server must be + // truncated to `maxSize` bytes. + // + // Experimental note: This behavior needs to be checked against + // various dataplanes; it may need to be changed. + // See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 + // for more. + // + // If 0, the body will not be sent to the authorization server. + // +optional + MaxSize uint16 `json:"maxSize,omitempty"` +} + // HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. // // Note that when a namespace different than the local namespace is specified, a diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index d7e4a6c2f4..6bbf75ba62 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -170,6 +170,21 @@ func (in *CookieConfig) DeepCopy() *CookieConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ForwardBodyConfig) DeepCopyInto(out *ForwardBodyConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForwardBodyConfig. +func (in *ForwardBodyConfig) DeepCopy() *ForwardBodyConfig { + if in == nil { + return nil + } + out := new(ForwardBodyConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Fraction) DeepCopyInto(out *Fraction) { *out = *in @@ -212,6 +227,26 @@ func (in *FrontendTLSValidation) DeepCopy() *FrontendTLSValidation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCAuthConfig) DeepCopyInto(out *GRPCAuthConfig) { + *out = *in + if in.AllowedRequestHeaders != nil { + in, out := &in.AllowedRequestHeaders, &out.AllowedRequestHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCAuthConfig. +func (in *GRPCAuthConfig) DeepCopy() *GRPCAuthConfig { + if in == nil { + return nil + } + out := new(GRPCAuthConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GRPCBackendRef) DeepCopyInto(out *GRPCBackendRef) { *out = *in @@ -868,6 +903,31 @@ func (in *GatewayTLSConfig) DeepCopy() *GatewayTLSConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPAuthConfig) DeepCopyInto(out *HTTPAuthConfig) { + *out = *in + if in.AllowedRequestHeaders != nil { + in, out := &in.AllowedRequestHeaders, &out.AllowedRequestHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AllowedResponseHeaders != nil { + in, out := &in.AllowedResponseHeaders, &out.AllowedResponseHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPAuthConfig. +func (in *HTTPAuthConfig) DeepCopy() *HTTPAuthConfig { + if in == nil { + return nil + } + out := new(HTTPAuthConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPBackendRef) DeepCopyInto(out *HTTPBackendRef) { *out = *in @@ -931,6 +991,37 @@ func (in *HTTPCORSFilter) DeepCopy() *HTTPCORSFilter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPExternalAuthFilter) DeepCopyInto(out *HTTPExternalAuthFilter) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) + if in.GRPCAuthConfig != nil { + in, out := &in.GRPCAuthConfig, &out.GRPCAuthConfig + *out = new(GRPCAuthConfig) + (*in).DeepCopyInto(*out) + } + if in.HTTPAuthConfig != nil { + in, out := &in.HTTPAuthConfig, &out.HTTPAuthConfig + *out = new(HTTPAuthConfig) + (*in).DeepCopyInto(*out) + } + if in.ForwardBody != nil { + in, out := &in.ForwardBody, &out.ForwardBody + *out = new(ForwardBodyConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPExternalAuthFilter. +func (in *HTTPExternalAuthFilter) DeepCopy() *HTTPExternalAuthFilter { + if in == nil { + return nil + } + out := new(HTTPExternalAuthFilter) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPHeader) DeepCopyInto(out *HTTPHeader) { *out = *in @@ -1192,6 +1283,11 @@ func (in *HTTPRouteFilter) DeepCopyInto(out *HTTPRouteFilter) { *out = new(HTTPCORSFilter) (*in).DeepCopyInto(*out) } + if in.ExternalAuth != nil { + in, out := &in.ExternalAuth, &out.ExternalAuth + *out = new(HTTPExternalAuthFilter) + (*in).DeepCopyInto(*out) + } if in.ExtensionRef != nil { in, out := &in.ExtensionRef, &out.ExtensionRef *out = new(LocalObjectReference) diff --git a/applyconfiguration/apis/v1/forwardbodyconfig.go b/applyconfiguration/apis/v1/forwardbodyconfig.go new file mode 100644 index 0000000000..79707409bc --- /dev/null +++ b/applyconfiguration/apis/v1/forwardbodyconfig.go @@ -0,0 +1,39 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// ForwardBodyConfigApplyConfiguration represents a declarative configuration of the ForwardBodyConfig type for use +// with apply. +type ForwardBodyConfigApplyConfiguration struct { + MaxSize *uint16 `json:"maxSize,omitempty"` +} + +// ForwardBodyConfigApplyConfiguration constructs a declarative configuration of the ForwardBodyConfig type for use with +// apply. +func ForwardBodyConfig() *ForwardBodyConfigApplyConfiguration { + return &ForwardBodyConfigApplyConfiguration{} +} + +// WithMaxSize sets the MaxSize field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the MaxSize field is set to the value of the last call. +func (b *ForwardBodyConfigApplyConfiguration) WithMaxSize(value uint16) *ForwardBodyConfigApplyConfiguration { + b.MaxSize = &value + return b +} diff --git a/applyconfiguration/apis/v1/grpcauthconfig.go b/applyconfiguration/apis/v1/grpcauthconfig.go new file mode 100644 index 0000000000..1a5c7d33c3 --- /dev/null +++ b/applyconfiguration/apis/v1/grpcauthconfig.go @@ -0,0 +1,41 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// GRPCAuthConfigApplyConfiguration represents a declarative configuration of the GRPCAuthConfig type for use +// with apply. +type GRPCAuthConfigApplyConfiguration struct { + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` +} + +// GRPCAuthConfigApplyConfiguration constructs a declarative configuration of the GRPCAuthConfig type for use with +// apply. +func GRPCAuthConfig() *GRPCAuthConfigApplyConfiguration { + return &GRPCAuthConfigApplyConfiguration{} +} + +// WithAllowedRequestHeaders adds the given value to the AllowedRequestHeaders field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the AllowedRequestHeaders field. +func (b *GRPCAuthConfigApplyConfiguration) WithAllowedRequestHeaders(values ...string) *GRPCAuthConfigApplyConfiguration { + for i := range values { + b.AllowedRequestHeaders = append(b.AllowedRequestHeaders, values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/httpauthconfig.go b/applyconfiguration/apis/v1/httpauthconfig.go new file mode 100644 index 0000000000..eff6ff903a --- /dev/null +++ b/applyconfiguration/apis/v1/httpauthconfig.go @@ -0,0 +1,61 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// HTTPAuthConfigApplyConfiguration represents a declarative configuration of the HTTPAuthConfig type for use +// with apply. +type HTTPAuthConfigApplyConfiguration struct { + Path *string `json:"path,omitempty"` + AllowedRequestHeaders []string `json:"allowedHeaders,omitempty"` + AllowedResponseHeaders []string `json:"allowedResponseHeaders,omitempty"` +} + +// HTTPAuthConfigApplyConfiguration constructs a declarative configuration of the HTTPAuthConfig type for use with +// apply. +func HTTPAuthConfig() *HTTPAuthConfigApplyConfiguration { + return &HTTPAuthConfigApplyConfiguration{} +} + +// WithPath sets the Path field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Path field is set to the value of the last call. +func (b *HTTPAuthConfigApplyConfiguration) WithPath(value string) *HTTPAuthConfigApplyConfiguration { + b.Path = &value + return b +} + +// WithAllowedRequestHeaders adds the given value to the AllowedRequestHeaders field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the AllowedRequestHeaders field. +func (b *HTTPAuthConfigApplyConfiguration) WithAllowedRequestHeaders(values ...string) *HTTPAuthConfigApplyConfiguration { + for i := range values { + b.AllowedRequestHeaders = append(b.AllowedRequestHeaders, values[i]) + } + return b +} + +// WithAllowedResponseHeaders adds the given value to the AllowedResponseHeaders field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the AllowedResponseHeaders field. +func (b *HTTPAuthConfigApplyConfiguration) WithAllowedResponseHeaders(values ...string) *HTTPAuthConfigApplyConfiguration { + for i := range values { + b.AllowedResponseHeaders = append(b.AllowedResponseHeaders, values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/httpexternalauthfilter.go b/applyconfiguration/apis/v1/httpexternalauthfilter.go new file mode 100644 index 0000000000..e56b112f2a --- /dev/null +++ b/applyconfiguration/apis/v1/httpexternalauthfilter.go @@ -0,0 +1,79 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +import ( + apisv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// HTTPExternalAuthFilterApplyConfiguration represents a declarative configuration of the HTTPExternalAuthFilter type for use +// with apply. +type HTTPExternalAuthFilterApplyConfiguration struct { + ExternalAuthProtocol *apisv1.HTTPRouteExternalAuthProtocol `json:"protocol,omitempty"` + BackendRef *BackendObjectReferenceApplyConfiguration `json:"backendRef,omitempty"` + GRPCAuthConfig *GRPCAuthConfigApplyConfiguration `json:"grpc,omitempty"` + HTTPAuthConfig *HTTPAuthConfigApplyConfiguration `json:"http,omitempty"` + ForwardBody *ForwardBodyConfigApplyConfiguration `json:"forwardBody,omitempty"` +} + +// HTTPExternalAuthFilterApplyConfiguration constructs a declarative configuration of the HTTPExternalAuthFilter type for use with +// apply. +func HTTPExternalAuthFilter() *HTTPExternalAuthFilterApplyConfiguration { + return &HTTPExternalAuthFilterApplyConfiguration{} +} + +// WithExternalAuthProtocol sets the ExternalAuthProtocol field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExternalAuthProtocol field is set to the value of the last call. +func (b *HTTPExternalAuthFilterApplyConfiguration) WithExternalAuthProtocol(value apisv1.HTTPRouteExternalAuthProtocol) *HTTPExternalAuthFilterApplyConfiguration { + b.ExternalAuthProtocol = &value + return b +} + +// WithBackendRef sets the BackendRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the BackendRef field is set to the value of the last call. +func (b *HTTPExternalAuthFilterApplyConfiguration) WithBackendRef(value *BackendObjectReferenceApplyConfiguration) *HTTPExternalAuthFilterApplyConfiguration { + b.BackendRef = value + return b +} + +// WithGRPCAuthConfig sets the GRPCAuthConfig field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GRPCAuthConfig field is set to the value of the last call. +func (b *HTTPExternalAuthFilterApplyConfiguration) WithGRPCAuthConfig(value *GRPCAuthConfigApplyConfiguration) *HTTPExternalAuthFilterApplyConfiguration { + b.GRPCAuthConfig = value + return b +} + +// WithHTTPAuthConfig sets the HTTPAuthConfig field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the HTTPAuthConfig field is set to the value of the last call. +func (b *HTTPExternalAuthFilterApplyConfiguration) WithHTTPAuthConfig(value *HTTPAuthConfigApplyConfiguration) *HTTPExternalAuthFilterApplyConfiguration { + b.HTTPAuthConfig = value + return b +} + +// WithForwardBody sets the ForwardBody field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ForwardBody field is set to the value of the last call. +func (b *HTTPExternalAuthFilterApplyConfiguration) WithForwardBody(value *ForwardBodyConfigApplyConfiguration) *HTTPExternalAuthFilterApplyConfiguration { + b.ForwardBody = value + return b +} diff --git a/applyconfiguration/apis/v1/httproutefilter.go b/applyconfiguration/apis/v1/httproutefilter.go index 2a46046bc6..d76c141316 100644 --- a/applyconfiguration/apis/v1/httproutefilter.go +++ b/applyconfiguration/apis/v1/httproutefilter.go @@ -32,6 +32,7 @@ type HTTPRouteFilterApplyConfiguration struct { RequestRedirect *HTTPRequestRedirectFilterApplyConfiguration `json:"requestRedirect,omitempty"` URLRewrite *HTTPURLRewriteFilterApplyConfiguration `json:"urlRewrite,omitempty"` CORS *HTTPCORSFilterApplyConfiguration `json:"cors,omitempty"` + ExternalAuth *HTTPExternalAuthFilterApplyConfiguration `json:"externalAuth,omitempty"` ExtensionRef *LocalObjectReferenceApplyConfiguration `json:"extensionRef,omitempty"` } @@ -97,6 +98,14 @@ func (b *HTTPRouteFilterApplyConfiguration) WithCORS(value *HTTPCORSFilterApplyC return b } +// WithExternalAuth sets the ExternalAuth field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExternalAuth field is set to the value of the last call. +func (b *HTTPRouteFilterApplyConfiguration) WithExternalAuth(value *HTTPExternalAuthFilterApplyConfiguration) *HTTPRouteFilterApplyConfiguration { + b.ExternalAuth = value + return b +} + // WithExtensionRef sets the ExtensionRef field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the ExtensionRef field is set to the value of the last call. diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index f71080402f..953f2863cd 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -288,6 +288,12 @@ var schemaYAML = typed.YAMLObject(`types: - name: lifetimeType type: scalar: string +- name: io.k8s.sigs.gateway-api.apis.v1.ForwardBodyConfig + map: + fields: + - name: maxSize + type: + scalar: numeric - name: io.k8s.sigs.gateway-api.apis.v1.Fraction map: fields: @@ -310,6 +316,15 @@ var schemaYAML = typed.YAMLObject(`types: - name: mode type: scalar: string +- name: io.k8s.sigs.gateway-api.apis.v1.GRPCAuthConfig + map: + fields: + - name: allowedHeaders + type: + list: + elementType: + scalar: string + elementRelationship: associative - name: io.k8s.sigs.gateway-api.apis.v1.GRPCBackendRef map: fields: @@ -663,6 +678,24 @@ var schemaYAML = typed.YAMLObject(`types: elementRelationship: associative keys: - port +- name: io.k8s.sigs.gateway-api.apis.v1.HTTPAuthConfig + map: + fields: + - name: allowedHeaders + type: + list: + elementType: + scalar: string + elementRelationship: associative + - name: allowedResponseHeaders + type: + list: + elementType: + scalar: string + elementRelationship: associative + - name: path + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.HTTPBackendRef map: fields: @@ -724,6 +757,25 @@ var schemaYAML = typed.YAMLObject(`types: - name: maxAge type: scalar: numeric +- name: io.k8s.sigs.gateway-api.apis.v1.HTTPExternalAuthFilter + map: + fields: + - name: backendRef + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.BackendObjectReference + default: {} + - name: forwardBody + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.ForwardBodyConfig + - name: grpc + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.GRPCAuthConfig + - name: http + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.HTTPAuthConfig + - name: protocol + type: + scalar: string - name: io.k8s.sigs.gateway-api.apis.v1.HTTPHeader map: fields: @@ -871,6 +923,9 @@ var schemaYAML = typed.YAMLObject(`types: - name: extensionRef type: namedType: io.k8s.sigs.gateway-api.apis.v1.LocalObjectReference + - name: externalAuth + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.HTTPExternalAuthFilter - name: requestHeaderModifier type: namedType: io.k8s.sigs.gateway-api.apis.v1.HTTPHeaderFilter diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 71851d893d..5acafbc2c1 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -52,6 +52,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.CommonRouteSpecApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("CookieConfig"): return &apisv1.CookieConfigApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ForwardBodyConfig"): + return &apisv1.ForwardBodyConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("Fraction"): return &apisv1.FractionApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("FrontendTLSValidation"): @@ -78,6 +80,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.GatewayStatusAddressApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("GatewayTLSConfig"): return &apisv1.GatewayTLSConfigApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("GRPCAuthConfig"): + return &apisv1.GRPCAuthConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("GRPCBackendRef"): return &apisv1.GRPCBackendRefApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("GRPCHeaderMatch"): @@ -96,10 +100,14 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.GRPCRouteSpecApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("GRPCRouteStatus"): return &apisv1.GRPCRouteStatusApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("HTTPAuthConfig"): + return &apisv1.HTTPAuthConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("HTTPBackendRef"): return &apisv1.HTTPBackendRefApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("HTTPCORSFilter"): return &apisv1.HTTPCORSFilterApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("HTTPExternalAuthFilter"): + return &apisv1.HTTPExternalAuthFilterApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("HTTPHeader"): return &apisv1.HTTPHeaderApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("HTTPHeaderFilter"): diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 65515a4e22..34876b54a0 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -773,6 +773,259 @@ spec: - kind - name type: object + externalAuth: + description: |- + ExternalAuth configures settings related to sending request details + to an external auth service. The external service MUST authenticate + the request, and MAY authorize the request as well. + + If there is any problem communicating with the external service, + this filter MUST fail closed. + + Support: Extended + properties: + backendRef: + description: |- + BackendRef is a reference to a backend to send authorization + requests to. + + The backend must speak the selected protocol (GRPC or HTTP) on the + referenced port. + + If the backend service requires TLS, use BackendTLSPolicy to tell the + implementation to supply the TLS details to be used to connect to that + backend. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + forwardBody: + description: |- + ForwardBody controls if requests to the authorization server should include + the body of the client request; and if so, how big that body is allowed + to be. + + It is expected that implementations will buffer the request body up to + `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + 4xx series error (413 or 403 are common examples), and fail processing + of the filter. + + If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + be forwarded. + + Feature Name: HTTPRouteExternalAuthForwardBody + properties: + maxSize: + description: |- + MaxSize specifies how large in bytes the largest body that will be buffered + and sent to the authorization server. If the body size is larger than + `maxSize`, then the body sent to the authorization server must be + truncated to `maxSize` bytes. + + Experimental note: This behavior needs to be checked against + various dataplanes; it may need to be changed. + See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 + for more. + + If 0, the body will not be sent to the authorization server. + type: integer + type: object + grpc: + description: |- + GRPCAuthConfig contains configuration for communication with ext_authz + protocol-speaking backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what headers from the client request + will be sent to the authorization server. + + If this list is empty, then the following headers must be sent: + + - `Authorization` + - `Location` + - `Proxy-Authenticate` + - `Set-Cookie` + - `WWW-Authenticate` + + If the list has entries, only those entries must be sent. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + http: + description: |- + HTTPAuthConfig contains configuration for communication with HTTP-speaking + backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what additional headers from the client request + will be sent to the authorization server. + + The following headers must always be sent to the authorization server, + regardless of this setting: + + * `Host` + * `Method` + * `Path` + * `Content-Length` + * `Authorization` + + If this list is empty, then only those headers must be sent. + + Note that `Content-Length` has a special behavior, in that the length + sent must be correct for the actual request to the external authorization + server - that is, it must reflect the actual number of bytes sent in the + body of the request to the authorization server. + + So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + to anything other than `0`, then the `Content-Length` of the authorization + request must be set to the actual number of bytes forwarded. + items: + type: string + type: array + x-kubernetes-list-type: set + allowedResponseHeaders: + description: |- + AllowedResponseHeaders specifies what headers from the authorization response + will be copied into the request to the backend. + + If this list is empty, then all headers from the authorization server + except Authority or Host must be copied. + items: + type: string + type: array + x-kubernetes-list-type: set + path: + description: |- + Path sets the prefix that paths from the client request will have added + when forwarded to the authorization server. + + When empty or unspecified, no prefix is added. + + Valid values are the same as the "value" regex for path values in the `match` + stanza, and the validation regex will screen out invalid paths in the same way. + Even with the validation, implementations MUST sanitize this input before using it + directly. + maxLength: 1024 + pattern: ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$ + type: string + type: object + protocol: + description: |- + ExternalAuthProtocol describes which protocol to use when communicating with an + ext_authz authorization server. + + When this is set to GRPC, each backend must use the Envoy ext_authz protocol + on the port specified in `backendRefs`. Requests and responses are defined + in the protobufs explained at: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + + When this is set to HTTP, each backend must respond with a `200` status + code in on a successful authorization. Any other code is considered + an authorization failure. + + Feature Names: + GRPC Support - HTTPRouteExternalAuthGRPC + HTTP Support - HTTPRouteExternalAuthHTTP + enum: + - HTTP + - GRPC + type: string + required: + - backendRef + - protocol + type: object + x-kubernetes-validations: + - message: grpc must be specified when protocol + is set to 'GRPC' + rule: 'self.protocol == ''GRPC'' ? has(self.grpc) + : true' + - message: protocol must be 'GRPC' when grpc is + set + rule: 'has(self.grpc) ? self.protocol == ''GRPC'' + : true' + - message: http must be specified when protocol + is set to 'HTTP' + rule: 'self.protocol == ''HTTP'' ? has(self.http) + : true' + - message: protocol must be 'HTTP' when http is + set + rule: 'has(self.http) ? self.protocol == ''HTTP'' + : true' requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request @@ -1386,6 +1639,7 @@ spec: - URLRewrite - ExtensionRef - CORS + - ExternalAuth type: string urlRewrite: description: |- @@ -1523,6 +1777,12 @@ spec: rule: '!(has(self.cors) && self.type != ''CORS'')' - message: filter.cors must be specified for CORS filter.type rule: '!(!has(self.cors) && self.type == ''CORS'')' + - message: filter.externalAuth must be nil if the filter.type + is not ExternalAuth + rule: '!(has(self.externalAuth) && self.type != ''ExternalAuth'')' + - message: filter.externalAuth must be specified for + ExternalAuth filter.type + rule: '!(!has(self.externalAuth) && self.type == ''ExternalAuth'')' maxItems: 16 type: array x-kubernetes-list-type: atomic @@ -1995,6 +2255,257 @@ spec: - kind - name type: object + externalAuth: + description: |- + ExternalAuth configures settings related to sending request details + to an external auth service. The external service MUST authenticate + the request, and MAY authorize the request as well. + + If there is any problem communicating with the external service, + this filter MUST fail closed. + + Support: Extended + properties: + backendRef: + description: |- + BackendRef is a reference to a backend to send authorization + requests to. + + The backend must speak the selected protocol (GRPC or HTTP) on the + referenced port. + + If the backend service requires TLS, use BackendTLSPolicy to tell the + implementation to supply the TLS details to be used to connect to that + backend. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + forwardBody: + description: |- + ForwardBody controls if requests to the authorization server should include + the body of the client request; and if so, how big that body is allowed + to be. + + It is expected that implementations will buffer the request body up to + `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + 4xx series error (413 or 403 are common examples), and fail processing + of the filter. + + If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + be forwarded. + + Feature Name: HTTPRouteExternalAuthForwardBody + properties: + maxSize: + description: |- + MaxSize specifies how large in bytes the largest body that will be buffered + and sent to the authorization server. If the body size is larger than + `maxSize`, then the body sent to the authorization server must be + truncated to `maxSize` bytes. + + Experimental note: This behavior needs to be checked against + various dataplanes; it may need to be changed. + See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 + for more. + + If 0, the body will not be sent to the authorization server. + type: integer + type: object + grpc: + description: |- + GRPCAuthConfig contains configuration for communication with ext_authz + protocol-speaking backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what headers from the client request + will be sent to the authorization server. + + If this list is empty, then the following headers must be sent: + + - `Authorization` + - `Location` + - `Proxy-Authenticate` + - `Set-Cookie` + - `WWW-Authenticate` + + If the list has entries, only those entries must be sent. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + http: + description: |- + HTTPAuthConfig contains configuration for communication with HTTP-speaking + backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what additional headers from the client request + will be sent to the authorization server. + + The following headers must always be sent to the authorization server, + regardless of this setting: + + * `Host` + * `Method` + * `Path` + * `Content-Length` + * `Authorization` + + If this list is empty, then only those headers must be sent. + + Note that `Content-Length` has a special behavior, in that the length + sent must be correct for the actual request to the external authorization + server - that is, it must reflect the actual number of bytes sent in the + body of the request to the authorization server. + + So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + to anything other than `0`, then the `Content-Length` of the authorization + request must be set to the actual number of bytes forwarded. + items: + type: string + type: array + x-kubernetes-list-type: set + allowedResponseHeaders: + description: |- + AllowedResponseHeaders specifies what headers from the authorization response + will be copied into the request to the backend. + + If this list is empty, then all headers from the authorization server + except Authority or Host must be copied. + items: + type: string + type: array + x-kubernetes-list-type: set + path: + description: |- + Path sets the prefix that paths from the client request will have added + when forwarded to the authorization server. + + When empty or unspecified, no prefix is added. + + Valid values are the same as the "value" regex for path values in the `match` + stanza, and the validation regex will screen out invalid paths in the same way. + Even with the validation, implementations MUST sanitize this input before using it + directly. + maxLength: 1024 + pattern: ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$ + type: string + type: object + protocol: + description: |- + ExternalAuthProtocol describes which protocol to use when communicating with an + ext_authz authorization server. + + When this is set to GRPC, each backend must use the Envoy ext_authz protocol + on the port specified in `backendRefs`. Requests and responses are defined + in the protobufs explained at: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + + When this is set to HTTP, each backend must respond with a `200` status + code in on a successful authorization. Any other code is considered + an authorization failure. + + Feature Names: + GRPC Support - HTTPRouteExternalAuthGRPC + HTTP Support - HTTPRouteExternalAuthHTTP + enum: + - HTTP + - GRPC + type: string + required: + - backendRef + - protocol + type: object + x-kubernetes-validations: + - message: grpc must be specified when protocol is set + to 'GRPC' + rule: 'self.protocol == ''GRPC'' ? has(self.grpc) : + true' + - message: protocol must be 'GRPC' when grpc is set + rule: 'has(self.grpc) ? self.protocol == ''GRPC'' : + true' + - message: http must be specified when protocol is set + to 'HTTP' + rule: 'self.protocol == ''HTTP'' ? has(self.http) : + true' + - message: protocol must be 'HTTP' when http is set + rule: 'has(self.http) ? self.protocol == ''HTTP'' : + true' requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request @@ -2604,6 +3115,7 @@ spec: - URLRewrite - ExtensionRef - CORS + - ExternalAuth type: string urlRewrite: description: |- @@ -2738,6 +3250,12 @@ spec: rule: '!(has(self.cors) && self.type != ''CORS'')' - message: filter.cors must be specified for CORS filter.type rule: '!(!has(self.cors) && self.type == ''CORS'')' + - message: filter.externalAuth must be nil if the filter.type + is not ExternalAuth + rule: '!(has(self.externalAuth) && self.type != ''ExternalAuth'')' + - message: filter.externalAuth must be specified for ExternalAuth + filter.type + rule: '!(!has(self.externalAuth) && self.type == ''ExternalAuth'')' maxItems: 16 type: array x-kubernetes-list-type: atomic @@ -4399,6 +4917,259 @@ spec: - kind - name type: object + externalAuth: + description: |- + ExternalAuth configures settings related to sending request details + to an external auth service. The external service MUST authenticate + the request, and MAY authorize the request as well. + + If there is any problem communicating with the external service, + this filter MUST fail closed. + + Support: Extended + properties: + backendRef: + description: |- + BackendRef is a reference to a backend to send authorization + requests to. + + The backend must speak the selected protocol (GRPC or HTTP) on the + referenced port. + + If the backend service requires TLS, use BackendTLSPolicy to tell the + implementation to supply the TLS details to be used to connect to that + backend. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + forwardBody: + description: |- + ForwardBody controls if requests to the authorization server should include + the body of the client request; and if so, how big that body is allowed + to be. + + It is expected that implementations will buffer the request body up to + `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + 4xx series error (413 or 403 are common examples), and fail processing + of the filter. + + If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + be forwarded. + + Feature Name: HTTPRouteExternalAuthForwardBody + properties: + maxSize: + description: |- + MaxSize specifies how large in bytes the largest body that will be buffered + and sent to the authorization server. If the body size is larger than + `maxSize`, then the body sent to the authorization server must be + truncated to `maxSize` bytes. + + Experimental note: This behavior needs to be checked against + various dataplanes; it may need to be changed. + See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 + for more. + + If 0, the body will not be sent to the authorization server. + type: integer + type: object + grpc: + description: |- + GRPCAuthConfig contains configuration for communication with ext_authz + protocol-speaking backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what headers from the client request + will be sent to the authorization server. + + If this list is empty, then the following headers must be sent: + + - `Authorization` + - `Location` + - `Proxy-Authenticate` + - `Set-Cookie` + - `WWW-Authenticate` + + If the list has entries, only those entries must be sent. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + http: + description: |- + HTTPAuthConfig contains configuration for communication with HTTP-speaking + backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what additional headers from the client request + will be sent to the authorization server. + + The following headers must always be sent to the authorization server, + regardless of this setting: + + * `Host` + * `Method` + * `Path` + * `Content-Length` + * `Authorization` + + If this list is empty, then only those headers must be sent. + + Note that `Content-Length` has a special behavior, in that the length + sent must be correct for the actual request to the external authorization + server - that is, it must reflect the actual number of bytes sent in the + body of the request to the authorization server. + + So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + to anything other than `0`, then the `Content-Length` of the authorization + request must be set to the actual number of bytes forwarded. + items: + type: string + type: array + x-kubernetes-list-type: set + allowedResponseHeaders: + description: |- + AllowedResponseHeaders specifies what headers from the authorization response + will be copied into the request to the backend. + + If this list is empty, then all headers from the authorization server + except Authority or Host must be copied. + items: + type: string + type: array + x-kubernetes-list-type: set + path: + description: |- + Path sets the prefix that paths from the client request will have added + when forwarded to the authorization server. + + When empty or unspecified, no prefix is added. + + Valid values are the same as the "value" regex for path values in the `match` + stanza, and the validation regex will screen out invalid paths in the same way. + Even with the validation, implementations MUST sanitize this input before using it + directly. + maxLength: 1024 + pattern: ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$ + type: string + type: object + protocol: + description: |- + ExternalAuthProtocol describes which protocol to use when communicating with an + ext_authz authorization server. + + When this is set to GRPC, each backend must use the Envoy ext_authz protocol + on the port specified in `backendRefs`. Requests and responses are defined + in the protobufs explained at: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + + When this is set to HTTP, each backend must respond with a `200` status + code in on a successful authorization. Any other code is considered + an authorization failure. + + Feature Names: + GRPC Support - HTTPRouteExternalAuthGRPC + HTTP Support - HTTPRouteExternalAuthHTTP + enum: + - HTTP + - GRPC + type: string + required: + - backendRef + - protocol + type: object + x-kubernetes-validations: + - message: grpc must be specified when protocol + is set to 'GRPC' + rule: 'self.protocol == ''GRPC'' ? has(self.grpc) + : true' + - message: protocol must be 'GRPC' when grpc is + set + rule: 'has(self.grpc) ? self.protocol == ''GRPC'' + : true' + - message: http must be specified when protocol + is set to 'HTTP' + rule: 'self.protocol == ''HTTP'' ? has(self.http) + : true' + - message: protocol must be 'HTTP' when http is + set + rule: 'has(self.http) ? self.protocol == ''HTTP'' + : true' requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request @@ -5012,6 +5783,7 @@ spec: - URLRewrite - ExtensionRef - CORS + - ExternalAuth type: string urlRewrite: description: |- @@ -5149,6 +5921,12 @@ spec: rule: '!(has(self.cors) && self.type != ''CORS'')' - message: filter.cors must be specified for CORS filter.type rule: '!(!has(self.cors) && self.type == ''CORS'')' + - message: filter.externalAuth must be nil if the filter.type + is not ExternalAuth + rule: '!(has(self.externalAuth) && self.type != ''ExternalAuth'')' + - message: filter.externalAuth must be specified for + ExternalAuth filter.type + rule: '!(!has(self.externalAuth) && self.type == ''ExternalAuth'')' maxItems: 16 type: array x-kubernetes-list-type: atomic @@ -5621,6 +6399,257 @@ spec: - kind - name type: object + externalAuth: + description: |- + ExternalAuth configures settings related to sending request details + to an external auth service. The external service MUST authenticate + the request, and MAY authorize the request as well. + + If there is any problem communicating with the external service, + this filter MUST fail closed. + + Support: Extended + properties: + backendRef: + description: |- + BackendRef is a reference to a backend to send authorization + requests to. + + The backend must speak the selected protocol (GRPC or HTTP) on the + referenced port. + + If the backend service requires TLS, use BackendTLSPolicy to tell the + implementation to supply the TLS details to be used to connect to that + backend. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + Support: Core (Services with a type other than ExternalName) + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + forwardBody: + description: |- + ForwardBody controls if requests to the authorization server should include + the body of the client request; and if so, how big that body is allowed + to be. + + It is expected that implementations will buffer the request body up to + `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a + 4xx series error (413 or 403 are common examples), and fail processing + of the filter. + + If unset, or `forwardBody.maxSize` is set to `0`, then the body will not + be forwarded. + + Feature Name: HTTPRouteExternalAuthForwardBody + properties: + maxSize: + description: |- + MaxSize specifies how large in bytes the largest body that will be buffered + and sent to the authorization server. If the body size is larger than + `maxSize`, then the body sent to the authorization server must be + truncated to `maxSize` bytes. + + Experimental note: This behavior needs to be checked against + various dataplanes; it may need to be changed. + See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 + for more. + + If 0, the body will not be sent to the authorization server. + type: integer + type: object + grpc: + description: |- + GRPCAuthConfig contains configuration for communication with ext_authz + protocol-speaking backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what headers from the client request + will be sent to the authorization server. + + If this list is empty, then the following headers must be sent: + + - `Authorization` + - `Location` + - `Proxy-Authenticate` + - `Set-Cookie` + - `WWW-Authenticate` + + If the list has entries, only those entries must be sent. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object + http: + description: |- + HTTPAuthConfig contains configuration for communication with HTTP-speaking + backends. + + If unset, implementations must assume the default behavior for each + included field is intended. + properties: + allowedHeaders: + description: |- + AllowedRequestHeaders specifies what additional headers from the client request + will be sent to the authorization server. + + The following headers must always be sent to the authorization server, + regardless of this setting: + + * `Host` + * `Method` + * `Path` + * `Content-Length` + * `Authorization` + + If this list is empty, then only those headers must be sent. + + Note that `Content-Length` has a special behavior, in that the length + sent must be correct for the actual request to the external authorization + server - that is, it must reflect the actual number of bytes sent in the + body of the request to the authorization server. + + So if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set + to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set + to anything other than `0`, then the `Content-Length` of the authorization + request must be set to the actual number of bytes forwarded. + items: + type: string + type: array + x-kubernetes-list-type: set + allowedResponseHeaders: + description: |- + AllowedResponseHeaders specifies what headers from the authorization response + will be copied into the request to the backend. + + If this list is empty, then all headers from the authorization server + except Authority or Host must be copied. + items: + type: string + type: array + x-kubernetes-list-type: set + path: + description: |- + Path sets the prefix that paths from the client request will have added + when forwarded to the authorization server. + + When empty or unspecified, no prefix is added. + + Valid values are the same as the "value" regex for path values in the `match` + stanza, and the validation regex will screen out invalid paths in the same way. + Even with the validation, implementations MUST sanitize this input before using it + directly. + maxLength: 1024 + pattern: ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$ + type: string + type: object + protocol: + description: |- + ExternalAuthProtocol describes which protocol to use when communicating with an + ext_authz authorization server. + + When this is set to GRPC, each backend must use the Envoy ext_authz protocol + on the port specified in `backendRefs`. Requests and responses are defined + in the protobufs explained at: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + + When this is set to HTTP, each backend must respond with a `200` status + code in on a successful authorization. Any other code is considered + an authorization failure. + + Feature Names: + GRPC Support - HTTPRouteExternalAuthGRPC + HTTP Support - HTTPRouteExternalAuthHTTP + enum: + - HTTP + - GRPC + type: string + required: + - backendRef + - protocol + type: object + x-kubernetes-validations: + - message: grpc must be specified when protocol is set + to 'GRPC' + rule: 'self.protocol == ''GRPC'' ? has(self.grpc) : + true' + - message: protocol must be 'GRPC' when grpc is set + rule: 'has(self.grpc) ? self.protocol == ''GRPC'' : + true' + - message: http must be specified when protocol is set + to 'HTTP' + rule: 'self.protocol == ''HTTP'' ? has(self.http) : + true' + - message: protocol must be 'HTTP' when http is set + rule: 'has(self.http) ? self.protocol == ''HTTP'' : + true' requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request @@ -6230,6 +7259,7 @@ spec: - URLRewrite - ExtensionRef - CORS + - ExternalAuth type: string urlRewrite: description: |- @@ -6364,6 +7394,12 @@ spec: rule: '!(has(self.cors) && self.type != ''CORS'')' - message: filter.cors must be specified for CORS filter.type rule: '!(!has(self.cors) && self.type == ''CORS'')' + - message: filter.externalAuth must be nil if the filter.type + is not ExternalAuth + rule: '!(has(self.externalAuth) && self.type != ''ExternalAuth'')' + - message: filter.externalAuth must be specified for ExternalAuth + filter.type + rule: '!(!has(self.externalAuth) && self.type == ''ExternalAuth'')' maxItems: 16 type: array x-kubernetes-list-type: atomic diff --git a/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-bad-http-path.yaml b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-bad-http-path.yaml new file mode 100644 index 0000000000..93ad3c98c9 --- /dev/null +++ b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-bad-http-path.yaml @@ -0,0 +1,12 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: invalid-filter-externalauth-empty +spec: + rules: + - filters: + - type: ExternalAuth + externalAuth: + protocol: HTTP + http: + path: /[] diff --git a/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-empty.yaml b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-empty.yaml new file mode 100644 index 0000000000..cba0c2b2bc --- /dev/null +++ b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-empty.yaml @@ -0,0 +1,8 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: invalid-filter-externalauth-empty +spec: + rules: + - filters: + - type: ExternalAuth diff --git a/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-no-protocol.yaml b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-no-protocol.yaml new file mode 100644 index 0000000000..96cc047e95 --- /dev/null +++ b/hack/invalid-examples/experimental/httproute/invalid-filter-externalauth-no-protocol.yaml @@ -0,0 +1,9 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: invalid-filter-externalauth-empty +spec: + rules: + - filters: + - type: ExternalAuth + externalAuth: {} diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index e674ba5140..588319b36e 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -88,8 +88,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.BackendRef": schema_sigsk8sio_gateway_api_apis_v1_BackendRef(ref), "sigs.k8s.io/gateway-api/apis/v1.CommonRouteSpec": schema_sigsk8sio_gateway_api_apis_v1_CommonRouteSpec(ref), "sigs.k8s.io/gateway-api/apis/v1.CookieConfig": schema_sigsk8sio_gateway_api_apis_v1_CookieConfig(ref), + "sigs.k8s.io/gateway-api/apis/v1.ForwardBodyConfig": schema_sigsk8sio_gateway_api_apis_v1_ForwardBodyConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.Fraction": schema_sigsk8sio_gateway_api_apis_v1_Fraction(ref), "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation": schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref), + "sigs.k8s.io/gateway-api/apis/v1.GRPCAuthConfig": schema_sigsk8sio_gateway_api_apis_v1_GRPCAuthConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.GRPCBackendRef": schema_sigsk8sio_gateway_api_apis_v1_GRPCBackendRef(ref), "sigs.k8s.io/gateway-api/apis/v1.GRPCHeaderMatch": schema_sigsk8sio_gateway_api_apis_v1_GRPCHeaderMatch(ref), "sigs.k8s.io/gateway-api/apis/v1.GRPCMethodMatch": schema_sigsk8sio_gateway_api_apis_v1_GRPCMethodMatch(ref), @@ -113,8 +115,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.GatewayStatus": schema_sigsk8sio_gateway_api_apis_v1_GatewayStatus(ref), "sigs.k8s.io/gateway-api/apis/v1.GatewayStatusAddress": schema_sigsk8sio_gateway_api_apis_v1_GatewayStatusAddress(ref), "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig": schema_sigsk8sio_gateway_api_apis_v1_GatewayTLSConfig(ref), + "sigs.k8s.io/gateway-api/apis/v1.HTTPAuthConfig": schema_sigsk8sio_gateway_api_apis_v1_HTTPAuthConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.HTTPBackendRef": schema_sigsk8sio_gateway_api_apis_v1_HTTPBackendRef(ref), "sigs.k8s.io/gateway-api/apis/v1.HTTPCORSFilter": schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref), + "sigs.k8s.io/gateway-api/apis/v1.HTTPExternalAuthFilter": schema_sigsk8sio_gateway_api_apis_v1_HTTPExternalAuthFilter(ref), "sigs.k8s.io/gateway-api/apis/v1.HTTPHeader": schema_sigsk8sio_gateway_api_apis_v1_HTTPHeader(ref), "sigs.k8s.io/gateway-api/apis/v1.HTTPHeaderFilter": schema_sigsk8sio_gateway_api_apis_v1_HTTPHeaderFilter(ref), "sigs.k8s.io/gateway-api/apis/v1.HTTPHeaderMatch": schema_sigsk8sio_gateway_api_apis_v1_HTTPHeaderMatch(ref), @@ -3063,6 +3067,26 @@ func schema_sigsk8sio_gateway_api_apis_v1_CookieConfig(ref common.ReferenceCallb } } +func schema_sigsk8sio_gateway_api_apis_v1_ForwardBodyConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ForwardBody configures if requests to the authorization server should include the body of the client request; and if so, how big that body is allowed to be.\n\nIf empty or unset, do not forward the body.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "maxSize": { + SchemaProps: spec.SchemaProps{ + Description: "MaxSize specifies how large in bytes the largest body that will be buffered and sent to the authorization server. If the body size is larger than `maxSize`, then the body sent to the authorization server must be truncated to `maxSize` bytes.\n\nExperimental note: This behavior needs to be checked against various dataplanes; it may need to be changed. See https://github.com/kubernetes-sigs/gateway-api/pull/4001#discussion_r2291405746 for more.\n\nIf 0, the body will not be sent to the authorization server.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + }, + }, + }, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_Fraction(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3131,6 +3155,39 @@ func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.Refer } } +func schema_sigsk8sio_gateway_api_apis_v1_GRPCAuthConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "GRPCAuthConfig contains configuration for communication with Auth server backends that speak Envoy's ext_authz gRPC protocol.\n\nRequests and responses are defined in the protobufs explained at: https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "allowedHeaders": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "AllowedRequestHeaders specifies what headers from the client request will be sent to the authorization server.\n\nIf this list is empty, then the following headers must be sent:\n\n- `Authorization` - `Location` - `Proxy-Authenticate` - `Set-Cookie` - `WWW-Authenticate`\n\nIf the list has entries, only those entries must be sent.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_GRPCBackendRef(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4298,6 +4355,66 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayTLSConfig(ref common.ReferenceC } } +func schema_sigsk8sio_gateway_api_apis_v1_HTTPAuthConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "HTTPAuthConfig contains configuration for communication with HTTP-speaking backends.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path sets the prefix that paths from the client request will have added when forwarded to the authorization server.\n\nWhen empty or unspecified, no prefix is added.\n\nValid values are the same as the \"value\" regex for path values in the `match` stanza, and the validation regex will screen out invalid paths in the same way. Even with the validation, implementations MUST sanitize this input before using it directly.", + Type: []string{"string"}, + Format: "", + }, + }, + "allowedHeaders": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "AllowedRequestHeaders specifies what additional headers from the client request will be sent to the authorization server.\n\nThe following headers must always be sent to the authorization server, regardless of this setting:\n\n* `Host` * `Method` * `Path` * `Content-Length` * `Authorization`\n\nIf this list is empty, then only those headers must be sent.\n\nNote that `Content-Length` has a special behavior, in that the length sent must be correct for the actual request to the external authorization server - that is, it must reflect the actual number of bytes sent in the body of the request to the authorization server.\n\nSo if the `forwardBody` stanza is unset, or `forwardBody.maxSize` is set to `0`, then `Content-Length` must be `0`. If `forwardBody.maxSize` is set to anything other than `0`, then the `Content-Length` of the authorization request must be set to the actual number of bytes forwarded.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "allowedResponseHeaders": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "AllowedResponseHeaders specifies what headers from the authorization response will be copied into the request to the backend.\n\nIf this list is empty, then all headers from the authorization server except Authority or Host must be copied.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_HTTPBackendRef(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4483,6 +4600,54 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPCORSFilter(ref common.ReferenceCal } } +func schema_sigsk8sio_gateway_api_apis_v1_HTTPExternalAuthFilter(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "HTTPExternalAuthFilter defines a filter that modifies requests by sending request details to an external authorization server.\n\nSupport: Extended Feature Name: HTTPRouteExternalAuth", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "protocol": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalAuthProtocol describes which protocol to use when communicating with an ext_authz authorization server.\n\nWhen this is set to GRPC, each backend must use the Envoy ext_authz protocol on the port specified in `backendRefs`. Requests and responses are defined in the protobufs explained at: https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto\n\nWhen this is set to HTTP, each backend must respond with a `200` status code in on a successful authorization. Any other code is considered an authorization failure.\n\nFeature Names: GRPC Support - HTTPRouteExternalAuthGRPC HTTP Support - HTTPRouteExternalAuthHTTP", + Type: []string{"string"}, + Format: "", + }, + }, + "backendRef": { + SchemaProps: spec.SchemaProps{ + Description: "BackendRef is a reference to a backend to send authorization requests to.\n\nThe backend must speak the selected protocol (GRPC or HTTP) on the referenced port.\n\nIf the backend service requires TLS, use BackendTLSPolicy to tell the implementation to supply the TLS details to be used to connect to that backend.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.BackendObjectReference"), + }, + }, + "grpc": { + SchemaProps: spec.SchemaProps{ + Description: "GRPCAuthConfig contains configuration for communication with ext_authz protocol-speaking backends.\n\nIf unset, implementations must assume the default behavior for each included field is intended.", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GRPCAuthConfig"), + }, + }, + "http": { + SchemaProps: spec.SchemaProps{ + Description: "HTTPAuthConfig contains configuration for communication with HTTP-speaking backends.\n\nIf unset, implementations must assume the default behavior for each included field is intended.", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.HTTPAuthConfig"), + }, + }, + "forwardBody": { + SchemaProps: spec.SchemaProps{ + Description: "ForwardBody controls if requests to the authorization server should include the body of the client request; and if so, how big that body is allowed to be.\n\nIt is expected that implementations will buffer the request body up to `forwardBody.maxSize` bytes. Bodies over that size must be rejected with a 4xx series error (413 or 403 are common examples), and fail processing of the filter.\n\nIf unset, or `forwardBody.maxSize` is set to `0`, then the body will not be forwarded.\n\nFeature Name: HTTPRouteExternalAuthForwardBody", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.ForwardBodyConfig"), + }, + }, + }, + Required: []string{"protocol", "backendRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.BackendObjectReference", "sigs.k8s.io/gateway-api/apis/v1.ForwardBodyConfig", "sigs.k8s.io/gateway-api/apis/v1.GRPCAuthConfig", "sigs.k8s.io/gateway-api/apis/v1.HTTPAuthConfig"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_HTTPHeader(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -4873,7 +5038,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteFilter(ref common.ReferenceCa Properties: map[string]spec.Schema{ "type": { SchemaProps: spec.SchemaProps{ - Description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels:\n\n- Core: Filter types and their corresponding configuration defined by\n \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All\n implementations must support core filters.\n\n- Extended: Filter types and their corresponding configuration defined by\n \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers\n are encouraged to support extended filters.\n\n- Implementation-specific: Filters that are defined and supported by\n specific vendors.\n In the future, filters showing convergence in behavior across multiple\n implementations will be considered for inclusion in extended or core\n conformance levels. Filter-specific configuration for such filters\n is specified using the ExtensionRef field. `Type` should be set to\n \"ExtensionRef\" for custom filters.\n\nImplementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior.\n\nIf a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response.\n\nNote that values may be added to this enum, implementations must ensure that unknown values will not cause a crash.\n\nUnknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`.\n\n", + Description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels:\n\n- Core: Filter types and their corresponding configuration defined by\n \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All\n implementations must support core filters.\n\n- Extended: Filter types and their corresponding configuration defined by\n \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers\n are encouraged to support extended filters.\n\n- Implementation-specific: Filters that are defined and supported by\n specific vendors.\n In the future, filters showing convergence in behavior across multiple\n implementations will be considered for inclusion in extended or core\n conformance levels. Filter-specific configuration for such filters\n is specified using the ExtensionRef field. `Type` should be set to\n \"ExtensionRef\" for custom filters.\n\nImplementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior.\n\nIf a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response.\n\nNote that values may be added to this enum, implementations must ensure that unknown values will not cause a crash.\n\nUnknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`.\n\n", Default: "", Type: []string{"string"}, Format: "", @@ -4915,6 +5080,12 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteFilter(ref common.ReferenceCa Ref: ref("sigs.k8s.io/gateway-api/apis/v1.HTTPCORSFilter"), }, }, + "externalAuth": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalAuth configures settings related to sending request details to an external auth service. The external service MUST authenticate the request, and MAY authorize the request as well.\n\nIf there is any problem communicating with the external service, this filter MUST fail closed.\n\nSupport: Extended\n\n", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.HTTPExternalAuthFilter"), + }, + }, "extensionRef": { SchemaProps: spec.SchemaProps{ Description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters.\n\nThis filter can be used multiple times within the same rule.\n\nSupport: Implementation-specific", @@ -4926,7 +5097,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteFilter(ref common.ReferenceCa }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.HTTPCORSFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPHeaderFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPRequestMirrorFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPRequestRedirectFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPURLRewriteFilter", "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference"}, + "sigs.k8s.io/gateway-api/apis/v1.HTTPCORSFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPExternalAuthFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPHeaderFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPRequestMirrorFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPRequestRedirectFilter", "sigs.k8s.io/gateway-api/apis/v1.HTTPURLRewriteFilter", "sigs.k8s.io/gateway-api/apis/v1.LocalObjectReference"}, } } diff --git a/pkg/test/cel/httproute_experimental_test.go b/pkg/test/cel/httproute_experimental_test.go index f6ff0d455b..9978d4ca11 100644 --- a/pkg/test/cel/httproute_experimental_test.go +++ b/pkg/test/cel/httproute_experimental_test.go @@ -568,3 +568,49 @@ func TestHTTPRequestMirrorFilterExperimental(t *testing.T) { }) } } + +func TestHTTPExternalAuthFilterExperimental(t *testing.T) { + tests := []struct { + name string + wantErrors []string + rules []gatewayv1.HTTPRouteRule + }{ + { + name: "HTTPRoute - Invalid because protocol is GRPC without GRPC config", + wantErrors: []string{"grpc must be specified when protocol is set to 'GRPC'"}, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterExternalAuth, + ExternalAuth: &gatewayv1.HTTPExternalAuthFilter{ + ExternalAuthProtocol: gatewayv1.HTTPRouteExternalAuthGRPCProtocol, + }, + }}, + }}, + }, + { + name: "HTTPRoute - Invalid because protocol is HTTP without HTTP config", + wantErrors: []string{"http must be specified when protocol is set to 'HTTP'"}, + rules: []gatewayv1.HTTPRouteRule{{ + Filters: []gatewayv1.HTTPRouteFilter{{ + Type: gatewayv1.HTTPRouteFilterExternalAuth, + ExternalAuth: &gatewayv1.HTTPExternalAuthFilter{ + ExternalAuthProtocol: gatewayv1.HTTPRouteExternalAuthHTTPProtocol, + }, + }}, + }}, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := &gatewayv1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), + Namespace: metav1.NamespaceDefault, + }, + Spec: gatewayv1.HTTPRouteSpec{Rules: tc.rules}, + } + validateHTTPRoute(t, route, tc.wantErrors) + }) + } + +} From d008cdea2652786c1711426056e059d127954f52 Mon Sep 17 00:00:00 2001 From: Eyal Paz <67443108+EyalPazz@users.noreply.github.com> Date: Tue, 26 Aug 2025 02:53:06 +0300 Subject: [PATCH 142/224] conformance: add test for optional address value (#3689) * conformance: add test for optional address value * fix: small resolutions after CR * fix: CR Resolution 2 * fix: only overlay addresses if needed * fix: conflict resolvement mistake * fix: CR comments --- .../tests/gateway-optional-address-value.go | 70 +++++++++++++++++++ .../tests/gateway-optional-address-value.yaml | 13 ++++ conformance/utils/kubernetes/helpers.go | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 conformance/tests/gateway-optional-address-value.go create mode 100644 conformance/tests/gateway-optional-address-value.yaml diff --git a/conformance/tests/gateway-optional-address-value.go b/conformance/tests/gateway-optional-address-value.go new file mode 100644 index 0000000000..78a59d687e --- /dev/null +++ b/conformance/tests/gateway-optional-address-value.go @@ -0,0 +1,70 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/types" + + v1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, GatewayOptionalAddressValue) +} + +var GatewayOptionalAddressValue = suite.ConformanceTest{ + ShortName: "GatewayOptionalAddressValue", + Description: "Check Gateway Support for GatewayAddressEmpty feature", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportGatewayAddressEmpty, + }, + Provisional: true, + Manifests: []string{ + "tests/gateway-optional-address-value.yaml", + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + + kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, []string{ns}) + + gwNN := types.NamespacedName{ + Name: "gateway-without-address-value", + Namespace: "gateway-conformance-infra", + } + ctx, cancel := context.WithTimeout(context.Background(), s.TimeoutConfig.DefaultTestTimeout) + defer cancel() + + t.Logf("waiting for Gateway %s to be ready for testing", gwNN.Name) + kubernetes.GatewayMustHaveLatestConditions(t, s.Client, s.TimeoutConfig, gwNN) + + t.Logf("retrieving Gateway %s/%s", gwNN.Namespace, gwNN.Name) + currentGW := &v1.Gateway{} + err := s.Client.Get(ctx, gwNN, currentGW) + require.NoError(t, err, "error getting Gateway: %v", err) + t.Logf("verifying that the Gateway %s/%s is accepted", gwNN.Namespace, gwNN.Name) + _, err = kubernetes.WaitForGatewayAddress(t, s.Client, s.TimeoutConfig, kubernetes.NewGatewayRef(gwNN, "http")) + require.NoError(t, err, "timed out waiting for Gateway address to be assigned") + }, +} diff --git a/conformance/tests/gateway-optional-address-value.yaml b/conformance/tests/gateway-optional-address-value.yaml new file mode 100644 index 0000000000..48e7ffdc32 --- /dev/null +++ b/conformance/tests/gateway-optional-address-value.yaml @@ -0,0 +1,13 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: gateway-without-address-value + namespace: gateway-conformance-infra +spec: + gatewayClassName: "{GATEWAY_CLASS_NAME}" + addresses: + - type: "IPAddress" + listeners: + - name: http + port: 8080 + protocol: HTTP diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index 1501d93571..ea9b8af63f 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -446,7 +446,7 @@ func WaitForGatewayAddress(t *testing.T, client client.Client, timeoutConfig con } port = strconv.FormatInt(int64(listener.Port), 10) for _, address := range gw.Status.Addresses { - if address.Type != nil && (*address.Type == gatewayv1.IPAddressType || *address.Type == v1alpha2.HostnameAddressType) { + if address.Type != nil { ipAddr = address.Value return true, nil } From c15b79217096f0375b971121d42098e665ee622a Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Tue, 26 Aug 2025 16:10:12 +0200 Subject: [PATCH 143/224] BackendTLSPolicy conformance tests for ResolvedRefs status condition (#4010) * BackendTLSPolicy conformance tests for ResolvedRefs status condition Signed-off-by: Norwin Schnyder * Apply PR feedback Signed-off-by: Norwin Schnyder * deprecate StatusCode of the excpected response in favor of StatusCodes Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- ...endtlspolicy-invalid-ca-certificate-ref.go | 98 +++++++++++++++++++ ...dtlspolicy-invalid-ca-certificate-ref.yaml | 97 ++++++++++++++++++ .../tests/backendtlspolicy-invalid-kind.go | 93 ++++++++++++++++++ .../tests/backendtlspolicy-invalid-kind.yaml | 51 ++++++++++ conformance/tests/backendtlspolicy.go | 26 +++-- conformance/utils/echo/pod.go | 20 +++- conformance/utils/http/http.go | 25 +++-- 7 files changed, 390 insertions(+), 20 deletions(-) create mode 100644 conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go create mode 100644 conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml create mode 100644 conformance/tests/backendtlspolicy-invalid-kind.go create mode 100644 conformance/tests/backendtlspolicy-invalid-kind.yaml diff --git a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go new file mode 100644 index 0000000000..824d8dd199 --- /dev/null +++ b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.go @@ -0,0 +1,98 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + h "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicyInvalidCACertificateRef) +} + +var BackendTLSPolicyInvalidCACertificateRef = suite.ConformanceTest{ + ShortName: "BackendTLSPolicyInvalidCACertificateRef", + Description: "A BackendTLSPolicy that specifies a single invalid CACertificateRef should have the Accepted and ResolvedRefs status condition set False with appropriate reasons, and HTTP requests to a backend targeted by this policy should fail with a 5xx response.", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + }, + Manifests: []string{"tests/backendtlspolicy-invalid-ca-certificate-ref.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "backendtlspolicy-invalid-ca-certificate-ref", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + + serverStr := "abc.example.com" + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + + for _, policyNN := range []types.NamespacedName{ + {Name: "nonexistent-ca-certificate-ref", Namespace: ns}, + {Name: "malformed-ca-certificate-ref", Namespace: ns}, + } { + t.Run("BackendTLSPolicy_"+policyNN.Name, func(t *testing.T) { + t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a Accepted Condition with status False and Reason NoValidCACertificate", func(t *testing.T) { + acceptedCond := metav1.Condition{ + Type: string(gatewayv1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionFalse, + Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonNoValidCACertificate), + } + + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a ResolvedRefs Condition with status False and Reason InvalidCACertificateRef", func(t *testing.T) { + resolvedRefsCond := metav1.Condition{ + Type: string(gatewayv1alpha3.BackendTLSPolicyConditionResolvedRefs), + Status: metav1.ConditionFalse, + Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonInvalidCACertificateRef), + } + + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, resolvedRefsCond) + }) + + t.Run("HTTP Request to backend targeted by an invalid BackendTLSPolicy receive a 5xx", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendtlspolicy-" + policyNN.Name, + }, + Response: h.Response{ + StatusCodes: []int{500, 502, 503}, + }, + }) + }) + }) + } + }, +} diff --git a/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml new file mode 100644 index 0000000000..138812fddb --- /dev/null +++ b/conformance/tests/backendtlspolicy-invalid-ca-certificate-ref.yaml @@ -0,0 +1,97 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backendtlspolicy-invalid-ca-certificate-ref + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + namespace: gateway-conformance-infra + hostnames: + - abc.example.com + rules: + - backendRefs: + - name: backendtlspolicy-nonexistent-ca-certificate-ref-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-nonexistent-ca-certificate-ref + - backendRefs: + - name: backendtlspolicy-malformed-ca-certificate-ref-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-malformed-ca-certificate-ref +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-nonexistent-ca-certificate-ref-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-malformed-ca-certificate-ref-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: nonexistent-ca-certificate-ref + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-nonexistent-ca-certificate-ref-test" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: "nonexistent-ca-certificate" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: malformed-ca-certificate-ref + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-malformed-ca-certificate-ref-test" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: "malformed-ca-certificate" + hostname: "abc.example.com" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: malformed-ca-certificate + namespace: gateway-conformance-infra +data: {} diff --git a/conformance/tests/backendtlspolicy-invalid-kind.go b/conformance/tests/backendtlspolicy-invalid-kind.go new file mode 100644 index 0000000000..5a3bba597e --- /dev/null +++ b/conformance/tests/backendtlspolicy-invalid-kind.go @@ -0,0 +1,93 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" + h "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicyInvalidKind) +} + +var BackendTLSPolicyInvalidKind = suite.ConformanceTest{ + ShortName: "BackendTLSPolicyInvalidKind", + Description: "A BackendTLSPolicy that specifies a single CACertificateRef with an invalid kind should have the Accepted and ResolvedRefs status condition set False with appropriate reasons, and HTTP requests to a backend targeted by this policy should fail with a 5xx response.", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + }, + Manifests: []string{"tests/backendtlspolicy-invalid-kind.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "backendtlspolicy-invalid-kind-test", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + + serverStr := "abc.example.com" + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + + policyNN := types.NamespacedName{Name: "invalid-kind", Namespace: ns} + + t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a Accepted Condition with status False and Reason NoValidCACertificate", func(t *testing.T) { + acceptedCond := metav1.Condition{ + Type: string(gatewayv1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionFalse, + Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonNoValidCACertificate), + } + + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("BackendTLSPolicy with a single invalid CACertificateRef has a ResolvedRefs Condition with status False and Reason InvalidKind", func(t *testing.T) { + resolvedRefsCond := metav1.Condition{ + Type: string(gatewayv1alpha3.BackendTLSPolicyConditionResolvedRefs), + Status: metav1.ConditionFalse, + Reason: string(gatewayv1alpha3.BackendTLSPolicyReasonInvalidKind), + } + + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, resolvedRefsCond) + }) + + t.Run("HTTP Request to backend targeted by an invalid BackendTLSPolicy receive a 5xx", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendtlspolicy-" + policyNN.Name, + }, + Response: h.Response{ + StatusCodes: []int{500, 502, 503}, + }, + }) + }) + }, +} diff --git a/conformance/tests/backendtlspolicy-invalid-kind.yaml b/conformance/tests/backendtlspolicy-invalid-kind.yaml new file mode 100644 index 0000000000..a7eaeb5d5c --- /dev/null +++ b/conformance/tests/backendtlspolicy-invalid-kind.yaml @@ -0,0 +1,51 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backendtlspolicy-invalid-kind-test + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + namespace: gateway-conformance-infra + hostnames: + - abc.example.com + rules: + - backendRefs: + - name: backendtlspolicy-invalid-kind-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-invalid-kind +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-invalid-kind-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: invalid-kind + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-invalid-kind-test" + validation: + caCertificateRefs: + - group: invalid.io + kind: InvalidKind + name: "invalid-kind" + hostname: "abc.example.com" diff --git a/conformance/tests/backendtlspolicy.go b/conformance/tests/backendtlspolicy.go index fc6c6576eb..62ed54c4af 100644 --- a/conformance/tests/backendtlspolicy.go +++ b/conformance/tests/backendtlspolicy.go @@ -20,11 +20,11 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1alpha3" h "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" @@ -54,20 +54,20 @@ var BackendTLSPolicy = suite.ConformanceTest{ gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) - policyCond := metav1.Condition{ + acceptedCond := metav1.Condition{ Type: string(v1alpha2.PolicyConditionAccepted), Status: metav1.ConditionTrue, Reason: string(v1alpha2.PolicyReasonAccepted), } + resolvedRefsCond := metav1.Condition{ + Type: string(v1alpha3.BackendTLSPolicyConditionResolvedRefs), + Status: metav1.ConditionTrue, + Reason: string(v1alpha3.BackendTLSPolicyReasonResolvedRefs), + } validPolicyNN := types.NamespacedName{Name: "normative-test-backendtlspolicy", Namespace: ns} - kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, policyCond) - - invalidPolicyNN := types.NamespacedName{Name: "backendtlspolicy-host-mismatch", Namespace: ns} - kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, policyCond) - - invalidCertPolicyNN := types.NamespacedName{Name: "backendtlspolicy-cert-mismatch", Namespace: ns} - kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, policyCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, acceptedCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, resolvedRefsCond) serverStr := "abc.example.com" @@ -107,6 +107,10 @@ var BackendTLSPolicy = suite.ConformanceTest{ // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched host will fail. t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched hostname should return an HTTP error", func(t *testing.T) { + invalidPolicyNN := types.NamespacedName{Name: "backendtlspolicy-host-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, acceptedCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, resolvedRefsCond) + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, h.ExpectedResponse{ Namespace: ns, @@ -120,6 +124,10 @@ var BackendTLSPolicy = suite.ConformanceTest{ // Verify that request sent to Service targeted by BackendTLSPolicy with mismatched cert should failed. t.Run("HTTP request send to Service targeted by BackendTLSPolicy with mismatched cert should return HTTP error", func(t *testing.T) { + invalidCertPolicyNN := types.NamespacedName{Name: "backendtlspolicy-cert-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, acceptedCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, resolvedRefsCond) + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, h.ExpectedResponse{ Namespace: ns, diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index 0222ff12dd..dff03ed5fa 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -20,6 +20,8 @@ import ( "bytes" "context" "fmt" + "slices" + "strconv" "strings" "testing" "time" @@ -84,8 +86,14 @@ func makeRequest(t *testing.T, exp *http.ExpectedResponse) []string { exp.Request.Method = "GET" } - if exp.Response.StatusCode == 0 { - exp.Response.StatusCode = 200 + // if the deprecated field StatusCode is set, append it to StatusCodes for backwards compatibility + //nolint:staticcheck + if exp.Response.StatusCode != 0 { + exp.Response.StatusCodes = append(exp.Response.StatusCodes, exp.Response.StatusCode) + } + + if len(exp.Response.StatusCodes) == 0 { + exp.Response.StatusCodes = []int{200} } r := exp.Request @@ -110,8 +118,12 @@ func compareRequest(exp http.ExpectedResponse, resp Response) error { } wantReq := exp.ExpectedRequest wantResp := exp.Response - if fmt.Sprint(wantResp.StatusCode) != resp.Code { - return fmt.Errorf("wanted status code %v, got %v", wantResp.StatusCode, resp.Code) + statusCode, err := strconv.Atoi(resp.Code) + if err != nil { + return fmt.Errorf("invalid status code '%v': %v", resp.Code, err) + } + if !slices.Contains(wantResp.StatusCodes, statusCode) { + return fmt.Errorf("wanted status code to be one of %v, got %d", wantResp.StatusCodes, statusCode) } if wantReq.Headers != nil { if resp.RequestHeaders == nil { diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index 50f8d1efdd..6cd68dd084 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -22,6 +22,7 @@ import ( "math/big" "net" "net/url" + "slices" "strings" "testing" "time" @@ -91,7 +92,9 @@ type ExpectedRequest struct { // Response defines expected properties of a response from a backend. type Response struct { + // Deprecated: Use StatusCodes instead, which supports matching against multiple status codes. StatusCode int + StatusCodes []int Headers map[string]string AbsentHeaders []string Protocol string @@ -138,8 +141,13 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch expected.Request.Method = "GET" } - if expected.Response.StatusCode == 0 { - expected.Response.StatusCode = 200 + // if the deprecated field StatusCode is set, append it to StatusCodes for backwards compatibility + if expected.Response.StatusCode != 0 { + expected.Response.StatusCodes = append(expected.Response.StatusCodes, expected.Response.StatusCode) + } + + if len(expected.Response.StatusCodes) == 0 { + expected.Response.StatusCodes = []int{200} } if expected.Request.Protocol == "" { @@ -300,12 +308,14 @@ func WaitForConsistentFailureResponse(t *testing.T, r roundtripper.RoundTripper, func CompareRoundTrip(t *testing.T, req *roundtripper.Request, cReq *roundtripper.CapturedRequest, cRes *roundtripper.CapturedResponse, expected ExpectedResponse) error { if roundtripper.IsTimeoutError(cRes.StatusCode) { - if roundtripper.IsTimeoutError(expected.Response.StatusCode) { - return nil + for _, statusCode := range expected.Response.StatusCodes { + if roundtripper.IsTimeoutError(statusCode) { + return nil + } } } - if expected.Response.StatusCode != cRes.StatusCode { - return fmt.Errorf("expected status code to be %d, got %d. CRes: %v", expected.Response.StatusCode, cRes.StatusCode, cRes) + if !slices.Contains(expected.Response.StatusCodes, cRes.StatusCode) { + return fmt.Errorf("expected status code to be one of %v, got %d. CRes: %v", expected.Response.StatusCodes, cRes.StatusCode, cRes) } if expected.Response.Protocol != "" && expected.Response.Protocol != cRes.Protocol { return fmt.Errorf("expected protocol to be %s, got %s", expected.Response.Protocol, cRes.Protocol) @@ -467,7 +477,8 @@ func (er *ExpectedResponse) GetTestCaseName(i int) string { if er.Backend != "" { return fmt.Sprintf("%s should go to %s", reqStr, er.Backend) } - return fmt.Sprintf("%s should receive a %d", reqStr, er.Response.StatusCode) + + return fmt.Sprintf("%s should receive one of %v", reqStr, er.Response.StatusCodes) } func setRedirectRequestDefaults(req *roundtripper.Request, cRes *roundtripper.CapturedResponse, expected *ExpectedResponse) { From cd9f05fdd8288a8156db1cfcce89abdefa1c7a52 Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Tue, 26 Aug 2025 12:30:09 -0700 Subject: [PATCH 144/224] remove http non mesh features from mesh profile (#4029) --- conformance/utils/suite/profiles.go | 1 - 1 file changed, 1 deletion(-) diff --git a/conformance/utils/suite/profiles.go b/conformance/utils/suite/profiles.go index 2f589ed4eb..996fe346dd 100644 --- a/conformance/utils/suite/profiles.go +++ b/conformance/utils/suite/profiles.go @@ -119,7 +119,6 @@ var ( ExtendedFeatures: sets.New[features.FeatureName](). Insert(features.SetsToNamesSet( features.MeshExtendedFeatures, - features.HTTPRouteExtendedFeatures, ).UnsortedList()...), } From d28cd59d37887be07b879f098cff7b14a87c0080 Mon Sep 17 00:00:00 2001 From: Eyal Paz <67443108+EyalPazz@users.noreply.github.com> Date: Tue, 26 Aug 2025 22:48:10 +0300 Subject: [PATCH 145/224] conformance: add test to check for proper cors allow-credentials behvior (#3990) * conformance: add test to check for proper cors allow-credentials behavior * chore: rephrase description * fix: SupportHTTPRouteCORS FeatureName --- .../tests/cors-allow-credentials-behavior.go | 100 ++++++++++++++++++ .../cors-allow-credentials-behavior.yaml | 32 ++++++ pkg/features/httproute.go | 9 ++ 3 files changed, 141 insertions(+) create mode 100644 conformance/tests/cors-allow-credentials-behavior.go create mode 100644 conformance/tests/cors-allow-credentials-behavior.yaml diff --git a/conformance/tests/cors-allow-credentials-behavior.go b/conformance/tests/cors-allow-credentials-behavior.go new file mode 100644 index 0000000000..391b3cee80 --- /dev/null +++ b/conformance/tests/cors-allow-credentials-behavior.go @@ -0,0 +1,100 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, CORSAllowCredentialsBehavior) +} + +var CORSAllowCredentialsBehavior = suite.ConformanceTest{ + ShortName: "CORSAllowCredentialsBehavior", + Description: "Validate ACA-Credentials responses", + Manifests: []string{"tests/cors-allow-credentials-behavior.yaml"}, + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportHTTPRouteCORS, + }, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "cors-allow-credentials", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + origin := "https://app.example" + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Method: "GET", + Path: "/cors-behavior-creds-false", + Headers: map[string]string{ + "Origin": origin, + "Cookie": "sid=abc123", + "Authorization": "Bearer test", + }, + }, + Response: http.Response{ + StatusCode: 200, + AbsentHeaders: []string{"Access-Control-Allow-Credentials"}, + }, + Namespace: ns, + }, + { + Request: http.Request{ + Method: "GET", + Path: "/cors-behavior-creds-true", + Headers: map[string]string{ + "Origin": origin, + "Cookie": "sid=abc123", + "Authorization": "Bearer test", + }, + }, + Response: http.Response{ + StatusCode: 200, + Headers: map[string]string{ + "Access-Control-Allow-Credentials": "true", + "Access-Control-Allow-Origin": origin, + }, + }, + Namespace: ns, + }, + } + + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) + }) + } + }, +} diff --git a/conformance/tests/cors-allow-credentials-behavior.yaml b/conformance/tests/cors-allow-credentials-behavior.yaml new file mode 100644 index 0000000000..13992e28f4 --- /dev/null +++ b/conformance/tests/cors-allow-credentials-behavior.yaml @@ -0,0 +1,32 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: cors-allow-credentials + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /cors-behavior-creds-false + backendRefs: + - name: infra-backend-v1 + port: 8080 + filters: + - cors: + allowCredentials: false + type: CORS + - matches: + - path: + type: PathPrefix + value: /cors-behavior-creds-true + backendRefs: + - name: infra-backend-v1 + port: 8080 + filters: + - cors: + allowCredentials: true + type: CORS + diff --git a/pkg/features/httproute.go b/pkg/features/httproute.go index 6c484da96c..53f93afdab 100644 --- a/pkg/features/httproute.go +++ b/pkg/features/httproute.go @@ -100,6 +100,9 @@ const ( // This option indicates support for the name field in the HTTPRouteRule (extended conformance) SupportHTTPRouteNamedRouteRule FeatureName = "HTTPRouteNamedRouteRule" + + // This option indicates support for the cors filter in the HTTPRouteFilter (extended conformance) + SupportHTTPRouteCORS FeatureName = "HTTPRouteCORS" ) var ( @@ -198,6 +201,11 @@ var ( Name: SupportHTTPRouteNamedRouteRule, Channel: FeatureChannelStandard, } + // HTTPRouteCORS contains metadata for the SupportHTTPRouteCORS feature. + HTTPRouteCORS = Feature{ + Name: SupportHTTPRouteCORS, + Channel: FeatureChannelExperimental, + } ) // HTTPRouteExtendedFeatures includes all extended features for HTTPRoute @@ -223,4 +231,5 @@ var HTTPRouteExtendedFeatures = sets.New( HTTPRouteBackendProtocolH2CFeature, HTTPRouteBackendProtocolWebSocketFeature, HTTPRouteNamedRouteRule, + HTTPRouteCORS, ) From 881105e859e69d4a5530b2b3fd4944448ee72784 Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Thu, 28 Aug 2025 01:53:10 +0200 Subject: [PATCH 146/224] Add Conformance tests for BackendTLSPolicy validating SANs with Type dsnName (#3983) * Add Conformance tests for BackendTLSPolicy validating SANs * review fixes * Validate URI SANs --- conformance/base/manifests.yaml | 33 ++ conformance/tests/backendtlspolicy-san.go | 163 ++++++++++ conformance/tests/backendtlspolicy-san.yaml | 341 ++++++++++++++++++++ conformance/tests/backendtlspolicy.yaml | 33 -- conformance/utils/kubernetes/certificate.go | 5 + conformance/utils/kubernetes/helpers.go | 4 +- conformance/utils/suite/suite.go | 5 + pkg/features/backendtlspolicy.go | 16 + 8 files changed, 565 insertions(+), 35 deletions(-) create mode 100644 conformance/tests/backendtlspolicy-san.go create mode 100644 conformance/tests/backendtlspolicy-san.yaml diff --git a/conformance/base/manifests.yaml b/conformance/base/manifests.yaml index 9380223ea0..d8f8c45a1c 100644 --- a/conformance/base/manifests.yaml +++ b/conformance/base/manifests.yaml @@ -95,6 +95,39 @@ spec: matchLabels: gateway-conformance: backend --- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: gateway-backendtlspolicy + namespace: gateway-conformance-infra +spec: + gatewayClassName: "{GATEWAY_CLASS_NAME}" + listeners: + - name: http + port: 80 + protocol: HTTP + hostname: "abc.example.com" + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: HTTPRoute + - name: https + port: 443 + protocol: HTTPS + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-checks-certificate + hostname: "abc.example.com" + allowedRoutes: + namespaces: + from: Same + kinds: + - kind: HTTPRoute +--- apiVersion: v1 kind: Service metadata: diff --git a/conformance/tests/backendtlspolicy-san.go b/conformance/tests/backendtlspolicy-san.go new file mode 100644 index 0000000000..38e7a2b43a --- /dev/null +++ b/conformance/tests/backendtlspolicy-san.go @@ -0,0 +1,163 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + h "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicySANValidation) +} + +var BackendTLSPolicySANValidation = suite.ConformanceTest{ + ShortName: "BackendTLSPolicySANValidation", + Description: "BackendTLSPolicySANValidation extend BackendTLSPolicy with SubjectAltNames validation", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + features.SupportBackendTLSPolicySANValidation, + }, + Manifests: []string{"tests/backendtlspolicy-san.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "route-backendtlspolicy-san-test", Namespace: ns} + gwNN := types.NamespacedName{Name: "gateway-backendtlspolicy", Namespace: ns} + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + policyCond := metav1.Condition{ + Type: string(v1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(v1alpha2.PolicyReasonAccepted), + } + + serverStr := "abc.example.com" + + // Verify that the request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed. + t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSSanDns", + SNI: serverStr, + }, + Response: h.Response{StatusCode: 200}, + }) + }) + + // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched dns SAN should fail. + t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched dns SAN should return an HTTP error", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSSanDnsMismatch", + SNI: serverStr, + }, + }) + }) + + // Verify that the request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed. + t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSSanUri", + SNI: serverStr, + }, + Response: h.Response{StatusCode: 200}, + }) + }) + + // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched uri SAN should fail. + t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched uri SAN should return an HTTP error", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri-mismatch", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSSanUriMismatch", + SNI: serverStr, + }, + }) + }) + + // Verify that the request sent to Service with valid BackendTLSPolicy containing multi SANs should succeed. + t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing multi SAN should succeed", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-sans", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSMultiSans", + SNI: serverStr, + }, + Response: h.Response{StatusCode: 200}, + }) + }) + + // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched multi SAN should fail. + t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched multi SAN should return an HTTP error", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-mismatch-sans", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) + + h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: serverStr, + Path: "/backendTLSMultiMismatchSans", + SNI: serverStr, + }, + }) + }) + }, +} diff --git a/conformance/tests/backendtlspolicy-san.yaml b/conformance/tests/backendtlspolicy-san.yaml new file mode 100644 index 0000000000..e3e0f79bf0 --- /dev/null +++ b/conformance/tests/backendtlspolicy-san.yaml @@ -0,0 +1,341 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: route-backendtlspolicy-san-test + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: gateway-backendtlspolicy + namespace: gateway-conformance-infra + hostnames: + - abc.example.com + rules: + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-dns-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSSanDns + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-dns-mismatch-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSSanDnsMismatch + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-uri-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSSanUri + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-uri-mismatch-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSSanUriMismatch + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-multiple-sans-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSMultiSans + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-multiple-mismatch-sans-test + port: 443 + matches: + - path: + type: Exact + value: /backendTLSMultiMismatchSans +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-san-dns-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-san-dns-mismatch-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-san-uri-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-san-uri-mismatch-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-multiple-sans-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-multiple-mismatch-sans-test + namespace: gateway-conformance-infra +spec: + selector: + app: backendtlspolicy-san-test + ports: + - name: "btls" + protocol: TCP + appProtocol: HTTPS + port: 443 + targetPort: 8443 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backendtlspolicy-san-test + namespace: gateway-conformance-infra + labels: + app: backendtlspolicy-san-test +spec: + replicas: 1 + selector: + matchLabels: + app: backendtlspolicy-san-test + template: + metadata: + labels: + app: backendtlspolicy-san-test + spec: + containers: + - name: backendtlspolicy-san-test + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd + volumeMounts: + - name: secret-volume + mountPath: /etc/secret-volume + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: TLS_SERVER_CERT + value: /etc/secret-volume/crt + - name: TLS_SERVER_PRIVKEY + value: /etc/secret-volume/key + resources: + requests: + cpu: 10m + volumes: + - name: secret-volume + secret: + # This secret is generated dynamically by the test suite. + secretName: tls-with-san-certificate + items: + - key: tls.crt + path: crt + - key: tls.key + path: key +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-san-dns + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-dns-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "Hostname" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-san-dns-mismatch + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-dns-mismatch-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "Hostname" + hostname: "dce.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-san-uri + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-uri-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "URI" + uri: "spiffe://abc.example.com/test-identity" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-san-uri-mismatch + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-san-uri-mismatch-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "URI" + uri: "spiffe://def.example.com/test-identity" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-multiple-sans + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-multiple-sans-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "URI" + uri: "spiffe://abc.example.com/test-identity" + - type: "Hostname" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: backendtlspolicy-multiple-mismatch-sans + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: backendtlspolicy-multiple-mismatch-sans-test + sectionName: "btls" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This secret is generated dynamically by the test suite. + name: "backend-tls-with-san-certificate" + hostname: "abc.example.com" + subjectAltNames: + - type: "URI" + uri: "spiffe://def.example.com/test-identity" + - type: "Hostname" + hostname: "def.example.com" diff --git a/conformance/tests/backendtlspolicy.yaml b/conformance/tests/backendtlspolicy.yaml index e048cc2e7b..6d0cab8e3f 100644 --- a/conformance/tests/backendtlspolicy.yaml +++ b/conformance/tests/backendtlspolicy.yaml @@ -1,37 +1,4 @@ apiVersion: gateway.networking.k8s.io/v1 -kind: Gateway -metadata: - name: gateway-backendtlspolicy - namespace: gateway-conformance-infra -spec: - gatewayClassName: "{GATEWAY_CLASS_NAME}" - listeners: - - name: http - port: 80 - protocol: HTTP - hostname: "abc.example.com" - allowedRoutes: - namespaces: - from: Same - kinds: - - kind: HTTPRoute - - name: https - port: 443 - protocol: HTTPS - tls: - mode: Terminate - certificateRefs: - - group: "" - kind: Secret - name: tls-checks-certificate - hostname: "abc.example.com" - allowedRoutes: - namespaces: - from: Same - kinds: - - kind: HTTPRoute ---- -apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: gateway-conformance-infra-test diff --git a/conformance/utils/kubernetes/certificate.go b/conformance/utils/kubernetes/certificate.go index 07c3c80787..1b2ee3af85 100644 --- a/conformance/utils/kubernetes/certificate.go +++ b/conformance/utils/kubernetes/certificate.go @@ -27,6 +27,7 @@ import ( "io" "math/big" "net" + "net/url" "strings" "testing" "time" @@ -119,6 +120,8 @@ func generateRSACert(hosts []string, keyOut, certOut io.Writer, ca *x509.Certifi template.IPAddresses = append(template.IPAddresses, ip) } else if err = validateHost(h); err == nil { template.DNSNames = append(template.DNSNames, h) + } else if u, parseErr := url.Parse(h); parseErr == nil { + template.URIs = append(template.URIs, u) } } @@ -215,6 +218,8 @@ func generateCACert(hosts []string) (*x509.Certificate, []byte, *rsa.PrivateKey, ca.IPAddresses = append(ca.IPAddresses, ip) } else if err := validateHost(h); err == nil { ca.DNSNames = append(ca.DNSNames, h) + } else if u, err := url.Parse(h); err == nil { + ca.URIs = append(ca.URIs, u) } } diff --git a/conformance/utils/kubernetes/helpers.go b/conformance/utils/kubernetes/helpers.go index ea9b8af63f..3309c8f29b 100644 --- a/conformance/utils/kubernetes/helpers.go +++ b/conformance/utils/kubernetes/helpers.go @@ -1003,7 +1003,7 @@ func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeo policy := &v1alpha3.BackendTLSPolicy{} err := client.Get(ctx, policyNN, policy) if err != nil { - return false, fmt.Errorf("error fetching BackendTLSPolicy: %w", err) + return false, fmt.Errorf("error fetching BackendTLSPolicy %v err: %w", policyNN, err) } for _, parent := range policy.Status.Ancestors { @@ -1024,7 +1024,7 @@ func BackendTLSPolicyMustHaveCondition(t *testing.T, client client.Client, timeo return false, nil }) - require.NoErrorf(t, waitErr, "error waiting for BackendTLSPolicy status to have a Condition %v", condition) + require.NoErrorf(t, waitErr, "error waiting for BackendTLSPolicy %v status to have a Condition %v", policyNN, condition) } // BackendTLSPolicyMustHaveLatestConditions will fail the test if there are diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 23c936536a..877c030f3c 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -394,6 +394,11 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) + // TODO(kl52752) Merge CA certificates for Backend TLS Policy and move Deployment to common file. + caConfigMap, ca, caPrivKey = kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-with-san-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}) + suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) + secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-with-san-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}, ca, caPrivKey) + suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) tlog.Logf(t, "Test Setup: Ensuring Gateways and Pods from base manifests are ready") namespaces := []string{ diff --git a/pkg/features/backendtlspolicy.go b/pkg/features/backendtlspolicy.go index 95d5017164..12c6a24ccc 100644 --- a/pkg/features/backendtlspolicy.go +++ b/pkg/features/backendtlspolicy.go @@ -25,6 +25,9 @@ import "k8s.io/apimachinery/pkg/util/sets" const ( // This option indicates support for BackendTLSPolicy. SupportBackendTLSPolicy FeatureName = "BackendTLSPolicy" + + // This option indicates support for BackendTLSPolicy SubjectAltName Validation. + SupportBackendTLSPolicySANValidation FeatureName = "BackendTLSPolicySANValidation" ) // TLSRouteFeature contains metadata for the TLSRoute feature. @@ -33,8 +36,21 @@ var BackendTLSPolicyFeature = Feature{ Channel: FeatureChannelExperimental, } +// BackendTLSPolicySanValidationFeature contains metadata for the BackendTLSPolicy +// SubjectAltName Validation feature. +var BackendTLSPolicySanValidationFeature = Feature{ + Name: SupportBackendTLSPolicySANValidation, + Channel: FeatureChannelExperimental, +} + // BackendTLSPolicyCoreFeatures includes all the supported features for the // BackendTLSPolicy API at a Core level of support. var BackendTLSPolicyCoreFeatures = sets.New( BackendTLSPolicyFeature, ) + +// BackendTLSPolicyExtendedFeatures includes all the supported features for the +// BackendTLSPolicy API at a Extended level of support. +var BackendTLSPolicyExtendedFeatures = sets.New( + BackendTLSPolicySanValidationFeature, +) From 0eb555076f79d4f9ecef47fb1aa5f45f747fc2cc Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Thu, 28 Aug 2025 01:53:17 +0200 Subject: [PATCH 147/224] Move BackendTLS configuration to GatewayTLSConfig (#4009) * Move BackendTLS configuration to GatewayTLSConfig * review --- apis/v1/gateway_types.go | 44 +- apis/v1/zz_generated.deepcopy.go | 50 +- .../apis/v1/frontendtlsconfig.go | 53 + applyconfiguration/apis/v1/gatewayspec.go | 9 - .../apis/v1/gatewaytlsconfig.go | 27 +- applyconfiguration/apis/v1/tlsconfig.go | 10 +- applyconfiguration/internal/internal.go | 35 +- applyconfiguration/utils.go | 2 + .../gateway.networking.k8s.io_gateways.yaml | 1286 +++++++++-------- examples/experimental/backend-tls.yaml | 18 + .../frontend-cert-validation.yaml | 31 +- geps/gep-3155/index.md | 17 +- pkg/generated/openapi/zz_generated.openapi.go | 98 +- 13 files changed, 918 insertions(+), 762 deletions(-) create mode 100644 applyconfiguration/apis/v1/frontendtlsconfig.go create mode 100644 examples/experimental/backend-tls.yaml diff --git a/apis/v1/gateway_types.go b/apis/v1/gateway_types.go index e85e81ba48..652101ff76 100644 --- a/apis/v1/gateway_types.go +++ b/apis/v1/gateway_types.go @@ -279,15 +279,6 @@ type GatewaySpec struct { // +optional Infrastructure *GatewayInfrastructure `json:"infrastructure,omitempty"` - // BackendTLS configures TLS settings for when this Gateway is connecting to - // backends with TLS. - // - // Support: Core - // - // +optional - // - BackendTLS *GatewayBackendTLS `json:"backendTLS,omitempty"` - // AllowedListeners defines which ListenerSets can be attached to this Gateway. // While this feature is experimental, the default value is to allow no ListenerSets. // @@ -296,7 +287,7 @@ type GatewaySpec struct { // +optional AllowedListeners *AllowedListeners `json:"allowedListeners,omitempty"` // - // GatewayTLSConfig specifies frontend tls configuration for gateway. + // TLS specifies frontend and backend tls configuration for entire gateway. // // Support: Extended // @@ -525,8 +516,6 @@ type GatewayBackendTLS struct { // ClientCertificateRef can reference to standard Kubernetes resources, i.e. // Secret, or implementation-specific custom resources. // - // This setting can be overridden on the service level by use of BackendTLSPolicy. - // // Support: Core // // +optional @@ -602,8 +591,31 @@ type ListenerTLSConfig struct { Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` } -// GatewayTLSConfig specifies frontend tls configuration for gateway. +// GatewayTLSConfig specifies frontend and backend tls configuration for gateway. type GatewayTLSConfig struct { + // Backend describes TLS configuration for gateway when connecting + // to backends. + // + // Note that this contains only details for the Gateway as a TLS client, + // and does _not_ imply behavior about how to choose which backend should + // get a TLS connection. That is determined by the presence of a BackendTLSPolicy. + // + // Support: Core + // + // +optional + // + Backend *GatewayBackendTLS `json:"backend,omitempty"` + + // Frontend describes TLS config when client connects to Gateway. + // Support: Core + // + // +optional + // + Frontend *FrontendTLSConfig `json:"frontend,omitempty"` +} + +// FrontendTLSConfig specifies frontend tls configuration for gateway. +type FrontendTLSConfig struct { // Default specifies the default client certificate validation configuration // for all Listeners handling HTTPS traffic, unless a per-port configuration // is defined. @@ -653,7 +665,7 @@ const ( // within this Gateway. Currently, it stores only the client certificate validation // configuration, but this may be extended in the future. type TLSConfig struct { - // FrontendValidation holds configuration information for validating the frontend (client). + // Validation holds configuration information for validating the frontend (client). // Setting this field will result in mutual authentication when connecting to the gateway. // In browsers this may result in a dialog appearing // that requests a user to specify the client certificate. @@ -661,9 +673,9 @@ type TLSConfig struct { // // Support: Core // - // +required + // +optional // - FrontendValidation FrontendTLSValidation `json:"frontendValidation"` + Validation *FrontendTLSValidation `json:"validation,omitempty"` } type TLSPortConfig struct { diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index 6bbf75ba62..bcbf489072 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -205,6 +205,29 @@ func (in *Fraction) DeepCopy() *Fraction { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FrontendTLSConfig) DeepCopyInto(out *FrontendTLSConfig) { + *out = *in + in.Default.DeepCopyInto(&out.Default) + if in.PerPort != nil { + in, out := &in.PerPort, &out.PerPort + *out = make([]TLSPortConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FrontendTLSConfig. +func (in *FrontendTLSConfig) DeepCopy() *FrontendTLSConfig { + if in == nil { + return nil + } + out := new(FrontendTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FrontendTLSValidation) DeepCopyInto(out *FrontendTLSValidation) { *out = *in @@ -777,11 +800,6 @@ func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { *out = new(GatewayInfrastructure) (*in).DeepCopyInto(*out) } - if in.BackendTLS != nil { - in, out := &in.BackendTLS, &out.BackendTLS - *out = new(GatewayBackendTLS) - (*in).DeepCopyInto(*out) - } if in.AllowedListeners != nil { in, out := &in.AllowedListeners, &out.AllowedListeners *out = new(AllowedListeners) @@ -883,13 +901,15 @@ func (in *GatewayStatusAddress) DeepCopy() *GatewayStatusAddress { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { *out = *in - in.Default.DeepCopyInto(&out.Default) - if in.PerPort != nil { - in, out := &in.PerPort, &out.PerPort - *out = make([]TLSPortConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + if in.Backend != nil { + in, out := &in.Backend, &out.Backend + *out = new(GatewayBackendTLS) + (*in).DeepCopyInto(*out) + } + if in.Frontend != nil { + in, out := &in.Frontend, &out.Frontend + *out = new(FrontendTLSConfig) + (*in).DeepCopyInto(*out) } } @@ -1962,7 +1982,11 @@ func (in *SupportedFeature) DeepCopy() *SupportedFeature { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { *out = *in - in.FrontendValidation.DeepCopyInto(&out.FrontendValidation) + if in.Validation != nil { + in, out := &in.Validation, &out.Validation + *out = new(FrontendTLSValidation) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig. diff --git a/applyconfiguration/apis/v1/frontendtlsconfig.go b/applyconfiguration/apis/v1/frontendtlsconfig.go new file mode 100644 index 0000000000..4cf8464927 --- /dev/null +++ b/applyconfiguration/apis/v1/frontendtlsconfig.go @@ -0,0 +1,53 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1 + +// FrontendTLSConfigApplyConfiguration represents a declarative configuration of the FrontendTLSConfig type for use +// with apply. +type FrontendTLSConfigApplyConfiguration struct { + Default *TLSConfigApplyConfiguration `json:"default,omitempty"` + PerPort []TLSPortConfigApplyConfiguration `json:"perPort,omitempty"` +} + +// FrontendTLSConfigApplyConfiguration constructs a declarative configuration of the FrontendTLSConfig type for use with +// apply. +func FrontendTLSConfig() *FrontendTLSConfigApplyConfiguration { + return &FrontendTLSConfigApplyConfiguration{} +} + +// WithDefault sets the Default field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Default field is set to the value of the last call. +func (b *FrontendTLSConfigApplyConfiguration) WithDefault(value *TLSConfigApplyConfiguration) *FrontendTLSConfigApplyConfiguration { + b.Default = value + return b +} + +// WithPerPort adds the given value to the PerPort field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the PerPort field. +func (b *FrontendTLSConfigApplyConfiguration) WithPerPort(values ...*TLSPortConfigApplyConfiguration) *FrontendTLSConfigApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithPerPort") + } + b.PerPort = append(b.PerPort, *values[i]) + } + return b +} diff --git a/applyconfiguration/apis/v1/gatewayspec.go b/applyconfiguration/apis/v1/gatewayspec.go index b123a40f9c..e976dc4827 100644 --- a/applyconfiguration/apis/v1/gatewayspec.go +++ b/applyconfiguration/apis/v1/gatewayspec.go @@ -29,7 +29,6 @@ type GatewaySpecApplyConfiguration struct { Listeners []ListenerApplyConfiguration `json:"listeners,omitempty"` Addresses []GatewaySpecAddressApplyConfiguration `json:"addresses,omitempty"` Infrastructure *GatewayInfrastructureApplyConfiguration `json:"infrastructure,omitempty"` - BackendTLS *GatewayBackendTLSApplyConfiguration `json:"backendTLS,omitempty"` AllowedListeners *AllowedListenersApplyConfiguration `json:"allowedListeners,omitempty"` TLS *GatewayTLSConfigApplyConfiguration `json:"tls,omitempty"` } @@ -82,14 +81,6 @@ func (b *GatewaySpecApplyConfiguration) WithInfrastructure(value *GatewayInfrast return b } -// WithBackendTLS sets the BackendTLS field in the declarative configuration to the given value -// and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the BackendTLS field is set to the value of the last call. -func (b *GatewaySpecApplyConfiguration) WithBackendTLS(value *GatewayBackendTLSApplyConfiguration) *GatewaySpecApplyConfiguration { - b.BackendTLS = value - return b -} - // WithAllowedListeners sets the AllowedListeners field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the AllowedListeners field is set to the value of the last call. diff --git a/applyconfiguration/apis/v1/gatewaytlsconfig.go b/applyconfiguration/apis/v1/gatewaytlsconfig.go index dbd3f443b1..4ec825dbee 100644 --- a/applyconfiguration/apis/v1/gatewaytlsconfig.go +++ b/applyconfiguration/apis/v1/gatewaytlsconfig.go @@ -21,8 +21,8 @@ package v1 // GatewayTLSConfigApplyConfiguration represents a declarative configuration of the GatewayTLSConfig type for use // with apply. type GatewayTLSConfigApplyConfiguration struct { - Default *TLSConfigApplyConfiguration `json:"default,omitempty"` - PerPort []TLSPortConfigApplyConfiguration `json:"perPort,omitempty"` + Backend *GatewayBackendTLSApplyConfiguration `json:"backend,omitempty"` + Frontend *FrontendTLSConfigApplyConfiguration `json:"frontend,omitempty"` } // GatewayTLSConfigApplyConfiguration constructs a declarative configuration of the GatewayTLSConfig type for use with @@ -31,23 +31,18 @@ func GatewayTLSConfig() *GatewayTLSConfigApplyConfiguration { return &GatewayTLSConfigApplyConfiguration{} } -// WithDefault sets the Default field in the declarative configuration to the given value +// WithBackend sets the Backend field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the Default field is set to the value of the last call. -func (b *GatewayTLSConfigApplyConfiguration) WithDefault(value *TLSConfigApplyConfiguration) *GatewayTLSConfigApplyConfiguration { - b.Default = value +// If called multiple times, the Backend field is set to the value of the last call. +func (b *GatewayTLSConfigApplyConfiguration) WithBackend(value *GatewayBackendTLSApplyConfiguration) *GatewayTLSConfigApplyConfiguration { + b.Backend = value return b } -// WithPerPort adds the given value to the PerPort field in the declarative configuration -// and returns the receiver, so that objects can be build by chaining "With" function invocations. -// If called multiple times, values provided by each call will be appended to the PerPort field. -func (b *GatewayTLSConfigApplyConfiguration) WithPerPort(values ...*TLSPortConfigApplyConfiguration) *GatewayTLSConfigApplyConfiguration { - for i := range values { - if values[i] == nil { - panic("nil value passed to WithPerPort") - } - b.PerPort = append(b.PerPort, *values[i]) - } +// WithFrontend sets the Frontend field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Frontend field is set to the value of the last call. +func (b *GatewayTLSConfigApplyConfiguration) WithFrontend(value *FrontendTLSConfigApplyConfiguration) *GatewayTLSConfigApplyConfiguration { + b.Frontend = value return b } diff --git a/applyconfiguration/apis/v1/tlsconfig.go b/applyconfiguration/apis/v1/tlsconfig.go index 1dfa5e024e..99a42ca482 100644 --- a/applyconfiguration/apis/v1/tlsconfig.go +++ b/applyconfiguration/apis/v1/tlsconfig.go @@ -21,7 +21,7 @@ package v1 // TLSConfigApplyConfiguration represents a declarative configuration of the TLSConfig type for use // with apply. type TLSConfigApplyConfiguration struct { - FrontendValidation *FrontendTLSValidationApplyConfiguration `json:"frontendValidation,omitempty"` + Validation *FrontendTLSValidationApplyConfiguration `json:"validation,omitempty"` } // TLSConfigApplyConfiguration constructs a declarative configuration of the TLSConfig type for use with @@ -30,10 +30,10 @@ func TLSConfig() *TLSConfigApplyConfiguration { return &TLSConfigApplyConfiguration{} } -// WithFrontendValidation sets the FrontendValidation field in the declarative configuration to the given value +// WithValidation sets the Validation field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the FrontendValidation field is set to the value of the last call. -func (b *TLSConfigApplyConfiguration) WithFrontendValidation(value *FrontendTLSValidationApplyConfiguration) *TLSConfigApplyConfiguration { - b.FrontendValidation = value +// If called multiple times, the Validation field is set to the value of the last call. +func (b *TLSConfigApplyConfiguration) WithValidation(value *FrontendTLSValidationApplyConfiguration) *TLSConfigApplyConfiguration { + b.Validation = value return b } diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 953f2863cd..974c4bd20f 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -304,6 +304,21 @@ var schemaYAML = typed.YAMLObject(`types: type: scalar: numeric default: 0 +- name: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSConfig + map: + fields: + - name: default + type: + namedType: io.k8s.sigs.gateway-api.apis.v1.TLSConfig + default: {} + - name: perPort + type: + list: + elementType: + namedType: io.k8s.sigs.gateway-api.apis.v1.TLSPortConfig + elementRelationship: associative + keys: + - port - name: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSValidation map: fields: @@ -598,9 +613,6 @@ var schemaYAML = typed.YAMLObject(`types: - name: allowedListeners type: namedType: io.k8s.sigs.gateway-api.apis.v1.AllowedListeners - - name: backendTLS - type: - namedType: io.k8s.sigs.gateway-api.apis.v1.GatewayBackendTLS - name: gatewayClassName type: scalar: string @@ -666,18 +678,12 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.sigs.gateway-api.apis.v1.GatewayTLSConfig map: fields: - - name: default + - name: backend type: - namedType: io.k8s.sigs.gateway-api.apis.v1.TLSConfig - default: {} - - name: perPort + namedType: io.k8s.sigs.gateway-api.apis.v1.GatewayBackendTLS + - name: frontend type: - list: - elementType: - namedType: io.k8s.sigs.gateway-api.apis.v1.TLSPortConfig - elementRelationship: associative - keys: - - port + namedType: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSConfig - name: io.k8s.sigs.gateway-api.apis.v1.HTTPAuthConfig map: fields: @@ -1311,10 +1317,9 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.sigs.gateway-api.apis.v1.TLSConfig map: fields: - - name: frontendValidation + - name: validation type: namedType: io.k8s.sigs.gateway-api.apis.v1.FrontendTLSValidation - default: {} - name: io.k8s.sigs.gateway-api.apis.v1.TLSPortConfig map: fields: diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 5acafbc2c1..274736cd6c 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -56,6 +56,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apisv1.ForwardBodyConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("Fraction"): return &apisv1.FractionApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("FrontendTLSConfig"): + return &apisv1.FrontendTLSConfigApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("FrontendTLSValidation"): return &apisv1.FrontendTLSValidationApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("Gateway"): diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index f04f7b978a..6e154e9548 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -215,70 +215,6 @@ spec: x-kubernetes-map-type: atomic type: object type: object - backendTLS: - description: |- - BackendTLS configures TLS settings for when this Gateway is connecting to - backends with TLS. - - Support: Core - properties: - clientCertificateRef: - description: |- - ClientCertificateRef is a reference to an object that contains a Client - Certificate and the associated private key. - - References to a resource in different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - - ClientCertificateRef can reference to standard Kubernetes resources, i.e. - Secret, or implementation-specific custom resources. - - This setting can be overridden on the service level by use of BackendTLSPolicy. - - Support: Core - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Secret - description: Kind is kind of the referent. For example "Secret". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: object gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -970,294 +906,363 @@ spec: == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' tls: description: |- - GatewayTLSConfig specifies frontend tls configuration for gateway. + TLS specifies frontend and backend tls configuration for entire gateway. Support: Extended properties: - default: + backend: description: |- - Default specifies the default client certificate validation configuration - for all Listeners handling HTTPS traffic, unless a per-port configuration - is defined. + Backend describes TLS configuration for gateway when connecting + to backends. - support: Core + Note that this contains only details for the Gateway as a TLS client, + and does _not_ imply behavior about how to choose which backend should + get a TLS connection. That is determined by the presence of a BackendTLSPolicy. + + Support: Core properties: - frontendValidation: + clientCertificateRef: description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will result in mutual authentication when connecting to the gateway. - In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. + ClientCertificateRef is a reference to an object that contains a Client + Certificate and the associated private key. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + ClientCertificateRef can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. Support: Core properties: - caCertificateRefs: + group: + default: "" description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one certificate in a ConfigMap - with different keys or more than one reference, or other kinds of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example - "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - mode: - default: AllowValidOnly + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: description: |- - FrontendValidationMode defines the mode for validating the client certificate. - There are two possible modes: - - - AllowValidOnly: In this mode, the gateway will accept connections only if - the client presents a valid certificate. This certificate must successfully - pass validation against the CA certificates specified in `CACertificateRefs`. - - AllowInsecureFallback: In this mode, the gateway will accept connections - even if the client certificate is not presented or fails verification. + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. - This approach delegates client authorization to the backend and introduce - a significant security risk. It should be used in testing environments or - on a temporary basis in non-testing environments. - - Defaults to AllowValidOnly. + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. Support: Core - enum: - - AllowValidOnly - - AllowInsecureFallback + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - - caCertificateRefs + - name type: object - required: - - frontendValidation type: object - perPort: + frontend: description: |- - PerPort specifies tls configuration assigned per port. - Per port configuration is optional. Once set this configuration overrides - the default configuration for all Listeners handling HTTPS traffic - that match this port. - Each override port requires a unique TLS configuration. - - support: Core - items: - properties: - port: - description: |- - The Port indicates the Port Number to which the TLS configuration will be - applied. This configuration will be applied to all Listeners handling HTTPS - traffic that match this port. - - Support: Core - format: int32 - maximum: 65535 - minimum: 1 - type: integer - tls: - description: |- - TLS store the configuration that will be applied to all Listeners handling - HTTPS traffic and matching given port. + Frontend describes TLS config when client connects to Gateway. + Support: Core + properties: + default: + description: |- + Default specifies the default client certificate validation configuration + for all Listeners handling HTTPS traffic, unless a per-port configuration + is defined. - Support: Core - properties: - frontendValidation: - description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will result in mutual authentication when connecting to the gateway. - In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. + support: Core + properties: + validation: + description: |- + Validation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. - Support: Core - properties: - caCertificateRefs: + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one certificate in a ConfigMap - with different keys or more than one reference, or other kinds of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. - For example "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - mode: - default: AllowValidOnly - description: |- - FrontendValidationMode defines the mode for validating the client certificate. - There are two possible modes: + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. - - AllowValidOnly: In this mode, the gateway will accept connections only if - the client presents a valid certificate. This certificate must successfully - pass validation against the CA certificates specified in `CACertificateRefs`. - - AllowInsecureFallback: In this mode, the gateway will accept connections - even if the client certificate is not presented or fails verification. + Defaults to AllowValidOnly. - This approach delegates client authorization to the backend and introduce - a significant security risk. It should be used in testing environments or - on a temporary basis in non-testing environments. + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + type: object + perPort: + description: |- + PerPort specifies tls configuration assigned per port. + Per port configuration is optional. Once set this configuration overrides + the default configuration for all Listeners handling HTTPS traffic + that match this port. + Each override port requires a unique TLS configuration. + + support: Core + items: + properties: + port: + description: |- + The Port indicates the Port Number to which the TLS configuration will be + applied. This configuration will be applied to all Listeners handling HTTPS + traffic that match this port. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + tls: + description: |- + TLS store the configuration that will be applied to all Listeners handling + HTTPS traffic and matching given port. - Defaults to AllowValidOnly. + Support: Core + properties: + validation: + description: |- + Validation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. Support: Core - enum: - - AllowValidOnly - - AllowInsecureFallback - type: string - required: - - caCertificateRefs + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + For example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object type: object required: - - frontendValidation + - port + - tls type: object - required: - - port - - tls - type: object - maxItems: 64 - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - x-kubernetes-validations: - - message: Port for TLS configuration must be unique within the - Gateway - rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) - required: - - default + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: Port for TLS configuration must be unique within + the Gateway + rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) + required: + - default + type: object type: object required: - gatewayClassName @@ -1762,70 +1767,6 @@ spec: x-kubernetes-map-type: atomic type: object type: object - backendTLS: - description: |- - BackendTLS configures TLS settings for when this Gateway is connecting to - backends with TLS. - - Support: Core - properties: - clientCertificateRef: - description: |- - ClientCertificateRef is a reference to an object that contains a Client - Certificate and the associated private key. - - References to a resource in different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - - ClientCertificateRef can reference to standard Kubernetes resources, i.e. - Secret, or implementation-specific custom resources. - - This setting can be overridden on the service level by use of BackendTLSPolicy. - - Support: Core - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Secret - description: Kind is kind of the referent. For example "Secret". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - name - type: object - type: object gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a @@ -2517,294 +2458,363 @@ spec: == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' tls: description: |- - GatewayTLSConfig specifies frontend tls configuration for gateway. + TLS specifies frontend and backend tls configuration for entire gateway. Support: Extended properties: - default: + backend: description: |- - Default specifies the default client certificate validation configuration - for all Listeners handling HTTPS traffic, unless a per-port configuration - is defined. + Backend describes TLS configuration for gateway when connecting + to backends. - support: Core + Note that this contains only details for the Gateway as a TLS client, + and does _not_ imply behavior about how to choose which backend should + get a TLS connection. That is determined by the presence of a BackendTLSPolicy. + + Support: Core properties: - frontendValidation: + clientCertificateRef: description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will result in mutual authentication when connecting to the gateway. - In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. + ClientCertificateRef is a reference to an object that contains a Client + Certificate and the associated private key. + + References to a resource in different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + + ClientCertificateRef can reference to standard Kubernetes resources, i.e. + Secret, or implementation-specific custom resources. Support: Core properties: - caCertificateRefs: + group: + default: "" description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one certificate in a ConfigMap - with different keys or more than one reference, or other kinds of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example - "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - mode: - default: AllowValidOnly + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: description: |- - FrontendValidationMode defines the mode for validating the client certificate. - There are two possible modes: - - - AllowValidOnly: In this mode, the gateway will accept connections only if - the client presents a valid certificate. This certificate must successfully - pass validation against the CA certificates specified in `CACertificateRefs`. - - AllowInsecureFallback: In this mode, the gateway will accept connections - even if the client certificate is not presented or fails verification. + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. - This approach delegates client authorization to the backend and introduce - a significant security risk. It should be used in testing environments or - on a temporary basis in non-testing environments. - - Defaults to AllowValidOnly. + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. Support: Core - enum: - - AllowValidOnly - - AllowInsecureFallback + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - - caCertificateRefs + - name type: object - required: - - frontendValidation type: object - perPort: + frontend: description: |- - PerPort specifies tls configuration assigned per port. - Per port configuration is optional. Once set this configuration overrides - the default configuration for all Listeners handling HTTPS traffic - that match this port. - Each override port requires a unique TLS configuration. - - support: Core - items: - properties: - port: - description: |- - The Port indicates the Port Number to which the TLS configuration will be - applied. This configuration will be applied to all Listeners handling HTTPS - traffic that match this port. - - Support: Core - format: int32 - maximum: 65535 - minimum: 1 - type: integer - tls: - description: |- - TLS store the configuration that will be applied to all Listeners handling - HTTPS traffic and matching given port. + Frontend describes TLS config when client connects to Gateway. + Support: Core + properties: + default: + description: |- + Default specifies the default client certificate validation configuration + for all Listeners handling HTTPS traffic, unless a per-port configuration + is defined. - Support: Core - properties: - frontendValidation: - description: |- - FrontendValidation holds configuration information for validating the frontend (client). - Setting this field will result in mutual authentication when connecting to the gateway. - In browsers this may result in a dialog appearing - that requests a user to specify the client certificate. - The maximum depth of a certificate chain accepted in verification is Implementation specific. + support: Core + properties: + validation: + description: |- + Validation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. - Support: Core - properties: - caCertificateRefs: + Support: Core + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: description: |- - CACertificateRefs contains one or more references to - Kubernetes objects that contain TLS certificates of - the Certificate Authorities that can be used - as a trust anchor to validate the certificates presented by the client. - - A single CA certificate reference to a Kubernetes ConfigMap - has "Core" support. - Implementations MAY choose to support attaching multiple CA certificates to - a Listener, but this behavior is implementation-specific. - - Support: Core - A single reference to a Kubernetes ConfigMap - with the CA certificate in a key named `ca.crt`. - - Support: Implementation-specific (More than one certificate in a ConfigMap - with different keys or more than one reference, or other kinds of resources). - - References to a resource in a different namespace are invalid UNLESS there - is a ReferenceGrant in the target namespace that allows the certificate - to be attached. If a ReferenceGrant does not allow this reference, the - "ResolvedRefs" condition MUST be set to False for this listener with the - "RefNotPermitted" reason. - items: - description: |- - ObjectReference identifies an API object including its namespace. + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. - References to objects with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate Conditions set - on the containing object. - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When set to the empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. - For example "ConfigMap" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referenced object. When unspecified, the local - namespace is inferred. - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-type: atomic - mode: - default: AllowValidOnly - description: |- - FrontendValidationMode defines the mode for validating the client certificate. - There are two possible modes: + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. - - AllowValidOnly: In this mode, the gateway will accept connections only if - the client presents a valid certificate. This certificate must successfully - pass validation against the CA certificates specified in `CACertificateRefs`. - - AllowInsecureFallback: In this mode, the gateway will accept connections - even if the client certificate is not presented or fails verification. + Defaults to AllowValidOnly. - This approach delegates client authorization to the backend and introduce - a significant security risk. It should be used in testing environments or - on a temporary basis in non-testing environments. + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object + type: object + perPort: + description: |- + PerPort specifies tls configuration assigned per port. + Per port configuration is optional. Once set this configuration overrides + the default configuration for all Listeners handling HTTPS traffic + that match this port. + Each override port requires a unique TLS configuration. + + support: Core + items: + properties: + port: + description: |- + The Port indicates the Port Number to which the TLS configuration will be + applied. This configuration will be applied to all Listeners handling HTTPS + traffic that match this port. + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + tls: + description: |- + TLS store the configuration that will be applied to all Listeners handling + HTTPS traffic and matching given port. - Defaults to AllowValidOnly. + Support: Core + properties: + validation: + description: |- + Validation holds configuration information for validating the frontend (client). + Setting this field will result in mutual authentication when connecting to the gateway. + In browsers this may result in a dialog appearing + that requests a user to specify the client certificate. + The maximum depth of a certificate chain accepted in verification is Implementation specific. Support: Core - enum: - - AllowValidOnly - - AllowInsecureFallback - type: string - required: - - caCertificateRefs + properties: + caCertificateRefs: + description: |- + CACertificateRefs contains one or more references to + Kubernetes objects that contain TLS certificates of + the Certificate Authorities that can be used + as a trust anchor to validate the certificates presented by the client. + + A single CA certificate reference to a Kubernetes ConfigMap + has "Core" support. + Implementations MAY choose to support attaching multiple CA certificates to + a Listener, but this behavior is implementation-specific. + + Support: Core - A single reference to a Kubernetes ConfigMap + with the CA certificate in a key named `ca.crt`. + + Support: Implementation-specific (More than one certificate in a ConfigMap + with different keys or more than one reference, or other kinds of resources). + + References to a resource in a different namespace are invalid UNLESS there + is a ReferenceGrant in the target namespace that allows the certificate + to be attached. If a ReferenceGrant does not allow this reference, the + "ResolvedRefs" condition MUST be set to False for this listener with the + "RefNotPermitted" reason. + items: + description: |- + ObjectReference identifies an API object including its namespace. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + + References to objects with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate Conditions set + on the containing object. + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When set to the empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + For example "ConfigMap" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + mode: + default: AllowValidOnly + description: |- + FrontendValidationMode defines the mode for validating the client certificate. + There are two possible modes: + + - AllowValidOnly: In this mode, the gateway will accept connections only if + the client presents a valid certificate. This certificate must successfully + pass validation against the CA certificates specified in `CACertificateRefs`. + - AllowInsecureFallback: In this mode, the gateway will accept connections + even if the client certificate is not presented or fails verification. + + This approach delegates client authorization to the backend and introduce + a significant security risk. It should be used in testing environments or + on a temporary basis in non-testing environments. + + Defaults to AllowValidOnly. + + Support: Core + enum: + - AllowValidOnly + - AllowInsecureFallback + type: string + required: + - caCertificateRefs + type: object type: object required: - - frontendValidation + - port + - tls type: object - required: - - port - - tls - type: object - maxItems: 64 - type: array - x-kubernetes-list-map-keys: - - port - x-kubernetes-list-type: map - x-kubernetes-validations: - - message: Port for TLS configuration must be unique within the - Gateway - rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) - required: - - default + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - port + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: Port for TLS configuration must be unique within + the Gateway + rule: self.all(t1, self.exists_one(t2, t1.port == t2.port)) + required: + - default + type: object type: object required: - gatewayClassName diff --git a/examples/experimental/backend-tls.yaml b/examples/experimental/backend-tls.yaml new file mode 100644 index 0000000000..94b8be09c7 --- /dev/null +++ b/examples/experimental/backend-tls.yaml @@ -0,0 +1,18 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: backend-tls +spec: + gatewayClassName: acme-lb + tls: + backend: + clientCertificateRef: + kind: Secret + group: "" + name: foo-example-cert + listeners: + - name: foo-https + protocol: HTTP + port: 80 + hostname: foo.example.com +--- diff --git a/examples/experimental/frontend-cert-validation.yaml b/examples/experimental/frontend-cert-validation.yaml index a7a9d4a14d..34ada262b4 100644 --- a/examples/experimental/frontend-cert-validation.yaml +++ b/examples/experimental/frontend-cert-validation.yaml @@ -5,12 +5,22 @@ metadata: spec: gatewayClassName: acme-lb tls: - default: - frontendValidation: - caCertificateRefs: - - kind: ConfigMap - group: "" - name: foo-example-com-ca-cert + frontend: + default: + validation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: foo-example-com-ca-cert + perPort: + - port: 8443 + tls: + validation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: foo-example-com-ca-cert + mode: "AllowInsecureFallback" listeners: - name: foo-https protocol: HTTPS @@ -21,5 +31,14 @@ spec: - kind: Secret group: "" name: foo-example-com-cert + - name: bar-https + protocol: HTTPS + port: 8443 + hostname: bar.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: bar-example-com-cert --- diff --git a/geps/gep-3155/index.md b/geps/gep-3155/index.md index b75b64cccf..41477c2266 100644 --- a/geps/gep-3155/index.md +++ b/geps/gep-3155/index.md @@ -43,13 +43,20 @@ Specifying credentials at the gateway level is the default operation mode, where backends will be presented with a single gateway certificate. Per-service overrides are subject for consideration as the future work. -**1. Add a new `BackendTLS` field at the top level of Gateways** +**1. Add a new `BackendValidation` field at TLSConfig struct located in GatewayTLSConfig.Default field** ```go -type GatewaySpec struct { - // BackendTLS configures TLS settings for when this Gateway is connecting to - // backends with TLS. - BackendTLS GatewayBackendTLS `json:"backendTLS,omitempty"'` +// TLSConfig describes TLS configuration that can apply to multiple Listeners +// within this Gateway. +type TLSConfig struct { + ... + // GatewayBackendTLS describes TLS configuration for gateway when connecting + // to backends. + // Support: Core + // + // +optional + // + BackendValidation *GatewayBackendTLS `json:"backendValidation,omitempty"` } type GatewayBackendTLS struct { // ClientCertificateRef is a reference to an object that contains a Client diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 588319b36e..1451e17d9e 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -90,6 +90,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/gateway-api/apis/v1.CookieConfig": schema_sigsk8sio_gateway_api_apis_v1_CookieConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.ForwardBodyConfig": schema_sigsk8sio_gateway_api_apis_v1_ForwardBodyConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.Fraction": schema_sigsk8sio_gateway_api_apis_v1_Fraction(ref), + "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSConfig": schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation": schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref), "sigs.k8s.io/gateway-api/apis/v1.GRPCAuthConfig": schema_sigsk8sio_gateway_api_apis_v1_GRPCAuthConfig(ref), "sigs.k8s.io/gateway-api/apis/v1.GRPCBackendRef": schema_sigsk8sio_gateway_api_apis_v1_GRPCBackendRef(ref), @@ -3113,6 +3114,51 @@ func schema_sigsk8sio_gateway_api_apis_v1_Fraction(ref common.ReferenceCallback) } } +func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "FrontendTLSConfig specifies frontend tls configuration for gateway.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "default": { + SchemaProps: spec.SchemaProps{ + Description: "Default specifies the default client certificate validation configuration for all Listeners handling HTTPS traffic, unless a per-port configuration is defined.\n\nsupport: Core\n\n", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSConfig"), + }, + }, + "perPort": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "port", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "PerPort specifies tls configuration assigned per port. Per port configuration is optional. Once set this configuration overrides the default configuration for all Listeners handling HTTPS traffic that match this port. Each override port requires a unique TLS configuration.\n\nsupport: Core\n\n", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"), + }, + }, + }, + }, + }, + }, + Required: []string{"default"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/gateway-api/apis/v1.TLSConfig", "sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"}, + } +} + func schema_sigsk8sio_gateway_api_apis_v1_FrontendTLSValidation(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3779,7 +3825,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayBackendTLS(ref common.Reference Properties: map[string]spec.Schema{ "clientCertificateRef": { SchemaProps: spec.SchemaProps{ - Description: "ClientCertificateRef is a reference to an object that contains a Client Certificate and the associated private key.\n\nReferences to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.\n\nClientCertificateRef can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources.\n\nThis setting can be overridden on the service level by use of BackendTLSPolicy.\n\nSupport: Core\n\n", + Description: "ClientCertificateRef is a reference to an object that contains a Client Certificate and the associated private key.\n\nReferences to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason.\n\nClientCertificateRef can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources.\n\nSupport: Core\n\n", Ref: ref("sigs.k8s.io/gateway-api/apis/v1.SecretObjectReference"), }, }, @@ -4149,12 +4195,6 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayInfrastructure"), }, }, - "backendTLS": { - SchemaProps: spec.SchemaProps{ - Description: "BackendTLS configures TLS settings for when this Gateway is connecting to backends with TLS.\n\nSupport: Core\n\n", - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS"), - }, - }, "allowedListeners": { SchemaProps: spec.SchemaProps{ Description: "AllowedListeners defines which ListenerSets can be attached to this Gateway. While this feature is experimental, the default value is to allow no ListenerSets.\n\n", @@ -4163,7 +4203,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, "tls": { SchemaProps: spec.SchemaProps{ - Description: "GatewayTLSConfig specifies frontend tls configuration for gateway.\n\nSupport: Extended\n\n", + Description: "TLS specifies frontend and backend tls configuration for entire gateway.\n\nSupport: Extended\n\n", Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig"), }, }, @@ -4172,7 +4212,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewaySpec(ref common.ReferenceCallba }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.AllowedListeners", "sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS", "sigs.k8s.io/gateway-api/apis/v1.GatewayInfrastructure", "sigs.k8s.io/gateway-api/apis/v1.GatewaySpecAddress", "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig", "sigs.k8s.io/gateway-api/apis/v1.Listener"}, + "sigs.k8s.io/gateway-api/apis/v1.AllowedListeners", "sigs.k8s.io/gateway-api/apis/v1.GatewayInfrastructure", "sigs.k8s.io/gateway-api/apis/v1.GatewaySpecAddress", "sigs.k8s.io/gateway-api/apis/v1.GatewayTLSConfig", "sigs.k8s.io/gateway-api/apis/v1.Listener"}, } } @@ -4314,44 +4354,26 @@ func schema_sigsk8sio_gateway_api_apis_v1_GatewayTLSConfig(ref common.ReferenceC return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "GatewayTLSConfig specifies frontend tls configuration for gateway.", + Description: "GatewayTLSConfig specifies frontend and backend tls configuration for gateway.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "default": { + "backend": { SchemaProps: spec.SchemaProps{ - Description: "Default specifies the default client certificate validation configuration for all Listeners handling HTTPS traffic, unless a per-port configuration is defined.\n\nsupport: Core\n\n", - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSConfig"), + Description: "Backend describes TLS configuration for gateway when connecting to backends.\n\nNote that this contains only details for the Gateway as a TLS client, and does _not_ imply behavior about how to choose which backend should get a TLS connection. That is determined by the presence of a BackendTLSPolicy.\n\nSupport: Core\n\n", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS"), }, }, - "perPort": { - VendorExtensible: spec.VendorExtensible{ - Extensions: spec.Extensions{ - "x-kubernetes-list-map-keys": []interface{}{ - "port", - }, - "x-kubernetes-list-type": "map", - }, - }, + "frontend": { SchemaProps: spec.SchemaProps{ - Description: "PerPort specifies tls configuration assigned per port. Per port configuration is optional. Once set this configuration overrides the default configuration for all Listeners handling HTTPS traffic that match this port. Each override port requires a unique TLS configuration.\n\nsupport: Core\n\n", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"), - }, - }, - }, + Description: "Frontend describes TLS config when client connects to Gateway. Support: Core\n\n", + Ref: ref("sigs.k8s.io/gateway-api/apis/v1.FrontendTLSConfig"), }, }, }, - Required: []string{"default"}, }, }, Dependencies: []string{ - "sigs.k8s.io/gateway-api/apis/v1.TLSConfig", "sigs.k8s.io/gateway-api/apis/v1.TLSPortConfig"}, + "sigs.k8s.io/gateway-api/apis/v1.FrontendTLSConfig", "sigs.k8s.io/gateway-api/apis/v1.GatewayBackendTLS"}, } } @@ -6230,15 +6252,13 @@ func schema_sigsk8sio_gateway_api_apis_v1_TLSConfig(ref common.ReferenceCallback Description: "TLSConfig describes TLS configuration that can apply to multiple Listeners within this Gateway. Currently, it stores only the client certificate validation configuration, but this may be extended in the future.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "frontendValidation": { + "validation": { SchemaProps: spec.SchemaProps{ - Description: "FrontendValidation holds configuration information for validating the frontend (client). Setting this field will result in mutual authentication when connecting to the gateway. In browsers this may result in a dialog appearing that requests a user to specify the client certificate. The maximum depth of a certificate chain accepted in verification is Implementation specific.\n\nSupport: Core\n\n", - Default: map[string]interface{}{}, + Description: "Validation holds configuration information for validating the frontend (client). Setting this field will result in mutual authentication when connecting to the gateway. In browsers this may result in a dialog appearing that requests a user to specify the client certificate. The maximum depth of a certificate chain accepted in verification is Implementation specific.\n\nSupport: Core\n\n", Ref: ref("sigs.k8s.io/gateway-api/apis/v1.FrontendTLSValidation"), }, }, }, - Required: []string{"frontendValidation"}, }, }, Dependencies: []string{ From 45326b1e90a24f54d9cd0b5938f925d6dddc0609 Mon Sep 17 00:00:00 2001 From: Roman Willi Date: Thu, 28 Aug 2025 02:11:11 +0200 Subject: [PATCH 148/224] conformance: Add Airlock Microgateway 4.7 reports for v1.3.0 (#4035) * conformance: Add Airlock Microgateway 4.7 report for v1.3.0 * conformance: Regenerate conformance tables --- .../v1.1.0/airlock-microgateway/README.md | 15 ++--- .../standard-4.7.0-default-report.yaml | 47 ++++++++++++++++ .../v1.1.1/airlock-microgateway/README.md | 9 +-- .../standard-4.7.0-default-report.yaml | 47 ++++++++++++++++ .../v1.2.0/airlock-microgateway/README.md | 9 +-- .../standard-4.7.0-default-report.yaml | 53 ++++++++++++++++++ .../v1.2.1/airlock-microgateway/README.md | 11 ++-- .../standard-4.7.0-default-report.yaml | 53 ++++++++++++++++++ .../v1.3.0/airlock-microgateway/README.md | 11 ++-- .../experimental-4.7.0-default-report.yaml | 55 ++++++++++++++++++ site-src/implementations.md | 2 +- site-src/implementations/v1.1.md | 3 +- site-src/implementations/v1.2.md | 56 +++++++++++-------- site-src/implementations/v1.3.md | 54 +++++++++++------- 14 files changed, 354 insertions(+), 71 deletions(-) create mode 100644 conformance/reports/v1.1.0/airlock-microgateway/standard-4.7.0-default-report.yaml create mode 100644 conformance/reports/v1.1.1/airlock-microgateway/standard-4.7.0-default-report.yaml create mode 100644 conformance/reports/v1.2.0/airlock-microgateway/standard-4.7.0-default-report.yaml create mode 100644 conformance/reports/v1.2.1/airlock-microgateway/standard-4.7.0-default-report.yaml create mode 100644 conformance/reports/v1.3.0/airlock-microgateway/experimental-4.7.0-default-report.yaml diff --git a/conformance/reports/v1.1.0/airlock-microgateway/README.md b/conformance/reports/v1.1.0/airlock-microgateway/README.md index a23522a4ad..37084e909e 100644 --- a/conformance/reports/v1.1.0/airlock-microgateway/README.md +++ b/conformance/reports/v1.1.0/airlock-microgateway/README.md @@ -4,19 +4,20 @@ | API channel | Implementation version | Mode | Report | |--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| -| experimental | [v4.4.0](https://github.com/airlock/microgateway/releases/tag/4.4.0) | default | [v4.4.0 report](./experimental-4.4.0-default-report.yaml) | -| standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [v4.5.0 report](./standard-4.5.0-default-report.yaml) | -| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [v4.6.0 report](./standard-4.6.0-default-report.yaml) | +| experimental | [v4.4.0](https://github.com/airlock/microgateway/releases/tag/4.4.0) | default | [link](./experimental-4.4.0-default-report.yaml) | +| standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./standard-4.5.0-default-report.yaml) | +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | +| standard | [v4.7.0](https://github.com/airlock/microgateway/releases/tag/4.7.0) | default | [link](./standard-4.7.0-default-report.yaml) | ## Reproduce -The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/conformance.md) on GitHub. > [!NOTE] > The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. -> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/?topic=MGW-00000056) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. > To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. > > The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. -> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. -> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. diff --git a/conformance/reports/v1.1.0/airlock-microgateway/standard-4.7.0-default-report.yaml b/conformance/reports/v1.1.0/airlock-microgateway/standard-4.7.0-default-report.yaml new file mode 100644 index 0000000000..37091df4ee --- /dev/null +++ b/conformance/reports/v1.1.0/airlock-microgateway/standard-4.7.0-default-report.yaml @@ -0,0 +1,47 @@ +apiVersion: gateway.networking.k8s.io/v1alpha1 +date: "2025-08-25T13:36:52Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.1.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.7.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/conformance/reports/v1.1.1/airlock-microgateway/README.md b/conformance/reports/v1.1.1/airlock-microgateway/README.md index a61abd8398..66143c04c5 100644 --- a/conformance/reports/v1.1.1/airlock-microgateway/README.md +++ b/conformance/reports/v1.1.1/airlock-microgateway/README.md @@ -6,16 +6,17 @@ |-------------|----------------------------------------------------------------------|---------|----------------------------------------------| | standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./standard-4.5.0-default-report.yaml) | | standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | +| standard | [v4.7.0](https://github.com/airlock/microgateway/releases/tag/4.7.0) | default | [link](./standard-4.7.0-default-report.yaml) | ## Reproduce -The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/conformance.md) on GitHub. > [!NOTE] > The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. -> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/?topic=MGW-00000056) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. > To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. > > The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. -> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. -> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. diff --git a/conformance/reports/v1.1.1/airlock-microgateway/standard-4.7.0-default-report.yaml b/conformance/reports/v1.1.1/airlock-microgateway/standard-4.7.0-default-report.yaml new file mode 100644 index 0000000000..3bc63624b0 --- /dev/null +++ b/conformance/reports/v1.1.1/airlock-microgateway/standard-4.7.0-default-report.yaml @@ -0,0 +1,47 @@ +apiVersion: gateway.networking.k8s.io/v1alpha1 +date: "2025-08-25T13:37:05Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.1.1 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.7.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 12 + Skipped: 0 + supportedFeatures: + - GatewayPort8080 + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteBackendTimeout + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestTimeout + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. diff --git a/conformance/reports/v1.2.0/airlock-microgateway/README.md b/conformance/reports/v1.2.0/airlock-microgateway/README.md index a61abd8398..66143c04c5 100644 --- a/conformance/reports/v1.2.0/airlock-microgateway/README.md +++ b/conformance/reports/v1.2.0/airlock-microgateway/README.md @@ -6,16 +6,17 @@ |-------------|----------------------------------------------------------------------|---------|----------------------------------------------| | standard | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./standard-4.5.0-default-report.yaml) | | standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | +| standard | [v4.7.0](https://github.com/airlock/microgateway/releases/tag/4.7.0) | default | [link](./standard-4.7.0-default-report.yaml) | ## Reproduce -The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/conformance.md) on GitHub. > [!NOTE] > The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. -> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/?topic=MGW-00000056) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. > To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. > > The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. -> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. -> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. diff --git a/conformance/reports/v1.2.0/airlock-microgateway/standard-4.7.0-default-report.yaml b/conformance/reports/v1.2.0/airlock-microgateway/standard-4.7.0-default-report.yaml new file mode 100644 index 0000000000..af660c0276 --- /dev/null +++ b/conformance/reports/v1.2.0/airlock-microgateway/standard-4.7.0-default-report.yaml @@ -0,0 +1,53 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-08-25T13:37:00Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.7.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/conformance/reports/v1.2.1/airlock-microgateway/README.md b/conformance/reports/v1.2.1/airlock-microgateway/README.md index 97c52418f9..e6c945bede 100644 --- a/conformance/reports/v1.2.1/airlock-microgateway/README.md +++ b/conformance/reports/v1.2.1/airlock-microgateway/README.md @@ -5,17 +5,18 @@ | API channel | Implementation version | Mode | Report | |--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v4.5.0](https://github.com/airlock/microgateway/releases/tag/4.5.0) | default | [link](./experimental-4.5.0-default-report.yaml) | -| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | +| standard | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./standard-4.6.0-default-report.yaml) | +| standard | [v4.7.0](https://github.com/airlock/microgateway/releases/tag/4.7.0) | default | [link](./standard-4.7.0-default-report.yaml) | ## Reproduce -The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/conformance.md) on GitHub. > [!NOTE] > The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. -> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/?topic=MGW-00000056) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. > To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. > > The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. -> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. -> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. diff --git a/conformance/reports/v1.2.1/airlock-microgateway/standard-4.7.0-default-report.yaml b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.7.0-default-report.yaml new file mode 100644 index 0000000000..53f5311c92 --- /dev/null +++ b/conformance/reports/v1.2.1/airlock-microgateway/standard-4.7.0-default-report.yaml @@ -0,0 +1,53 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-08-25T13:37:50Z" +gatewayAPIChannel: standard +gatewayAPIVersion: v1.2.1 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.7.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/conformance/reports/v1.3.0/airlock-microgateway/README.md b/conformance/reports/v1.3.0/airlock-microgateway/README.md index bae978e399..6270457010 100644 --- a/conformance/reports/v1.3.0/airlock-microgateway/README.md +++ b/conformance/reports/v1.3.0/airlock-microgateway/README.md @@ -5,16 +5,17 @@ | API channel | Implementation version | Mode | Report | |--------------|----------------------------------------------------------------------|---------|--------------------------------------------------| | experimental | [v4.6.0](https://github.com/airlock/microgateway/releases/tag/4.6.0) | default | [link](./experimental-4.6.0-default-report.yaml) | +| experimental | [v4.7.0](https://github.com/airlock/microgateway/releases/tag/4.7.0) | default | [link](./experimental-4.7.0-default-report.yaml) | ## Reproduce -The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/conformance.md) on GitHub. +The Airlock Microgateway conformance report can be reproduced by following the steps in the [Gateway API conformance guide](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/conformance.md) on GitHub. > [!NOTE] > The `HTTPRouteWeight` test fires 10 concurrent request to 3 backends totaling in 500 requests to assert a distribution that matches the configured weight. -> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/#data/1675772882054.html) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. +> Please be aware that this test exceeds the [5 req/sec rate-limit](https://docs.airlock.com/microgateway/latest/?topic=MGW-00000056) enforced in the [community edition](https://www.airlock.com/en/secure-access-hub/components/microgateway/community-edition) , causing the test to fail. > To successfully pass this test a [premium license](https://www.airlock.com/en/secure-access-hub/components/microgateway/premium-edition) is required. -> +> > The Airlock Microgateway drops all request headers except for a well-known built-in standard and tracing headers list (e.g., Accept, Cookie, X-CSRF-TOKEN) to reduce the attack surface. -> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/examples/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. -> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. \ No newline at end of file +> Therefore, to run the conformance tests, a `ContentSecurityPolicy` with a `HeaderRewrites` (see [`conformance-report.yaml`](https://github.com/airlock/microgateway/tree/main/gateway-api/conformance/manifests/conformance-report.yaml)) is required to disable request header filtering for all `HTTPRoute` tests relying on the `MakeRequestAndExpectEventuallyConsistentResponse` assertion. +> Regardless of whether request header filtering is enabled or disabled, header-based routing works as specified in the Gateway API, as the headers are only filtered before the request is forwarded to the upstream. diff --git a/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.7.0-default-report.yaml b/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.7.0-default-report.yaml new file mode 100644 index 0000000000..000e78772b --- /dev/null +++ b/conformance/reports/v1.3.0/airlock-microgateway/experimental-4.7.0-default-report.yaml @@ -0,0 +1,55 @@ +apiVersion: gateway.networking.k8s.io/v1 +date: "2025-08-25T13:33:58Z" +gatewayAPIChannel: experimental +gatewayAPIVersion: v1.3.0 +implementation: + contact: + - https://www.airlock.com/en/contact + organization: airlock + project: microgateway + url: https://github.com/airlock/microgateway + version: 4.7.0 +kind: ConformanceReport +mode: default +profiles: +- core: + result: success + statistics: + Failed: 0 + Passed: 33 + Skipped: 0 + extended: + result: success + statistics: + Failed: 0 + Passed: 18 + Skipped: 0 + supportedFeatures: + - GatewayInfrastructurePropagation + - GatewayPort8080 + - HTTPRouteBackendProtocolH2C + - HTTPRouteBackendProtocolWebSocket + - HTTPRouteBackendTimeout + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRouteParentRefPort + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestTimeout + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + unsupportedFeatures: + - GatewayAddressEmpty + - GatewayHTTPListenerIsolation + - GatewayStaticAddresses + - HTTPRouteBackendRequestHeaderModification + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteRequestPercentageMirror + name: GATEWAY-HTTP + summary: Core tests succeeded. Extended tests succeeded. +succeededProvisionalTests: +- GatewayInfrastructure diff --git a/site-src/implementations.md b/site-src/implementations.md index 0d97e76468..dc12477c22 100644 --- a/site-src/implementations.md +++ b/site-src/implementations.md @@ -205,7 +205,7 @@ Airlock Microgateway protects your applications and microservices with the tried #### Features - Comprehensive WAAP (formerly known as WAF) with security features like Deny Rules to protect against known attacks (OWASP Top 10), header filtering, JSON parsing, OpenAPI specification enforcement, and GraphQL schema validation -- Identity aware proxy which makes it possible to enforce authentication using JWT authentication or OIDC +- Identity aware proxy which makes it possible to enforce authentication using JWT authentication or OIDC, with OAuth 2.0 Token Introspection and Token Exchange for continuous validation and secure delegation across services - Reverse proxy functionality with request routing rules, TLS termination and remote IP extraction - Easy-to-use Grafana dashboards which provide valuable insights in allowed and blocked traffic and other metrics diff --git a/site-src/implementations/v1.1.md b/site-src/implementations/v1.1.md index 21063b28e6..69a3326bfb 100644 --- a/site-src/implementations/v1.1.md +++ b/site-src/implementations/v1.1.md @@ -19,13 +19,14 @@ Implementations only appear in this page if they pass Core conformance for the r | Organization | Project | Version | Mode | Gateway Port 8080 | HTTPRoute Host Rewrite | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Port Redirect | HTTPRoute Parent Ref Port | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | |:----------------|:-----------------------------------|:-------------------|:---------------------------------|:--------------------|:-------------------------|:--------------------------|:---------------------------|:-----------------------------------------|:----------------------------|:----------------------------|:-------------------------|:---------------------------------|:--------------------------|:----------------------------|:----------------------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------------------|:----------------------------| | GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-global-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.7.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | airlock | microgateway | v4.4.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | | cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/site-src/implementations/v1.2.md b/site-src/implementations/v1.2.md index c26434b418..a3728f6aca 100644 --- a/site-src/implementations/v1.2.md +++ b/site-src/implementations/v1.2.md @@ -16,32 +16,39 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Path Rewrite | HTTPRoute Response Header Modification | HTTPRoute Method Matching | HTTPRoute Query Param Matching | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Parent Ref Port | HTTPRoute Port Redirect | HTTPRoute Request Timeout | HTTPRoute Scheme Redirect | HTTPRoute Path Redirect | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | -|:---------------|:------------------------------|:----------|:-----------------------|:-------------------------|:-------------------------|:-----------------------------------------|:----------------------------|:---------------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:----------------------------|:--------------------------|:----------------------------|:----------------------------|:--------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | -| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | -| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | HTTPRoute Destination Port Matching | HTTPRoute Path Redirect | HTTPRoute Port Redirect | HTTPRoute Scheme Redirect | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Parent Ref Port | HTTPRoute Request Timeout | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | +|:----------------|:-----------------------------------|:----------|:-----------------------|:-------------------------|:----------------------------|:-------------------------|:---------------------------------|:-----------------------------------------|:--------------------------------------|:--------------------------|:--------------------------|:----------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:----------------------------|:----------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.7.9 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.7.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | +| kubvernor | kubvernor | 0.1.0 | default | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | ### GRPCRoute -| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | -|:---------------|:------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| -| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | -| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | -| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | -| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | -| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:----------------|:-----------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.7.9 | default | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kubvernor | kubvernor | 0.1.0 | default | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v2.0.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | ### TLSRoute @@ -50,7 +57,8 @@ Implementations only appear in this page if they pass Core conformance for the r | cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | | istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v2.0.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | | projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | diff --git a/site-src/implementations/v1.3.md b/site-src/implementations/v1.3.md index 552e98cd54..653a8b8077 100644 --- a/site-src/implementations/v1.3.md +++ b/site-src/implementations/v1.3.md @@ -16,34 +16,48 @@ Implementations only appear in this page if they pass Core conformance for the r ### HTTPRoute -| Organization | Project | Version | Mode | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | -|:---------------|:--------------|:----------|:--------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------| -| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | +|:---------------|:---------------------|:------------|:-----------------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------| +| agentgateway | agentgateway | v0.6.0-dev | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| airlock | microgateway | 4.6.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| airlock | microgateway | 4.7.0 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | GatewayNamespace | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.1.0-main | default | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | ### GRPCRoute -| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | -|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | -| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:-----------------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | GatewayNamespace | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| envoyproxy | envoy-gateway | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | ### TLSRoute -| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | -|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | -| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:-----------------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.5.0 | GatewayNamespace | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| envoyproxy | envoy-gateway | v1.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v2.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | ## Mesh Profile ### HTTPRoute -| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | HTTPRoute Parent Ref Port | Mesh Consumer Route | -|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------------|:----------------------| -| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | -| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | Mesh Consumer Route | Mesh HTTPRoute Backend Request Header Modification | Mesh HTTPRoute Query Param Matching | Mesh HTTPRoute Redirect Port | Mesh HTTPRoute Scheme Redirect | +|:---------------|:-------------------------------|:----------------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------|:-----------------------------------------------------|:--------------------------------------|:-------------------------------|:---------------------------------| +| Buoyant | Buoyant Enterprise for Linkerd | enterprise-2.18 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Linkerd | Linkerd | version-2.18 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | \ No newline at end of file From e9fecd3f16c44f763edd938bc0f767ee0fd9c8bc Mon Sep 17 00:00:00 2001 From: Fabian Bao Date: Thu, 28 Aug 2025 08:59:10 +0800 Subject: [PATCH 149/224] fix conformance test HTTPRouteWeight (#4038) --- conformance/tests/httproute-weight.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/conformance/tests/httproute-weight.go b/conformance/tests/httproute-weight.go index fa85deb9bf..bafd768ad8 100644 --- a/conformance/tests/httproute-weight.go +++ b/conformance/tests/httproute-weight.go @@ -59,8 +59,10 @@ var HTTPRouteWeight = suite.ConformanceTest{ t.Run("Requests should have a distribution that matches the weight", func(t *testing.T) { expected := http.ExpectedResponse{ - Request: http.Request{Path: "/"}, - Response: http.Response{StatusCode: 200}, + Request: http.Request{Path: "/"}, + Response: http.Response{ + StatusCodes: []int{200}, + }, Namespace: "gateway-conformance-infra", } From ef4c5b022f49cbeb10de2be32eed3737030f15ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 22:53:09 -0700 Subject: [PATCH 150/224] build(deps): bump google.golang.org/grpc from 1.74.2 to 1.75.0 (#4019) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.74.2 to 1.75.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.74.2...v1.75.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.75.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 30 ++++++++++++++++-------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index c818773daf..4f1a98f789 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/stretchr/testify v1.10.0 golang.org/x/net v0.43.0 golang.org/x/sync v0.16.0 - google.golang.org/grpc v1.74.2 + google.golang.org/grpc v1.75.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/protobuf v1.36.7 k8s.io/api v0.33.4 @@ -77,7 +77,7 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.35.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index b6f7fbce18..4f59623791 100644 --- a/go.sum +++ b/go.sum @@ -148,16 +148,16 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= -go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= -go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= -go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= -go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= -go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= -go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= -go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -221,10 +221,12 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= From 22b29c17541b3034e92bab3e135e127d5dd2f666 Mon Sep 17 00:00:00 2001 From: Ricardo Pchevuzinske Katz Date: Thu, 28 Aug 2025 02:53:16 -0300 Subject: [PATCH 151/224] Fix cors cel (#4032) * CORS: support a single wildcard entry as origin * CORS: Add test for CRD validations --- apis/v1/httproute_types.go | 3 +- apis/v1/shared_types.go | 11 ++ apis/v1/zz_generated.deepcopy.go | 2 +- applyconfiguration/apis/v1/httpcorsfilter.go | 4 +- .../gateway.networking.k8s.io_httproutes.yaml | 56 +++++--- pkg/test/cel/httproute_experimental_test.go | 129 ++++++++++++++++++ 6 files changed, 181 insertions(+), 24 deletions(-) diff --git a/apis/v1/httproute_types.go b/apis/v1/httproute_types.go index 53fae56716..5dad01e00a 100644 --- a/apis/v1/httproute_types.go +++ b/apis/v1/httproute_types.go @@ -1404,8 +1404,9 @@ type HTTPCORSFilter struct { // Support: Extended // +listType=set // +kubebuilder:validation:MaxItems=64 + // +kubebuilder:validation:XValidation:message="AllowOrigins cannot contain '*' alongside other origins",rule="!('*' in self && self.size() > 1)" // +optional - AllowOrigins []AbsoluteURI `json:"allowOrigins,omitempty"` + AllowOrigins []CORSOrigin `json:"allowOrigins,omitempty"` // AllowCredentials indicates whether the actual cross-origin request allows // to include credentials. diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 5b5ed4cfed..99299acda8 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -608,6 +608,17 @@ type PreciseHostname string // +kubebuilder:validation:Pattern=`^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?` type AbsoluteURI string +// The CORSOrigin MUST NOT be a relative URI, and it MUST follow the URI syntax and +// encoding rules specified in RFC3986. The CORSOrigin MUST include both a +// scheme (e.g., "http" or "spiffe") and a scheme-specific-part, or it should be a single '*' character. +// URIs that include an authority MUST include a fully qualified domain name or +// IP address as the host. +// The below regex was generated to simplify the assertion of scheme://host: being port optional +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`(^\*$)|(^([a-zA-Z][a-zA-Z0-9+\-.]+):\/\/([^:/?#]+)(:([0-9]{1,5}))?$)` +type CORSOrigin string + // Group refers to a Kubernetes Group. It must either be an empty string or a // RFC 1123 subdomain. // diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/v1/zz_generated.deepcopy.go index bcbf489072..be8e2485c2 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/v1/zz_generated.deepcopy.go @@ -976,7 +976,7 @@ func (in *HTTPCORSFilter) DeepCopyInto(out *HTTPCORSFilter) { *out = *in if in.AllowOrigins != nil { in, out := &in.AllowOrigins, &out.AllowOrigins - *out = make([]AbsoluteURI, len(*in)) + *out = make([]CORSOrigin, len(*in)) copy(*out, *in) } if in.AllowCredentials != nil { diff --git a/applyconfiguration/apis/v1/httpcorsfilter.go b/applyconfiguration/apis/v1/httpcorsfilter.go index cc556b3e8a..b4b9776b3a 100644 --- a/applyconfiguration/apis/v1/httpcorsfilter.go +++ b/applyconfiguration/apis/v1/httpcorsfilter.go @@ -25,7 +25,7 @@ import ( // HTTPCORSFilterApplyConfiguration represents a declarative configuration of the HTTPCORSFilter type for use // with apply. type HTTPCORSFilterApplyConfiguration struct { - AllowOrigins []apisv1.AbsoluteURI `json:"allowOrigins,omitempty"` + AllowOrigins []apisv1.CORSOrigin `json:"allowOrigins,omitempty"` AllowCredentials *bool `json:"allowCredentials,omitempty"` AllowMethods []apisv1.HTTPMethodWithWildcard `json:"allowMethods,omitempty"` AllowHeaders []apisv1.HTTPHeaderName `json:"allowHeaders,omitempty"` @@ -42,7 +42,7 @@ func HTTPCORSFilter() *HTTPCORSFilterApplyConfiguration { // WithAllowOrigins adds the given value to the AllowOrigins field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the AllowOrigins field. -func (b *HTTPCORSFilterApplyConfiguration) WithAllowOrigins(values ...apisv1.AbsoluteURI) *HTTPCORSFilterApplyConfiguration { +func (b *HTTPCORSFilterApplyConfiguration) WithAllowOrigins(values ...apisv1.CORSOrigin) *HTTPCORSFilterApplyConfiguration { for i := range values { b.AllowOrigins = append(b.AllowOrigins, values[i]) } diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 34876b54a0..0329311362 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -657,18 +657,22 @@ spec: Support: Extended items: description: |- - The AbsoluteURI MUST NOT be a relative URI, and it MUST follow the URI syntax and - encoding rules specified in RFC3986. The AbsoluteURI MUST include both a - scheme (e.g., "http" or "spiffe") and a scheme-specific-part. URIs that - include an authority MUST include a fully qualified domain name or + The CORSOrigin MUST NOT be a relative URI, and it MUST follow the URI syntax and + encoding rules specified in RFC3986. The CORSOrigin MUST include both a + scheme (e.g., "http" or "spiffe") and a scheme-specific-part, or it should be a single '*' character. + URIs that include an authority MUST include a fully qualified domain name or IP address as the host. maxLength: 253 minLength: 1 - pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + pattern: (^\*$)|(^([a-zA-Z][a-zA-Z0-9+\-.]+):\/\/([^:/?#]+)(:([0-9]{1,5}))?$) type: string maxItems: 64 type: array x-kubernetes-list-type: set + x-kubernetes-validations: + - message: AllowOrigins cannot contain '*' alongside + other origins + rule: '!(''*'' in self && self.size() > 1)' exposeHeaders: description: |- ExposeHeaders indicates which HTTP response headers can be exposed @@ -2139,18 +2143,22 @@ spec: Support: Extended items: description: |- - The AbsoluteURI MUST NOT be a relative URI, and it MUST follow the URI syntax and - encoding rules specified in RFC3986. The AbsoluteURI MUST include both a - scheme (e.g., "http" or "spiffe") and a scheme-specific-part. URIs that - include an authority MUST include a fully qualified domain name or + The CORSOrigin MUST NOT be a relative URI, and it MUST follow the URI syntax and + encoding rules specified in RFC3986. The CORSOrigin MUST include both a + scheme (e.g., "http" or "spiffe") and a scheme-specific-part, or it should be a single '*' character. + URIs that include an authority MUST include a fully qualified domain name or IP address as the host. maxLength: 253 minLength: 1 - pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + pattern: (^\*$)|(^([a-zA-Z][a-zA-Z0-9+\-.]+):\/\/([^:/?#]+)(:([0-9]{1,5}))?$) type: string maxItems: 64 type: array x-kubernetes-list-type: set + x-kubernetes-validations: + - message: AllowOrigins cannot contain '*' alongside + other origins + rule: '!(''*'' in self && self.size() > 1)' exposeHeaders: description: |- ExposeHeaders indicates which HTTP response headers can be exposed @@ -4801,18 +4809,22 @@ spec: Support: Extended items: description: |- - The AbsoluteURI MUST NOT be a relative URI, and it MUST follow the URI syntax and - encoding rules specified in RFC3986. The AbsoluteURI MUST include both a - scheme (e.g., "http" or "spiffe") and a scheme-specific-part. URIs that - include an authority MUST include a fully qualified domain name or + The CORSOrigin MUST NOT be a relative URI, and it MUST follow the URI syntax and + encoding rules specified in RFC3986. The CORSOrigin MUST include both a + scheme (e.g., "http" or "spiffe") and a scheme-specific-part, or it should be a single '*' character. + URIs that include an authority MUST include a fully qualified domain name or IP address as the host. maxLength: 253 minLength: 1 - pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + pattern: (^\*$)|(^([a-zA-Z][a-zA-Z0-9+\-.]+):\/\/([^:/?#]+)(:([0-9]{1,5}))?$) type: string maxItems: 64 type: array x-kubernetes-list-type: set + x-kubernetes-validations: + - message: AllowOrigins cannot contain '*' alongside + other origins + rule: '!(''*'' in self && self.size() > 1)' exposeHeaders: description: |- ExposeHeaders indicates which HTTP response headers can be exposed @@ -6283,18 +6295,22 @@ spec: Support: Extended items: description: |- - The AbsoluteURI MUST NOT be a relative URI, and it MUST follow the URI syntax and - encoding rules specified in RFC3986. The AbsoluteURI MUST include both a - scheme (e.g., "http" or "spiffe") and a scheme-specific-part. URIs that - include an authority MUST include a fully qualified domain name or + The CORSOrigin MUST NOT be a relative URI, and it MUST follow the URI syntax and + encoding rules specified in RFC3986. The CORSOrigin MUST include both a + scheme (e.g., "http" or "spiffe") and a scheme-specific-part, or it should be a single '*' character. + URIs that include an authority MUST include a fully qualified domain name or IP address as the host. maxLength: 253 minLength: 1 - pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? + pattern: (^\*$)|(^([a-zA-Z][a-zA-Z0-9+\-.]+):\/\/([^:/?#]+)(:([0-9]{1,5}))?$) type: string maxItems: 64 type: array x-kubernetes-list-type: set + x-kubernetes-validations: + - message: AllowOrigins cannot contain '*' alongside + other origins + rule: '!(''*'' in self && self.size() > 1)' exposeHeaders: description: |- ExposeHeaders indicates which HTTP response headers can be exposed diff --git a/pkg/test/cel/httproute_experimental_test.go b/pkg/test/cel/httproute_experimental_test.go index 9978d4ca11..b9d2289e58 100644 --- a/pkg/test/cel/httproute_experimental_test.go +++ b/pkg/test/cel/httproute_experimental_test.go @@ -241,6 +241,135 @@ func toDuration(durationString string) *gatewayv1.Duration { return (*gatewayv1.Duration)(&durationString) } +func TestHTTPRouteCORS(t *testing.T) { + tests := []struct { + name string + wantErrors []string + corsfilter *gatewayv1.HTTPCORSFilter + }{ + { + name: "Valid cors should be accepted", + wantErrors: nil, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "https://xpto.com", + "http://*.abcd.com", + "http://*.abcd.com:12345", + }, + }, + }, + { + name: "Using wildcard only is accepted", + wantErrors: nil, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "*", + }, + }, + }, + { + name: "Wildcard and other hosts on the same origin list should be denied", + wantErrors: []string{"AllowOrigins cannot contain '*' alongside other origins"}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "*", + "https://xpto.com", + }, + }, + }, + { + name: "An origin without the format scheme://host should be denied", + wantErrors: []string{"Invalid value: \"xpto.com\": spec.rules[0].filters[0].cors.allowOrigins[1] in body should match"}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "https://xpto.com", + "xpto.com", + }, + }, + }, + { + name: "An origin as http://*.com should be accepted", + wantErrors: nil, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "https://*.com", + }, + }, + }, + { + name: "An origin with an invalid port should be denied", + wantErrors: []string{"Invalid value: \"https://xpto.com:notaport\": spec.rules[0].filters[0].cors.allowOrigins[0] in body should match"}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "https://xpto.com:notaport", + }, + }, + }, + { + name: "An origin with an value before the scheme definition should be denied", + wantErrors: []string{"Invalid value: \"xpto/https://xpto.com\""}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowOrigins: []gatewayv1.CORSOrigin{ + "xpto/https://xpto.com", + }, + }, + }, + { + name: "Using an invalid HTTP method should be denied", + wantErrors: []string{"Unsupported value: \"BAZINGA\""}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowMethods: []gatewayv1.HTTPMethodWithWildcard{ + "BAZINGA", + }, + }, + }, + { + name: "Using wildcard and a valid method should be denied", + wantErrors: []string{"AllowMethods cannot contain '*' alongside other methods"}, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowMethods: []gatewayv1.HTTPMethodWithWildcard{ + "GET", + "*", + "POST", + }, + }, + }, + { + name: "Using an array of valid methods should be accepted", + wantErrors: nil, + corsfilter: &gatewayv1.HTTPCORSFilter{ + AllowMethods: []gatewayv1.HTTPMethodWithWildcard{ + "GET", + "OPTIONS", + "POST", + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + route := &gatewayv1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("foo-%v", time.Now().UnixNano()), + Namespace: metav1.NamespaceDefault, + }, + Spec: gatewayv1.HTTPRouteSpec{Rules: []gatewayv1.HTTPRouteRule{ + { + Filters: []gatewayv1.HTTPRouteFilter{ + { + Type: gatewayv1.HTTPRouteFilterCORS, + CORS: tc.corsfilter, + }, + }, + }, + }}, + } + validateHTTPRoute(t, route, tc.wantErrors) + }) + } +} + func TestHTTPRouteTimeouts(t *testing.T) { tests := []struct { name string From a82c06b8f54322e1db58144b7a78bd992fb6c4d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 23:11:09 -0700 Subject: [PATCH 152/224] build(deps): bump github.com/stretchr/testify from 1.10.0 to 1.11.0 (#4020) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4f1a98f789..bd1a6d9147 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.0 require ( github.com/elastic/crd-ref-docs v0.2.0 github.com/miekg/dns v1.1.68 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 golang.org/x/net v0.43.0 golang.org/x/sync v0.16.0 google.golang.org/grpc v1.75.0 diff --git a/go.sum b/go.sum index 4f59623791..4120b93f2a 100644 --- a/go.sum +++ b/go.sum @@ -140,8 +140,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= From a108a1007cb1aa3caa86206e1b36f2b0e7bd49fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 23:11:16 -0700 Subject: [PATCH 153/224] build(deps): bump mkdocs-material in /hack/mkdocs/image (#4022) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.16 to 9.6.18. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.16...9.6.18) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hack/mkdocs/image/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/mkdocs/image/requirements.txt b/hack/mkdocs/image/requirements.txt index e4d6677b63..940b186b39 100644 --- a/hack/mkdocs/image/requirements.txt +++ b/hack/mkdocs/image/requirements.txt @@ -10,7 +10,7 @@ MarkupSafe==3.0.2 mkdocs==1.6.1 mkdocs-awesome-pages-plugin==2.10.1 mkdocs-macros-plugin==1.3.7 -mkdocs-material==9.6.16 +mkdocs-material==9.6.18 mkdocs-redirects==1.2.2 mkdocs-mermaid2-plugin==1.2.1 pandas>=2.0.3 From 64dfa32dc16aaab4b7f6c28ad78aadfe34ca9be0 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Thu, 28 Aug 2025 16:37:13 +0200 Subject: [PATCH 154/224] simplify BackendTLSPolicy test infrastructure and remove unnecessary code (#4016) * simplify BackendTLSPolicy test infrastructure and remove unnecessary code Signed-off-by: Norwin Schnyder * rebase to 'origin/main' and refactor BackendTLSPolicy validation and normative tests --------- Signed-off-by: Norwin Schnyder --- conformance/base/manifests.yaml | 33 ----- conformance/tests/backendtlspolicy-san.go | 34 ++--- conformance/tests/backendtlspolicy-san.yaml | 120 ++++++----------- conformance/tests/backendtlspolicy.go | 96 ++++++++------ conformance/tests/backendtlspolicy.yaml | 125 ++++++------------ conformance/utils/kubernetes/certificate.go | 21 +-- .../utils/kubernetes/certificate_test.go | 101 -------------- conformance/utils/suite/suite.go | 13 +- 8 files changed, 162 insertions(+), 381 deletions(-) delete mode 100644 conformance/utils/kubernetes/certificate_test.go diff --git a/conformance/base/manifests.yaml b/conformance/base/manifests.yaml index d8f8c45a1c..9380223ea0 100644 --- a/conformance/base/manifests.yaml +++ b/conformance/base/manifests.yaml @@ -95,39 +95,6 @@ spec: matchLabels: gateway-conformance: backend --- -apiVersion: gateway.networking.k8s.io/v1 -kind: Gateway -metadata: - name: gateway-backendtlspolicy - namespace: gateway-conformance-infra -spec: - gatewayClassName: "{GATEWAY_CLASS_NAME}" - listeners: - - name: http - port: 80 - protocol: HTTP - hostname: "abc.example.com" - allowedRoutes: - namespaces: - from: Same - kinds: - - kind: HTTPRoute - - name: https - port: 443 - protocol: HTTPS - tls: - mode: Terminate - certificateRefs: - - group: "" - kind: Secret - name: tls-checks-certificate - hostname: "abc.example.com" - allowedRoutes: - namespaces: - from: Same - kinds: - - kind: HTTPRoute ---- apiVersion: v1 kind: Service metadata: diff --git a/conformance/tests/backendtlspolicy-san.go b/conformance/tests/backendtlspolicy-san.go index 38e7a2b43a..bbcb334d1b 100644 --- a/conformance/tests/backendtlspolicy-san.go +++ b/conformance/tests/backendtlspolicy-san.go @@ -46,8 +46,8 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Manifests: []string{"tests/backendtlspolicy-san.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "route-backendtlspolicy-san-test", Namespace: ns} - gwNN := types.NamespacedName{Name: "gateway-backendtlspolicy", Namespace: ns} + routeNN := types.NamespacedName{Name: "backendtlspolicy-san-test", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) @@ -63,7 +63,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ // Verify that the request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed. t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing dns SAN should succeed", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns", Namespace: ns} + policyNN := types.NamespacedName{Name: "san-dns", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -71,16 +71,16 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSSanDns", + Path: "/backendtlspolicy-san-dns", SNI: serverStr, }, - Response: h.Response{StatusCode: 200}, + Response: h.Response{StatusCodes: []int{200}}, }) }) // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched dns SAN should fail. t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched dns SAN should return an HTTP error", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-san-dns-mismatch", Namespace: ns} + policyNN := types.NamespacedName{Name: "san-dns-mismatch", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -88,7 +88,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSSanDnsMismatch", + Path: "/backendtlspolicy-san-dns-mismatch", SNI: serverStr, }, }) @@ -96,7 +96,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ // Verify that the request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed. t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing uri SAN should succeed", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri", Namespace: ns} + policyNN := types.NamespacedName{Name: "san-uri", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -104,16 +104,16 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSSanUri", + Path: "/backendtlspolicy-san-uri", SNI: serverStr, }, - Response: h.Response{StatusCode: 200}, + Response: h.Response{StatusCodes: []int{200}}, }) }) // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched uri SAN should fail. t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched uri SAN should return an HTTP error", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-san-uri-mismatch", Namespace: ns} + policyNN := types.NamespacedName{Name: "san-uri-mismatch", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -121,7 +121,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSSanUriMismatch", + Path: "/backendtlspolicy-san-uri-mismatch", SNI: serverStr, }, }) @@ -129,7 +129,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ // Verify that the request sent to Service with valid BackendTLSPolicy containing multi SANs should succeed. t.Run("HTTP request sent to Service with valid BackendTLSPolicy containing multi SAN should succeed", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-sans", Namespace: ns} + policyNN := types.NamespacedName{Name: "multiple-sans", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -137,16 +137,16 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSMultiSans", + Path: "/backendtlspolicy-multiple-sans", SNI: serverStr, }, - Response: h.Response{StatusCode: 200}, + Response: h.Response{StatusCodes: []int{200}}, }) }) // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched multi SAN should fail. t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched multi SAN should return an HTTP error", func(t *testing.T) { - policyNN := types.NamespacedName{Name: "backendtlspolicy-multiple-mismatch-sans", Namespace: ns} + policyNN := types.NamespacedName{Name: "multiple-mismatch-sans", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, policyCond) h.MakeRequestAndExpectFailure(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, @@ -154,7 +154,7 @@ var BackendTLSPolicySANValidation = suite.ConformanceTest{ Namespace: ns, Request: h.Request{ Host: serverStr, - Path: "/backendTLSMultiMismatchSans", + Path: "/backendtlspolicy-multiple-mismatch-sans", SNI: serverStr, }, }) diff --git a/conformance/tests/backendtlspolicy-san.yaml b/conformance/tests/backendtlspolicy-san.yaml index e3e0f79bf0..7bf7a26dfd 100644 --- a/conformance/tests/backendtlspolicy-san.yaml +++ b/conformance/tests/backendtlspolicy-san.yaml @@ -1,11 +1,11 @@ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: route-backendtlspolicy-san-test + name: backendtlspolicy-san-test namespace: gateway-conformance-infra spec: parentRefs: - - name: gateway-backendtlspolicy + - name: same-namespace namespace: gateway-conformance-infra hostnames: - abc.example.com @@ -18,7 +18,7 @@ spec: matches: - path: type: Exact - value: /backendTLSSanDns + value: /backendtlspolicy-san-dns - backendRefs: - group: "" kind: Service @@ -27,7 +27,7 @@ spec: matches: - path: type: Exact - value: /backendTLSSanDnsMismatch + value: /backendtlspolicy-san-dns-mismatch - backendRefs: - group: "" kind: Service @@ -36,7 +36,7 @@ spec: matches: - path: type: Exact - value: /backendTLSSanUri + value: /backendtlspolicy-san-uri - backendRefs: - group: "" kind: Service @@ -45,7 +45,7 @@ spec: matches: - path: type: Exact - value: /backendTLSSanUriMismatch + value: /backendtlspolicy-san-uri-mismatch - backendRefs: - group: "" kind: Service @@ -54,7 +54,7 @@ spec: matches: - path: type: Exact - value: /backendTLSMultiSans + value: /backendtlspolicy-multiple-sans - backendRefs: - group: "" kind: Service @@ -63,7 +63,7 @@ spec: matches: - path: type: Exact - value: /backendTLSMultiMismatchSans + value: /backendtlspolicy-multiple-mismatch-sans --- apiVersion: v1 kind: Service @@ -72,7 +72,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -86,7 +86,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -101,7 +101,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -116,7 +116,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -131,7 +131,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -146,7 +146,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-san-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -154,60 +154,10 @@ spec: port: 443 targetPort: 8443 --- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: backendtlspolicy-san-test - namespace: gateway-conformance-infra - labels: - app: backendtlspolicy-san-test -spec: - replicas: 1 - selector: - matchLabels: - app: backendtlspolicy-san-test - template: - metadata: - labels: - app: backendtlspolicy-san-test - spec: - containers: - - name: backendtlspolicy-san-test - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd - volumeMounts: - - name: secret-volume - mountPath: /etc/secret-volume - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: TLS_SERVER_CERT - value: /etc/secret-volume/crt - - name: TLS_SERVER_PRIVKEY - value: /etc/secret-volume/key - resources: - requests: - cpu: 10m - volumes: - - name: secret-volume - secret: - # This secret is generated dynamically by the test suite. - secretName: tls-with-san-certificate - items: - - key: tls.crt - path: crt - - key: tls.key - path: key ---- apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-san-dns + name: san-dns namespace: gateway-conformance-infra spec: targetRefs: @@ -219,8 +169,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "Hostname" @@ -229,7 +180,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-san-dns-mismatch + name: san-dns-mismatch namespace: gateway-conformance-infra spec: targetRefs: @@ -241,8 +192,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "Hostname" @@ -251,7 +203,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-san-uri + name: san-uri namespace: gateway-conformance-infra spec: targetRefs: @@ -263,8 +215,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "URI" @@ -273,7 +226,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-san-uri-mismatch + name: san-uri-mismatch namespace: gateway-conformance-infra spec: targetRefs: @@ -285,8 +238,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "URI" @@ -295,7 +249,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-multiple-sans + name: multiple-sans namespace: gateway-conformance-infra spec: targetRefs: @@ -307,8 +261,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "URI" @@ -319,7 +274,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-multiple-mismatch-sans + name: multiple-mismatch-sans namespace: gateway-conformance-infra spec: targetRefs: @@ -331,8 +286,9 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-with-san-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" subjectAltNames: - type: "URI" diff --git a/conformance/tests/backendtlspolicy.go b/conformance/tests/backendtlspolicy.go index 62ed54c4af..203f3f8948 100644 --- a/conformance/tests/backendtlspolicy.go +++ b/conformance/tests/backendtlspolicy.go @@ -47,12 +47,6 @@ var BackendTLSPolicy = suite.ConformanceTest{ Manifests: []string{"tests/backendtlspolicy.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "gateway-conformance-infra-test", Namespace: ns} - gwNN := types.NamespacedName{Name: "gateway-backendtlspolicy", Namespace: ns} - - kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) - gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) - kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) acceptedCond := metav1.Condition{ Type: string(v1alpha2.PolicyConditionAccepted), @@ -65,49 +59,71 @@ var BackendTLSPolicy = suite.ConformanceTest{ Reason: string(v1alpha3.BackendTLSPolicyReasonResolvedRefs), } - validPolicyNN := types.NamespacedName{Name: "normative-test-backendtlspolicy", Namespace: ns} - kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, acceptedCond) - kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, resolvedRefsCond) - - serverStr := "abc.example.com" - - // Verify that the request sent to Service with valid BackendTLSPolicy should succeed. - t.Run("HTTP request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { - h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + t.Run("Re-encrypt HTTPS request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { + routeNN := types.NamespacedName{Name: "backendtlspolicy-reencrypt", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace-with-https-listener", Namespace: ns} + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + validPolicyNN := types.NamespacedName{Name: "normative-test", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, acceptedCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, resolvedRefsCond) + + // For the re-encrypt case, we need to use the cert for the frontend tls listener. + certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns} + cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) + if err != nil { + t.Fatalf("unexpected error finding TLS secret: %v", err) + } + // Verify that the request to a re-encrypted call to /backendTLS should succeed. + tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, keyPem, "https-listener.org", h.ExpectedResponse{ Namespace: ns, Request: h.Request{ - Host: serverStr, - Path: "/backendTLS", - SNI: serverStr, + Host: "https-listener.org", + Path: "/backendtlspolicy", + SNI: "https-listener.org", + }, + ExpectedRequest: &h.ExpectedRequest{ + Request: h.Request{ + Path: "/backendtlspolicy", + SNI: "abc.example.com", + }, }, - Response: h.Response{StatusCode: 200}, + Response: h.Response{StatusCodes: []int{200}}, }) }) - // For the re-encrypt case, we need to use the cert for the frontend tls listener. - certNN := types.NamespacedName{Name: "tls-checks-certificate", Namespace: ns} - cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) - if err != nil { - t.Fatalf("unexpected error finding TLS secret: %v", err) - } - // Verify that the request to a re-encrypted call to /backendTLS should succeed. - t.Run("Re-encrypt HTTPS request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { - tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, cPem, keyPem, serverStr, + routeNN := types.NamespacedName{Name: "backendtlspolicy", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + // Verify that the request sent to Service with valid BackendTLSPolicy should succeed. + t.Run("HTTP request sent to Service with valid BackendTLSPolicy should succeed", func(t *testing.T) { + validPolicyNN := types.NamespacedName{Name: "normative-test", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, acceptedCond) + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, validPolicyNN, gwNN, resolvedRefsCond) + + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, h.ExpectedResponse{ Namespace: ns, Request: h.Request{ - Host: serverStr, - Path: "/backendTLS", - SNI: serverStr, + Host: "abc.example.com", + Path: "/backendtlspolicy", + SNI: "abc.example.com", }, - Response: h.Response{StatusCode: 200}, + Response: h.Response{StatusCodes: []int{200}}, }) }) // Verify that the request sent to a Service targeted by a BackendTLSPolicy with mismatched host will fail. t.Run("HTTP request sent to Service targeted by BackendTLSPolicy with mismatched hostname should return an HTTP error", func(t *testing.T) { - invalidPolicyNN := types.NamespacedName{Name: "backendtlspolicy-host-mismatch", Namespace: ns} + invalidPolicyNN := types.NamespacedName{Name: "host-mismatch", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, acceptedCond) kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidPolicyNN, gwNN, resolvedRefsCond) @@ -115,16 +131,16 @@ var BackendTLSPolicy = suite.ConformanceTest{ h.ExpectedResponse{ Namespace: ns, Request: h.Request{ - Host: serverStr, - Path: "/backendTLSHostMismatch", - SNI: serverStr, + Host: "abc.example.org", + Path: "/backendtlspolicy-host-mismatch", + SNI: "abc.example.com", }, }) }) // Verify that request sent to Service targeted by BackendTLSPolicy with mismatched cert should failed. t.Run("HTTP request send to Service targeted by BackendTLSPolicy with mismatched cert should return HTTP error", func(t *testing.T) { - invalidCertPolicyNN := types.NamespacedName{Name: "backendtlspolicy-cert-mismatch", Namespace: ns} + invalidCertPolicyNN := types.NamespacedName{Name: "cert-mismatch", Namespace: ns} kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, acceptedCond) kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, invalidCertPolicyNN, gwNN, resolvedRefsCond) @@ -132,9 +148,9 @@ var BackendTLSPolicy = suite.ConformanceTest{ h.ExpectedResponse{ Namespace: ns, Request: h.Request{ - Host: serverStr, - Path: "/backendTLSCertMismatch", - SNI: serverStr, + Host: "abc.example.com", + Path: "/backendtlspolicy-cert-mismatch", + SNI: "abc.example.com", }, }) }) diff --git a/conformance/tests/backendtlspolicy.yaml b/conformance/tests/backendtlspolicy.yaml index 6d0cab8e3f..db9a017c39 100644 --- a/conformance/tests/backendtlspolicy.yaml +++ b/conformance/tests/backendtlspolicy.yaml @@ -1,11 +1,11 @@ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: gateway-conformance-infra-test + name: backendtlspolicy namespace: gateway-conformance-infra spec: parentRefs: - - name: gateway-backendtlspolicy + - name: same-namespace namespace: gateway-conformance-infra hostnames: - abc.example.com @@ -18,7 +18,7 @@ spec: matches: - path: type: Exact - value: /backendTLS + value: /backendtlspolicy - backendRefs: - group: "" kind: Service @@ -27,7 +27,7 @@ spec: matches: - path: type: Exact - value: /backendTLSHostMismatch + value: /backendtlspolicy-host-mismatch - backendRefs: - group: "" kind: Service @@ -36,7 +36,29 @@ spec: matches: - path: type: Exact - value: /backendTLSCertMismatch + value: /backendtlspolicy-cert-mismatch +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backendtlspolicy-reencrypt + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace-with-https-listener + namespace: gateway-conformance-infra + hostnames: + - https-listener.org + rules: + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy --- apiVersion: v1 kind: Service @@ -45,7 +67,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -59,7 +81,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -74,7 +96,7 @@ metadata: namespace: gateway-conformance-infra spec: selector: - app: backendtlspolicy-test + app: tls-backend ports: - name: "btls" protocol: TCP @@ -82,76 +104,10 @@ spec: port: 443 targetPort: 8443 --- -# Deployment must not be applied until after the secret is generated. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: backendtlspolicy-test - namespace: gateway-conformance-infra - labels: - app: backendtlspolicy-test -spec: - replicas: 1 - selector: - matchLabels: - app: backendtlspolicy-test - template: - metadata: - labels: - app: backendtlspolicy-test - spec: - containers: - - name: backendtlspolicy-test - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20240412-v1.0.0-394-g40c666fd - volumeMounts: - - name: ca-volume - mountPath: /etc/ca-volume - - name: secret-volume - mountPath: /etc/secret-volume - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: CA_CERT - value: /etc/ca-volume/crt - - name: CA_CERT_KEY - value: /etc/ca-volume/key - - name: TLS_SERVER_CERT - value: /etc/secret-volume/crt - - name: TLS_SERVER_PRIVKEY - value: /etc/secret-volume/key - resources: - requests: - cpu: 10m - volumes: - - name: ca-volume - configMap: - # This configMap is generated dynamically by the test suite. - name: backend-tls-checks-certificate - items: - - key: ca.crt - path: crt - - key: key.crt - path: key - - name: secret-volume - secret: - # This secret is generated dynamically by the test suite. - secretName: tls-checks-certificate - items: - - key: tls.crt - path: crt - - key: tls.key - path: key ---- apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: normative-test-backendtlspolicy + name: normative-test namespace: gateway-conformance-infra spec: targetRefs: @@ -163,14 +119,15 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-checks-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "abc.example.com" --- apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-host-mismatch + name: host-mismatch namespace: gateway-conformance-infra spec: targetRefs: @@ -182,14 +139,15 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-checks-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" hostname: "mismatch.example.com" --- apiVersion: gateway.networking.k8s.io/v1alpha3 kind: BackendTLSPolicy metadata: - name: backendtlspolicy-cert-mismatch + name: cert-mismatch namespace: gateway-conformance-infra spec: targetRefs: @@ -201,6 +159,7 @@ spec: caCertificateRefs: - group: "" kind: ConfigMap - # This secret is generated dynamically by the test suite. - name: "backend-tls-mismatch-certificate" + # This ConfigMap is generated dynamically by the test suite. + # It contains a random, unused CA certificate to force validation to fail. + name: "mismatch-ca-certificate" hostname: "abc.example.com" diff --git a/conformance/utils/kubernetes/certificate.go b/conformance/utils/kubernetes/certificate.go index 1b2ee3af85..8d9b935793 100644 --- a/conformance/utils/kubernetes/certificate.go +++ b/conformance/utils/kubernetes/certificate.go @@ -151,12 +151,10 @@ func generateRSACert(hosts []string, keyOut, certOut io.Writer, ca *x509.Certifi // MustCreateCACertConfigMap will create a ConfigMap containing a CA Certificate, given a TLS Secret // for that CA certificate. Also returns the CA certificate. -func MustCreateCACertConfigMap(t *testing.T, namespace, configMapName string, hosts []string) (*corev1.ConfigMap, *x509.Certificate, *rsa.PrivateKey) { - require.NotEmpty(t, hosts, "require a non-empty hosts for Subject Alternate Name values") - +func MustCreateCACertConfigMap(t *testing.T, namespace, configMapName string) (*corev1.ConfigMap, *x509.Certificate, *rsa.PrivateKey) { var certData, keyData bytes.Buffer - ca, caBytes, caPrivKey, err := generateCACert(hosts) + ca, caBytes, caPrivKey, err := generateCACert() if err != nil { t.Errorf("failed to generate CA certificate and key: %v", err) return nil, nil, nil @@ -187,8 +185,8 @@ func MustCreateCACertConfigMap(t *testing.T, namespace, configMapName string, ho return caConfigMap, ca, caPrivKey } -// generateCACert generates a CA and a CA-signed certificate valid for a year. -func generateCACert(hosts []string) (*x509.Certificate, []byte, *rsa.PrivateKey, error) { +// generateCACert generates a CA certificate valid for a year. +func generateCACert() (*x509.Certificate, []byte, *rsa.PrivateKey, error) { var caBytes []byte // Create the CA certificate template. @@ -212,17 +210,6 @@ func generateCACert(hosts []string) (*x509.Certificate, []byte, *rsa.PrivateKey, BasicConstraintsValid: true, } - // Ensure only valid hosts make it into the CA cert. - for _, h := range hosts { - if ip := net.ParseIP(h); ip != nil { - ca.IPAddresses = append(ca.IPAddresses, ip) - } else if err := validateHost(h); err == nil { - ca.DNSNames = append(ca.DNSNames, h) - } else if u, err := url.Parse(h); err == nil { - ca.URIs = append(ca.URIs, u) - } - } - // Generate the private key to sign certificates. caPrivKey, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { diff --git a/conformance/utils/kubernetes/certificate_test.go b/conformance/utils/kubernetes/certificate_test.go deleted file mode 100644 index f6c78048a9..0000000000 --- a/conformance/utils/kubernetes/certificate_test.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2024 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package kubernetes - -import ( - "bytes" - "crypto/x509" - "encoding/pem" - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_generateCACert(t *testing.T) { - tests := []struct { - name string - hosts []string - expectedErr []string - }{ - { - name: "one host generates cert with no host", - hosts: []string{}, - }, - { - name: "one host generates cert for same host", - hosts: []string{"abc.example.com"}, - }, - { - name: "wildcard generates cert for same host", - hosts: []string{"*.example.com"}, - }, - { - name: "two hosts generates cert for both hosts", - hosts: []string{"abc.example.com", "def.example.com"}, - }, - { - name: "bad host generates cert for no host", - hosts: []string{"--abc.example.com"}, - expectedErr: []string{"x509: certificate is not valid for any names, but wanted to match --abc.example.com"}, - }, - { - name: "one good host and one bad host generates cert for only good host", - hosts: []string{"---.example.com", "def.example.com"}, - expectedErr: []string{"x509: certificate is valid xxx for def.example.com, not ---.example.com", ""}, - }, - } - - var serverKey, serverCert bytes.Buffer - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - serverCert.Reset() - serverKey.Reset() - // Test the function generateCACert. We can only test normative function - // and hostnames, everything else is hardcoded. - _, caBytes, caPrivKey, err := generateCACert(tc.hosts) - require.NoError(t, err, "unexpected error generating RSA certificate") - - var certData bytes.Buffer - if err := pem.Encode(&certData, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil { - require.NoError(t, err, "failed to create certificater") - } - - var keyData bytes.Buffer - if err := pem.Encode(&keyData, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey)}); err != nil { - require.NoError(t, err, "failed to create key") - } - - // Test that the CA certificate is decodable, parseable, and has the configured hostname/s. - block, _ := pem.Decode(certData.Bytes()) - if block == nil { - require.FailNow(t, "failed to decode PEM block containing cert") - } else if block.Type == "CERTIFICATE" { - cert, err := x509.ParseCertificate(block.Bytes) - require.NoError(t, err, "failed to parse certificate") - for idx, h := range tc.hosts { - err = cert.VerifyHostname(h) - if err != nil && len(tc.expectedErr) > 0 && tc.expectedErr[idx] == "" { - require.EqualValues(t, tc.expectedErr[idx], err.Error(), "certificate verification failed") - } else if err == nil && len(tc.expectedErr) > 0 && tc.expectedErr[idx] != "" { - require.EqualValues(t, tc.expectedErr[idx], err, "expected an error but certification verification succeeded") - } - } - } - }) - } -} diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index 877c030f3c..e3c098a89b 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -388,17 +388,14 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) secret = kubernetes.MustCreateSelfSignedCertSecret(t, "gateway-conformance-app-backend", "tls-passthrough-checks-certificate", []string{"abc.example.com"}) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) - caConfigMapBST, _, _ := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-mismatch-certificate", []string{"nex.example.com"}) - suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMapBST}, suite.Cleanup) - caConfigMap, ca, caPrivKey := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-checks-certificate", []string{"abc.example.com"}) + caConfigMap, ca, caPrivKey := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "tls-checks-ca-certificate") suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) - secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com"}, ca, caPrivKey) + secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}, ca, caPrivKey) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) - // TODO(kl52752) Merge CA certificates for Backend TLS Policy and move Deployment to common file. - caConfigMap, ca, caPrivKey = kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "backend-tls-with-san-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}) + + // The following CA ceritficate is used for BackendTLSPolicy testing to intentionally force TLS validation to fail. + caConfigMap, _, _ = kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "mismatch-ca-certificate") suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) - secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-with-san-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}, ca, caPrivKey) - suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) tlog.Logf(t, "Test Setup: Ensuring Gateways and Pods from base manifests are ready") namespaces := []string{ From 180e20fd1ea1de1cfd06d64d9892af2ae54f83de Mon Sep 17 00:00:00 2001 From: Erik Godding Boye Date: Thu, 28 Aug 2025 18:57:10 +0200 Subject: [PATCH 155/224] Upgrade dependencies to K8s 1.34 (#4044) Signed-off-by: Erik Godding Boye --- .github/workflows/crd-validation.yml | 2 +- applyconfiguration/apis/v1/gateway.go | 17 +++ applyconfiguration/apis/v1/gatewayclass.go | 17 +++ applyconfiguration/apis/v1/grpcroute.go | 17 +++ applyconfiguration/apis/v1/httproute.go | 17 +++ applyconfiguration/apis/v1alpha2/grpcroute.go | 17 +++ .../apis/v1alpha2/referencegrant.go | 17 +++ applyconfiguration/apis/v1alpha2/tcproute.go | 17 +++ applyconfiguration/apis/v1alpha2/tlsroute.go | 17 +++ applyconfiguration/apis/v1alpha2/udproute.go | 17 +++ .../apis/v1alpha3/backendtlspolicy.go | 17 +++ applyconfiguration/apis/v1alpha3/tlsroute.go | 17 +++ applyconfiguration/apis/v1beta1/gateway.go | 17 +++ .../apis/v1beta1/gatewayclass.go | 17 +++ applyconfiguration/apis/v1beta1/httproute.go | 17 +++ .../apis/v1beta1/referencegrant.go | 17 +++ .../apisx/v1alpha1/xbackendtrafficpolicy.go | 17 +++ .../apisx/v1alpha1/xlistenerset.go | 17 +++ applyconfiguration/internal/internal.go | 2 +- applyconfiguration/utils.go | 6 +- ....networking.k8s.io_backendtlspolicies.yaml | 1 - ...eway.networking.k8s.io_gatewayclasses.yaml | 1 - .../gateway.networking.k8s.io_gateways.yaml | 1 - .../gateway.networking.k8s.io_grpcroutes.yaml | 1 - .../gateway.networking.k8s.io_httproutes.yaml | 1 - ...way.networking.k8s.io_referencegrants.yaml | 1 - .../gateway.networking.k8s.io_tcproutes.yaml | 1 - .../gateway.networking.k8s.io_tlsroutes.yaml | 1 - .../gateway.networking.k8s.io_udproutes.yaml | 1 - ...king.x-k8s.io_xbackendtrafficpolicies.yaml | 1 - ...way.networking.x-k8s.io_xlistenersets.yaml | 1 - ...eway.networking.k8s.io_gatewayclasses.yaml | 1 - .../gateway.networking.k8s.io_gateways.yaml | 1 - .../gateway.networking.k8s.io_grpcroutes.yaml | 1 - .../gateway.networking.k8s.io_httproutes.yaml | 1 - ...way.networking.k8s.io_referencegrants.yaml | 1 - go.mod | 54 ++++---- go.sum | 127 +++++++++--------- .../versioned/fake/clientset_generated.go | 4 +- pkg/generated/openapi/zz_generated.openapi.go | 34 +++-- 40 files changed, 406 insertions(+), 128 deletions(-) diff --git a/.github/workflows/crd-validation.yml b/.github/workflows/crd-validation.yml index 4aa88c5a99..4daf0bb4ad 100644 --- a/.github/workflows/crd-validation.yml +++ b/.github/workflows/crd-validation.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: # Available versions at https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/HEAD/envtest-releases.yaml - k8s_version: [v1.33.0, v1.32.0, v1.31.0, v1.30.3, v1.29.5] + k8s_version: [v1.34.0, v1.33.0, v1.32.0, v1.31.0, v1.30.3] crd_channel: [standard, experimental] steps: - name: Checkout code diff --git a/applyconfiguration/apis/v1/gateway.go b/applyconfiguration/apis/v1/gateway.go index 98ee1b9ad0..f8e8ef1c88 100644 --- a/applyconfiguration/apis/v1/gateway.go +++ b/applyconfiguration/apis/v1/gateway.go @@ -82,6 +82,7 @@ func extractGateway(gateway *apisv1.Gateway, fieldManager string, subresource st b.WithAPIVersion("gateway.networking.k8s.io/v1") return b, nil } +func (b GatewayApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *GatewayApplyConfiguration) WithStatus(value *GatewayStatusApplyConfigur return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GatewayApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1/gatewayclass.go b/applyconfiguration/apis/v1/gatewayclass.go index fa6792f343..6decda5d97 100644 --- a/applyconfiguration/apis/v1/gatewayclass.go +++ b/applyconfiguration/apis/v1/gatewayclass.go @@ -80,6 +80,7 @@ func extractGatewayClass(gatewayClass *apisv1.GatewayClass, fieldManager string, b.WithAPIVersion("gateway.networking.k8s.io/v1") return b, nil } +func (b GatewayClassApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -255,8 +256,24 @@ func (b *GatewayClassApplyConfiguration) WithStatus(value *GatewayClassStatusApp return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GatewayClassApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1/grpcroute.go b/applyconfiguration/apis/v1/grpcroute.go index d7e0568e9c..0329721334 100644 --- a/applyconfiguration/apis/v1/grpcroute.go +++ b/applyconfiguration/apis/v1/grpcroute.go @@ -82,6 +82,7 @@ func extractGRPCRoute(gRPCRoute *apisv1.GRPCRoute, fieldManager string, subresou b.WithAPIVersion("gateway.networking.k8s.io/v1") return b, nil } +func (b GRPCRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *GRPCRouteApplyConfiguration) WithStatus(value *GRPCRouteStatusApplyConf return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GRPCRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1/httproute.go b/applyconfiguration/apis/v1/httproute.go index 31863abdb7..e3e8491656 100644 --- a/applyconfiguration/apis/v1/httproute.go +++ b/applyconfiguration/apis/v1/httproute.go @@ -82,6 +82,7 @@ func extractHTTPRoute(hTTPRoute *apisv1.HTTPRoute, fieldManager string, subresou b.WithAPIVersion("gateway.networking.k8s.io/v1") return b, nil } +func (b HTTPRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *HTTPRouteApplyConfiguration) WithStatus(value *HTTPRouteStatusApplyConf return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *HTTPRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha2/grpcroute.go b/applyconfiguration/apis/v1alpha2/grpcroute.go index 89e1e21b3d..630100094c 100644 --- a/applyconfiguration/apis/v1alpha2/grpcroute.go +++ b/applyconfiguration/apis/v1alpha2/grpcroute.go @@ -83,6 +83,7 @@ func extractGRPCRoute(gRPCRoute *apisv1alpha2.GRPCRoute, fieldManager string, su b.WithAPIVersion("gateway.networking.k8s.io/v1alpha2") return b, nil } +func (b GRPCRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *GRPCRouteApplyConfiguration) WithStatus(value *apisv1.GRPCRouteStatusAp return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GRPCRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GRPCRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha2/referencegrant.go b/applyconfiguration/apis/v1alpha2/referencegrant.go index 032cf3617c..94c63566ef 100644 --- a/applyconfiguration/apis/v1alpha2/referencegrant.go +++ b/applyconfiguration/apis/v1alpha2/referencegrant.go @@ -82,6 +82,7 @@ func extractReferenceGrant(referenceGrant *apisv1alpha2.ReferenceGrant, fieldMan b.WithAPIVersion("gateway.networking.k8s.io/v1alpha2") return b, nil } +func (b ReferenceGrantApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -249,8 +250,24 @@ func (b *ReferenceGrantApplyConfiguration) WithSpec(value *v1beta1.ReferenceGran return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *ReferenceGrantApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha2/tcproute.go b/applyconfiguration/apis/v1alpha2/tcproute.go index 1984f6f98d..036923a476 100644 --- a/applyconfiguration/apis/v1alpha2/tcproute.go +++ b/applyconfiguration/apis/v1alpha2/tcproute.go @@ -82,6 +82,7 @@ func extractTCPRoute(tCPRoute *apisv1alpha2.TCPRoute, fieldManager string, subre b.WithAPIVersion("gateway.networking.k8s.io/v1alpha2") return b, nil } +func (b TCPRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *TCPRouteApplyConfiguration) WithStatus(value *TCPRouteStatusApplyConfig return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *TCPRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *TCPRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *TCPRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *TCPRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha2/tlsroute.go b/applyconfiguration/apis/v1alpha2/tlsroute.go index d427cde2b4..759e9edadb 100644 --- a/applyconfiguration/apis/v1alpha2/tlsroute.go +++ b/applyconfiguration/apis/v1alpha2/tlsroute.go @@ -82,6 +82,7 @@ func extractTLSRoute(tLSRoute *apisv1alpha2.TLSRoute, fieldManager string, subre b.WithAPIVersion("gateway.networking.k8s.io/v1alpha2") return b, nil } +func (b TLSRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *TLSRouteApplyConfiguration) WithStatus(value *TLSRouteStatusApplyConfig return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *TLSRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha2/udproute.go b/applyconfiguration/apis/v1alpha2/udproute.go index 2403b41fb7..67b23c0bd1 100644 --- a/applyconfiguration/apis/v1alpha2/udproute.go +++ b/applyconfiguration/apis/v1alpha2/udproute.go @@ -82,6 +82,7 @@ func extractUDPRoute(uDPRoute *apisv1alpha2.UDPRoute, fieldManager string, subre b.WithAPIVersion("gateway.networking.k8s.io/v1alpha2") return b, nil } +func (b UDPRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *UDPRouteApplyConfiguration) WithStatus(value *UDPRouteStatusApplyConfig return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *UDPRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *UDPRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *UDPRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *UDPRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha3/backendtlspolicy.go b/applyconfiguration/apis/v1alpha3/backendtlspolicy.go index 2892af15db..dc5180214d 100644 --- a/applyconfiguration/apis/v1alpha3/backendtlspolicy.go +++ b/applyconfiguration/apis/v1alpha3/backendtlspolicy.go @@ -83,6 +83,7 @@ func extractBackendTLSPolicy(backendTLSPolicy *apisv1alpha3.BackendTLSPolicy, fi b.WithAPIVersion("gateway.networking.k8s.io/v1alpha3") return b, nil } +func (b BackendTLSPolicyApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *BackendTLSPolicyApplyConfiguration) WithStatus(value *v1alpha2.PolicySt return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *BackendTLSPolicyApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *BackendTLSPolicyApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1alpha3/tlsroute.go b/applyconfiguration/apis/v1alpha3/tlsroute.go index ff65509c71..766f654d9c 100644 --- a/applyconfiguration/apis/v1alpha3/tlsroute.go +++ b/applyconfiguration/apis/v1alpha3/tlsroute.go @@ -83,6 +83,7 @@ func extractTLSRoute(tLSRoute *apisv1alpha3.TLSRoute, fieldManager string, subre b.WithAPIVersion("gateway.networking.k8s.io/v1alpha3") return b, nil } +func (b TLSRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *TLSRouteApplyConfiguration) WithStatus(value *v1alpha2.TLSRouteStatusAp return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *TLSRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *TLSRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1beta1/gateway.go b/applyconfiguration/apis/v1beta1/gateway.go index 3b623558db..cb50454304 100644 --- a/applyconfiguration/apis/v1beta1/gateway.go +++ b/applyconfiguration/apis/v1beta1/gateway.go @@ -83,6 +83,7 @@ func extractGateway(gateway *apisv1beta1.Gateway, fieldManager string, subresour b.WithAPIVersion("gateway.networking.k8s.io/v1beta1") return b, nil } +func (b GatewayApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *GatewayApplyConfiguration) WithStatus(value *apisv1.GatewayStatusApplyC return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GatewayApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GatewayApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1beta1/gatewayclass.go b/applyconfiguration/apis/v1beta1/gatewayclass.go index d7cecd62e7..f4ecfeabd8 100644 --- a/applyconfiguration/apis/v1beta1/gatewayclass.go +++ b/applyconfiguration/apis/v1beta1/gatewayclass.go @@ -81,6 +81,7 @@ func extractGatewayClass(gatewayClass *apisv1beta1.GatewayClass, fieldManager st b.WithAPIVersion("gateway.networking.k8s.io/v1beta1") return b, nil } +func (b GatewayClassApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -256,8 +257,24 @@ func (b *GatewayClassApplyConfiguration) WithStatus(value *apisv1.GatewayClassSt return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *GatewayClassApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *GatewayClassApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1beta1/httproute.go b/applyconfiguration/apis/v1beta1/httproute.go index 18e2ca9672..1bb7243e32 100644 --- a/applyconfiguration/apis/v1beta1/httproute.go +++ b/applyconfiguration/apis/v1beta1/httproute.go @@ -83,6 +83,7 @@ func extractHTTPRoute(hTTPRoute *apisv1beta1.HTTPRoute, fieldManager string, sub b.WithAPIVersion("gateway.networking.k8s.io/v1beta1") return b, nil } +func (b HTTPRouteApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *HTTPRouteApplyConfiguration) WithStatus(value *apisv1.HTTPRouteStatusAp return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *HTTPRouteApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *HTTPRouteApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apis/v1beta1/referencegrant.go b/applyconfiguration/apis/v1beta1/referencegrant.go index 0ebd1cd168..e3fff69f0a 100644 --- a/applyconfiguration/apis/v1beta1/referencegrant.go +++ b/applyconfiguration/apis/v1beta1/referencegrant.go @@ -81,6 +81,7 @@ func extractReferenceGrant(referenceGrant *apisv1beta1.ReferenceGrant, fieldMana b.WithAPIVersion("gateway.networking.k8s.io/v1beta1") return b, nil } +func (b ReferenceGrantApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -248,8 +249,24 @@ func (b *ReferenceGrantApplyConfiguration) WithSpec(value *ReferenceGrantSpecApp return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *ReferenceGrantApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *ReferenceGrantApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go b/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go index 427d596546..99a39f03a7 100644 --- a/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go +++ b/applyconfiguration/apisx/v1alpha1/xbackendtrafficpolicy.go @@ -83,6 +83,7 @@ func extractXBackendTrafficPolicy(xBackendTrafficPolicy *apisxv1alpha1.XBackendT b.WithAPIVersion("gateway.networking.x-k8s.io/v1alpha1") return b, nil } +func (b XBackendTrafficPolicyApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -258,8 +259,24 @@ func (b *XBackendTrafficPolicyApplyConfiguration) WithStatus(value *v1alpha2.Pol return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *XBackendTrafficPolicyApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *XBackendTrafficPolicyApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *XBackendTrafficPolicyApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *XBackendTrafficPolicyApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/apisx/v1alpha1/xlistenerset.go b/applyconfiguration/apisx/v1alpha1/xlistenerset.go index 75519a1711..829f2d9405 100644 --- a/applyconfiguration/apisx/v1alpha1/xlistenerset.go +++ b/applyconfiguration/apisx/v1alpha1/xlistenerset.go @@ -82,6 +82,7 @@ func extractXListenerSet(xListenerSet *apisxv1alpha1.XListenerSet, fieldManager b.WithAPIVersion("gateway.networking.x-k8s.io/v1alpha1") return b, nil } +func (b XListenerSetApplyConfiguration) IsApplyConfiguration() {} // WithKind sets the Kind field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. @@ -257,8 +258,24 @@ func (b *XListenerSetApplyConfiguration) WithStatus(value *ListenerSetStatusAppl return b } +// GetKind retrieves the value of the Kind field in the declarative configuration. +func (b *XListenerSetApplyConfiguration) GetKind() *string { + return b.TypeMetaApplyConfiguration.Kind +} + +// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration. +func (b *XListenerSetApplyConfiguration) GetAPIVersion() *string { + return b.TypeMetaApplyConfiguration.APIVersion +} + // GetName retrieves the value of the Name field in the declarative configuration. func (b *XListenerSetApplyConfiguration) GetName() *string { b.ensureObjectMetaApplyConfigurationExists() return b.ObjectMetaApplyConfiguration.Name } + +// GetNamespace retrieves the value of the Namespace field in the declarative configuration. +func (b *XListenerSetApplyConfiguration) GetNamespace() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Namespace +} diff --git a/applyconfiguration/internal/internal.go b/applyconfiguration/internal/internal.go index 974c4bd20f..131b10d81d 100644 --- a/applyconfiguration/internal/internal.go +++ b/applyconfiguration/internal/internal.go @@ -22,7 +22,7 @@ import ( fmt "fmt" sync "sync" - typed "sigs.k8s.io/structured-merge-diff/v4/typed" + typed "sigs.k8s.io/structured-merge-diff/v6/typed" ) func Parser() *typed.Parser { diff --git a/applyconfiguration/utils.go b/applyconfiguration/utils.go index 274736cd6c..06ea379351 100644 --- a/applyconfiguration/utils.go +++ b/applyconfiguration/utils.go @@ -21,7 +21,7 @@ package applyconfiguration import ( runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" - testing "k8s.io/client-go/testing" + managedfields "k8s.io/apimachinery/pkg/util/managedfields" v1 "sigs.k8s.io/gateway-api/apis/v1" v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" v1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3" @@ -277,6 +277,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return nil } -func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter { - return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()} +func NewTypeConverter(scheme *runtime.Scheme) managedfields.TypeConverter { + return managedfields.NewSchemeTypeConverter(scheme, internal.Parser()) } diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index b5a05f1be6..c3beb7c42d 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: gateway.networking.k8s.io/policy: Direct name: backendtlspolicies.gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml index 831fbf4a8f..e022113f1f 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml index 6e154e9548..349b14cdfd 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: gateways.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml index 3a40ee2314..e714fd0f51 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml index 0329311362..9170ad2aa4 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: httproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml index ac146b270c..65afd84fc1 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml index 9de083257d..35a9e01a86 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: tcproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml index dce65f876b..d8b177e3e8 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml index 1f7be3d34c..305ddaba13 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: udproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml index 3e6d06b210..1a3881759d 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xbackendtrafficpolicies.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null labels: gateway.networking.k8s.io/policy: Direct name: xbackendtrafficpolicies.gateway.networking.x-k8s.io diff --git a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml index 6d5a5bd5f9..0d5def81a0 100644 --- a/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml +++ b/config/crd/experimental/gateway.networking.x-k8s.io_xlistenersets.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: experimental - creationTimestamp: null name: xlistenersets.gateway.networking.x-k8s.io spec: group: gateway.networking.x-k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml index 9268f6f173..a1973f5b64 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard - creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml index 8b7b0a02e5..98914347d2 100644 --- a/config/crd/standard/gateway.networking.k8s.io_gateways.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_gateways.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard - creationTimestamp: null name: gateways.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml index 4e81b08878..b02f9a41d1 100644 --- a/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard - creationTimestamp: null name: grpcroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml index dfa6af4c77..b57a508f39 100644 --- a/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard - creationTimestamp: null name: httproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml index 6a2d368971..d25ccd2753 100644 --- a/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml +++ b/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml @@ -5,7 +5,6 @@ metadata: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.3.0 gateway.networking.k8s.io/channel: standard - creationTimestamp: null name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io diff --git a/go.mod b/go.mod index bd1a6d9147..3359ba2e1c 100644 --- a/go.mod +++ b/go.mod @@ -10,18 +10,18 @@ require ( golang.org/x/sync v0.16.0 google.golang.org/grpc v1.75.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 - google.golang.org/protobuf v1.36.7 - k8s.io/api v0.33.4 - k8s.io/apiextensions-apiserver v0.33.4 - k8s.io/apimachinery v0.33.4 - k8s.io/client-go v0.33.4 - k8s.io/code-generator v0.33.4 - k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 + google.golang.org/protobuf v1.36.8 + k8s.io/api v0.34.0 + k8s.io/apiextensions-apiserver v0.34.0 + k8s.io/apimachinery v0.34.0 + k8s.io/client-go v0.34.0 + k8s.io/code-generator v0.34.0 + k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 + k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/controller-tools v0.18.0 - sigs.k8s.io/structured-merge-diff/v4 v4.7.0 - sigs.k8s.io/yaml v1.5.0 + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 + sigs.k8s.io/yaml v1.6.0 ) require ( @@ -30,18 +30,18 @@ require ( github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.12.0 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fatih/color v1.18.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-logr/logr v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonpointer v0.21.2 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/goccy/go-yaml v1.18.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect @@ -50,40 +50,42 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.23.0 // indirect + github.com/prometheus/procfs v0.17.0 // indirect github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.7 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.41.0 // indirect - golang.org/x/mod v0.26.0 // indirect + golang.org/x/mod v0.27.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/term v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.35.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.36.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 // indirect + k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d // indirect k8s.io/klog/v2 v2.130.1 // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 4120b93f2a..6abcd96c8a 100644 --- a/go.sum +++ b/go.sum @@ -19,28 +19,28 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elastic/crd-ref-docs v0.2.0 h1:U17MyGX71j4qfKTvYxbR4qZGoA1hc2thy7kseGYmP+o= github.com/elastic/crd-ref-docs v0.2.0/go.mod h1:0bklkJhTG7nC6AVsdDi0wt5bGoqvzdZSzMMQkilZ6XM= -github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= -github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA= +github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -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-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= 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/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= @@ -51,9 +51,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= -github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -79,8 +78,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -97,8 +96,9 @@ github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVO github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -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/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= @@ -111,26 +111,25 @@ github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= +github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -166,8 +165,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= -go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -175,8 +174,8 @@ golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -203,14 +202,14 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -223,19 +222,19 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -246,35 +245,33 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk= -k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc= -k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU= -k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs= -k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s= -k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw= -k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY= -k8s.io/code-generator v0.33.4 h1:DiA801QxqApRIBh3OWULasVAUA237XnYvFNMh+E34Y8= -k8s.io/code-generator v0.33.4/go.mod h1:ifWxKWhEl/Z1K7WmWAyOBEf3ex/i546ingCzLC8YVIY= -k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= -k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE= +k8s.io/api v0.34.0/go.mod h1:YzgkIzOOlhl9uwWCZNqpw6RJy9L2FK4dlJeayUoydug= +k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc= +k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0= +k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0= +k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo= +k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY= +k8s.io/code-generator v0.34.0 h1:Ze2i1QsvUprIlX3oHiGv09BFQRLCz+StA8qKwwFzees= +k8s.io/code-generator v0.34.0/go.mod h1:Py2+4w2HXItL8CGhks8uI/wS3Y93wPKO/9mBQUYNua0= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d h1:qUrYOinhdAUL0xxhA4gPqogPBaS9nIq2l2kTb6pmeB0= +k8s.io/gengo/v2 v2.0.0-20250820003526-c297c0c1eb9d/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaCjDbf07wVh6yaUlTpunnkE= +k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= +k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= sigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE= sigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= -sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index b1600ecbd3..78e540a88d 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -113,8 +113,8 @@ func NewClientset(objects ...runtime.Object) *Clientset { cs.AddReactor("*", "*", testing.ObjectReaction(o)) cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { var opts metav1.ListOptions - if watchActcion, ok := action.(testing.WatchActionImpl); ok { - opts = watchActcion.ListOptions + if watchAction, ok := action.(testing.WatchActionImpl); ok { + opts = watchAction.ListOptions } gvr := action.GetResource() ns := action.GetNamespace() diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 1451e17d9e..111ea8af74 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -2867,7 +2867,8 @@ func schema_sigsk8sio_gateway_api_apis_v1_AllowedRoutes(ref common.ReferenceCall return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "AllowedRoutes defines which Routes may be attached to this Listener.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "namespaces": { VendorExtensible: spec.VendorExtensible{ @@ -2961,7 +2962,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_BackendRef(ref common.ReferenceCallbac return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "BackendRef defines how a Route should forward a request to a Kubernetes resource.\n\nNote that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.", + Description: "BackendRef defines how a Route should forward a request to a Kubernetes resource.\n\nNote that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.\n\n\n\nWhen the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port.\n\nImplementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726.\n\nIf a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service.\n\nIf a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason.\n\n\n\nNote that when the BackendTLSPolicy object is enabled by the implementation, there are some extra rules about validity to consider here. See the fields where this struct is used for more information about the exact behavior.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { @@ -4441,7 +4442,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPBackendRef(ref common.ReferenceCal return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPBackendRef defines how a HTTPRoute should forward an HTTP request.", + Description: "HTTPBackendRef defines how a HTTPRoute forwards a HTTP request.\n\nNote that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.\n\n\n\nWhen the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port.\n\nImplementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726.\n\nIf a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service.\n\nIf a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason.\n\n", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { @@ -4704,7 +4705,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPHeaderFilter(ref common.ReferenceC return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPHeaderFilter defines a filter that modifies the headers of an HTTP request or response.", + Description: "HTTPHeaderFilter defines a filter that modifies the headers of an HTTP request or response. Only one action for a given header name is permitted. Filters specifying multiple actions of the same or different type for any one header name are invalid. Configuration to set or add multiple values for a header must use RFC 7230 header value formatting, separating each value with a comma.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "set": { @@ -4847,7 +4848,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPPathModifier(ref common.ReferenceC return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPPathModifier defines configuration for path modifiers. ", + Description: "HTTPPathModifier defines configuration for path modifiers.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { @@ -5055,7 +5056,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteFilter(ref common.ReferenceCa return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter.", + Description: "HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter.\n\n ", Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { @@ -5500,7 +5501,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPRouteTimeouts(ref common.Reference return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute.", + Description: "HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. Timeout values are represented with Gateway API Duration formatting.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "request": { @@ -5527,7 +5528,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_HTTPURLRewriteFilter(ref common.Refere return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "HTTPURLRewriteFilter defines a filter that modifies a request during forwarding. At most one of these filters may be used on a Route rule. This MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter.\n\nSupport: Extended\n\n", + Description: "HTTPURLRewriteFilter defines a filter that modifies a request during forwarding. At most one of these filters may be used on a Route rule. This MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter.\n\nSupport: Extended", Type: []string{"object"}, Properties: map[string]spec.Schema{ "hostname": { @@ -5715,7 +5716,8 @@ func schema_sigsk8sio_gateway_api_apis_v1_ListenerTLSConfig(ref common.Reference return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "ListenerTLSConfig describes a TLS configuration for a listener.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "mode": { SchemaProps: spec.SchemaProps{ @@ -5937,7 +5939,7 @@ func schema_sigsk8sio_gateway_api_apis_v1_ParentReference(ref common.ReferenceCa return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). The only kind of parent resource with \"Core\" support is Gateway. This API may be extended in the future to support additional kinds of parent resources, such as HTTPRoute.\n\nNote that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.", + Description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support:\n\n* Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only)\n\nThis API may be extended in the future to support additional kinds of parent resources.\n\nThe API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { @@ -5994,7 +5996,8 @@ func schema_sigsk8sio_gateway_api_apis_v1_RouteGroupKind(ref common.ReferenceCal return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "RouteGroupKind indicates the group and kind of a Route resource.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ @@ -6181,7 +6184,8 @@ func schema_sigsk8sio_gateway_api_apis_v1_SessionPersistence(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "SessionPersistence defines the desired state of SessionPersistence.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "sessionName": { SchemaProps: spec.SchemaProps{ @@ -6418,7 +6422,8 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_LocalPolicyTargetReference(ref c return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "LocalPolicyTargetReference identifies an API object to apply a direct or inherited policy to. This should be used as part of Policy resources that can target Gateway API resources. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "group": { SchemaProps: spec.SchemaProps{ @@ -6598,7 +6603,8 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha2_PolicyStatus(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "PolicyStatus defines the common attributes that all Policies should include within their status.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "ancestors": { VendorExtensible: spec.VendorExtensible{ From 56cc1c41b95b6998504eb2deb7702900e4325e12 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal <68310924+sarthyparty@users.noreply.github.com> Date: Thu, 28 Aug 2025 14:01:10 -0700 Subject: [PATCH 156/224] Add GRPCRoute weighted backendRefs test (#3962) * Add GRPCRoute weighted backendRefs test * fix verify * fix verify again --- conformance/tests/grpcroute-weight.go | 98 ++++++++++ conformance/tests/grpcroute-weight.yaml | 19 ++ conformance/tests/httproute-weight.go | 118 +++--------- conformance/tests/mesh/grpcroute-weight.go | 83 +++++++++ conformance/tests/mesh/grpcroute-weight.yaml | 22 +++ conformance/tests/mesh/httproute-weight.go | 108 +++-------- conformance/utils/echo/pod.go | 40 +++- conformance/utils/grpc/grpc.go | 18 ++ conformance/utils/http/http.go | 51 +---- conformance/utils/weight/senders.go | 31 ++++ conformance/utils/weight/weight.go | 185 +++++++++++++++++++ 11 files changed, 541 insertions(+), 232 deletions(-) create mode 100644 conformance/tests/grpcroute-weight.go create mode 100644 conformance/tests/grpcroute-weight.yaml create mode 100644 conformance/tests/mesh/grpcroute-weight.go create mode 100644 conformance/tests/mesh/grpcroute-weight.yaml create mode 100644 conformance/utils/weight/senders.go create mode 100644 conformance/utils/weight/weight.go diff --git a/conformance/tests/grpcroute-weight.go b/conformance/tests/grpcroute-weight.go new file mode 100644 index 0000000000..ba5a4d5681 --- /dev/null +++ b/conformance/tests/grpcroute-weight.go @@ -0,0 +1,98 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "fmt" + "testing" + + "google.golang.org/grpc/codes" + "k8s.io/apimachinery/pkg/types" + + v1 "sigs.k8s.io/gateway-api/apis/v1" + pb "sigs.k8s.io/gateway-api/conformance/echo-basic/grpcechoserver" + "sigs.k8s.io/gateway-api/conformance/utils/grpc" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/weight" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, GRPCRouteWeight) +} + +var GRPCRouteWeight = suite.ConformanceTest{ + ShortName: "GRPCRouteWeight", + Description: "An GRPCRoute with weighted backends", + Manifests: []string{"tests/grpcroute-weight.yaml"}, + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportGRPCRoute, + }, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + var ( + ns = "gateway-conformance-infra" + routeNN = types.NamespacedName{Name: "weighted-backends", Namespace: ns} + gwNN = types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr = kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &v1.GRPCRoute{}, true, routeNN) + ) + + t.Run("Requests should have a distribution that matches the weight", func(t *testing.T) { + expected := grpc.ExpectedResponse{ + EchoRequest: &pb.EchoRequest{}, + Response: grpc.Response{Code: codes.OK}, + Namespace: "gateway-conformance-infra", + } + + // Assert request succeeds before doing our distribution check + grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.GRPCClient, suite.TimeoutConfig, gwAddr, expected) + + expectedWeights := map[string]float64{ + "grpc-infra-backend-v1": 0.7, + "grpc-infra-backend-v2": 0.3, + "grpc-infra-backend-v3": 0.0, + } + + sender := weight.NewFunctionBasedSender(func() (string, error) { + uniqueExpected := expected + if err := grpc.AddEntropy(&uniqueExpected); err != nil { + return "", fmt.Errorf("error adding entropy: %w", err) + } + client := &grpc.DefaultClient{} + defer client.Close() + resp, err := client.SendRPC(t, gwAddr, uniqueExpected, suite.TimeoutConfig.MaxTimeToConsistency) + if err != nil { + return "", fmt.Errorf("failed to send gRPC request: %w", err) + } + if resp.Code != codes.OK { + return "", fmt.Errorf("expected OK response, got %v", resp.Code) + } + return resp.Response.GetAssertions().GetContext().GetPod(), nil + }) + + for i := 0; i < weight.MaxTestRetries; i++ { + if err := weight.TestWeightedDistribution(sender, expectedWeights); err != nil { + t.Logf("Traffic distribution test failed (%d/%d): %s", i+1, weight.MaxTestRetries, err) + } else { + return + } + } + t.Fatal("Weighted distribution tests failed") + }) + }, +} diff --git a/conformance/tests/grpcroute-weight.yaml b/conformance/tests/grpcroute-weight.yaml new file mode 100644 index 0000000000..944d3b7486 --- /dev/null +++ b/conformance/tests/grpcroute-weight.yaml @@ -0,0 +1,19 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: weighted-backends + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - backendRefs: + - name: grpc-infra-backend-v1 + port: 8080 + weight: 70 + - name: grpc-infra-backend-v2 + port: 8080 + weight: 30 + - name: grpc-infra-backend-v3 + port: 8080 + weight: 0 diff --git a/conformance/tests/httproute-weight.go b/conformance/tests/httproute-weight.go index bafd768ad8..f7a1254f7d 100644 --- a/conformance/tests/httproute-weight.go +++ b/conformance/tests/httproute-weight.go @@ -17,21 +17,15 @@ limitations under the License. package tests import ( - "cmp" - "errors" "fmt" - "math" - "slices" - "strings" - "sync" "testing" - "golang.org/x/sync/errgroup" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/weight" "sigs.k8s.io/gateway-api/pkg/features" ) @@ -69,9 +63,31 @@ var HTTPRouteWeight = suite.ConformanceTest{ // Assert request succeeds before doing our distribution check http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expected) - for i := 0; i < 10; i++ { - if err := testDistribution(t, suite, gwAddr, expected); err != nil { - t.Logf("Traffic distribution test failed (%d/10): %s", i+1, err) + expectedWeights := map[string]float64{ + "infra-backend-v1": 0.7, + "infra-backend-v2": 0.3, + "infra-backend-v3": 0.0, + } + + sender := weight.NewFunctionBasedSender(func() (string, error) { + uniqueExpected := expected + if err := http.AddEntropy(&uniqueExpected); err != nil { + return "", fmt.Errorf("error adding entropy: %w", err) + } + req := http.MakeRequest(t, &uniqueExpected, gwAddr, "HTTP", "http") + cReq, cRes, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + return "", fmt.Errorf("failed to roundtrip request: %w", err) + } + if err := http.CompareRoundTrip(t, &req, cReq, cRes, expected); err != nil { + return "", fmt.Errorf("response expectation failed for request: %w", err) + } + return cReq.Pod, nil + }) + + for i := 0; i < weight.MaxTestRetries; i++ { + if err := weight.TestWeightedDistribution(sender, expectedWeights); err != nil { + t.Logf("Traffic distribution test failed (%d/%d): %s", i+1, weight.MaxTestRetries, err) } else { return } @@ -80,85 +96,3 @@ var HTTPRouteWeight = suite.ConformanceTest{ }) }, } - -func testDistribution(t *testing.T, suite *suite.ConformanceTestSuite, gwAddr string, expected http.ExpectedResponse) error { - const ( - concurrentRequests = 10 - tolerancePercentage = 0.05 - totalRequests = 500.0 - ) - var ( - roundTripper = suite.RoundTripper - - g errgroup.Group - seenMutex sync.Mutex - seen = make(map[string]float64, 3 /* number of backends */) - expectedWeights = map[string]float64{ - "infra-backend-v1": 0.7, - "infra-backend-v2": 0.3, - "infra-backend-v3": 0.0, - } - ) - g.SetLimit(concurrentRequests) - for i := 0.0; i < totalRequests; i++ { - g.Go(func() error { - uniqueExpected := expected - if err := http.AddEntropy(&uniqueExpected); err != nil { - return fmt.Errorf("error adding entropy: %w", err) - } - req := http.MakeRequest(t, &uniqueExpected, gwAddr, "HTTP", "http") - cReq, cRes, err := roundTripper.CaptureRoundTrip(req) - if err != nil { - return fmt.Errorf("failed to roundtrip request: %w", err) - } - if err := http.CompareRoundTrip(t, &req, cReq, cRes, expected); err != nil { - return fmt.Errorf("response expectation failed for request: %w", err) - } - - seenMutex.Lock() - defer seenMutex.Unlock() - - for expectedBackend := range expectedWeights { - if strings.HasPrefix(cReq.Pod, expectedBackend) { - seen[expectedBackend]++ - return nil - } - } - - return fmt.Errorf("request was handled by an unexpected pod %q", cReq.Pod) - }) - } - - if err := g.Wait(); err != nil { - return fmt.Errorf("error while sending requests: %w", err) - } - - var errs []error - if len(seen) != 2 { - errs = append(errs, fmt.Errorf("expected only two backends to receive traffic")) - } - - for wantBackend, wantPercent := range expectedWeights { - gotCount, ok := seen[wantBackend] - - if !ok && wantPercent != 0.0 { - errs = append(errs, fmt.Errorf("expect traffic to hit backend %q - but none was received", wantBackend)) - continue - } - - gotPercent := gotCount / totalRequests - - if math.Abs(gotPercent-wantPercent) > tolerancePercentage { - errs = append(errs, fmt.Errorf("backend %q weighted traffic of %v not within tolerance %v (+/-%f)", - wantBackend, - gotPercent, - wantPercent, - tolerancePercentage, - )) - } - } - slices.SortFunc(errs, func(a, b error) int { - return cmp.Compare(a.Error(), b.Error()) - }) - return errors.Join(errs...) -} diff --git a/conformance/tests/mesh/grpcroute-weight.go b/conformance/tests/mesh/grpcroute-weight.go new file mode 100644 index 0000000000..0157119691 --- /dev/null +++ b/conformance/tests/mesh/grpcroute-weight.go @@ -0,0 +1,83 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package meshtests + +import ( + "fmt" + "testing" + + "sigs.k8s.io/gateway-api/conformance/utils/echo" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/weight" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + MeshConformanceTests = append(MeshConformanceTests, MeshGRPCRouteWeight) +} + +var MeshGRPCRouteWeight = suite.ConformanceTest{ + ShortName: "MeshGRPCRouteWeight", + Description: "A GRPCRoute with weighted backends in mesh mode", + Manifests: []string{"tests/mesh/grpcroute-weight.yaml"}, + Features: []features.FeatureName{ + features.SupportMesh, + features.SupportGRPCRoute, + }, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1) + + t.Run("Requests should have a distribution that matches the weight", func(t *testing.T) { + // Create a gRPC request using the mesh client framework + expected := http.ExpectedResponse{ + Request: http.Request{Protocol: "grpc", Path: "", Host: "echo:7070"}, + Response: http.Response{StatusCode: 200}, + Namespace: "gateway-conformance-mesh", + } + + // Assert request succeeds before doing our distribution check + client.MakeRequestAndExpectEventuallyConsistentResponse(t, expected, s.TimeoutConfig) + + expectedWeights := map[string]float64{ + "echo-v1": 0.7, + "echo-v2": 0.3, + } + + sender := weight.NewFunctionBasedSender(func() (string, error) { + uniqueExpected := expected + if err := http.AddEntropy(&uniqueExpected); err != nil { + return "", fmt.Errorf("error adding entropy: %w", err) + } + _, cRes, err := client.CaptureRequestResponseAndCompare(t, uniqueExpected) + if err != nil { + return "", fmt.Errorf("failed gRPC mesh request: %w", err) + } + return cRes.Hostname, nil + }) + + for i := 0; i < weight.MaxTestRetries; i++ { + if err := weight.TestWeightedDistribution(sender, expectedWeights); err != nil { + t.Logf("Traffic distribution test failed (%d/%d): %s", i+1, weight.MaxTestRetries, err) + } else { + return + } + } + t.Fatal("Weighted distribution tests failed") + }) + }, +} diff --git a/conformance/tests/mesh/grpcroute-weight.yaml b/conformance/tests/mesh/grpcroute-weight.yaml new file mode 100644 index 0000000000..b14eb7772c --- /dev/null +++ b/conformance/tests/mesh/grpcroute-weight.yaml @@ -0,0 +1,22 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: mesh-grpc-weighted-backends + namespace: gateway-conformance-mesh +spec: + parentRefs: + - group: "" + kind: Service + name: echo + port: 7070 + rules: + - backendRefs: + - name: echo-v1 + port: 7070 + weight: 70 + - name: echo-v2 + port: 7070 + weight: 30 + - name: echo-v3 + port: 7070 + weight: 0 diff --git a/conformance/tests/mesh/httproute-weight.go b/conformance/tests/mesh/httproute-weight.go index 844d5471e7..ceccca95f1 100644 --- a/conformance/tests/mesh/httproute-weight.go +++ b/conformance/tests/mesh/httproute-weight.go @@ -17,20 +17,13 @@ limitations under the License. package meshtests import ( - "cmp" - "errors" "fmt" - "math" - "slices" - "strings" - "sync" "testing" - "golang.org/x/sync/errgroup" - "sigs.k8s.io/gateway-api/conformance/utils/echo" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/conformance/utils/weight" "sigs.k8s.io/gateway-api/pkg/features" ) @@ -59,89 +52,32 @@ var MeshHTTPRouteWeight = suite.ConformanceTest{ // Assert request succeeds before doing our distribution check client.MakeRequestAndExpectEventuallyConsistentResponse(t, expected, s.TimeoutConfig) - for i := 0; i < 10; i++ { - if err := testDistribution(t, client, expected); err != nil { - t.Logf("Traffic distribution test failed (%d/10): %s", i+1, err) - } else { - return - } - } - t.Fatal("Weighted distribution tests failed") - }) - }, -} -func testDistribution(t *testing.T, client echo.MeshPod, expected http.ExpectedResponse) error { - const ( - concurrentRequests = 10 - tolerancePercentage = 0.05 - totalRequests = 500.0 - ) - var ( - g errgroup.Group - seenMutex sync.Mutex - seen = make(map[string]float64, 2 /* number of backends */) - expectedWeights = map[string]float64{ - "echo-v1": 0.7, - "echo-v2": 0.3, - } - ) - g.SetLimit(concurrentRequests) - for i := 0.0; i < totalRequests; i++ { - g.Go(func() error { - uniqueExpected := expected - if err := http.AddEntropy(&uniqueExpected); err != nil { - return fmt.Errorf("error adding entropy: %w", err) - } - _, cRes, err := client.CaptureRequestResponseAndCompare(t, uniqueExpected) - if err != nil { - return fmt.Errorf("failed: %w", err) + expectedWeights := map[string]float64{ + "echo-v1": 0.7, + "echo-v2": 0.3, } - seenMutex.Lock() - defer seenMutex.Unlock() + sender := weight.NewFunctionBasedSender(func() (string, error) { + uniqueExpected := expected + if err := http.AddEntropy(&uniqueExpected); err != nil { + return "", fmt.Errorf("error adding entropy: %w", err) + } + _, cRes, err := client.CaptureRequestResponseAndCompare(t, uniqueExpected) + if err != nil { + return "", fmt.Errorf("failed mesh request: %w", err) + } + return cRes.Hostname, nil + }) - for expectedBackend := range expectedWeights { - if strings.HasPrefix(cRes.Hostname, expectedBackend) { - seen[expectedBackend]++ - return nil + for i := 0; i < weight.MaxTestRetries; i++ { + if err := weight.TestWeightedDistribution(sender, expectedWeights); err != nil { + t.Logf("Traffic distribution test failed (%d/%d): %s", i+1, weight.MaxTestRetries, err) + } else { + return } } - - return fmt.Errorf("request was handled by an unexpected pod %q", cRes.Hostname) + t.Fatal("Weighted distribution tests failed") }) - } - - if err := g.Wait(); err != nil { - return fmt.Errorf("error while sending requests: %w", err) - } - - var errs []error - if len(seen) != 2 { - errs = append(errs, fmt.Errorf("expected only two backends to receive traffic")) - } - - for wantBackend, wantPercent := range expectedWeights { - gotCount, ok := seen[wantBackend] - - if !ok && wantPercent != 0.0 { - errs = append(errs, fmt.Errorf("expect traffic to hit backend %q - but none was received", wantBackend)) - continue - } - - gotPercent := gotCount / totalRequests - - if math.Abs(gotPercent-wantPercent) > tolerancePercentage { - errs = append(errs, fmt.Errorf("backend %q weighted traffic of %v not within tolerance %v (+/-%f)", - wantBackend, - gotPercent, - wantPercent, - tolerancePercentage, - )) - } - } - slices.SortFunc(errs, func(a, b error) int { - return cmp.Compare(a.Error(), b.Error()) - }) - return errors.Join(errs...) + }, } diff --git a/conformance/utils/echo/pod.go b/conformance/utils/echo/pod.go index dff03ed5fa..1a3e40fb6c 100644 --- a/conformance/utils/echo/pod.go +++ b/conformance/utils/echo/pod.go @@ -82,7 +82,15 @@ func makeRequest(t *testing.T, exp *http.ExpectedResponse) []string { if exp.Request.Host == "" { exp.Request.Host = "echo" } - if exp.Request.Method == "" { + + r := exp.Request + protocol := strings.ToLower(r.Protocol) + if protocol == "" { + protocol = "http" + } + + // Only set default method for HTTP protocols, not for gRPC + if protocol != "grpc" && exp.Request.Method == "" { exp.Request.Method = "GET" } @@ -96,14 +104,9 @@ func makeRequest(t *testing.T, exp *http.ExpectedResponse) []string { exp.Response.StatusCodes = []int{200} } - r := exp.Request - protocol := strings.ToLower(r.Protocol) - if protocol == "" { - protocol = "http" - } host := http.CalculateHost(t, r.Host, protocol) args := []string{"client", fmt.Sprintf("%s://%s%s", protocol, host, r.Path)} - if r.Method != "" { + if protocol != "grpc" && r.Method != "" { args = append(args, "--method="+r.Method) } for k, v := range r.Headers { @@ -118,11 +121,32 @@ func compareRequest(exp http.ExpectedResponse, resp Response) error { } wantReq := exp.ExpectedRequest wantResp := exp.Response + + // Parse the response status code statusCode, err := strconv.Atoi(resp.Code) if err != nil { return fmt.Errorf("invalid status code '%v': %v", resp.Code, err) } - if !slices.Contains(wantResp.StatusCodes, statusCode) { + + // Handle gRPC protocol special case for status code mapping + if strings.ToLower(exp.Request.Protocol) == "grpc" { + // For gRPC, we need to handle the status code mapping + // The Istio echo client reports HTTP status codes even for gRPC requests + expectedStatusCodes := make([]int, len(wantResp.StatusCodes)) + copy(expectedStatusCodes, wantResp.StatusCodes) + + // Map gRPC status 0 (OK) to HTTP 200 if needed + for i, code := range expectedStatusCodes { + if code == 0 { + expectedStatusCodes[i] = 200 + } + } + + if !slices.Contains(expectedStatusCodes, statusCode) { + return fmt.Errorf("wanted gRPC status code to be one of %v (mapped to HTTP), got %d", wantResp.StatusCodes, statusCode) + } + } else if !slices.Contains(wantResp.StatusCodes, statusCode) { + // For HTTP, use the status codes directly return fmt.Errorf("wanted status code to be one of %v, got %d", wantResp.StatusCodes, statusCode) } if wantReq.Headers != nil { diff --git a/conformance/utils/grpc/grpc.go b/conformance/utils/grpc/grpc.go index 70adfe2eac..25b1d7abf8 100644 --- a/conformance/utils/grpc/grpc.go +++ b/conformance/utils/grpc/grpc.go @@ -35,6 +35,7 @@ import ( "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/tlog" + "sigs.k8s.io/gateway-api/conformance/utils/weight" ) const ( @@ -289,3 +290,20 @@ func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, c Client, ti http.AwaitConvergence(t, timeoutConfig.RequiredConsecutiveSuccesses, timeoutConfig.MaxTimeToConsistency, sendRPC) tlog.Logf(t, "Request passed") } + +// AddEntropy adds randomness to ExpectedResponse to avoid caching issues and ensure each request is unique. +// It randomly chooses to add a delay, random metadata, or both. +func AddEntropy(exp *ExpectedResponse) error { + addRandomMetadata := func(randomValue string) error { + if exp.RequestMetadata == nil { + exp.RequestMetadata = &RequestMetadata{} + } + if exp.RequestMetadata.Metadata == nil { + exp.RequestMetadata.Metadata = make(map[string]string) + } + exp.RequestMetadata.Metadata["x-jitter"] = randomValue + return nil + } + + return weight.AddRandomEntropy(addRandomMetadata) +} diff --git a/conformance/utils/http/http.go b/conformance/utils/http/http.go index 6cd68dd084..2d116423c1 100644 --- a/conformance/utils/http/http.go +++ b/conformance/utils/http/http.go @@ -17,9 +17,7 @@ limitations under the License. package http import ( - "crypto/rand" "fmt" - "math/big" "net" "net/url" "slices" @@ -30,6 +28,7 @@ import ( "sigs.k8s.io/gateway-api/conformance/utils/config" "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" "sigs.k8s.io/gateway-api/conformance/utils/tlog" + "sigs.k8s.io/gateway-api/conformance/utils/weight" ) // ExpectedResponse defines the response expected for a given request. @@ -497,53 +496,13 @@ func setRedirectRequestDefaults(req *roundtripper.Request, cRes *roundtripper.Ca } } -// addEntropy adds jitter to the request by adding either a delay up to 1 second, or a random header value, or both. +// AddEntropy adds jitter to the request by adding either a delay up to 1 second, or a random header value, or both. func AddEntropy(exp *ExpectedResponse) error { - randomNumber := func(limit int64) (*int64, error) { - number, err := rand.Int(rand.Reader, big.NewInt(limit)) - if err != nil { - return nil, err - } - n := number.Int64() - return &n, nil - } - - // adds a delay - delay := func(limit int64) error { - randomSleepDuration, err := randomNumber(limit) - if err != nil { - return err - } - time.Sleep(time.Duration(*randomSleepDuration) * time.Millisecond) - return nil - } - // adds random header value - randomHeader := func(limit int64) error { - randomHeaderValue, err := randomNumber(limit) - if err != nil { - return err - } + addRandomHeader := func(randomValue string) error { exp.Request.Headers = make(map[string]string) - exp.Request.Headers["X-Jitter"] = fmt.Sprintf("%d", *randomHeaderValue) + exp.Request.Headers["X-Jitter"] = randomValue return nil } - random, err := randomNumber(3) - if err != nil { - return err - } - - switch *random { - case 0: - return delay(1000) - case 1: - return randomHeader(10000) - case 2: - if err := delay(1000); err != nil { - return err - } - return randomHeader(10000) - default: - return fmt.Errorf("invalid random value: %d", *random) - } + return weight.AddRandomEntropy(addRandomHeader) } diff --git a/conformance/utils/weight/senders.go b/conformance/utils/weight/senders.go new file mode 100644 index 0000000000..304ead0e9f --- /dev/null +++ b/conformance/utils/weight/senders.go @@ -0,0 +1,31 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package weight + +// FunctionBasedSender implements RequestSender using a function +type FunctionBasedSender struct { + sendFunc func() (string, error) +} + +func (s *FunctionBasedSender) SendRequest() (string, error) { + return s.sendFunc() +} + +// NewFunctionBasedSender creates a RequestSender from a function +func NewFunctionBasedSender(sendFunc func() (string, error)) RequestSender { + return &FunctionBasedSender{sendFunc: sendFunc} +} diff --git a/conformance/utils/weight/weight.go b/conformance/utils/weight/weight.go new file mode 100644 index 0000000000..123719ae17 --- /dev/null +++ b/conformance/utils/weight/weight.go @@ -0,0 +1,185 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package weight + +import ( + "cmp" + "crypto/rand" + "errors" + "fmt" + "math" + "math/big" + "slices" + "strconv" + "strings" + "sync" + "time" + + "golang.org/x/sync/errgroup" +) + +const ( + // MaxTestRetries is the maximum number of times to retry the weight distribution test + // if it fails due to statistical variance before considering it a real failure + MaxTestRetries = 10 +) + +// RequestSender defines an interface for sending requests (HTTP, gRPC, or mesh) +type RequestSender interface { + SendRequest() (podName string, err error) +} + +// extractBackendName extracts the backend name from a pod name by removing deployment and pod hash suffixes +func extractBackendName(podName string) string { + // Pod names follow the pattern: {backend-name}-{deployment-hash}-{pod-hash} + // We need to remove the last two dash-separated components + parts := strings.Split(podName, "-") + if len(parts) < 3 { + return podName // fallback to original name if pattern doesn't match + } + // Remove last two components (deployment hash and pod hash) + return strings.Join(parts[:len(parts)-2], "-") +} + +// TestWeightedDistribution tests that requests are distributed according to expected weights +func TestWeightedDistribution(sender RequestSender, expectedWeights map[string]float64) error { + const ( + concurrentRequests = 10 + tolerancePercentage = 0.05 + totalRequests = 500 + ) + + var ( + g errgroup.Group + seenMutex sync.Mutex + seen = make(map[string]float64, len(expectedWeights)) + ) + + g.SetLimit(concurrentRequests) + for i := 0; i < totalRequests; i++ { + g.Go(func() error { + podName, err := sender.SendRequest() + if err != nil { + return err + } + + // Extract the backend name from the pod name + backendName := extractBackendName(podName) + + seenMutex.Lock() + defer seenMutex.Unlock() + + if _, exists := expectedWeights[backendName]; exists { + seen[backendName]++ + return nil + } + + return fmt.Errorf("request was handled by an unexpected pod %q (extracted backend: %q)", podName, backendName) + }) + } + + if err := g.Wait(); err != nil { + return fmt.Errorf("error while sending requests: %w", err) + } + + // Count how many backends should receive traffic (weight > 0) + expectedActiveBackends := 0 + for _, weight := range expectedWeights { + if weight > 0.0 { + expectedActiveBackends++ + } + } + + var errs []error + if len(seen) != expectedActiveBackends { + errs = append(errs, fmt.Errorf("expected %d backends to receive traffic, but got %d", expectedActiveBackends, len(seen))) + } + + for wantBackend, wantPercent := range expectedWeights { + gotCount, ok := seen[wantBackend] + + if !ok && wantPercent != 0.0 { + errs = append(errs, fmt.Errorf("expect traffic to hit backend %q - but none was received", wantBackend)) + continue + } + + gotPercent := gotCount / float64(totalRequests) + + if math.Abs(gotPercent-wantPercent) > tolerancePercentage { + errs = append(errs, fmt.Errorf("backend %q weighted traffic of %v not within tolerance %v (+/-%f)", + wantBackend, + gotPercent, + wantPercent, + tolerancePercentage, + )) + } + } + + slices.SortFunc(errs, func(a, b error) int { + return cmp.Compare(a.Error(), b.Error()) + }) + return errors.Join(errs...) +} + +// Entropy utilities + +// addRandomDelay adds a random delay up to the specified limit in milliseconds +func addRandomDelay(limit int) { + n, err := rand.Int(rand.Reader, big.NewInt(int64(limit))) + if err != nil { + // Fallback to no delay if crypto/rand fails + return + } + randomSleepDuration := n.Int64() + time.Sleep(time.Duration(randomSleepDuration) * time.Millisecond) +} + +// AddRandomEntropy randomly chooses to add delay, random value, or both +// The addRandomValue function should be provided by the caller to handle +// protocol-specific ways of adding the random value (HTTP headers, gRPC metadata, etc.) +func AddRandomEntropy(addRandomValue func(string) error) error { + n, err := rand.Int(rand.Reader, big.NewInt(3)) + if err != nil { + // Fallback to case 0 if crypto/rand fails + addRandomDelay(1000) + return err + } + random := n.Int64() + + switch random { + case 0: + addRandomDelay(1000) + return nil + case 1: + valueN, err := rand.Int(rand.Reader, big.NewInt(10000)) + if err != nil { + return fmt.Errorf("failed to generate random value: %w", err) + } + randomValue := valueN.Int64() + return addRandomValue(strconv.FormatInt(randomValue, 10)) + case 2: + addRandomDelay(1000) + valueN, err := rand.Int(rand.Reader, big.NewInt(10000)) + if err != nil { + return fmt.Errorf("failed to generate random value: %w", err) + } + randomValue := valueN.Int64() + return addRandomValue(strconv.FormatInt(randomValue, 10)) + default: + return fmt.Errorf("invalid random value: %d", random) + } +} From 506bacdd62d6efada67dbed3e822be051a8eb469 Mon Sep 17 00:00:00 2001 From: Flynn Date: Thu, 28 Aug 2025 17:31:09 -0400 Subject: [PATCH 157/224] chore(build): Clean up excessive warnings from "make generate" (#4045) * chore(build): Clean up excessive warnings from "make generate" Signed-off-by: Flynn * chore(lint): Draconian gofumpt is Draconian Signed-off-by: Flynn --------- Signed-off-by: Flynn --- apis/v1alpha2/object_reference_types.go | 35 --- apis/v1alpha2/referencegrant_types.go | 8 - apis/v1alpha2/shared_types.go | 275 +++--------------------- apis/v1alpha3/shared_types.go | 60 ------ apis/v1beta1/gateway_types.go | 89 -------- apis/v1beta1/gatewayclass_types.go | 14 -- apis/v1beta1/httproute_types.go | 150 ------------- apis/v1beta1/object_reference_types.go | 35 --- apis/v1beta1/shared_types.go | 210 ------------------ apisx/v1alpha1/shared_types.go | 43 ++-- 10 files changed, 38 insertions(+), 881 deletions(-) diff --git a/apis/v1alpha2/object_reference_types.go b/apis/v1alpha2/object_reference_types.go index 13ae680cfe..3dea734b16 100644 --- a/apis/v1alpha2/object_reference_types.go +++ b/apis/v1alpha2/object_reference_types.go @@ -18,43 +18,8 @@ package v1alpha2 import v1 "sigs.k8s.io/gateway-api/apis/v1" -// LocalObjectReference identifies an API object within the namespace of the -// referrer. -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type LocalObjectReference = v1.LocalObjectReference -// SecretObjectReference identifies an API object including its namespace, -// defaulting to Secret. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type SecretObjectReference = v1.SecretObjectReference -// BackendObjectReference defines how an ObjectReference that is -// specific to BackendRef. It includes a few additional fields and features -// than a regular ObjectReference. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type BackendObjectReference = v1.BackendObjectReference diff --git a/apis/v1alpha2/referencegrant_types.go b/apis/v1alpha2/referencegrant_types.go index 372022f77c..2c23455004 100644 --- a/apis/v1alpha2/referencegrant_types.go +++ b/apis/v1alpha2/referencegrant_types.go @@ -59,16 +59,8 @@ type ReferenceGrantList struct { Items []ReferenceGrant `json:"items"` } -// ReferenceGrantSpec identifies a cross namespace relationship that is trusted -// for Gateway API. -// +k8s:deepcopy-gen=false type ReferenceGrantSpec = v1beta1.ReferenceGrantSpec -// ReferenceGrantFrom describes trusted namespaces and kinds. -// +k8s:deepcopy-gen=false type ReferenceGrantFrom = v1beta1.ReferenceGrantFrom -// ReferenceGrantTo describes what Kinds are allowed as targets of the -// references. -// +k8s:deepcopy-gen=false type ReferenceGrantTo = v1beta1.ReferenceGrantTo diff --git a/apis/v1alpha2/shared_types.go b/apis/v1alpha2/shared_types.go index 3d2f787909..df39d4253f 100644 --- a/apis/v1alpha2/shared_types.go +++ b/apis/v1alpha2/shared_types.go @@ -18,45 +18,14 @@ package v1alpha2 import v1 "sigs.k8s.io/gateway-api/apis/v1" -// ParentReference identifies an API object (usually a Gateway) that can be considered -// a parent of this resource (usually a route). The only kind of parent resource -// with "Core" support is Gateway. This API may be extended in the future to -// support additional kinds of parent resources, such as HTTPRoute. -// -// Note that there are specific rules for ParentRefs which cross namespace -// boundaries. Cross-namespace references are only valid if they are explicitly -// allowed by something in the namespace they are referring to. For example: -// Gateway has the AllowedRoutes field, and ReferenceGrant provides a -// generic way to enable any other kind of cross-namespace reference. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// +k8s:deepcopy-gen=false -type ParentReference = v1.ParentReference - -// CommonRouteSpec defines the common attributes that all Routes MUST include -// within their spec. -// +k8s:deepcopy-gen=false -type CommonRouteSpec = v1.CommonRouteSpec - -// PortNumber defines a network port. -type PortNumber = v1.PortNumber - -// BackendRef defines how a Route should forward a request to a Kubernetes -// resource. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// +k8s:deepcopy-gen=false -type BackendRef = v1.BackendRef - -// RouteConditionType is a type of condition for a route. -type RouteConditionType = v1.RouteConditionType - -// RouteConditionReason is a reason for a route condition. -type RouteConditionReason = v1.RouteConditionReason +type ( + ParentReference = v1.ParentReference + CommonRouteSpec = v1.CommonRouteSpec + PortNumber = v1.PortNumber + BackendRef = v1.BackendRef + RouteConditionType = v1.RouteConditionType + RouteConditionReason = v1.RouteConditionReason +) const ( // This condition indicates whether the route has been accepted or rejected @@ -140,215 +109,22 @@ const ( RouteReasonBackendNotFound RouteConditionReason = "BackendNotFound" ) -// RouteParentStatus describes the status of a route with respect to an -// associated Parent. -// +k8s:deepcopy-gen=false -type RouteParentStatus = v1.RouteParentStatus - -// RouteStatus defines the common attributes that all Routes MUST include within -// their status. -// +k8s:deepcopy-gen=false -type RouteStatus = v1.RouteStatus - -// Hostname is the fully qualified domain name of a network host. This matches -// the RFC 1123 definition of a hostname with 2 notable exceptions: -// -// 1. IPs are not allowed. -// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard -// label must appear by itself as the first label. -// -// Hostname can be "precise" which is a domain name without the terminating -// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a -// domain name prefixed with a single wildcard label (e.g. `*.example.com`). -// -// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case -// alphanumeric characters or '-', and must start and end with an alphanumeric -// character. No other punctuation is allowed. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Hostname = v1.Hostname - -// PreciseHostname is the fully qualified domain name of a network host. This -// matches the RFC 1123 definition of a hostname with 1 notable exception that -// numeric IP addresses are not allowed. -// -// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case -// alphanumeric characters or '-', and must start and end with an alphanumeric -// character. No other punctuation is allowed. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type PreciseHostname = v1.PreciseHostname - -// Group refers to a Kubernetes Group. It must either be an empty string or a -// RFC 1123 subdomain. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 -// -// Valid values include: -// -// * "" - empty string implies core Kubernetes API group -// * "networking.k8s.io" -// * "foo.example.com" -// -// Invalid values include: -// -// * "example.com/bar" - "/" is an invalid character -// -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -type Group = v1.Group - -// Kind refers to a Kubernetes Kind. -// -// Valid values include: -// -// * "Service" -// * "HTTPRoute" -// -// Invalid values include: -// -// * "invalid/kind" - "/" is an invalid character -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=63 -// +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` -type Kind = v1.Kind - -// ObjectName refers to the name of a Kubernetes object. -// Object names can have a variety of forms, including RFC1123 subdomains, -// RFC 1123 labels, or RFC 1035 labels. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -type ObjectName = v1.ObjectName - -// Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 -// -// This is used for Namespace name validation here: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 -// -// Valid values include: -// -// * "example" -// -// Invalid values include: -// -// * "example.com" - "." is an invalid character -// -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=63 -type Namespace = v1.Namespace - -// SectionName is the name of a section in a Kubernetes resource. -// -// In the following resources, SectionName is interpreted as the following: -// -// * Gateway: Listener name -// * HTTPRoute: HTTPRouteRule name -// * Service: Port name -// -// Section names can have a variety of forms, including RFC 1123 subdomains, -// RFC 1123 labels, or RFC 1035 labels. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 -// -// Valid values include: -// -// * "example" -// * "foo-example" -// * "example.com" -// * "foo.example.com" -// -// Invalid values include: -// -// * "example.com/bar" - "/" is an invalid character -// -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -type SectionName = v1.SectionName - -// GatewayController is the name of a Gateway API controller. It must be a -// domain prefixed path. -// -// Valid values include: -// -// * "example.com/bar" -// -// Invalid values include: -// -// * "example.com" - must include path -// * "foo.example.com" - must include path -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type GatewayController = v1.GatewayController - -// AnnotationKey is the key of an annotation in Gateway API. This is used for -// validation of maps such as TLS options. This matches the Kubernetes -// "qualified name" validation that is used for annotations and other common -// values. -// -// Valid values include: -// -// * example -// * example.com -// * example.com/path -// * example.com/path.html -// -// Invalid values include: -// -// * example~ - "~" is an invalid character -// * example.com. - cannot start or end with "." -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` -type AnnotationKey = v1.AnnotationKey - -// AnnotationValue is the value of an annotation in Gateway API. This is used -// for validation of maps such as TLS options. This roughly matches Kubernetes -// annotation validation, although the length validation in that case is based -// on the entire size of the annotations struct. -// -// +kubebuilder:validation:MinLength=0 -// +kubebuilder:validation:MaxLength=4096 -type AnnotationValue = v1.AnnotationValue - -// AddressType defines how a network address is represented as a text string. -// This may take two possible forms: -// -// * A predefined CamelCase string identifier (currently limited to `IPAddress` or `Hostname`) -// * A domain-prefixed string identifier (like `acme.io/CustomAddressType`) -// -// Values `IPAddress` and `Hostname` have Extended support. -// -// The `NamedAddress` value has been deprecated in favor of implementation -// specific domain-prefixed strings. -// -// All other values, including domain-prefixed values have Implementation-specific support, -// which are used in implementation-specific behaviors. Support for additional -// predefined CamelCase identifiers may be added in future releases. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` -type AddressType = v1.AddressType - -// Duration is a string value representing a duration in time. The format is as specified -// in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. -type Duration = v1.Duration +type ( + RouteParentStatus = v1.RouteParentStatus + RouteStatus = v1.RouteStatus + Hostname = v1.Hostname + PreciseHostname = v1.PreciseHostname + Group = v1.Group + Kind = v1.Kind + ObjectName = v1.ObjectName + Namespace = v1.Namespace + SectionName = v1.SectionName + GatewayController = v1.GatewayController + AnnotationKey = v1.AnnotationKey + AnnotationValue = v1.AnnotationValue + AddressType = v1.AddressType + Duration = v1.Duration +) const ( // A textual representation of a numeric IP address. IPv4 @@ -382,7 +158,4 @@ const ( NamedAddressType AddressType = "NamedAddress" ) -// SessionPersistence defines the desired state of -// SessionPersistence. -// +k8s:deepcopy-gen=false type SessionPersistence = v1.SessionPersistence diff --git a/apis/v1alpha3/shared_types.go b/apis/v1alpha3/shared_types.go index fa487f96d4..a54a211d89 100644 --- a/apis/v1alpha3/shared_types.go +++ b/apis/v1alpha3/shared_types.go @@ -18,72 +18,12 @@ package v1alpha3 import v1 "sigs.k8s.io/gateway-api/apis/v1" -// CommonRouteSpec defines the common attributes that all Routes MUST include -// within their spec. -// +k8s:deepcopy-gen=false type CommonRouteSpec = v1.CommonRouteSpec -// BackendRef defines how a Route should forward a request to a Kubernetes -// resource. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// +k8s:deepcopy-gen=false type BackendRef = v1.BackendRef -// RouteStatus defines the common attributes that all Routes MUST include within -// their status. -// +k8s:deepcopy-gen=false type RouteStatus = v1.RouteStatus -// Hostname is the fully qualified domain name of a network host. This matches -// the RFC 1123 definition of a hostname with 2 notable exceptions: -// -// 1. IPs are not allowed. -// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard -// label must appear by itself as the first label. -// -// Hostname can be "precise" which is a domain name without the terminating -// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a -// domain name prefixed with a single wildcard label (e.g. `*.example.com`). -// -// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case -// alphanumeric characters or '-', and must start and end with an alphanumeric -// character. No other punctuation is allowed. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` type Hostname = v1.Hostname -// SectionName is the name of a section in a Kubernetes resource. -// -// In the following resources, SectionName is interpreted as the following: -// -// * Gateway: Listener name -// * HTTPRoute: HTTPRouteRule name -// * Service: Port name -// -// Section names can have a variety of forms, including RFC 1123 subdomains, -// RFC 1123 labels, or RFC 1035 labels. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 -// -// Valid values include: -// -// * "example" -// * "foo-example" -// * "example.com" -// * "foo.example.com" -// -// Invalid values include: -// -// * "example.com/bar" - "/" is an invalid character -// -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 type SectionName = v1.SectionName diff --git a/apis/v1beta1/gateway_types.go b/apis/v1beta1/gateway_types.go index 60bac20c94..6c3e102762 100644 --- a/apis/v1beta1/gateway_types.go +++ b/apis/v1beta1/gateway_types.go @@ -44,123 +44,34 @@ type GatewayList struct { Items []Gateway `json:"items"` } -// GatewaySpec defines the desired state of Gateway. -// -// Not all possible combinations of options specified in the Spec are -// valid. Some invalid configurations can be caught synchronously via CRD -// validation, but there are many cases that will require asynchronous -// signaling via the GatewayStatus block. -// +k8s:deepcopy-gen=false type GatewaySpec = v1.GatewaySpec -// Listener embodies the concept of a logical endpoint where a Gateway accepts -// network connections. -// +k8s:deepcopy-gen=false type Listener = v1.Listener -// ProtocolType defines the application protocol accepted by a Listener. -// Implementations are not required to accept all the defined protocols. If an -// implementation does not support a specified protocol, it MUST set the -// "Accepted" condition to False for the affected Listener with a reason of -// "UnsupportedProtocol". -// -// Core ProtocolType values are listed in the table below. -// -// Implementations can define their own protocols if a core ProtocolType does not -// exist. Such definitions must use prefixed name, such as -// `mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core -// protocols. Any protocol defined by implementations will fall under -// implementation-specific conformance. -// -// Valid values include: -// -// * "HTTP" - Core support -// * "example.com/bar" - Implementation-specific support -// -// Invalid values include: -// -// * "example.com" - must include path if domain is used -// * "foo.example.com" - must include path if domain is used -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=255 -// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$` -// +k8s:deepcopy-gen=false type ProtocolType = v1.ProtocolType -// ListenerTLSConfig describes a TLS configuration. -// +k8s:deepcopy-gen=false type ListenerTLSConfig = v1.ListenerTLSConfig -// TLSModeType type defines how a Gateway handles TLS sessions. -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Ready Condition for the Listener to `status: False`, with a -// Reason of `Invalid`. -// -// +kubebuilder:validation:Enum=Terminate;Passthrough -// +k8s:deepcopy-gen=false type TLSModeType = v1.TLSModeType -// AllowedRoutes defines which Routes may be attached to this Listener. -// +k8s:deepcopy-gen=false type AllowedRoutes = v1.AllowedRoutes -// FromNamespaces specifies namespace from which Routes may be attached to a -// Gateway. -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Ready Condition for the Listener to `status: False`, with a -// Reason of `Invalid`. -// -// +kubebuilder:validation:Enum=All;Selector;Same -// +k8s:deepcopy-gen=false type FromNamespaces = v1.FromNamespaces -// RouteNamespaces indicate which namespaces Routes should be selected from. -// +k8s:deepcopy-gen=false type RouteNamespaces = v1.RouteNamespaces -// RouteGroupKind indicates the group and kind of a Route resource. -// +k8s:deepcopy-gen=false type RouteGroupKind = v1.RouteGroupKind -// GatewaySpecAddress describes an address that can be bound to a Gateway. -// +k8s:deepcopy-gen=false type GatewaySpecAddress = v1.GatewaySpecAddress -// GatewayStatus defines the observed state of Gateway. -// +k8s:deepcopy-gen=false type GatewayStatus = v1.GatewayStatus -// GatewayConditionType is a type of condition associated with a -// Gateway. This type should be used with the GatewayStatus.Conditions -// field. -// +k8s:deepcopy-gen=false type GatewayConditionType = v1.GatewayConditionType -// GatewayConditionReason defines the set of reasons that explain why a -// particular Gateway condition type has been raised. -// +k8s:deepcopy-gen=false type GatewayConditionReason = v1.GatewayConditionReason -// ListenerStatus is the status associated with a Listener. -// +k8s:deepcopy-gen=false type ListenerStatus = v1.ListenerStatus -// ListenerConditionType is a type of condition associated with the -// listener. This type should be used with the ListenerStatus.Conditions -// field. -// +k8s:deepcopy-gen=false type ListenerConditionType = v1.ListenerConditionType -// ListenerConditionReason defines the set of reasons that explain -// why a particular Listener condition type has been raised. -// +k8s:deepcopy-gen=false type ListenerConditionReason = v1.ListenerConditionReason diff --git a/apis/v1beta1/gatewayclass_types.go b/apis/v1beta1/gatewayclass_types.go index 0a704a7811..37b47ef236 100644 --- a/apis/v1beta1/gatewayclass_types.go +++ b/apis/v1beta1/gatewayclass_types.go @@ -60,26 +60,12 @@ type GatewayClassList struct { Items []GatewayClass `json:"items"` } -// GatewayClassSpec reflects the configuration of a class of Gateways. -// +k8s:deepcopy-gen=false type GatewayClassSpec = v1.GatewayClassSpec -// ParametersReference identifies an API object containing controller-specific -// configuration resource within the cluster. -// +k8s:deepcopy-gen=false type ParametersReference = v1.ParametersReference -// GatewayClassConditionType is the type for status conditions on -// Gateway resources. This type should be used with the -// GatewayClassStatus.Conditions field. -// +k8s:deepcopy-gen=false type GatewayClassConditionType = v1.GatewayClassConditionType -// GatewayClassConditionReason defines the set of reasons that explain why a -// particular GatewayClass condition type has been raised. -// +k8s:deepcopy-gen=false type GatewayClassConditionReason = v1.GatewayClassConditionReason -// GatewayClassStatus is the current status for the GatewayClass. -// +k8s:deepcopy-gen=false type GatewayClassStatus = v1.GatewayClassStatus diff --git a/apis/v1beta1/httproute_types.go b/apis/v1beta1/httproute_types.go index 81c7e228c1..a1b15767bf 100644 --- a/apis/v1beta1/httproute_types.go +++ b/apis/v1beta1/httproute_types.go @@ -44,198 +44,48 @@ type HTTPRouteList struct { Items []HTTPRoute `json:"items"` } -// HTTPRouteSpec defines the desired state of HTTPRoute -// +k8s:deepcopy-gen=false type HTTPRouteSpec = v1.HTTPRouteSpec -// HTTPRouteRule defines semantics for matching an HTTP request based on -// conditions (matches), processing it (filters), and forwarding the request to -// an API object (backendRefs). -// +k8s:deepcopy-gen=false type HTTPRouteRule = v1.HTTPRouteRule -// PathMatchType specifies the semantics of how HTTP paths should be compared. -// Valid PathMatchType values, along with their conformance level, are: -// -// * "Exact" - Core -// * "PathPrefix" - Core -// * "RegularExpression" - Implementation Specific -// -// PathPrefix and Exact paths must be syntactically valid: -// -// - Must begin with the `/` character -// - Must not contain consecutive `/` characters (e.g. `/foo///`, `//`). -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Accepted Condition for the Route to `status: False`, with a -// Reason of `UnsupportedValue`. -// -// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression -// +k8s:deepcopy-gen=false type PathMatchType = v1.PathMatchType -// HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. -// +k8s:deepcopy-gen=false type HTTPPathMatch = v1.HTTPPathMatch -// HeaderMatchType specifies the semantics of how HTTP header values should be -// compared. Valid HeaderMatchType values, along with their conformance levels, are: -// -// * "Exact" - Core -// * "RegularExpression" - Implementation Specific -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Accepted Condition for the Route to `status: False`, with a -// Reason of `UnsupportedValue`. -// -// +kubebuilder:validation:Enum=Exact;RegularExpression -// +k8s:deepcopy-gen=false type HeaderMatchType = v1.HeaderMatchType -// HTTPHeaderName is the name of an HTTP header. -// -// Valid values include: -// * "Authorization" -// * "Set-Cookie" -// -// Invalid values include: -// -// - ":method" - ":" is an invalid character. This means that HTTP/2 pseudo -// headers are not currently supported by this type. -// -// * "/invalid" - "/" is an invalid character -// +k8s:deepcopy-gen=false type HTTPHeaderName = v1.HTTPHeaderName -// HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request -// headers. -// +k8s:deepcopy-gen=false type HTTPHeaderMatch = v1.HTTPHeaderMatch -// QueryParamMatchType specifies the semantics of how HTTP query parameter -// values should be compared. Valid QueryParamMatchType values, along with their -// conformance levels, are: -// -// * "Exact" - Core -// * "RegularExpression" - Implementation Specific -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Accepted Condition for the Route to `status: False`, with a -// Reason of `UnsupportedValue`. -// -// +kubebuilder:validation:Enum=Exact;RegularExpression -// +k8s:deepcopy-gen=false type QueryParamMatchType = v1.QueryParamMatchType -// HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP -// query parameters. -// +k8s:deepcopy-gen=false type HTTPQueryParamMatch = v1.HTTPQueryParamMatch -// HTTPMethod describes how to select a HTTP route by matching the HTTP -// method as defined by -// [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and -// [RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2). -// The value is expected in upper case. -// -// Note that values may be added to this enum, implementations -// must ensure that unknown values will not cause a crash. -// -// Unknown values here must result in the implementation setting the -// Accepted Condition for the Route to `status: False`, with a -// Reason of `UnsupportedValue`. -// -// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH -// +k8s:deepcopy-gen=false type HTTPMethod = v1.HTTPMethod -// HTTPRouteMatch defines the predicate used to match requests to a given -// action. Multiple match types are ANDed together, i.e. the match will -// evaluate to true only if all conditions are satisfied. -// -// For example, the match below will match a HTTP request only if its path -// starts with `/foo` AND it contains the `version: v1` header: -// -// ``` -// match: -// -// path: -// value: "/foo" -// headers: -// - name: "version" -// value "v1" -// -// ``` -// +k8s:deepcopy-gen=false type HTTPRouteMatch = v1.HTTPRouteMatch -// HTTPRouteFilter defines processing steps that must be completed during the -// request or response lifecycle. HTTPRouteFilters are meant as an extension -// point to express processing that may be done in Gateway implementations. Some -// examples include request or response modification, implementing -// authentication strategies, rate-limiting, and traffic shaping. API -// guarantee/conformance is defined based on the type of the filter. -// +k8s:deepcopy-gen=false type HTTPRouteFilter = v1.HTTPRouteFilter -// HTTPRouteFilterType identifies a type of HTTPRoute filter. -// +k8s:deepcopy-gen=false type HTTPRouteFilterType = v1.HTTPRouteFilterType -// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. -// +k8s:deepcopy-gen=false type HTTPRouteTimeouts = v1.HTTPRouteTimeouts -// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. -// +k8s:deepcopy-gen=false type HTTPHeader = v1.HTTPHeader -// HTTPHeaderFilter defines a filter that modifies the headers of an HTTP request -// or response. -// +k8s:deepcopy-gen=false type HTTPHeaderFilter = v1.HTTPHeaderFilter -// HTTPPathModifierType defines the type of path redirect or rewrite. -// +k8s:deepcopy-gen=false type HTTPPathModifierType = v1.HTTPPathModifierType -// HTTPPathModifier defines configuration for path modifiers. -// -// +k8s:deepcopy-gen=false type HTTPPathModifier = v1.HTTPPathModifier -// HTTPRequestRedirect defines a filter that redirects a request. This filter -// MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. -// +k8s:deepcopy-gen=false type HTTPRequestRedirectFilter = v1.HTTPRequestRedirectFilter -// HTTPURLRewriteFilter defines a filter that modifies a request during -// forwarding. At most one of these filters may be used on a Route rule. This -// MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. -// -// Support: Extended -// -// -// +k8s:deepcopy-gen=false type HTTPURLRewriteFilter = v1.HTTPURLRewriteFilter -// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. -// +k8s:deepcopy-gen=false type HTTPRequestMirrorFilter = v1.HTTPRequestMirrorFilter -// HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. -// +k8s:deepcopy-gen=false type HTTPBackendRef = v1.HTTPBackendRef -// HTTPRouteStatus defines the observed state of HTTPRoute. -// +k8s:deepcopy-gen=false type HTTPRouteStatus = v1.HTTPRouteStatus diff --git a/apis/v1beta1/object_reference_types.go b/apis/v1beta1/object_reference_types.go index 64a904e1e0..dcb22b1aa4 100644 --- a/apis/v1beta1/object_reference_types.go +++ b/apis/v1beta1/object_reference_types.go @@ -18,43 +18,8 @@ package v1beta1 import v1 "sigs.k8s.io/gateway-api/apis/v1" -// LocalObjectReference identifies an API object within the namespace of the -// referrer. -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type LocalObjectReference = v1.LocalObjectReference -// SecretObjectReference identifies an API object including its namespace, -// defaulting to Secret. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type SecretObjectReference = v1.SecretObjectReference -// BackendObjectReference defines how an ObjectReference that is -// specific to BackendRef. It includes a few additional fields and features -// than a regular ObjectReference. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// -// References to objects with invalid Group and Kind are not valid, and must -// be rejected by the implementation, with appropriate Conditions set -// on the containing object. -// +k8s:deepcopy-gen=false type BackendObjectReference = v1.BackendObjectReference diff --git a/apis/v1beta1/shared_types.go b/apis/v1beta1/shared_types.go index ce1c430649..2f924a062c 100644 --- a/apis/v1beta1/shared_types.go +++ b/apis/v1beta1/shared_types.go @@ -18,44 +18,16 @@ package v1beta1 import v1 "sigs.k8s.io/gateway-api/apis/v1" -// ParentReference identifies an API object (usually a Gateway) that can be considered -// a parent of this resource (usually a route). The only kind of parent resource -// with "Core" support is Gateway. This API may be extended in the future to -// support additional kinds of parent resources, such as HTTPRoute. -// -// Note that there are specific rules for ParentRefs which cross namespace -// boundaries. Cross-namespace references are only valid if they are explicitly -// allowed by something in the namespace they are referring to. For example: -// Gateway has the AllowedRoutes field, and ReferenceGrant provides a -// generic way to enable any other kind of cross-namespace reference. -// -// The API object must be valid in the cluster; the Group and Kind must -// be registered in the cluster for this reference to be valid. -// +k8s:deepcopy-gen=false type ParentReference = v1.ParentReference -// CommonRouteSpec defines the common attributes that all Routes MUST include -// within their spec. -// +k8s:deepcopy-gen=false type CommonRouteSpec = v1.CommonRouteSpec -// PortNumber defines a network port. type PortNumber = v1.PortNumber -// BackendRef defines how a Route should forward a request to a Kubernetes -// resource. -// -// Note that when a namespace different than the local namespace is specified, a -// ReferenceGrant object is required in the referent namespace to allow that -// namespace's owner to accept the reference. See the ReferenceGrant -// documentation for details. -// +k8s:deepcopy-gen=false type BackendRef = v1.BackendRef -// RouteConditionType is a type of condition for a route. type RouteConditionType = v1.RouteConditionType -// RouteConditionReason is a reason for a route condition. type RouteConditionReason = v1.RouteConditionReason const ( @@ -140,214 +112,32 @@ const ( RouteReasonBackendNotFound RouteConditionReason = "BackendNotFound" ) -// RouteParentStatus describes the status of a route with respect to an -// associated Parent. -// +k8s:deepcopy-gen=false type RouteParentStatus = v1.RouteParentStatus -// RouteStatus defines the common attributes that all Routes MUST include within -// their status. -// +k8s:deepcopy-gen=false type RouteStatus = v1.RouteStatus -// Hostname is the fully qualified domain name of a network host. This matches -// the RFC 1123 definition of a hostname with 2 notable exceptions: -// -// 1. IPs are not allowed. -// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard -// label must appear by itself as the first label. -// -// Hostname can be "precise" which is a domain name without the terminating -// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a -// domain name prefixed with a single wildcard label (e.g. `*.example.com`). -// -// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case -// alphanumeric characters or '-', and must start and end with an alphanumeric -// character. No other punctuation is allowed. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` type Hostname = v1.Hostname -// PreciseHostname is the fully qualified domain name of a network host. This -// matches the RFC 1123 definition of a hostname with 1 notable exception that -// numeric IP addresses are not allowed. -// -// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case -// alphanumeric characters or '-', and must start and end with an alphanumeric -// character. No other punctuation is allowed. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` type PreciseHostname = v1.PreciseHostname -// Group refers to a Kubernetes Group. It must either be an empty string or a -// RFC 1123 subdomain. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 -// -// Valid values include: -// -// * "" - empty string implies core Kubernetes API group -// * "networking.k8s.io" -// * "foo.example.com" -// -// Invalid values include: -// -// * "example.com/bar" - "/" is an invalid character -// -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` type Group = v1.Group -// Kind refers to a Kubernetes Kind. -// -// Valid values include: -// -// * "Service" -// * "HTTPRoute" -// -// Invalid values include: -// -// * "invalid/kind" - "/" is an invalid character -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=63 -// +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` type Kind = v1.Kind -// ObjectName refers to the name of a Kubernetes object. -// Object names can have a variety of forms, including RFC 1123 subdomains, -// RFC 1123 labels, or RFC 1035 labels. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 type ObjectName = v1.ObjectName -// Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 -// -// This is used for Namespace name validation here: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 -// -// Valid values include: -// -// * "example" -// -// Invalid values include: -// -// * "example.com" - "." is an invalid character -// -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=63 type Namespace = v1.Namespace -// SectionName is the name of a section in a Kubernetes resource. -// -// In the following resources, SectionName is interpreted as the following: -// -// * Gateway: Listener name -// * HTTPRoute: HTTPRouteRule name -// * Service: Port name -// -// Section names can have a variety of forms, including RFC 1123 subdomains, -// RFC 1123 labels, or RFC 1035 labels. -// -// This validation is based off of the corresponding Kubernetes validation: -// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 -// -// Valid values include: -// -// * "example" -// * "foo-example" -// * "example.com" -// * "foo.example.com" -// -// Invalid values include: -// -// * "example.com/bar" - "/" is an invalid character -// -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 type SectionName = v1.SectionName -// GatewayController is the name of a Gateway API controller. It must be a -// domain prefixed path. -// -// Valid values include: -// -// * "example.com/bar" -// -// Invalid values include: -// -// * "example.com" - must include path -// * "foo.example.com" - must include path -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` type GatewayController = v1.GatewayController -// AnnotationKey is the key of an annotation in Gateway API. This is used for -// validation of maps such as TLS options. This matches the Kubernetes -// "qualified name" validation that is used for annotations and other common -// values. -// -// Valid values include: -// -// * example -// * example.com -// * example.com/path -// * example.com/path.html -// -// Invalid values include: -// -// * example~ - "~" is an invalid character -// * example.com. - cannot start or end with "." -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` type AnnotationKey = v1.AnnotationKey -// AnnotationValue is the value of an annotation in Gateway API. This is used -// for validation of maps such as TLS options. This roughly matches Kubernetes -// annotation validation, although the length validation in that case is based -// on the entire size of the annotations struct. -// -// +kubebuilder:validation:MinLength=0 -// +kubebuilder:validation:MaxLength=4096 type AnnotationValue = v1.AnnotationValue -// AddressType defines how a network address is represented as a text string. -// This may take two possible forms: -// -// * A predefined CamelCase string identifier (currently limited to `IPAddress` or `Hostname`) -// * A domain-prefixed string identifier (like `acme.io/CustomAddressType`) -// -// Values `IPAddress` and `Hostname` have Extended support. -// -// The `NamedAddress` value has been deprecated in favor of implementation -// specific domain-prefixed strings. -// -// All other values, including domain-prefixed values have Implementation-specific support, -// which are used in implementation-specific behaviors. Support for additional -// predefined CamelCase identifiers may be added in future releases. -// -// +kubebuilder:validation:MinLength=1 -// +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` type AddressType = v1.AddressType -// Duration is a string value representing a duration in time. The format is as specified -// in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. type Duration = v1.Duration const ( diff --git a/apisx/v1alpha1/shared_types.go b/apisx/v1alpha1/shared_types.go index 848ff53b18..01331bf8cd 100644 --- a/apisx/v1alpha1/shared_types.go +++ b/apisx/v1alpha1/shared_types.go @@ -22,36 +22,21 @@ import ( ) type ( - // +k8s:deepcopy-gen=false - AllowedRoutes = v1.AllowedRoutes - // +k8s:deepcopy-gen=false - ListenerTLSConfig = v1.ListenerTLSConfig - // +k8s:deepcopy-gen=false - Group = v1.Group - // +k8s:deepcopy-gen=false - Hostname = v1.Hostname - // +k8s:deepcopy-gen=false - Kind = v1.Kind - // +k8s:deepcopy-gen=false - ObjectName = v1.ObjectName - // +k8s:deepcopy-gen=false - PortNumber = v1.PortNumber - // +k8s:deepcopy-gen=false - ProtocolType = v1.ProtocolType - // +k8s:deepcopy-gen=false - RouteGroupKind = v1.RouteGroupKind - // +k8s:deepcopy-gen=false - SectionName = v1.SectionName - // +k8s:deepcopy-gen=false - Namespace = v1.Namespace - // +k8s:deepcopy-gen=false - Duration = v1.Duration - // +k8s:deepcopy-gen=false - PolicyStatus = v1alpha2.PolicyStatus - // +k8s:deepcopy-gen=false + AllowedRoutes = v1.AllowedRoutes + ListenerTLSConfig = v1.ListenerTLSConfig + Group = v1.Group + Hostname = v1.Hostname + Kind = v1.Kind + ObjectName = v1.ObjectName + PortNumber = v1.PortNumber + ProtocolType = v1.ProtocolType + RouteGroupKind = v1.RouteGroupKind + SectionName = v1.SectionName + Namespace = v1.Namespace + Duration = v1.Duration + PolicyStatus = v1alpha2.PolicyStatus LocalPolicyTargetReference = v1alpha2.LocalPolicyTargetReference - // +k8s:deepcopy-gen=false - SessionPersistence = v1.SessionPersistence + SessionPersistence = v1.SessionPersistence ) // ParentGatewayReference identifies an API object including its namespace, From 8ec8a83aad40bc14cd33b3982469ef9f65e2fcff Mon Sep 17 00:00:00 2001 From: Nick Young Date: Fri, 29 Aug 2025 08:41:09 +1000 Subject: [PATCH 158/224] Update release manager role description (#4040) This commit updates the RELEASE_MANAGEMENT.md docs about how Gateway API releases are managed, and adds a RELEASE_MANAGER.md file to a new `roles` directory, that may also hold role definitions for other Gateway API roles. Signed-off-by: Nick Young --- RELEASE_MANAGEMENT.md | 39 +++++++------ roles/RELEASE_MANAGER.md | 120 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 18 deletions(-) create mode 100644 roles/RELEASE_MANAGER.md diff --git a/RELEASE_MANAGEMENT.md b/RELEASE_MANAGEMENT.md index 78d0020843..b4dcbe8e5c 100644 --- a/RELEASE_MANAGEMENT.md +++ b/RELEASE_MANAGEMENT.md @@ -1,13 +1,8 @@ # Release Management Major and minor releases for Gateway API are managed by a "Release Manager". -The responsibilities of the release manager include: - -* Creating and managing a GitHub Milestone for the release. -* Creating and managing a GitHub Project board for the release. -* Creating and managing a GitHub Discussion Boards announcement for the release. - * This includes discussions to handle scoping for each release _channel_ as well. -* Working through the [Release Cycle](#release-phases) for the release. +The responsibilities of the release manager are defined in the [Release Manager] +role definition doc. This management process ultimately results in the manager of the release shipping the release as per the [Release Process]. We will go into more detail @@ -19,6 +14,7 @@ about this in the sections that follow. [Release Cycle]:https://gateway-api.sigs.k8s.io/contributing/release-cycle/ [Release Process]:/RELEASE.md +[Release Manager]:/roles/RELEASE_MANAGER.md ## Assigning a Release Manager @@ -91,18 +87,25 @@ cycle is outlined in the [Release Cycle] documentation and should be followed according to that. The release manager is responsible for communicating with the community and -seeking volunteers for features to be included in the release, and thus the -release will be considered a **feature release**. If there are few or no -volunteers the release may simply end being a smaller **maintenance release**. +seeking volunteers for features to be included in the release. + +Each enhancement included in the release must have at least two people +responsible for it: + +* **Owner**: This is the person who asks for the GEP to be included in the + release, and who is primarily responsible for doing the work to make the feature + happen. +* **Shepherd**: This is the person who agrees to be the primary reviewer, and + to assist the feature through the GEP review process. Ideally, this person has + been a feature owner in the past and has experience with the GEP review process, + and can help smooth out any rough patches. -> **Note**: Updates on the community sync and discussion boards about the -> release process should be communicated regularly. We recommend bi-weekly -> unless there's a clear reason to do more, or less. +The Release Manager is expected to communicate regularly with Owners and Shepherds +about the progress of their feature. -> **Note**: Communicating whether a release is expected to be a **feature -> release** or a **maintenance release** is largely done via the [Milestone]. -> However, the final GitHub release should also make note of this in the -> release description. +Additionally, the Release Manager MUST keep the broader community updated on the +release, including what is currently in scope for the release, and any changes +or updates. This MUST be done at least weekly. Release candidates--and the eventual final release--must utilize the [Release Process](/RELEASE.md) for delivery. @@ -116,7 +119,7 @@ final release when it is cut. ## Time Extensions -Extensions to timelines may be requested by contributors. Our guidelines for +Extensions to deadlines may be requested by contributors. Our guidelines for this are based on the Kubernetes process: * Extensions can be granted on a per-GEP basis diff --git a/roles/RELEASE_MANAGER.md b/roles/RELEASE_MANAGER.md new file mode 100644 index 0000000000..2fa5f0f913 --- /dev/null +++ b/roles/RELEASE_MANAGER.md @@ -0,0 +1,120 @@ +# Gateway API Release Manager + +## Overview + +The Gateway API release manager role is responsible for coordinating and managing the release, taking ultimate accountability for the success of the release, and ensuring that a retrospective happens. + +This role is based on the Release Lead role in Kubernetes SIG-Release, and is intended to be similar - a servant leader of the release, not the primary decision maker. + +As a Release Manager, you should expect to spend a lot of time talking to people about the status of changes, tracking changes yourself, and updating the community about what changes are in and out of scope for the release. + +## Authority and Responsibility + +The release manager has the authority to: + +* Bring together the project’s leadership (including maintainers and other leads) to coordinate decisions about what is in scope for the release +* Bring together the project’s leadership to coordinate decisions about granting extensions to deadlines in specific cases +* Perform the actual release +* Call the community (or some parts of it) together for status and retrospective meetings outside of the normal meeting cadence +* Remind reviewers and approvers of outstanding work that needs to be done +* Delegate these authorities to others (with the agreement of the maintainer team) + +The release manager has the responsibility to: + +* Ensure that the release has agreed-on dates for the final release, and for as many phases as possible. The community has indicated a clear preference for dates communicated up front as much as possible. +* Ensure the release happens on the agreed upon date, or as close as possible, including assisting the community in meeting agreed-upon deadlines +* Ensure that the community is informed about the progress of the release during the burndown process, particularly what is in and out of scope of the release. This can be by the maintenance of Github Boards or Milestones, or any other method that the Release Manager agrees with the leadership team and the community +* Notify feature owners if their feature is at risk of or has fallen out of scope for the release +* Refine the design of and improve documentation for the release process itself +* Prepare the change log for the release +* Coordinate the blog post for the release +* Perform the implementation page review process after the release + +There are some practical requirements that fall out of these lists. + +The release manager must + +* Update the community no less than weekly on work that is currently slated for the release +* Try to minimize the amount of reviews required in short time frames (that is, try to remind people to spread out the work across the release as much as possible, rather than happening just before or on the deadlines) + +## Time commitments + +The release manager is expected to keep both themselves and the community up to date about what is happening, which will require a reasonably large amount of time each week, and that time should be expected to increase when deadlines are approaching. You should plan on, *at a minimum*, **1 to 2 hours per working day** to begin with, with probably **half your time** spent on the release at busy times, and an **entire day or two** for the actual release cutting process. + +## Release dates and deadlines + +The Release Manager is responsible for: + +* Ensuring that a final release date is picked as early as possible and communicated to the community for planning purposes. This is the most important date, and should be designed so that any timing mistakes have a minimal impact on it, as the community will depend on the release being on or *very* close to this date. +* Ensuring that intermediate deadlines are chosen and communicated as early as possible, and that any changes to those deadlines are both discussed by the leadership team and communicated to the community well in advance of them being relevant. +* Ensuring that deadline extensions are kept to a minimum, and are on a case-by-case basis only. Feature leads MUST ask for extensions before they can be granted, and there MUST be enough time for the entire leadership team to see and agree with the extension before it is granted. Practically, this means that there must be a *minimum* of 24-48 hours (not counting weekends) between an extension being asked for and the deadline that is being extended. + +## Work examples in the current release phases + +### Scoping + +The scoping phase is about determining what will get focus in the next release. + +The way that the community determines what work is in scope for the release is ultimately up to the release manager, although they are expected to build some consensus amongst both the maintainers and the community about the method. + +In the interest of ensuring that the changes we include are what the community is interested in, and that we are doing necessary but boring work like tech debt reduction, scoping MUST involve: + +* Community feedback +* Maintainer input (to ensure we try to solve underlying issues as well as new features) +* Reviewer input (to ensure that we keep changes deliverable within a release cycle) +* Ensuring that features are moving towards Standard, and are not stuck in Experimental + +In all cases, the Release Manager *must* ensure that all the factors involved in the scoping decisions are publicly available. + +For example, for v1.4, we had scoping performed using the votes on the Github discussions that proposed inclusion (which are publicly visible, and attributable to individuals), and for v1.3, we used community votes plus some additional factors like “difficulty of change” and “future importance”. In the v1.3 case, those weights were agreed upon by the maintainers and made available in a [world-readable Google sheet](https://docs.google.com/spreadsheets/d/1tLVmYHCyVuRLwnvMJuYMhiEtVX0fUF1aLHBLIc7mBKE/edit?gid=0#gid=0). + +### GEP Refinement + +The GEP refinement phase is about getting the agreed-upon GEPs to the phase they need to be at so that required API changes can be made in the next phase. + +Generally, this involves the feature owners pushing PRs with their proposed changes, and their reviewer sponsor coordinating getting the changes reviewed. + +The release manager’s most important role here is reminding everyone what changes are on the table, and poking feature owners to ensure they are actually working on the required changes. This is *much* more work than it sounds, particularly because contentious changes can often run to hundreds of comments that need to be tracked and followed up. + +Generally, tracking requested changes should be the role of the feature owner and/or the reviewer sponsor, but the Release Manager should feel confident to chase things that look like they may have been missed. + +The Release Manager is encouraged to set deadlines within this phase for gates like “GEP PR is open” “GEP PR is merged at Provisional”, “GEP PR is merged at Implementable”. Note that once a GEP is Implementable, this phase is complete for that GEP. + +The Release Manager should also feel free to perform reviews themselves if they have the context and bandwidth to do so. + +The Release Manager is responsible for notifying feature owners if their feature has fallen out of scope due to missing deadlines. + +The Release Manager is the final arbiter for approving extensions for deadlines in this phase, and should do so *only* if the extension is requested in public, and on a case-by-case basis. No extensions for everything. + +### API implementation phase + +In this phase, we expect to merge any required changes to the API itself into the repo, preferably with conformance tests to ensure that implementations do things correctly when implementing the new changes. + +The Release Manager’s role here is to: + +* Keep track of changes as they happen +* Remind feature owners of upcoming deadlines +* Communicate what features are ongoing, what at risk, and what are out of scope +* Ensure that deadlines are met +* Grant extensions for deadlines, if required, on a case-by-case basis. + +Generally, in this phase, most of the changes are relatively straightforward, as most argument happens during the design phase in GEP Refinement. However, sometimes actually making the changes to the API, and in particular writing conformance tests, can show problems with the APIs as designed that may need further API changes to fix. Part of the Release Manager’s role is to be the arbiter of judgement calls about if further API changes are deliverable in the required timeframe, or if the change should be pushed back to the next version. + +### API Review and Release Candidate phase + +In this phase, we MUST get sign-off from SIG-Network API reviewers for *all* API changes. This is a requirement of having an official [`k8s.io`](http://k8s.io) API, and is not negotiable. Practically, API reviewers are usually very busy, and it can be difficult to get time with them, so it’s important to ensure that all the pending API changes are completed before getting the API reviewers to look. + +The API reviewers *may* review an RC build, which would coincide with making the RC available to the community. That does run the risk that early implementers may need to change things as a result of API review feedback (this has definitely happened before). + +The Release Candidate builds are intended to allow implementations to get started on actually implementing the API changes from the release early, so that they can provide feedback about the implementation experience, and source early user feedback if possible. + +We generally try to do at least two candidate releases, with the requirement being that there MUST NOT be any changes between the final RC and the actual release. + +## Measuring success + +Getting a release out at all is a success! + +But to be able to quantify releases a bit, and evaluate if changes to the release process are helping or not, we track some metrics about each release, which can be summarized into two main buckets: + +* Release size (How many features, and how large is each feature? How many new conformance tests added? Any process changes during the release timeframe?) +* Release timeliness (Was the release released on the targeted date? Did we meet agreed upon deadlines within the release schedule? How many extensions did we need to grant during the release?) From 9098973c15bd56601074fe36ab33bbf3e83964db Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Fri, 29 Aug 2025 14:05:10 +0200 Subject: [PATCH 159/224] clarify terminology for gateway TLS (#4036) --- geps/gep-2907/index.md | 156 +++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 99 deletions(-) diff --git a/geps/gep-2907/index.md b/geps/gep-2907/index.md index a44451bde2..c9a57602c1 100644 --- a/geps/gep-2907/index.md +++ b/geps/gep-2907/index.md @@ -8,11 +8,14 @@ This GEP aims to define high level TLS terminology and structure within Gateway API to ensure that all our independent proposals related to TLS result in a coherent set of APIs. This will result in some adjustments to provisional and experimental TLS-related GEPs, specifically [BackendTLSPolicy](../gep-1897/index.md) -and [Client Certificate Verification](../gep-91/index.md). ## Goals -* Define high-level terminology for how we refer to TLS in Gateway API. -* Define top level fields where TLS configuration can live. +1. Define high-level terminology for how we refer to TLS in Gateway API. +2. Define top level fields where TLS configuration can live for all below cases: +* Client to Gateway (Frontend) TLS configuration. +* Gateway to Client TLS configuration (Client Certificate Validation) +* Gateway to backend (Gateway Client Certificate) +3. Document how to use `BackendTLSPolicy` to support Gateway to Backend TLS configuration. ## Non-Goals * Add or change fields directly. (This may inspire changes in other GEPs @@ -30,29 +33,15 @@ in scope for this GEP. In the future, this GEP may be expanded to include: ## Introduction -### Where TLS could be configured -We have three different places where we might want to configure TLS: - -#### A. Gateways -Config attached at this layer will apply to everything behind a single address -such as a virtual IP. +### TLS mode -#### B. Gateway Listeners -Each Gateway contains multiple “Listeners”. Each HTTPS Listener in a Gateway -must have a unique combination of protocol, port, and SNI (Server Name -Indication). TLS configuration attached at this layer should be [isolated via -SNI](../../guides/implementers.md#listener-isolation). +TLS can be configured with two distinct modes: +* **Passthrough**: The Gateway forwards encrypted traffic directly to the backend from the entity originating the connection (called later a client). The TLS connection is established between the client and the backend; the Gateway does not participate in the TLS handshake. -#### C. BackendTLSPolicy -This policy allows us to attach unique TLS configuration per Backend. Depending -on the organization, this policy may be owned by the application owner or the -cluster operator. Note that this configuration will be used by all Gateways -(potentially from different implementations) that are connecting to the backend. +* **Terminate**: The Gateway acts as a man-in-the-middle, terminating the client's TLS connection and originating a separate connection to the backend when routing the traffic. Both connections can independently support TLS and mutual TLS due to their distinct TLS configurations. The Gateway's dual role as a client or server affects the placement of TLS settings needed for given connection. ### "Frontend" and "Backend" -A guiding principle in this naming is to use consistent naming for “Downstream” -(1+2) and “Upstream” (3+4), similar to Envoy. To avoid the confusion with what -is upstream and downstream, Gateway API will use “Frontend” (1+2) and “Backend” +A guiding principle in this naming is to use consistent naming for both TLS connections “Downstream” (1+2) and “Upstream” (3+4) handled by the Gateway (similar to Envoy). To avoid the confusion with what is upstream and downstream, Gateway API will use “Frontend” (1+2) and “Backend” (3+4). * **Frontend:** The entity connecting to a Gateway, typically a client @@ -73,43 +62,34 @@ flowchart LR The above diagram depicts these four segments as edges in a graph. -### TLS mode +#### Frontend configuration -TLS can be configured with two distinct modes: +In the Frontend TLS connection Gateway acts as a server and presents Server certificate during TLS handshake. Client connects to the Gateway on domain basis and this is desired to configure Server certificates on the Listener. +In the mutual frontend TLS Gateway needs to verify client certificates with configured CA. It was expected that CA configuration would be also defined on Listener but due to connection coalescing this solution was not secure. We decided to move client certificate validation configuration on the Gateway level and allow for per port overrides. + +#### Backend configuration + +In the Backend connection Gateway acts as a client. The nature of the connection (HTTP or HTTPS) is configured on the Service using BackendTLSPolicy. If BackendTLSPolicy is defined for a Service, the Gateway must establish an HTTPS connection with the backend. During the TLS handshake, the backend presents a Server certificate. The Gateway validates this certificate against a CA certificate (and optionally SANs) configured by BackendTLSPolicy. +For mutual backend TLS, the Gateway's identity must be configured. This identity, a client certificate set on the Gateway object, will be presented by the Gateway. The Gateway uses the same client certificate for all backend connections originating mutual TLS. -* **Terminate**: the TLS connection is instantiated between the frontend and the - Gateway. The connection between the Gateway and the backend is left unencrypted - unless a new TLS connection between the two entities is configured via BackendTLSPolicy. -* **Passthrough**: the TLS connection is instantiated between the frontend and the - backend. The traffic flows through the Gateway encrypted, and the Gateway is not - able to decrypt or inspect the encrypted portions of the TLS stream. ## Proposed Segments -Note that this does not represent any form of commitment that any of these -fields or concepts will exist within Gateway API. If or when they do, we propose -the following naming structure: -### 1. Validate Client Certificate provided by Frontend + +### 1. Gateway level configuration + +Gateway-level configurations are required for both Frontend and Backend connections. We propose a top-level GatewayTLSConfig that is divided into independent Backend and Frontend configurations. | Proposed Placement | Name | Status | |-|-|-| -| Gateway Listener | `Listener.TLS.FrontendValidation` | Proposed | +| Gateway | `Gateway.TLS.Frontend` | Proposed | +| Gateway | `Gateway.TLS.Backend` | Proposed | #### Rationale -Use FrontendValidation to leave room for concepts like trust anchors and trust -domains. Anything not strictly tied to validation would belong to Listener.TLS -which is now reserved exclusively for “Frontend” TLS configuration (1+2). - -#### Why Not Frontend.Validation? -Part of the idea behind this GEP is that Listener.TLS is really entirely focused -on 1+2 - the bits of TLS between frontend and Gateway. That means that if we -were to add any additional TLS configuration in the Listener.TLS struct, it -would tied to that limited scope, and thus we don't really need a separate -Frontend struct. +From the security point of view both TLS configurations require a Gateway level field. The configurations are independent and can coexist. -One could make an argument that Listener.TLS.Validation should be the field name -here to avoid any ambiguity, but in this specific context, we think that it's -probably helpful to specifically spell out frontend. +#### Why Not Listener.Frontend? +Due to connection coalescing, the client certificate validation for the frontend was moved to a Gateway level field to address security concerns. [GEP-91 Update PR](https://github.com/kubernetes-sigs/gateway-api/pull/3942) #### Why Not FrontendTLSPolicy? It could be reasonable to try to mirror BackendTLSPolicy for Frontend TLS. As we @@ -129,7 +109,7 @@ We don't think either of those reasons really apply to frontend TLS. Instead, frontend TLS could theoretically be configured either for an entire Gateway, or a specific Gateway listener. Given that many implementations already support distinguishing this config per SNI, it seems to make sense to start with -listener level attachment. We think that the persona that would be responsible +Listener level attachment. We think that the persona that would be responsible for a Gateway is not sufficiently different than the persona that would be responsible for frontend TLS, so the current proposal is likely the best option available to us. @@ -145,17 +125,30 @@ This is already finalized in the API and so we're stuck with this name. In hindsight a name that was more clearly tied to frontend TLS would have been ideal here. -### 3. Configure Client Certificate that Gateway should use to connect to Backend +### 3. Configure Client Certificate Validation for Frontend + +Client certificate validation will reside at the Gateway level. This configuration will be +either applied globally to all Listeners in the Gateway or can be overridden on a per-port basis. | Proposed Placement | Name | Status | |-|-|-| -| Gateway | `Gateway.Spec.BackendTLS.ClientCertificateRef` | Not Proposed | -| BackendTLSPolicy | `BackendTLSPolicy.Spec.ClientCertificateRef` | Not Proposed | +| Gateway | `Gateway.TLS.Frontend.Default.Validation` | Proposed | +| Gateway | `Gateway.TLS.Frontend.PerPort` | Proposed | #### Rationale -It's not yet obvious which of the above options are preferable, but a case could -be made for either or both. If we add a `BackendTLS` struct to Gateway it would -leave room for concepts like TLS version, ALPN, cipher suites, etc. +Gateway level configuration for client certificate validation was chosen due to security issue. + +#### Why per port override +HTTPS connection can be reused between multiple Listeners sharing the same port. This might lead to bypassing client certificate validation configuration for a given Listener becasue new TLS handshake will not be triggered for different hostname. + +### 4. Configure Client Certificate that Gateway should use to connect to Backend + +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway | `Gateway.Spec.TLS.Backend.ClientCertificateRef` | Proposed | + +#### Rationale +Client certificate is part of Gateway identity and should not be overriden per backend. #### Why Not Listener level to match FrontendValidation? In general, we'd expect this identity to represent a Gateway as a whole, and @@ -167,7 +160,7 @@ use when connecting to a backend, it should likely either be tied directly to the Gateway or Backend, but the Listener is not particularly relevant in this context. -### 4. Validate Server Certificate that is provided by Backend +### 5. Validate Server Certificate that is provided by Backend | Proposed Placement | Name | Status | |-|-|-| | Gateway | `Gateway.Spec.BackendTLS.Validation` | Not Proposed | @@ -179,42 +172,7 @@ already clearly backend-focused, config like TLS Version, ALPN, and cipher suites, could live at the same level without confusion. It's also plausible that some Gateways may want to express Gateway-wide CAs that are trusted. -#### Why BackendTLS on Gateways? -Although this GEP is intentionally not committing to adding new fields or -features, it's possible that at some point in the future we may want to have -some kind of Backend TLS config at the Gateway level. For example, it may be -useful to configure a set of CAs that a Gateway trusts or a client cert that a -Gateway should use to connect to all backends. If this existed, there would -likely be some overlap in config with BackendTLSPolicy, and if a future GEP -proposed this, it would need to include how overlapping config should be -handled. - -#### Why the inconsistency between Frontend and Backend TLS config on Gateways? -If we were to populate all the possible fields described in this GEP, we'd end -up with the following config on Gateways: - -``` -Gateway.Spec.Listeners.TLS.FrontendValidation -Gateway.Spec.Listeners.TLS -Gateway.Spec.BackendTLS.ClientCertificateRef -Gateway.Spec.BackendTLS.Validation -``` - -This is all tied to the need to provide backwards compatibility with the TLS -config that is already GA on Listeners (`Listener.TLS`). If we were naming that -field today with the broader vision of TLS configuration throughout Gateway API -we would almost certainly choose a more descriptive name that was more clearly -tied to Frontend TLS. Unfortunately we're too late to change that name, but we -can try to make the rest of the terminology clearly tied to frontend or backend -TLS. - -One [suggestion by @candita](https://github.com/kubernetes-sigs/gateway-api/pull/2910#discussion_r1552534017) -would be to introduce a Listener like resource for BackendTLS, resulting in a -more consistent naming scheme within Gateway TLS configuration. Although it's -not yet clear if we need this additional layer, we should reconsider it as we're -further developing Backend TLS. - -### 5. Configure TLS mode +### 6. Configure TLS mode | Proposed Placement | Name | Status | |-|-|-| @@ -236,8 +194,8 @@ does not need to be provided, as the TLS termination is handled by the backend. ## Routes and TLS -Multiple routes can be attached to listeners specifying TLS configuration. This section -intends to clearly state how and when Routes can attach to listeners with TLS configuration. +Multiple routes can be attached to Listeners specifying TLS configuration. This section +intends to clearly state how and when Routes can attach to Listeners with TLS configuration. ### Context @@ -265,12 +223,12 @@ with the compatible protocol. |-----------|---------|---------------|----------------| | HTTP | `HTTPRoute`/`GRPCRoute` | no | no | | HTTPS | `HTTPRoute`/`GRPCRoute` | yes | no | -| TLS | `TLSRoute` | yes | yes | +| TLS | `TLSRoute` | yes | yes | | TCP | `TCPRoute` | yes | no | | UDP | `UDPRoute` | no | no | > [!NOTE] -> When the traffic is routed to the backend via a listener configured with TLS `Passthrough` -> and a compatible route, the packets are left untouched by the gateway. In order to -> terminate the TLS connection to the gateway and forward the traffic unencrypted to the backend, -> a listener configured with TLS `Terminate` and a compatible route must be used. +> When the traffic is routed to the backend via a Listener configured with TLS `Passthrough` +> and a compatible route, the packets are left untouched by the Gateway. In order to +> terminate the TLS connection to the Gateway and forward the traffic unencrypted to the backend, +> a Listener configured with TLS `Terminate` and a compatible route must be used. From acba76c51b8c081999edc586e0ff0e4f53c327a3 Mon Sep 17 00:00:00 2001 From: Steve Kriss Date: Fri, 29 Aug 2025 16:17:09 -0400 Subject: [PATCH 160/224] add GRPCRouteExtendedFeatures to AllFeatures list (#4046) Signed-off-by: Steve Kriss --- pkg/features/features.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/features/features.go b/pkg/features/features.go index 2a67d0065f..dd12532cf8 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -61,6 +61,7 @@ var ( Insert(MeshCoreFeatures.UnsortedList()...). Insert(MeshExtendedFeatures.UnsortedList()...). Insert(GRPCRouteCoreFeatures.UnsortedList()...). + Insert(GRPCRouteExtendedFeatures.UnsortedList()...). Insert(BackendTLSPolicyCoreFeatures.UnsortedList()...) featureMap = map[FeatureName]Feature{} From 9e01e2bfa8b8a430eacce8f878c5cb33e77c8ec8 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Fri, 29 Aug 2025 22:55:09 +0200 Subject: [PATCH 161/224] add BackendTLSPolicyExtendedFeatures to AllFeatures list (#4047) Signed-off-by: Norwin Schnyder --- pkg/features/features.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/features/features.go b/pkg/features/features.go index dd12532cf8..1fbf43f0e6 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -62,7 +62,8 @@ var ( Insert(MeshExtendedFeatures.UnsortedList()...). Insert(GRPCRouteCoreFeatures.UnsortedList()...). Insert(GRPCRouteExtendedFeatures.UnsortedList()...). - Insert(BackendTLSPolicyCoreFeatures.UnsortedList()...) + Insert(BackendTLSPolicyCoreFeatures.UnsortedList()...). + Insert(BackendTLSPolicyExtendedFeatures.UnsortedList()...) featureMap = map[FeatureName]Feature{} ) From f04abecca9aabcac3529a871ce2aa3235ef19b45 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Mon, 1 Sep 2025 12:15:14 +0200 Subject: [PATCH 162/224] describe TargetRefs conflict-resolution rules in BackendTLSPolicy (#4048) Signed-off-by: Norwin Schnyder --- apis/v1alpha3/backendtlspolicy_types.go | 17 +++++++++++++++++ ...ay.networking.k8s.io_backendtlspolicies.yaml | 16 ++++++++++++++++ pkg/generated/openapi/zz_generated.openapi.go | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index 9c5c019d46..edfe82d657 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -76,6 +76,23 @@ type BackendTLSPolicySpec struct { // be unique across all targetRef entries in the BackendTLSPolicy. // * They select different sectionNames in the same target. // + // + // When more than one BackendTLSPolicy selects the same target and + // sectionName, implementations MUST determine precedence using the + // following criteria, continuing on ties: + // + // * The older policy by creation timestamp takes precedence. For + // example, a policy with a creation timestamp of "2021-07-15 + // 01:02:03" MUST be given precedence over a policy with a + // creation timestamp of "2021-07-15 01:02:04". + // * The policy appearing first in alphabetical order by {name}. + // For example, a policy named `bar` is given precedence over a + // policy named `baz`. + // + // For any BackendTLSPolicy that does not take precedence, the + // implementation MUST ensure the `Accepted` Condition is set to + // `status: False`, with Reason `Conflicted`. + // // Support: Extended for Kubernetes Service // // Support: Implementation-specific for any other resource diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index c3beb7c42d..9a3d148731 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -92,6 +92,22 @@ spec: be unique across all targetRef entries in the BackendTLSPolicy. * They select different sectionNames in the same target. + When more than one BackendTLSPolicy selects the same target and + sectionName, implementations MUST determine precedence using the + following criteria, continuing on ties: + + * The older policy by creation timestamp takes precedence. For + example, a policy with a creation timestamp of "2021-07-15 + 01:02:03" MUST be given precedence over a policy with a + creation timestamp of "2021-07-15 01:02:04". + * The policy appearing first in alphabetical order by {name}. + For example, a policy named `bar` is given precedence over a + policy named `baz`. + + For any BackendTLSPolicy that does not take precedence, the + implementation MUST ensure the `Accepted` Condition is set to + `status: False`, with Reason `Conflicted`. + Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 111ea8af74..d34c24079d 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7548,7 +7548,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicySpec(ref common. }, }, SchemaProps: spec.SchemaProps{ - Description: "TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy.\n\nTargetRefs must be _distinct_. This means either that:\n\n* They select different targets. If this is the case, then targetRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, and `name` must\n be unique across all targetRef entries in the BackendTLSPolicy.\n* They select different sectionNames in the same target.\n\nSupport: Extended for Kubernetes Service\n\nSupport: Implementation-specific for any other resource", + Description: "TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy.\n\nTargetRefs must be _distinct_. This means either that:\n\n* They select different targets. If this is the case, then targetRef\n entries are distinct. In terms of fields, this means that the\n multi-part key defined by `group`, `kind`, and `name` must\n be unique across all targetRef entries in the BackendTLSPolicy.\n* They select different sectionNames in the same target.\n\nWhen more than one BackendTLSPolicy selects the same target and sectionName, implementations MUST determine precedence using the following criteria, continuing on ties:\n\n* The older policy by creation timestamp takes precedence. For\n example, a policy with a creation timestamp of \"2021-07-15\n 01:02:03\" MUST be given precedence over a policy with a\n creation timestamp of \"2021-07-15 01:02:04\".\n* The policy appearing first in alphabetical order by {name}.\n For example, a policy named `bar` is given precedence over a\n policy named `baz`.\n\nFor any BackendTLSPolicy that does not take precedence, the implementation MUST ensure the `Accepted` Condition is set to `status: False`, with Reason `Conflicted`.\n\nSupport: Extended for Kubernetes Service\n\nSupport: Implementation-specific for any other resource", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ From 477155df8c608a4a0715c7f0d5046cb22a8e7529 Mon Sep 17 00:00:00 2001 From: Erik Godding Boye Date: Tue, 2 Sep 2025 01:31:12 +0200 Subject: [PATCH 163/224] Fix PortNumber type to support controller-gen (#4049) Signed-off-by: Erik Godding Boye --- apis/v1/shared_types.go | 2 +- applyconfiguration/apis/v1/backendobjectreference.go | 4 ++-- applyconfiguration/apis/v1/backendref.go | 2 +- applyconfiguration/apis/v1/grpcbackendref.go | 2 +- applyconfiguration/apis/v1/httpbackendref.go | 2 +- applyconfiguration/apis/v1/httprequestredirectfilter.go | 4 ++-- applyconfiguration/apis/v1/listener.go | 4 ++-- applyconfiguration/apis/v1/parentreference.go | 4 ++-- applyconfiguration/apis/v1/tlsportconfig.go | 8 ++------ applyconfiguration/apisx/v1alpha1/listenerentry.go | 4 ++-- applyconfiguration/apisx/v1alpha1/listenerentrystatus.go | 4 ++-- 11 files changed, 18 insertions(+), 22 deletions(-) diff --git a/apis/v1/shared_types.go b/apis/v1/shared_types.go index 99299acda8..2b38e32cd6 100644 --- a/apis/v1/shared_types.go +++ b/apis/v1/shared_types.go @@ -232,7 +232,7 @@ type CommonRouteSpec struct { } // PortNumber defines a network port. -type PortNumber int32 +type PortNumber = int32 // BackendRef defines how a Route should forward a request to a Kubernetes // resource. diff --git a/applyconfiguration/apis/v1/backendobjectreference.go b/applyconfiguration/apis/v1/backendobjectreference.go index 58337304af..5106b76cba 100644 --- a/applyconfiguration/apis/v1/backendobjectreference.go +++ b/applyconfiguration/apis/v1/backendobjectreference.go @@ -29,7 +29,7 @@ type BackendObjectReferenceApplyConfiguration struct { Kind *apisv1.Kind `json:"kind,omitempty"` Name *apisv1.ObjectName `json:"name,omitempty"` Namespace *apisv1.Namespace `json:"namespace,omitempty"` - Port *apisv1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` } // BackendObjectReferenceApplyConfiguration constructs a declarative configuration of the BackendObjectReference type for use with @@ -73,7 +73,7 @@ func (b *BackendObjectReferenceApplyConfiguration) WithNamespace(value apisv1.Na // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *BackendObjectReferenceApplyConfiguration) WithPort(value apisv1.PortNumber) *BackendObjectReferenceApplyConfiguration { +func (b *BackendObjectReferenceApplyConfiguration) WithPort(value int32) *BackendObjectReferenceApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apis/v1/backendref.go b/applyconfiguration/apis/v1/backendref.go index 838dd6f6a3..cac582c7b9 100644 --- a/applyconfiguration/apis/v1/backendref.go +++ b/applyconfiguration/apis/v1/backendref.go @@ -70,7 +70,7 @@ func (b *BackendRefApplyConfiguration) WithNamespace(value apisv1.Namespace) *Ba // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *BackendRefApplyConfiguration) WithPort(value apisv1.PortNumber) *BackendRefApplyConfiguration { +func (b *BackendRefApplyConfiguration) WithPort(value int32) *BackendRefApplyConfiguration { b.BackendObjectReferenceApplyConfiguration.Port = &value return b } diff --git a/applyconfiguration/apis/v1/grpcbackendref.go b/applyconfiguration/apis/v1/grpcbackendref.go index 75465480fe..7f9513b528 100644 --- a/applyconfiguration/apis/v1/grpcbackendref.go +++ b/applyconfiguration/apis/v1/grpcbackendref.go @@ -70,7 +70,7 @@ func (b *GRPCBackendRefApplyConfiguration) WithNamespace(value apisv1.Namespace) // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *GRPCBackendRefApplyConfiguration) WithPort(value apisv1.PortNumber) *GRPCBackendRefApplyConfiguration { +func (b *GRPCBackendRefApplyConfiguration) WithPort(value int32) *GRPCBackendRefApplyConfiguration { b.BackendObjectReferenceApplyConfiguration.Port = &value return b } diff --git a/applyconfiguration/apis/v1/httpbackendref.go b/applyconfiguration/apis/v1/httpbackendref.go index 28fda8dd7b..d935ce0a17 100644 --- a/applyconfiguration/apis/v1/httpbackendref.go +++ b/applyconfiguration/apis/v1/httpbackendref.go @@ -70,7 +70,7 @@ func (b *HTTPBackendRefApplyConfiguration) WithNamespace(value apisv1.Namespace) // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *HTTPBackendRefApplyConfiguration) WithPort(value apisv1.PortNumber) *HTTPBackendRefApplyConfiguration { +func (b *HTTPBackendRefApplyConfiguration) WithPort(value int32) *HTTPBackendRefApplyConfiguration { b.BackendObjectReferenceApplyConfiguration.Port = &value return b } diff --git a/applyconfiguration/apis/v1/httprequestredirectfilter.go b/applyconfiguration/apis/v1/httprequestredirectfilter.go index a9d82b90d5..7a2ea005d0 100644 --- a/applyconfiguration/apis/v1/httprequestredirectfilter.go +++ b/applyconfiguration/apis/v1/httprequestredirectfilter.go @@ -28,7 +28,7 @@ type HTTPRequestRedirectFilterApplyConfiguration struct { Scheme *string `json:"scheme,omitempty"` Hostname *apisv1.PreciseHostname `json:"hostname,omitempty"` Path *HTTPPathModifierApplyConfiguration `json:"path,omitempty"` - Port *apisv1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` StatusCode *int `json:"statusCode,omitempty"` } @@ -65,7 +65,7 @@ func (b *HTTPRequestRedirectFilterApplyConfiguration) WithPath(value *HTTPPathMo // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *HTTPRequestRedirectFilterApplyConfiguration) WithPort(value apisv1.PortNumber) *HTTPRequestRedirectFilterApplyConfiguration { +func (b *HTTPRequestRedirectFilterApplyConfiguration) WithPort(value int32) *HTTPRequestRedirectFilterApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apis/v1/listener.go b/applyconfiguration/apis/v1/listener.go index c7d3b08023..29faef1b00 100644 --- a/applyconfiguration/apis/v1/listener.go +++ b/applyconfiguration/apis/v1/listener.go @@ -27,7 +27,7 @@ import ( type ListenerApplyConfiguration struct { Name *apisv1.SectionName `json:"name,omitempty"` Hostname *apisv1.Hostname `json:"hostname,omitempty"` - Port *apisv1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` Protocol *apisv1.ProtocolType `json:"protocol,omitempty"` TLS *ListenerTLSConfigApplyConfiguration `json:"tls,omitempty"` AllowedRoutes *AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` @@ -58,7 +58,7 @@ func (b *ListenerApplyConfiguration) WithHostname(value apisv1.Hostname) *Listen // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *ListenerApplyConfiguration) WithPort(value apisv1.PortNumber) *ListenerApplyConfiguration { +func (b *ListenerApplyConfiguration) WithPort(value int32) *ListenerApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apis/v1/parentreference.go b/applyconfiguration/apis/v1/parentreference.go index b0cb0652b5..6880ca6d5b 100644 --- a/applyconfiguration/apis/v1/parentreference.go +++ b/applyconfiguration/apis/v1/parentreference.go @@ -30,7 +30,7 @@ type ParentReferenceApplyConfiguration struct { Namespace *apisv1.Namespace `json:"namespace,omitempty"` Name *apisv1.ObjectName `json:"name,omitempty"` SectionName *apisv1.SectionName `json:"sectionName,omitempty"` - Port *apisv1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` } // ParentReferenceApplyConfiguration constructs a declarative configuration of the ParentReference type for use with @@ -82,7 +82,7 @@ func (b *ParentReferenceApplyConfiguration) WithSectionName(value apisv1.Section // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *ParentReferenceApplyConfiguration) WithPort(value apisv1.PortNumber) *ParentReferenceApplyConfiguration { +func (b *ParentReferenceApplyConfiguration) WithPort(value int32) *ParentReferenceApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apis/v1/tlsportconfig.go b/applyconfiguration/apis/v1/tlsportconfig.go index bc9043a149..f19c733782 100644 --- a/applyconfiguration/apis/v1/tlsportconfig.go +++ b/applyconfiguration/apis/v1/tlsportconfig.go @@ -18,14 +18,10 @@ limitations under the License. package v1 -import ( - apisv1 "sigs.k8s.io/gateway-api/apis/v1" -) - // TLSPortConfigApplyConfiguration represents a declarative configuration of the TLSPortConfig type for use // with apply. type TLSPortConfigApplyConfiguration struct { - Port *apisv1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` TLS *TLSConfigApplyConfiguration `json:"tls,omitempty"` } @@ -38,7 +34,7 @@ func TLSPortConfig() *TLSPortConfigApplyConfiguration { // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *TLSPortConfigApplyConfiguration) WithPort(value apisv1.PortNumber) *TLSPortConfigApplyConfiguration { +func (b *TLSPortConfigApplyConfiguration) WithPort(value int32) *TLSPortConfigApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apisx/v1alpha1/listenerentry.go b/applyconfiguration/apisx/v1alpha1/listenerentry.go index b72cf4e044..d9f4dc9a4e 100644 --- a/applyconfiguration/apisx/v1alpha1/listenerentry.go +++ b/applyconfiguration/apisx/v1alpha1/listenerentry.go @@ -28,7 +28,7 @@ import ( type ListenerEntryApplyConfiguration struct { Name *v1.SectionName `json:"name,omitempty"` Hostname *v1.Hostname `json:"hostname,omitempty"` - Port *v1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` Protocol *v1.ProtocolType `json:"protocol,omitempty"` TLS *apisv1.ListenerTLSConfigApplyConfiguration `json:"tls,omitempty"` AllowedRoutes *apisv1.AllowedRoutesApplyConfiguration `json:"allowedRoutes,omitempty"` @@ -59,7 +59,7 @@ func (b *ListenerEntryApplyConfiguration) WithHostname(value v1.Hostname) *Liste // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *ListenerEntryApplyConfiguration) WithPort(value v1.PortNumber) *ListenerEntryApplyConfiguration { +func (b *ListenerEntryApplyConfiguration) WithPort(value int32) *ListenerEntryApplyConfiguration { b.Port = &value return b } diff --git a/applyconfiguration/apisx/v1alpha1/listenerentrystatus.go b/applyconfiguration/apisx/v1alpha1/listenerentrystatus.go index 64d652a426..888f57d75d 100644 --- a/applyconfiguration/apisx/v1alpha1/listenerentrystatus.go +++ b/applyconfiguration/apisx/v1alpha1/listenerentrystatus.go @@ -28,7 +28,7 @@ import ( // with apply. type ListenerEntryStatusApplyConfiguration struct { Name *v1.SectionName `json:"name,omitempty"` - Port *v1.PortNumber `json:"port,omitempty"` + Port *int32 `json:"port,omitempty"` SupportedKinds []apisv1.RouteGroupKindApplyConfiguration `json:"supportedKinds,omitempty"` AttachedRoutes *int32 `json:"attachedRoutes,omitempty"` Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` @@ -51,7 +51,7 @@ func (b *ListenerEntryStatusApplyConfiguration) WithName(value v1.SectionName) * // WithPort sets the Port field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Port field is set to the value of the last call. -func (b *ListenerEntryStatusApplyConfiguration) WithPort(value v1.PortNumber) *ListenerEntryStatusApplyConfiguration { +func (b *ListenerEntryStatusApplyConfiguration) WithPort(value int32) *ListenerEntryStatusApplyConfiguration { b.Port = &value return b } From 4a150bf91a2c8cc87e8bf1d4d3a365f3e0f1d447 Mon Sep 17 00:00:00 2001 From: kl52752 <89914070+kl52752@users.noreply.github.com> Date: Tue, 2 Sep 2025 10:13:14 +0200 Subject: [PATCH 164/224] Specify SAN validation precedence over Hostname validation (#4039) --- apis/v1alpha3/backendtlspolicy_types.go | 6 +++++- .../gateway.networking.k8s.io_backendtlspolicies.yaml | 6 +++++- geps/gep-3155/index.md | 4 ++++ pkg/generated/openapi/zz_generated.openapi.go | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apis/v1alpha3/backendtlspolicy_types.go b/apis/v1alpha3/backendtlspolicy_types.go index edfe82d657..cbd2c46410 100644 --- a/apis/v1alpha3/backendtlspolicy_types.go +++ b/apis/v1alpha3/backendtlspolicy_types.go @@ -201,7 +201,11 @@ type BackendTLSPolicyValidation struct { // backends: // // 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). - // 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. + // 2. Hostname MUST be used for authentication and MUST match the certificate + // served by the matching backend, unless SubjectAltNames is specified. + // 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + // but MUST NOT be used for authentication. If you want to use the value + // of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. // // Support: Core // diff --git a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml index 9a3d148731..b110a95a73 100644 --- a/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +++ b/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -272,7 +272,11 @@ spec: backends: 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). - 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. + 2. Hostname MUST be used for authentication and MUST match the certificate + served by the matching backend, unless SubjectAltNames is specified. + 3. If SubjectAltNames are specified, Hostname can be used for certificate selection + but MUST NOT be used for authentication. If you want to use the value + of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. Support: Core maxLength: 253 diff --git a/geps/gep-3155/index.md b/geps/gep-3155/index.md index 41477c2266..06324f6811 100644 --- a/geps/gep-3155/index.md +++ b/geps/gep-3155/index.md @@ -99,6 +99,10 @@ type BackendTLSPolicyValidation struct { // SubjectAltNames contains one or more Subject Alternative Names. // When specified, the certificate served from the backend MUST have at least one // Subject Alternate Name matching one of the specified SubjectAltNames. + // If SubjectAltNames are specified, Hostname MUST NOT be used for authentication, + // even if this would cause a failure in the case that the SubjectAltNames do not match. + // If you want to use Hostname for authentication, you must add Hostname to the SubjectAltNames list. + // // +kubebuilder:validation:MaxItems=5 SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index d34c24079d..dd27f75ee5 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -7632,7 +7632,7 @@ func schema_sigsk8sio_gateway_api_apis_v1alpha3_BackendTLSPolicyValidation(ref c }, "hostname": { SchemaProps: spec.SchemaProps{ - Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified.\n\nSupport: Core", + Description: "Hostname is used for two purposes in the connection between Gateways and backends:\n\n1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate\n served by the matching backend, unless SubjectAltNames is specified.\n3. If SubjectAltNames are specified, Hostname can be used for certificate selection\n but MUST NOT be used for authentication. If you want to use the value\n of the Hostname field for authentication, you MUST add it to the SubjectAltNames list.\n\nSupport: Core", Default: "", Type: []string{"string"}, Format: "", From 59a1a4ee1a87bdcb8772b15875af69383d028327 Mon Sep 17 00:00:00 2001 From: Norwin Schnyder Date: Tue, 2 Sep 2025 19:47:14 +0200 Subject: [PATCH 165/224] BackendTLSPolicy conformance tests for conflict resolution (#4043) * BackendTLSPolicy conformance tests for conflict resolution Signed-off-by: Norwin Schnyder * fix linting errors Signed-off-by: Norwin Schnyder * apply PR feedback Signed-off-by: Norwin Schnyder --------- Signed-off-by: Norwin Schnyder --- .../backendtlspolicy-conflict-resolution.go | 155 +++++++++++++ .../backendtlspolicy-conflict-resolution.yaml | 214 ++++++++++++++++++ conformance/utils/suite/suite.go | 2 +- 3 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 conformance/tests/backendtlspolicy-conflict-resolution.go create mode 100644 conformance/tests/backendtlspolicy-conflict-resolution.yaml diff --git a/conformance/tests/backendtlspolicy-conflict-resolution.go b/conformance/tests/backendtlspolicy-conflict-resolution.go new file mode 100644 index 0000000000..6aac39c9df --- /dev/null +++ b/conformance/tests/backendtlspolicy-conflict-resolution.go @@ -0,0 +1,155 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tests + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + h "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + "sigs.k8s.io/gateway-api/pkg/features" +) + +func init() { + ConformanceTests = append(ConformanceTests, BackendTLSPolicyConflictResolution) +} + +var BackendTLSPolicyConflictResolution = suite.ConformanceTest{ + ShortName: "BackendTLSPolicyConflictResolution", + Description: "Verifies that when multiple BackendTLSPolicies target the same Service, only one policy is accepted while conflicting policies are rejected, and traffic continues to route successfully.", + Features: []features.FeatureName{ + features.SupportGateway, + features.SupportHTTPRoute, + features.SupportBackendTLSPolicy, + }, + Manifests: []string{"tests/backendtlspolicy-conflict-resolution.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "backendtlspolicy-conflict-resolution", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + + kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns}) + gwAddr := kubernetes.GatewayAndRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), &gatewayv1.HTTPRoute{}, false, routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + acceptedCond := metav1.Condition{ + Type: string(v1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionTrue, + Reason: string(v1alpha2.PolicyReasonAccepted), + } + conflictedCond := metav1.Condition{ + Type: string(v1alpha2.PolicyConditionAccepted), + Status: metav1.ConditionFalse, + Reason: string(v1alpha2.PolicyReasonConflicted), + } + + t.Run("Conflicting BackendTLSPolicies targeting the same Service without a section name", func(t *testing.T) { + t.Run("First BackendTLSPolicy should be accepted", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "conflicted-without-section-name-1", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("Second BackendTLSPolicy should have a false Accepted condition with reason Conflicted ", func(t *testing.T) { + // This is not specific to BackendTLSPolicy, it follows the conflict-resolution rules, as defined in GEP-713. + conflictedPolicyNN := types.NamespacedName{Name: "conflicted-without-section-name-2", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, conflictedPolicyNN, gwNN, conflictedCond) + }) + + t.Run("HTTP request sent to Service using the accepted BackendTLSPolicy should succeed", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: "abc.example.com", + Path: "/backendtlspolicy-conflicted-without-section-name", + SNI: "other.example.com", + }, + Response: h.Response{StatusCode: 200}, + }) + }) + }) + + t.Run("Conflicting BackendTLSPolicies targeting the same Service with the same section name", func(t *testing.T) { + t.Run("First BackendTLSPolicy should be accepted", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "conflicted-with-section-name-1", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("Second BackendTLSPolicy should have a false Accepted condition with reason Conflicted ", func(t *testing.T) { + // This is not specific to BackendTLSPolicy, it follows the conflict-resolution rules, as defined in GEP-713. + conflictedPolicyNN := types.NamespacedName{Name: "conflicted-with-section-name-2", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, conflictedPolicyNN, gwNN, conflictedCond) + }) + + t.Run("HTTP request sent to Service using the accepted BackendTLSPolicy should succeed", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: "abc.example.com", + Path: "/backendtlspolicy-conflicted-with-section-name", + SNI: "other.example.com", + }, + Response: h.Response{StatusCode: 200}, + }) + }) + }) + + t.Run("BackendTLSPolicies targeting the same Service with and without a section name", func(t *testing.T) { + t.Run("BackendTLSPolicy with section name should be accepted", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "not-conflicted-with-section-name", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("BackendTLSPolicy without section name should be accepted", func(t *testing.T) { + policyNN := types.NamespacedName{Name: "not-conflicted-without-section-name", Namespace: ns} + kubernetes.BackendTLSPolicyMustHaveCondition(t, suite.Client, suite.TimeoutConfig, policyNN, gwNN, acceptedCond) + }) + + t.Run("HTTP request sent to Service using the BackendTLSPolicy with section name should succeed", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: "abc.example.com", + Path: "/backendtlspolicy-not-conflicted-with-section-name", + SNI: "other.example.com", + }, + Response: h.Response{StatusCode: 200}, + }) + }) + t.Run("HTTP request sent to Service using the BackendTLSPolicy without section name should succeed", func(t *testing.T) { + h.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, + h.ExpectedResponse{ + Namespace: ns, + Request: h.Request{ + Host: "abc.example.com", + Path: "/backendtlspolicy-not-conflicted-without-section-name", + SNI: "abc.example.com", + }, + Response: h.Response{StatusCode: 200}, + }) + }) + }) + }, +} diff --git a/conformance/tests/backendtlspolicy-conflict-resolution.yaml b/conformance/tests/backendtlspolicy-conflict-resolution.yaml new file mode 100644 index 0000000000..5d5e6583f9 --- /dev/null +++ b/conformance/tests/backendtlspolicy-conflict-resolution.yaml @@ -0,0 +1,214 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backendtlspolicy-conflict-resolution + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + hostnames: + - abc.example.com + rules: + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-conflicted-without-section-name-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-conflicted-without-section-name + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-conflicted-with-section-name-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-conflicted-with-section-name + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-not-conflicted-test + port: 443 + matches: + - path: + type: Exact + value: /backendtlspolicy-not-conflicted-with-section-name + - backendRefs: + - group: "" + kind: Service + name: backendtlspolicy-not-conflicted-test + port: 8443 + matches: + - path: + type: Exact + value: /backendtlspolicy-not-conflicted-without-section-name +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-conflicted-without-section-name-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https" + protocol: TCP + port: 443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-conflicted-with-section-name-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https-1" + protocol: TCP + port: 443 + targetPort: 8443 + - name: "https-2" + protocol: TCP + port: 8443 + targetPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + name: backendtlspolicy-not-conflicted-test + namespace: gateway-conformance-infra +spec: + selector: + app: tls-backend + ports: + - name: "https-1" + protocol: TCP + port: 443 + targetPort: 8443 + - name: "https-2" + protocol: TCP + port: 8443 + targetPort: 8443 +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: conflicted-without-section-name-1 + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-conflicted-without-section-name-test" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "other.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: conflicted-without-section-name-2 + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-conflicted-without-section-name-test" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: conflicted-with-section-name-1 + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-conflicted-with-section-name-test" + sectionName: "https-1" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "other.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: conflicted-with-section-name-2 + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-conflicted-with-section-name-test" + sectionName: "https-1" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "abc.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: not-conflicted-with-section-name + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-not-conflicted-test" + sectionName: "https-1" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "other.example.com" +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy +metadata: + name: not-conflicted-without-section-name + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: "backendtlspolicy-not-conflicted-test" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + # This ConfigMap is generated dynamically by the test suite. + # It contains the CA certificate used to sign the tls-backend serving certificate. + name: "tls-checks-ca-certificate" + hostname: "abc.example.com" diff --git a/conformance/utils/suite/suite.go b/conformance/utils/suite/suite.go index e3c098a89b..31db06c596 100644 --- a/conformance/utils/suite/suite.go +++ b/conformance/utils/suite/suite.go @@ -390,7 +390,7 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) caConfigMap, ca, caPrivKey := kubernetes.MustCreateCACertConfigMap(t, "gateway-conformance-infra", "tls-checks-ca-certificate") suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup) - secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity"}, ca, caPrivKey) + secret = kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "tls-checks-certificate", []string{"abc.example.com", "spiffe://abc.example.com/test-identity", "other.example.com"}, ca, caPrivKey) suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup) // The following CA ceritficate is used for BackendTLSPolicy testing to intentionally force TLS validation to fail. From 1da7c3706cb478284dec0c3051bfc875be617a49 Mon Sep 17 00:00:00 2001 From: Antonio Ojea Date: Tue, 2 Sep 2025 22:11:14 +0200 Subject: [PATCH 166/224] prevent controller-runtime stack traces logger (#4054) --- conformance/conformance.go | 5 +++++ go.mod | 1 + 2 files changed, 6 insertions(+) diff --git a/conformance/conformance.go b/conformance/conformance.go index ce7a465c60..3921310575 100644 --- a/conformance/conformance.go +++ b/conformance/conformance.go @@ -36,6 +36,8 @@ import ( clientset "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/yaml" ) @@ -43,6 +45,9 @@ import ( // ConformanceOptions struct. It will also initialize the various clients // required by the tests. func DefaultOptions(t *testing.T) suite.ConformanceOptions { + // This line prevents controller-runtime from complaining about log.SetLogger never being called + log.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) + cfg, err := config.GetConfig() require.NoError(t, err, "error loading Kubernetes config") clientOptions := client.Options{} diff --git a/go.mod b/go.mod index 3359ba2e1c..070b21f600 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.2 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect From 702cfd27bbfdd006f0df3a10bb8cbb0d20e8647a Mon Sep 17 00:00:00 2001 From: Enrico Date: Wed, 3 Sep 2025 21:05:14 +0200 Subject: [PATCH 167/224] Add new BackendTLSPolicy configuration options to documentation (#3563) * Add new BackendTLSPolicy configuration options to documentation: - Gateway backendTLS field - subjectAltNames field - options field The documentation includes descriptions of each new field along with their purpose, usage constraints and reference links. * Update site-src/api-types/backendtlspolicy.md --------- Co-authored-by: Shane Utt --- site-src/api-types/backendtlspolicy.md | 36 ++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/site-src/api-types/backendtlspolicy.md b/site-src/api-types/backendtlspolicy.md index ac57bd04ec..084d338ee7 100644 --- a/site-src/api-types/backendtlspolicy.md +++ b/site-src/api-types/backendtlspolicy.md @@ -36,11 +36,13 @@ The specification of a [BackendTLSPolicy][backendtlspolicy] consists of: - [Validation][validation] - Defines the configuration for TLS, including hostname, CACertificateRefs, and WellKnownCACertificates. - [Hostname][hostname] - Defines the Server Name Indication (SNI) that the Gateway uses to connect to the backend. +- [SubjectAltNames][subjectAltNames] - Specifies one or more Subject Alternative Names that the backend certificate must match. When specified, the certificate must have at least one matching SAN. This field enables separation between SNI (hostname) and certificate identity validation. A maximum of 5 SANs are allowed. - [CACertificateRefs][caCertificateRefs] - Defines one or more references to objects that contain PEM-encoded TLS certificates, which are used to establish a TLS handshake between the Gateway and backend Pod. Either CACertificateRefs or WellKnownCACertificates may be specified, but not both. - [WellKnownCACertificates][wellKnownCACertificates] - Specifies whether system CA certificates may be used in the TLS handshake between the Gateway and backend Pod. Either CACertificateRefs or WellKnownCACertificates may be specified, but not both. +- [Options][options] - A map of key/value pairs enabling extended TLS configuration for implementations that choose to provide support. Check your implementation's documentation for details. The following chart outlines the object definitions and relationship: ```mermaid @@ -48,7 +50,7 @@ flowchart LR backendTLSPolicy[["backendTLSPolicy