Operator Changes for K8s Gateway API Conformance#2168
Conversation
Dependency Validation ResultsDependency name: k8s.io/api Dependency name: k8s.io/apimachinery Dependency name: k8s.io/client-go Dependency name: sigs.k8s.io/gateway-api Next Steps
|
📝 WalkthroughSummaryThis PR introduces comprehensive changes to make the api-platform Kubernetes operator compatible with the Gateway API specification. The work encompasses operator API extensions, controller implementations, runtime model enhancements, and xDS translation updates to support Gateway API-style routing constructs. Key ChangesAPI and Schema Extensions
Runtime and Translation Layer
Gateway Controller ImplementationIntroduced multiple new controller modules for Gateway API conformance:
Gateway Reconciliation Enhancements
Additional Updates
TestingComprehensive test coverage added for:
ImpactThe PR enables the operator to manage Kubernetes gateways using Gateway API HTTPRoute resources as the primary configuration mechanism, with full support for advanced routing features (header matching, path matching, direct responses, weighted backends) while maintaining backward compatibility through deterministic configuration hashing and dependency management. WalkthroughThis PR extends the gateway stack with advanced routing primitives and a new Gateway API–native control plane. On the data plane side, the OpenAPI management schema, generated Go models, and Kubernetes CRD types gain Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 19
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
kubernetes/gateway-operator/internal/controller/httproute_controller.go (1)
215-239:⚠️ Potential issue | 🟠 Major | ⚡ Quick winClean up the current gateway deployment on non-retryable build failures.
If
BuildAPIConfigFromHTTPRoutestarts failing after a route was already deployed, this branch only patches status and returns. The previously deployed RestApi stays active on the Gateway, so runtime state can drift from the HTTPRoute. For invalid/non-retryable config errors, delete the current deployment before exiting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/gateway-operator/internal/controller/httproute_controller.go` around lines 215 - 239, On non-retryable build failures (i.e., when BuildAPIConfigFromHTTPRoute returns an error and requeueAfter==0 — typically IsHTTPRouteBackendRefError or IsInvalidHTTPRouteConfigError), delete the currently deployed RestApi on the Gateway so runtime state doesn't drift: after calling r.patchResolvedRefsForParents(...) and before returning (inside the same error branch), invoke a deletion helper such as r.deleteGatewayRestAPI(ctx, parentGW, route) (create this helper if it doesn't exist), log any deletion error via log.Error, and then return the existing ctrl.Result{}; keep transient errors (requeueAfter>0) behavior unchanged.kubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yaml (1)
2-19:⚠️ Potential issue | 🟠 MajorFix Helm CRD bundle gating to be per-CRD
- Line 6 builds a single
$crdfromfiles/gateway-api-standard/standard-crds.yaml, and the template does only onelookupusing$crd.metadata.name.- Line 19 then emits the entire
standard-crds.yamlbundle (the bundle contains multipleCustomResourceDefinitiondocuments), so the ownership/existence decision is applied to the whole bundle rather than each CRD document.- Split the bundle into individual CRD documents and perform the
lookup/ownership check per CRD before emitting each one.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yaml` around lines 2 - 19, The template currently parses the entire standard-crds.yaml into a single $crd and runs lookup/ownership checks once, then emits the whole bundle; instead, parse the file into individual CRD documents and iterate them so lookup and the $ownedByThisRelease gating happen per document: use fromYaml ($.Files.Get $p) as a list (range over each item, e.g., $doc), perform lookup "apiextensions.k8s.io/v1" "CustomResourceDefinition" "" $doc.metadata.name and the same annotation/label checks for each $doc, and emit each CRD individually (e.g., toYaml $doc) only when its per-CRD check passes. Ensure you keep the same variables ($paths, $p) and preserve existing annotation/label checks but applied inside the per-document loop.
🟡 Minor comments (2)
kubernetes/gateway-operator/api/v1alpha1/restapi_types.go-280-288 (1)
280-288:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winEnforce the documented weight range.
Line 286 documents
Weightas0-100, but the CRD does not validate that range. Invalid weights would still be accepted and can produce unexpected routing behavior. Add the matching min/max validation.Suggested change
type WeightedUpstream struct { // Url Backend URL (host and port; no path) // +kubebuilder:validation:Required Url string `json:"url"` // Weight Load balancing weight (0-100) // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=100 Weight *int `json:"weight,omitempty"` }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/gateway-operator/api/v1alpha1/restapi_types.go` around lines 280 - 288, The Weight field in the WeightedUpstream struct lacks CRD validation for the documented 0-100 range; add kubebuilder validation annotations to enforce Minimum=0 and Maximum=100 on the Weight field (e.g., add +kubebuilder:validation:Minimum=0 and +kubebuilder:validation:Maximum=100 above the Weight declaration) so the CRD rejects values outside 0–100 while keeping the existing pointer type and json tag.kubernetes/gateway-operator/api/v1alpha1/restapi_types.go-176-185 (1)
176-185:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winConstrain direct-response status codes to valid HTTP ranges.
Line 180 currently accepts any integer, so invalid
directResponse.statusCodevalues can pass CRD validation. Add bounds such as100-599here to keep the contract aligned with HTTP semantics.Suggested change
type OperationDirectResponse struct { // StatusCode HTTP status code // +kubebuilder:validation:Required + // +kubebuilder:validation:Minimum=100 + // +kubebuilder:validation:Maximum=599 StatusCode int `json:"statusCode"`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/gateway-operator/api/v1alpha1/restapi_types.go` around lines 176 - 185, The StatusCode field on the OperationDirectResponse struct currently allows any integer; update the kubebuilder validation tags on StatusCode (the StatusCode int `json:"statusCode"`) to constrain values to the HTTP range by adding +kubebuilder:validation:Minimum=100 and +kubebuilder:validation:Maximum=599 (and keep the existing Required tag), so CRD validation rejects values outside 100–599.
🧹 Nitpick comments (2)
gateway/gateway-controller/api/management-openapi.yaml (1)
4136-4140: ⚡ Quick winConsider specifying a default value for
pathMatchType.The
pathMatchTypefield lacks a default value. When omitted, the routing behavior should be explicitly documented either via a default value or in the description. If the intent is to match the Gateway API HTTPRoute default (which is typicallyExactfor path matching), consider addingdefault: Exact.📝 Suggested default value
pathMatchType: type: string description: Path matching semantics for the operation route enum: [Exact, PathPrefix] + default: Exact example: Exact🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gateway/gateway-controller/api/management-openapi.yaml` around lines 4136 - 4140, Add an explicit default for the pathMatchType schema entry in management-openapi.yaml by setting default: Exact and update the description to state that when omitted the default is Exact (matching the Gateway API HTTPRoute default); modify the schema block for the property named pathMatchType so it includes the default key and a brief note in its description about the default behavior.kubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.go (1)
788-863: ⚡ Quick winAdd a passing
parametersRefcase.This suite only exercises nil and missing references. A success-path test with a registered object would cover the real lookup path and would catch regressions where valid
parametersRefobjects are rejected.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.go` around lines 788 - 863, Add a positive test case to TestValidateParametersRef that exercises the real lookup path: extend the test table with a case whose Gateway.Spec.Infrastructure.ParametersRef points to a corev1.ConfigMap (Group "" / Kind "ConfigMap", Name e.g. "valid-config") and mark wantValid=true; to make the fake client return that object, add a per-test field (e.g. objects []client.Object) and when building the client use fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.objects...).Build(); ensure the scheme registers corev1 (corev1.AddToScheme) and include a corev1.ConfigMap in tt.objects for the passing case so validateParametersRef actually finds it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@gateway/gateway-controller/api/management-openapi.yaml`:
- Around line 4179-4182: The statusCode schema currently allows any integer; add
OpenAPI numeric range constraints so only valid HTTP status codes (100–599) are
accepted by updating the statusCode property to include minimum: 100 and
maximum: 599. Locate the statusCode field in the OpenAPI spec (the integer
schema with description "HTTP status code returned directly without contacting
an upstream") and add the minimum and maximum keys to enforce the 100–599 range.
- Around line 4005-4010: The vhostList array items are missing pattern
validation; update the schema for vhostList.items to include the same
hostname/wildcard regex used by the existing vhost (and vhosts.main) definitions
so only valid hostnames or a leading wildcard (e.g. *.example.com) are allowed;
locate the vhostList schema and add a "pattern" property with the approved regex
(matching the vhost/vhosts.main patterns) and keep the example unchanged.
- Around line 4195-4197: The OperationResponseHeader.schema is missing RFC 7230
token validation for its name property; update the OperationResponseHeader
definition so the name field includes the same pattern/format validation used by
OperationHeaderMatch (i.e., the RFC 7230 token regex) and an example that still
conforms to that pattern, ensuring response header names are validated
consistently.
- Around line 4154-4167: Add RFC 7230 token validation to the
OperationHeaderMatch.name property in the OpenAPI spec: update
OperationHeaderMatch -> properties -> name to include a pattern that restricts
the header name to RFC7230 tchar characters (no spaces, only allowed
punctuation, letters and digits), for example using the token regex
^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$ and keep the existing description/example; this
ensures invalid header names are rejected at schema validation time before
translating to Envoy.
In `@gateway/gateway-controller/pkg/transform/restapi_test.go`:
- Around line 357-360: The test is asserting DefaultCluster against the internal
rdc.UpstreamClusters key (e.g. "upstream_sandbox_*") but the transform contract
exposes the Envoy-facing name; update the hard-coded expectedSandboxCluster and
the route-loop assertions to compute/compare against EnvoyClusterName instead of
the internal ClusterKey. Locate the expectations referencing
expectedSandboxCluster and any assertions that compare route.DefaultCluster (or
route.GetDefaultCluster()) and replace them to call or construct the
EnvoyClusterName for the matching upstream (using the same logic/function used
by the transform code that generates EnvoyClusterName) so the tests validate the
Envoy-facing cluster name rather than the rdc.UpstreamClusters map key. Ensure
both the sandbox/main route checks (around the previous expectedSandboxCluster
and the route-loop assertions) are changed consistently.
In `@gateway/gateway-controller/pkg/transform/restapi.go`:
- Around line 234-255: The code currently collapses per-endpoint schemes into a
single cluster-level TLS flag in the loop over def.Upstreams (parsedURL,
endpoints, tlsEnabled) and this loses mixed http/https information; update the
transformation to preserve scheme/TLS per endpoint by adding a scheme or tls
field to models.Endpoint (set ep.Scheme or ep.TLS based on parsedURL.Scheme) and
remove/avoid using the single tlsEnabled cluster flag, or alternatively detect
mixed schemes while iterating (using parsedURL.Scheme) and return an error
rejecting mixed-scheme upstreams before assigning
rdc.UpstreamClusters[defClusterKey]; update the construction of
models.UpstreamCluster and models.Endpoint accordingly so endpoint-level scheme
is retained.
In `@gateway/gateway-controller/pkg/xds/translator.go`:
- Around line 633-691: createWeightedCluster currently builds a STRICT_DNS
cluster without TLS even when tls.Enabled is true; mirror the single-endpoint
path in createCluster by attaching an Envoy TLS transport socket to the cluster
when tls != nil && tls.Enabled: construct an
envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext (set Sni to ep.Host
or the given name as appropriate and include any ca/cert configs from
models.UpstreamTLS), wrap it with anypb.New and assign it to the returned
cluster via Cluster.TransportSocket = &core.TransportSocket{ Name: "tls",
ConfigType: &core.TransportSocket_TypedConfig{ TypedConfig:
anypb.New(<UpstreamTlsContext>) } }; ensure you import and reuse the same TLS
construction logic used in createCluster (or centralize into a helper) so
createWeightedCluster sets transport socket when tls.Enabled.
- Around line 508-562: setDirectResponseMatch currently diverges from
createRouteFromRDC by converting parameterized paths into literal regexes and
downgrading RegularExpression header matchers to exact matches; update it to
reuse the same path and header matching logic as createRouteFromRDC so
direct-response routes match identically. Specifically, for path handling in
setDirectResponseMatch (function name: setDirectResponseMatch, symbols:
fullPath, operationPath, r.Match.PathSpecifier, route.RouteMatch_SafeRegex,
route.RouteMatch_Path) detect and handle parameterized paths using the same
logic as createRouteFromRDC (or extract that logic into a shared helper and call
it) instead of always falling back to QuoteMeta; and for header matching
(symbols: rdcRoute.MatchHeaders, route.HeaderMatcher, HeaderMatchSpecifier)
preserve the original match types by mapping RegularExpression header entries to
the regex/safe-regex header matcher variant (using matcher.RegexMatcher) rather
than converting them to StringMatcher exact matches. Ensure you either call
createRouteFromRDC or factor out and reuse its path/header-matching helpers so
behavior is identical.
In `@kubernetes/gateway-operator/api/v1alpha1/restapi_types.go`:
- Around line 235-253: The Upstream struct currently allows both Url and Ref to
be omitted or set together; update the CRD schema for Upstream so exactly one of
Url or Ref is required by adding an OpenAPI oneOf rule to the Upstream type (use
a kubebuilder marker to emit a oneOf on the Upstream schema referencing the
properties "url" and "ref") so the CRD enforces either Url (Upstream.Url) XOR
Ref (Upstream.Ref) but not both.
In `@kubernetes/gateway-operator/go.mod`:
- Around line 17-22: The k8s.io/* modules in go.mod are misaligned: update the
k8s.io/cli-runtime module entry to the same minor version as the others (e.g.,
change k8s.io/cli-runtime v0.33.3 → v0.35.1) so k8s.io/api, k8s.io/apimachinery,
k8s.io/client-go and cli-runtime share the same minor; after editing the module
line for k8s.io/cli-runtime, run go mod tidy to resolve transitive versions and
verify builds and tests that use client-go, apimachinery, api, and cli-runtime
(look for the k8s.io/cli-runtime, k8s.io/client-go, k8s.io/apimachinery,
k8s.io/api entries).
In `@kubernetes/gateway-operator/internal/controller/gateway_addresses.go`:
- Line 25: The code currently exposes the loopback constant
localClusterNodeAddressFallback ("127.0.0.1") for NodePort gateways which causes
incorrect Gateway status; update the address-resolution logic so NodePort-backed
Gateways never publish 127.0.0.1. In the function that computes gateway
addresses (the code path that uses localClusterNodeAddressFallback and is
consumed by k8s_gateway_controller.go when updating Gateway status), remove the
unconditional fallback for NodePort: either attempt to derive real node IPs
(e.g., from Node.Status.Addresses or the Service's nodePort endpoints) and
publish those, or leave the Gateway's address list empty/unset until a
non-loopback address can be resolved. Ensure any references to
localClusterNodeAddressFallback are not written into Gateway status for
NodePort-backed Gateways.
In `@kubernetes/gateway-operator/internal/controller/httproute_backends.go`:
- Around line 45-61: The helper serviceConnectionPort currently hides failures
by returning the Service port for headless Services when p.TargetPort is
non-numeric; change it to fail explicitly instead of silently falling back:
update serviceConnectionPort to return a resolvable numeric port or an
error/sentinel (e.g., (int32, error) or (int32, bool)) when svc.Spec.ClusterIP
== corev1.ClusterIPNone and p.TargetPort.Type != intstr.Int, and propagate that
error to callers so backend resolution can either query Endpoints/EndpointSlices
to resolve the numeric pod port or abort with a clear failure; ensure you
reference the p.TargetPort check in serviceConnectionPort and update all callers
to handle the new error/sentinel path.
- Around line 190-198: The current handler collapses all c.Get errors into a
permanent RouteReasonBackendNotFound; change the logic in the block where
c.Get(ctx, key, svc) is handled so only apierrors.IsNotFound(err) sets
ref.Reason = gatewayv1.RouteReasonBackendNotFound and the "backend Service ...
not found" message, while any other error preserves it as a transient read
failure (e.g., set a different ref.Reason such as an internal/read-failed reason
or leave ref.OK=false and set ref.Message to include the error) so callers like
firstBackendURL can distinguish retryable lookup failures from true missing
backends; update the error branch message to include the actual error details
(fmt.Sprintf("get backend Service %s: %v", key.String(), err)) and ensure ref
fields (ref.OK, ref.Reason, ref.Message) reflect transient vs permanent
outcomes.
In `@kubernetes/gateway-operator/internal/controller/httproute_compile.go`:
- Around line 60-65: The contextPath computed from
route.Annotations[AnnHTTPRouteContext] (variable contextPath in
httproute_compile.go) must be normalized to match the APIConfigData.Context
schema (no trailing slash, except root "/"); update the branch that sets
contextPath so that after trimming and adding a leading slash you also strip any
trailing slash when the path length > 1 (preserve "/" for empty), ensuring
APIConfigData.Context is produced as a non-trailing-slash path; locate the logic
around contextPath and replace the current else-if handling with this
normalization.
In `@kubernetes/gateway-operator/internal/controller/httproute_filters.go`:
- Around line 107-135: The handler for gatewayv1.HTTPRouteFilterRequestRedirect
currently synthesizes a Location using "localhost" and a default scheme when
redir.Hostname or redir.Scheme are missing; instead detect when either
redir.Hostname or redir.Scheme is nil/empty and do NOT synthesize an absolute
URL (remove the locHost/"localhost" fallback). For shapes the current
apiv1.OperationDirectResponse cannot represent (i.e., status-only redirects or
redirects missing hostname/scheme) either reject/return an unsupported-redirect
error or skip/apply a non-direct response path so we don't emit a misleading
Location header; update the gatewayv1.HTTPRouteFilterRequestRedirect handling
(variable redir and the creation of apiv1.OperationDirectResponse named direct)
to perform this validation and return/mark unsupported rather than constructing
a fabricated URL.
In `@kubernetes/gateway-operator/internal/controller/httproute_referencegrant.go`:
- Around line 88-103: Change crossNamespaceSecretReferenceGrantPermitted to
return (bool, error) and surface API list errors instead of conflating them with
"no grant". Specifically, update the function signature
crossNamespaceSecretReferenceGrantPermitted(ctx context.Context, c
client.Client, gwNS, secretNS, secretName string) to return (bool, error),
return (true, nil) when secretNS == gwNS, return (false, err) when c.List(ctx,
&list, client.InNamespace(secretNS)) returns an error, and otherwise return
(true, nil) or (false, nil) based on
referenceGrantAllowsGatewayToSecret(&list.Items[i].Spec, gwNS, secretName). Also
update all callers to handle the error return (requeue on transient lookup
errors and only reject when the boolean result is false with a nil error).
In `@kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go`:
- Around line 494-509: The reconcile path treats the gateway runtime Service as
required but discovery via discoverGatewayRuntimeService can fail while skipHelm
remains true, leaving reconcile stuck; update the self-heal/expected-resources
check to include the runtime Service (or trigger a Helm repair when discovery
fails) by adding the runtime Service to the resources validated before honoring
skipHelm, and/or when discoverGatewayRuntimeService or
resolveGatewayAddressesFromService returns missing/empty, call the existing Helm
repair flow (same place that handles Deployments/ controller Service) or clear
skipHelm so patchGatewayStatus can request a re-install; reference
discoverGatewayRuntimeService, resolveGatewayAddressesFromService and
patchGatewayStatus to locate where to add the runtime Service validation or
invoke the Helm repair path.
In `@kubernetes/gateway-operator/internal/helm/client.go`:
- Around line 395-410: The current GetReleaseName collapses long gateway names
to a fixed 8-hex suffix (helmReleaseHashHexChars), which raises collision risk;
change GetReleaseName to compute the hash-length dynamically from the 53-char
limit so more of the hex digest is used when the gateway name would overflow.
Specifically, replace the fixed helmReleaseHashHexChars usage in GetReleaseName
with a computed allowedHashChars = maxHelmReleaseNameLen -
len(helmReleaseNameSuffix) - len(helmReleaseHashPrefix) (clamped to a sensible
minimum like 8), then return helmReleaseHashPrefix +
hex.EncodeToString(sum[:])[:allowedHashChars]; update or remove the fixed
constant helmReleaseHashHexChars accordingly and keep references to
GetReleaseName, helmReleaseNameSuffix, helmReleaseHashPrefix, and
maxHelmReleaseNameLen to locate the change.
---
Outside diff comments:
In `@kubernetes/gateway-operator/internal/controller/httproute_controller.go`:
- Around line 215-239: On non-retryable build failures (i.e., when
BuildAPIConfigFromHTTPRoute returns an error and requeueAfter==0 — typically
IsHTTPRouteBackendRefError or IsInvalidHTTPRouteConfigError), delete the
currently deployed RestApi on the Gateway so runtime state doesn't drift: after
calling r.patchResolvedRefsForParents(...) and before returning (inside the same
error branch), invoke a deletion helper such as r.deleteGatewayRestAPI(ctx,
parentGW, route) (create this helper if it doesn't exist), log any deletion
error via log.Error, and then return the existing ctrl.Result{}; keep transient
errors (requeueAfter>0) behavior unchanged.
In `@kubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yaml`:
- Around line 2-19: The template currently parses the entire standard-crds.yaml
into a single $crd and runs lookup/ownership checks once, then emits the whole
bundle; instead, parse the file into individual CRD documents and iterate them
so lookup and the $ownedByThisRelease gating happen per document: use fromYaml
($.Files.Get $p) as a list (range over each item, e.g., $doc), perform lookup
"apiextensions.k8s.io/v1" "CustomResourceDefinition" "" $doc.metadata.name and
the same annotation/label checks for each $doc, and emit each CRD individually
(e.g., toYaml $doc) only when its per-CRD check passes. Ensure you keep the same
variables ($paths, $p) and preserve existing annotation/label checks but applied
inside the per-document loop.
---
Minor comments:
In `@kubernetes/gateway-operator/api/v1alpha1/restapi_types.go`:
- Around line 280-288: The Weight field in the WeightedUpstream struct lacks CRD
validation for the documented 0-100 range; add kubebuilder validation
annotations to enforce Minimum=0 and Maximum=100 on the Weight field (e.g., add
+kubebuilder:validation:Minimum=0 and +kubebuilder:validation:Maximum=100 above
the Weight declaration) so the CRD rejects values outside 0–100 while keeping
the existing pointer type and json tag.
- Around line 176-185: The StatusCode field on the OperationDirectResponse
struct currently allows any integer; update the kubebuilder validation tags on
StatusCode (the StatusCode int `json:"statusCode"`) to constrain values to the
HTTP range by adding +kubebuilder:validation:Minimum=100 and
+kubebuilder:validation:Maximum=599 (and keep the existing Required tag), so CRD
validation rejects values outside 100–599.
---
Nitpick comments:
In `@gateway/gateway-controller/api/management-openapi.yaml`:
- Around line 4136-4140: Add an explicit default for the pathMatchType schema
entry in management-openapi.yaml by setting default: Exact and update the
description to state that when omitted the default is Exact (matching the
Gateway API HTTPRoute default); modify the schema block for the property named
pathMatchType so it includes the default key and a brief note in its description
about the default behavior.
In
`@kubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.go`:
- Around line 788-863: Add a positive test case to TestValidateParametersRef
that exercises the real lookup path: extend the test table with a case whose
Gateway.Spec.Infrastructure.ParametersRef points to a corev1.ConfigMap (Group ""
/ Kind "ConfigMap", Name e.g. "valid-config") and mark wantValid=true; to make
the fake client return that object, add a per-test field (e.g. objects
[]client.Object) and when building the client use
fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.objects...).Build();
ensure the scheme registers corev1 (corev1.AddToScheme) and include a
corev1.ConfigMap in tt.objects for the passing case so validateParametersRef
actually finds it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 03fa64e4-c9d9-4047-8fa7-a6fe98ed73b8
⛔ Files ignored due to path filters (1)
kubernetes/gateway-operator/go.sumis excluded by!**/*.sum
📒 Files selected for processing (59)
gateway/gateway-controller/api/management-openapi.yamlgateway/gateway-controller/cmd/controller/main.gogateway/gateway-controller/pkg/api/management/generated.gogateway/gateway-controller/pkg/models/runtime_deploy_config.gogateway/gateway-controller/pkg/transform/restapi.gogateway/gateway-controller/pkg/transform/restapi_test.gogateway/gateway-controller/pkg/xds/route_discriminator_test.gogateway/gateway-controller/pkg/xds/translator.gogateway/gateway-controller/pkg/xds/translator_test.gogateway/gateway-runtime/policy-engine/internal/kernel/translator.gogateway/gateway-runtime/policy-engine/internal/kernel/translator_test.gogateway/gateway-runtime/policy-engine/pkg/engine/types.gokubernetes/gateway-operator/api/v1alpha1/restapi_types.gokubernetes/gateway-operator/api/v1alpha1/zz_generated.deepcopy.gokubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yamlkubernetes/gateway-operator/config/rbac/role.yamlkubernetes/gateway-operator/go.modkubernetes/gateway-operator/internal/controller/gateway_addresses.gokubernetes/gateway-operator/internal/controller/gateway_addresses_test.gokubernetes/gateway-operator/internal/controller/gateway_api_annotations.gokubernetes/gateway-operator/internal/controller/gateway_attached_routes.gokubernetes/gateway-operator/internal/controller/gateway_attached_routes_test.gokubernetes/gateway-operator/internal/controller/gateway_infra.gokubernetes/gateway-operator/internal/controller/gateway_listener_validation.gokubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.gokubernetes/gateway-operator/internal/controller/gateway_listeners_overlay.gokubernetes/gateway-operator/internal/controller/gateway_listeners_overlay_test.gokubernetes/gateway-operator/internal/controller/httproute_attachment.gokubernetes/gateway-operator/internal/controller/httproute_attachment_test.gokubernetes/gateway-operator/internal/controller/httproute_backends.gokubernetes/gateway-operator/internal/controller/httproute_backends_test.gokubernetes/gateway-operator/internal/controller/httproute_compile.gokubernetes/gateway-operator/internal/controller/httproute_compile_test.gokubernetes/gateway-operator/internal/controller/httproute_controller.gokubernetes/gateway-operator/internal/controller/httproute_enqueue.gokubernetes/gateway-operator/internal/controller/httproute_filters.gokubernetes/gateway-operator/internal/controller/httproute_filters_test.gokubernetes/gateway-operator/internal/controller/httproute_mapper.gokubernetes/gateway-operator/internal/controller/httproute_mapper_test.gokubernetes/gateway-operator/internal/controller/httproute_parents.gokubernetes/gateway-operator/internal/controller/httproute_referencegrant.gokubernetes/gateway-operator/internal/controller/k8s_gateway_controller.gokubernetes/gateway-operator/internal/controller/k8s_gateway_controller_test.gokubernetes/gateway-operator/internal/controller/llmproxy_controller_test.gokubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.gokubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.gokubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.gokubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.gokubernetes/gateway-operator/internal/helm/client.gokubernetes/gateway-operator/internal/helm/client_test.gokubernetes/helm/operator-helm-chart/files/gateway-api-standard/gatewayclasses.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/gateways.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/grpcroutes.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/httproutes.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/referencegrants.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/standard-crds.yamlkubernetes/helm/operator-helm-chart/templates/_helpers.tplkubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yamlsdk/core/policy/v1alpha2/action.go
💤 Files with no reviewable changes (6)
- kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go
- kubernetes/helm/operator-helm-chart/files/gateway-api-standard/referencegrants.gateway.networking.k8s.io.yaml
- kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go
- kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go
- kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go
- kubernetes/helm/operator-helm-chart/files/gateway-api-standard/gatewayclasses.gateway.networking.k8s.io.yaml
| // The default cluster must be the name Envoy knows the cluster by, which in the | ||
| // RDC path is the rdc.UpstreamClusters map key (ClusterKey), i.e. | ||
| // "upstream_sandbox_<host>_<port>" — not the sanitized "cluster_<scheme>_<host>" form. | ||
| const expectedSandboxCluster = "upstream_sandbox_sandbox-backend_9080" |
There was a problem hiding this comment.
Use the Envoy cluster name contract in these assertions.
These tests now pin DefaultCluster to the internal rdc.UpstreamClusters key (upstream_*), but the transform contract uses the Envoy-facing cluster name instead. Please update both the hard-coded sandbox expectation and the route-loop assertion to validate against the generated EnvoyClusterName, not the internal map key. Based on learnings: in gateway/gateway-controller/pkg/transform/, DefaultCluster for sandbox/main routes should use EnvoyClusterName rather than the internal ClusterKey.
Also applies to: 390-390, 395-430
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@gateway/gateway-controller/pkg/transform/restapi_test.go` around lines 357 -
360, The test is asserting DefaultCluster against the internal
rdc.UpstreamClusters key (e.g. "upstream_sandbox_*") but the transform contract
exposes the Envoy-facing name; update the hard-coded expectedSandboxCluster and
the route-loop assertions to compute/compare against EnvoyClusterName instead of
the internal ClusterKey. Locate the expectations referencing
expectedSandboxCluster and any assertions that compare route.DefaultCluster (or
route.GetDefaultCluster()) and replace them to call or construct the
EnvoyClusterName for the matching upstream (using the same logic/function used
by the transform code that generates EnvoyClusterName) so the tests validate the
Envoy-facing cluster name rather than the rdc.UpstreamClusters map key. Ensure
both the sandbox/main route checks (around the previous expectedSandboxCluster
and the route-loop assertions) are changed consistently.
Source: Learnings
| for _, target := range parentTargets { | ||
| attached, _, _ := evaluateHTTPRouteAttachment(ctx, c, parentGW, route, target.ref) | ||
| if !attached { | ||
| continue | ||
| } | ||
| for _, listener := range parentGW.Spec.Listeners { | ||
| if !parentRefAttachesToListener(target.ref, listener) { | ||
| continue | ||
| } | ||
| listenerHost := "" | ||
| if listener.Hostname != nil { | ||
| listenerHost = string(*listener.Hostname) | ||
| } | ||
| if len(route.Spec.Hostnames) == 0 { | ||
| // Route matches all hostnames; constrain to the listener's hostname if it has one. | ||
| if listenerHost != "" { | ||
| addHost(listenerHost) | ||
| } | ||
| continue | ||
| } | ||
| for _, rh := range route.Spec.Hostnames { | ||
| if h, ok := intersectHostname(string(rh), listenerHost); ok { | ||
| addHost(h) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Derive vhosts from the listeners that actually accepted the route.
evaluateHTTPRouteAttachment(..., target.ref) only tells you that at least one listener for that parent accepted the route. The inner loop then adds hostnames from every listener matched by parentRefAttachesToListener, even if that listener was filtered out by AllowedRoutes, namespace checks, or hostname mismatch. With a gateway-wide parentRef, this can emit vhosts for listeners the route never attached to. Please reuse the same per-listener acceptance predicate here and add a regression test for the mixed-listener case.
| case gatewayv1.HTTPRouteFilterRequestRedirect: | ||
| if f.RequestRedirect == nil { | ||
| continue | ||
| } | ||
| redir := f.RequestRedirect | ||
| status := 302 | ||
| if redir.StatusCode != nil { | ||
| status = int(*redir.StatusCode) | ||
| } | ||
| host := "" | ||
| if redir.Hostname != nil { | ||
| host = string(*redir.Hostname) | ||
| } | ||
| scheme := "http" | ||
| if redir.Scheme != nil && *redir.Scheme != "" { | ||
| scheme = string(*redir.Scheme) | ||
| } | ||
| locHost := host | ||
| if locHost == "" { | ||
| locHost = "localhost" | ||
| } | ||
| headers := []apiv1.OperationResponseHeader{{ | ||
| Name: "Location", | ||
| Value: fmt.Sprintf("%s://%s", scheme, locHost), | ||
| }} | ||
| direct = &apiv1.OperationDirectResponse{ | ||
| StatusCode: status, | ||
| Headers: headers, | ||
| } |
There was a problem hiding this comment.
Do not synthesize redirect targets with http://localhost.
When RequestRedirect omits scheme or hostname, this code rewrites the redirect to a new absolute URL instead of preserving the original request authority/path. Status-only or partial redirects will point clients at the wrong location. Either preserve unspecified components, or reject redirect shapes the current direct-response model cannot represent faithfully.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kubernetes/gateway-operator/internal/controller/httproute_filters.go` around
lines 107 - 135, The handler for gatewayv1.HTTPRouteFilterRequestRedirect
currently synthesizes a Location using "localhost" and a default scheme when
redir.Hostname or redir.Scheme are missing; instead detect when either
redir.Hostname or redir.Scheme is nil/empty and do NOT synthesize an absolute
URL (remove the locHost/"localhost" fallback). For shapes the current
apiv1.OperationDirectResponse cannot represent (i.e., status-only redirects or
redirects missing hostname/scheme) either reject/return an unsupported-redirect
error or skip/apply a non-direct response path so we don't emit a misleading
Location header; update the gatewayv1.HTTPRouteFilterRequestRedirect handling
(variable redir and the creation of apiv1.OperationDirectResponse named direct)
to perform this validation and return/mark unsupported rather than constructing
a fabricated URL.
| // crossNamespaceSecretReferenceGrantPermitted checks whether a Gateway may reference a Secret | ||
| // in another namespace per Gateway API ReferenceGrant rules. Grants must exist in the Secret namespace. | ||
| func crossNamespaceSecretReferenceGrantPermitted(ctx context.Context, c client.Client, gwNS, secretNS, secretName string) bool { | ||
| if secretNS == gwNS { | ||
| return true | ||
| } | ||
| var list gatewayv1beta1.ReferenceGrantList | ||
| if err := c.List(ctx, &list, client.InNamespace(secretNS)); err != nil { | ||
| return false | ||
| } | ||
| for i := range list.Items { | ||
| if referenceGrantAllowsGatewayToSecret(&list.Items[i].Spec, gwNS, secretName) { | ||
| return true | ||
| } | ||
| } | ||
| return false |
There was a problem hiding this comment.
Return lookup errors from cross-namespace Secret grant checks.
false currently means both “no grant permits this” and “listing ReferenceGrants failed.” That makes a temporary API read problem indistinguishable from a real deny. Change this helper to return (bool, error) so callers can requeue on lookup failures and only reject when the grant check actually completes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kubernetes/gateway-operator/internal/controller/httproute_referencegrant.go`
around lines 88 - 103, Change crossNamespaceSecretReferenceGrantPermitted to
return (bool, error) and surface API list errors instead of conflating them with
"no grant". Specifically, update the function signature
crossNamespaceSecretReferenceGrantPermitted(ctx context.Context, c
client.Client, gwNS, secretNS, secretName string) to return (bool, error),
return (true, nil) when secretNS == gwNS, return (false, err) when c.List(ctx,
&list, client.InNamespace(secretNS)) returns an error, and otherwise return
(true, nil) or (false, nil) based on
referenceGrantAllowsGatewayToSecret(&list.Items[i].Spec, gwNS, secretName). Also
update all callers to handle the error return (requeue on transient lookup
errors and only reject when the boolean result is false with a nil error).
| runtimeSvc, err := discoverGatewayRuntimeService(ctx, r.Client, gw.Name, ns) | ||
| if err != nil { | ||
| return fmt.Errorf("discover gateway runtime service: %w", err) | ||
| } | ||
| addrs := resolveGatewayAddressesFromService(runtimeSvc) | ||
| if runtimeSvc.Spec.Type == corev1.ServiceTypeLoadBalancer && len(addrs) == 0 { | ||
| pendingMsg := "Waiting for LoadBalancer address to be assigned to gateway runtime Service" | ||
| _ = r.patchGatewayStatus(ctx, gw, listenerStatuses, nil, metav1.Condition{ | ||
| Type: string(gatewayv1.GatewayConditionProgrammed), | ||
| Status: metav1.ConditionFalse, | ||
| Reason: string(gatewayv1.GatewayReasonPending), | ||
| Message: pendingMsg, | ||
| ObservedGeneration: gw.Generation, | ||
| LastTransitionTime: metav1.Now(), | ||
| }, | ||
| }) | ||
| return fmt.Errorf("pending: %s", pendingMsg) |
There was a problem hiding this comment.
Make the Helm self-heal check include the runtime Service.
This new path treats the gateway-runtime Service as required, but skipHelm can still stay true when that Service is missing because the earlier resource check only verifies Deployments and the controller Service. In that state, reconcile will keep returning pending/error here without ever re-running Helm to recreate the runtime Service. Fold the runtime Service into the expected-resource check, or force a repair path when discovery fails here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go`
around lines 494 - 509, The reconcile path treats the gateway runtime Service as
required but discovery via discoverGatewayRuntimeService can fail while skipHelm
remains true, leaving reconcile stuck; update the self-heal/expected-resources
check to include the runtime Service (or trigger a Helm repair when discovery
fails) by adding the runtime Service to the resources validated before honoring
skipHelm, and/or when discoverGatewayRuntimeService or
resolveGatewayAddressesFromService returns missing/empty, call the existing Helm
repair flow (same place that handles Deployments/ controller Service) or clear
skipHelm so patchGatewayStatus can request a re-install; reference
discoverGatewayRuntimeService, resolveGatewayAddressesFromService and
patchGatewayStatus to locate where to add the runtime Service validation or
invoke the Helm repair path.
| const ( | ||
| helmReleaseNameSuffix = "-gw" | ||
| maxHelmReleaseNameLen = 53 | ||
| helmReleaseHashPrefix = "gw-" | ||
| helmReleaseHashHexChars = 8 | ||
| ) | ||
|
|
||
| // GetReleaseName generates a stable Helm release name from a gateway name. | ||
| // Helm release names must be DNS-1123 labels and at most 53 characters. | ||
| func GetReleaseName(gatewayName string) string { | ||
| // Helm release names must be DNS-compliant | ||
| // Gateway name is already validated as a Kubernetes resource name | ||
| return fmt.Sprintf("%s-gateway", gatewayName) | ||
| candidate := gatewayName + helmReleaseNameSuffix | ||
| if len(candidate) <= maxHelmReleaseNameLen { | ||
| return candidate | ||
| } | ||
| sum := sha256.Sum256([]byte(gatewayName)) | ||
| return helmReleaseHashPrefix + hex.EncodeToString(sum[:])[:helmReleaseHashHexChars] |
There was a problem hiding this comment.
Increase the hashed suffix length to avoid release-name collisions.
Long gateway names now collapse into gw- plus 8 hex chars. That makes the Helm release mapping many-to-one, so two distinct long Gateway names can resolve to the same release and then share install/discovery state. Use a longer digest segment, or reserve more of the 53-character budget for the hash, so the mapping stays effectively unique.
Suggested direction
const (
helmReleaseNameSuffix = "-gw"
maxHelmReleaseNameLen = 53
helmReleaseHashPrefix = "gw-"
- helmReleaseHashHexChars = 8
+ helmReleaseHashHexChars = 16
)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@kubernetes/gateway-operator/internal/helm/client.go` around lines 395 - 410,
The current GetReleaseName collapses long gateway names to a fixed 8-hex suffix
(helmReleaseHashHexChars), which raises collision risk; change GetReleaseName to
compute the hash-length dynamically from the 53-char limit so more of the hex
digest is used when the gateway name would overflow. Specifically, replace the
fixed helmReleaseHashHexChars usage in GetReleaseName with a computed
allowedHashChars = maxHelmReleaseNameLen - len(helmReleaseNameSuffix) -
len(helmReleaseHashPrefix) (clamped to a sensible minimum like 8), then return
helmReleaseHashPrefix + hex.EncodeToString(sum[:])[:allowedHashChars]; update or
remove the fixed constant helmReleaseHashHexChars accordingly and keep
references to GetReleaseName, helmReleaseNameSuffix, helmReleaseHashPrefix, and
maxHelmReleaseNameLen to locate the change.
6d7ded8 to
183a217
Compare
Dependency Validation ResultsDependency name: k8s.io/api Dependency name: k8s.io/apimachinery Dependency name: k8s.io/client-go Dependency name: sigs.k8s.io/gateway-api Next Steps
|
183a217 to
27f55a8
Compare
Dependency Validation ResultsDependency name: k8s.io/api Dependency name: k8s.io/apimachinery Dependency name: k8s.io/client-go Dependency name: sigs.k8s.io/gateway-api Next Steps
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
kubernetes/gateway-operator/internal/controller/gateway_addresses.go (1)
72-73:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid publishing loopback as the NodePort Gateway status address.
Line 73 currently emits
127.0.0.1, which is not an appropriate externally meaningful status address for NodePort. Return no address until a resolvable node address is available, or derive node addresses before setting status.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@kubernetes/gateway-operator/internal/controller/gateway_addresses.go` around lines 72 - 73, The nodePortGatewayAddresses function currently returns a gateway address based on localClusterNodeAddressFallback, which resolves to the loopback address 127.0.0.1 and is not appropriate for external NodePort Gateway communication. Fix this by modifying the function to either return an empty address slice when only the loopback address is available, or implement logic to derive and use actual resolvable node addresses instead of falling back to the loopback address. Ensure that the function gatewayIPAddress is only called with a legitimate external node address, or return an empty slice if no such address can be determined.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@kubernetes/gateway-operator/internal/controller/gateway_addresses.go`:
- Around line 72-73: The nodePortGatewayAddresses function currently returns a
gateway address based on localClusterNodeAddressFallback, which resolves to the
loopback address 127.0.0.1 and is not appropriate for external NodePort Gateway
communication. Fix this by modifying the function to either return an empty
address slice when only the loopback address is available, or implement logic to
derive and use actual resolvable node addresses instead of falling back to the
loopback address. Ensure that the function gatewayIPAddress is only called with
a legitimate external node address, or return an empty slice if no such address
can be determined.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bdc79a68-37a7-447c-92d9-c8de2fd17fe9
⛔ Files ignored due to path filters (2)
go.work.sumis excluded by!**/*.sumkubernetes/gateway-operator/go.sumis excluded by!**/*.sum
📒 Files selected for processing (55)
gateway/gateway-controller/api/management-openapi.yamlgateway/gateway-controller/cmd/controller/main.gogateway/gateway-controller/pkg/api/management/generated.gogateway/gateway-controller/pkg/models/runtime_deploy_config.gogateway/gateway-controller/pkg/transform/restapi.gogateway/gateway-controller/pkg/transform/restapi_test.gogateway/gateway-controller/pkg/xds/route_discriminator_test.gogateway/gateway-controller/pkg/xds/translator.gogateway/gateway-controller/pkg/xds/translator_test.gokubernetes/gateway-operator/api/v1alpha1/restapi_types.gokubernetes/gateway-operator/api/v1alpha1/zz_generated.deepcopy.gokubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yamlkubernetes/gateway-operator/config/rbac/role.yamlkubernetes/gateway-operator/go.modkubernetes/gateway-operator/internal/controller/gateway_addresses.gokubernetes/gateway-operator/internal/controller/gateway_addresses_test.gokubernetes/gateway-operator/internal/controller/gateway_api_annotations.gokubernetes/gateway-operator/internal/controller/gateway_attached_routes.gokubernetes/gateway-operator/internal/controller/gateway_attached_routes_test.gokubernetes/gateway-operator/internal/controller/gateway_infra.gokubernetes/gateway-operator/internal/controller/gateway_listener_validation.gokubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.gokubernetes/gateway-operator/internal/controller/gateway_listeners_overlay.gokubernetes/gateway-operator/internal/controller/gateway_listeners_overlay_test.gokubernetes/gateway-operator/internal/controller/httproute_attachment.gokubernetes/gateway-operator/internal/controller/httproute_attachment_test.gokubernetes/gateway-operator/internal/controller/httproute_backends.gokubernetes/gateway-operator/internal/controller/httproute_backends_test.gokubernetes/gateway-operator/internal/controller/httproute_compile.gokubernetes/gateway-operator/internal/controller/httproute_compile_test.gokubernetes/gateway-operator/internal/controller/httproute_controller.gokubernetes/gateway-operator/internal/controller/httproute_enqueue.gokubernetes/gateway-operator/internal/controller/httproute_filters.gokubernetes/gateway-operator/internal/controller/httproute_filters_test.gokubernetes/gateway-operator/internal/controller/httproute_mapper.gokubernetes/gateway-operator/internal/controller/httproute_mapper_test.gokubernetes/gateway-operator/internal/controller/httproute_parents.gokubernetes/gateway-operator/internal/controller/httproute_referencegrant.gokubernetes/gateway-operator/internal/controller/k8s_gateway_controller.gokubernetes/gateway-operator/internal/controller/k8s_gateway_controller_test.gokubernetes/gateway-operator/internal/controller/llmproxy_controller_test.gokubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.gokubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.gokubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.gokubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.gokubernetes/gateway-operator/internal/helm/client.gokubernetes/gateway-operator/internal/helm/client_test.gokubernetes/helm/operator-helm-chart/files/gateway-api-standard/gatewayclasses.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/gateways.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/grpcroutes.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/httproutes.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/referencegrants.gateway.networking.k8s.io.yamlkubernetes/helm/operator-helm-chart/files/gateway-api-standard/standard-crds.yamlkubernetes/helm/operator-helm-chart/templates/_helpers.tplkubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yaml
💤 Files with no reviewable changes (6)
- kubernetes/helm/operator-helm-chart/files/gateway-api-standard/referencegrants.gateway.networking.k8s.io.yaml
- kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go
- kubernetes/helm/operator-helm-chart/files/gateway-api-standard/gatewayclasses.gateway.networking.k8s.io.yaml
- kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go
- kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go
- kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go
✅ Files skipped from review due to trivial changes (3)
- kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yaml
- kubernetes/gateway-operator/api/v1alpha1/zz_generated.deepcopy.go
- gateway/gateway-controller/pkg/api/management/generated.go
🚧 Files skipped from review as they are similar to previous changes (40)
- kubernetes/gateway-operator/internal/controller/httproute_parents.go
- kubernetes/gateway-operator/internal/controller/gateway_api_annotations.go
- kubernetes/gateway-operator/internal/controller/k8s_gateway_controller_test.go
- kubernetes/gateway-operator/internal/controller/gateway_infra.go
- kubernetes/gateway-operator/config/rbac/role.yaml
- kubernetes/helm/operator-helm-chart/templates/gateway-api-crds.yaml
- kubernetes/gateway-operator/internal/controller/gateway_attached_routes_test.go
- gateway/gateway-controller/pkg/models/runtime_deploy_config.go
- kubernetes/gateway-operator/internal/controller/httproute_filters_test.go
- kubernetes/gateway-operator/internal/helm/client.go
- kubernetes/gateway-operator/internal/controller/gateway_listeners_overlay.go
- gateway/gateway-controller/cmd/controller/main.go
- kubernetes/gateway-operator/internal/helm/client_test.go
- kubernetes/gateway-operator/internal/controller/httproute_mapper.go
- gateway/gateway-controller/pkg/xds/route_discriminator_test.go
- kubernetes/gateway-operator/internal/controller/httproute_referencegrant.go
- kubernetes/helm/operator-helm-chart/templates/_helpers.tpl
- kubernetes/gateway-operator/internal/controller/httproute_attachment_test.go
- kubernetes/gateway-operator/internal/controller/httproute_compile.go
- gateway/gateway-controller/pkg/transform/restapi_test.go
- kubernetes/gateway-operator/go.mod
- kubernetes/gateway-operator/internal/controller/httproute_compile_test.go
- kubernetes/gateway-operator/internal/controller/httproute_backends_test.go
- kubernetes/gateway-operator/internal/controller/httproute_filters.go
- gateway/gateway-controller/pkg/transform/restapi.go
- kubernetes/gateway-operator/internal/controller/httproute_enqueue.go
- kubernetes/gateway-operator/internal/controller/gateway_attached_routes.go
- kubernetes/gateway-operator/internal/controller/httproute_backends.go
- gateway/gateway-controller/api/management-openapi.yaml
- kubernetes/gateway-operator/internal/controller/gateway_addresses_test.go
- kubernetes/gateway-operator/api/v1alpha1/restapi_types.go
- kubernetes/gateway-operator/internal/controller/gateway_listeners_overlay_test.go
- kubernetes/gateway-operator/internal/controller/gateway_listener_validation.go
- kubernetes/gateway-operator/internal/controller/httproute_attachment.go
- kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go
- kubernetes/gateway-operator/internal/controller/gateway_listener_validation_test.go
- kubernetes/gateway-operator/internal/controller/httproute_mapper_test.go
- gateway/gateway-controller/pkg/xds/translator.go
- kubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.go
- kubernetes/gateway-operator/internal/controller/httproute_controller.go
Purpose
This PR adds the changes required for making the current api-platform kubernetes operator compatible with the gateway-api