Skip to content

fix(translator): warn when mergeGateways is set on an EnvoyProxy referenced by a Gateway - #10478

Open
lyelgate wants to merge 4 commits into
envoyproxy:mainfrom
lyelgate:fix/envoyproxy-mergegateways-on-gateway
Open

lyelgate wants to merge 4 commits into
envoyproxy:mainfrom
lyelgate:fix/envoyproxy-mergegateways-on-gateway

Conversation

@lyelgate

@lyelgate lyelgate commented Nov 1, 2026

Copy link
Copy Markdown

What this PR does / why we need it:

mergeGateways is only read from the EnvoyProxy referenced by the GatewayClass, or the default EnvoyProxy spec (IsMergeGatewaysEnabled in internal/gatewayapi/helpers.go). Setting it on an EnvoyProxy referenced by a Gateway through infrastructure.parametersRef has no effect. That EnvoyProxy reports Accepted with no warning, so the user has no way to tell why their Gateways aren't merged.

#3601 suggested CEL validation for this. CEL can't express it: whether an EnvoyProxy is referenced by a Gateway or by a GatewayClass isn't known from the EnvoyProxy object itself. The translator does know, and EnvoyProxy already has a per-ancestor Warning condition for this kind of problem. SetEnvoyProxyWarnings reports deprecated fields and patch fields ignored because patching is disabled. This PR adds a third source of warnings to it, for fields that have no effect on an EnvoyProxy referenced by a Gateway, and reports spec.mergeGateways there:

The following fields have no effect on an EnvoyProxy referenced by a Gateway and were ignored, set them on the EnvoyProxy referenced by the GatewayClass instead: spec.mergeGateways

Details:

  • Only the Gateway's own EnvoyProxy spec is checked (envoyproxyMap[key]), not the merged result, the same way deprecated fields are checked there. A GatewayClass-level mergeGateways doesn't trigger it.
  • It fires whenever the field is set, true or false, since neither value takes effect.
  • The reason, UnsupportedField, is defined next to the helper in internal/gatewayapi/status, the same way the policy reasons such as PolicyReasonUnsupportedField are. There is no change under /api.
  • With three possible sources, the reason and message merge in SetEnvoyProxyWarnings now goes through a small addWarning closure instead of a nested if/else. The existing deprecated and patch-disabled behavior and messages are unchanged, and the existing unit tests pass as is (with the new argument).

Changes:

  • internal/gatewayapi/status/envoyproxy.go: EnvoyProxyReasonUnsupportedField, and an unsupportedFields argument to SetEnvoyProxyWarnings.
  • internal/gatewayapi/translator.go: gatewayUnsupportedFieldsUsedInEnvoyProxy, passed for Gateway-referenced EnvoyProxies (nil for the GatewayClass one).
  • internal/gatewayapi/status/envoyproxy_test.go: cases for the new warning alone and merged with the other two.
  • internal/gatewayapi/testdata/envoyproxy-mergegateways-on-gateway.{in,out}.yaml: one Gateway whose EnvoyProxy sets mergeGateways, and one whose EnvoyProxy doesn't, as a control.
  • site/content/en/latest/tasks/operations/deployment-mode.md: one sentence noting the field has no effect on a Gateway-referenced EnvoyProxy.
  • release-notes/current/other_changes/3601-envoyproxy-mergegateways-on-gateway.md.

Testing:

  • The new test case fails on main without the change and passes with it.
  • go test ./internal/... passes.
  • go test ./internal/gatewayapi ./internal/xds/translator --override-testdata=true leaves no diff in existing golden files.
  • golangci-lint (repo config, CI build tags) on ./internal/gatewayapi/..., codespell, yamllint and tools/boilerplate/verify-boilerplate.sh are clean.

Which issue(s) this PR fixes:

Fixes #3601


PR Checklist

  • Authorship & ownership: Coding agents / AI assistants are welcome, but I have reviewed every change, understand how and why it works, can explain and maintain it, and take full responsibility for this PR. I have not submitted generated output I do not understand.
  • DCO: All commits are signed off (git commit -s). See DCO: Sign your work.
  • API agreed first: N/A: no changes under /api.
  • Required checks pass: make generate gen-check, make lint, and the unit-test/coverage build pass. (Flaky e2e failures are not considered breakages, but gen-check, lint, and coverage MUST pass.) Locally I ran the parts this change touches (listed under Testing); the full targets will run in CI.
  • Tests added/updated: New/changed code is covered by appropriate tests.
  • Docs: User-facing changes update the docs, either in this PR or a follow-up PR.
  • Release notes: Added a release-note fragment under release-notes/current/.
  • Generated files committed: N/A: no API, Helm chart or module changes.
  • Scope & compatibility: The PR is reasonably scoped (no unrelated changes) and preserves backward compatibility, or any breaking change is called out above and documented in release-notes/current/breaking_changes/.
  • Codex review: Requested a Codex review and addressed all of its comments.
  • Copilot review: Requested a Copilot review and addressed all of its comments.

…renced by a Gateway

mergeGateways is only read from the EnvoyProxy referenced by the
GatewayClass (or the default EnvoyProxy spec). Setting it on an
EnvoyProxy referenced by a Gateway through infrastructure.parametersRef
had no effect, and nothing said so.

Report it as a Warning condition with reason UnsupportedField on that
EnvoyProxy's ancestor status, through the existing SetEnvoyProxyWarnings
path used for deprecated and patch-disabled fields.

Fixes envoyproxy#3601

Signed-off-by: Lakhan Yelgate <39281685+lyelgate@users.noreply.github.com>
@lyelgate
lyelgate requested a review from a team as a code owner November 1, 2026 09:11
@netlify

netlify Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit e0918a6
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/6ae779e29370fb3d8a5c2d85
😎 Deploy Preview https://deploy-preview-10478--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T17:45:53.219400Z e0918a6 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 720190e880

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}
status.SetEnvoyProxyWarnings(ep, ancestor, deprecatedFieldsUsedInEnvoyProxy(envoyproxyMap[key]), patchedFields)
status.SetEnvoyProxyWarnings(ep, ancestor, deprecatedFieldsUsedInEnvoyProxy(envoyproxyMap[key]), patchedFields,
gatewayUnsupportedFieldsUsedInEnvoyProxy(envoyproxyMap[key]))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Warn before default merge mode skips the Gateway proxy

When EnvoyGateway.envoyProxy.mergeGateways is true, attachEnvoyProxy skips the Gateway's parametersRef (internal/gatewayapi/contexts.go:105-114), leaving envoyProxyFromGateway false, so this new helper is never called. A referenced EnvoyProxy that sets mergeGateways—notably false to try to override the default—still gets no UnsupportedField condition even though the new docs and release note say Gateway-referenced proxies do; inspect the raw reference before attachment is suppressed (or explicitly reject it).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. When Gateways are already merged, the Gateway's parametersRef is ignored entirely, so that EnvoyProxy gets no status at all. I've scoped the docs and the release note to Gateways that are not merged, in 313ff34.

Comment on lines +706 to +707
status.SetEnvoyProxyWarnings(ep, ancestor, deprecatedFieldsUsedInEnvoyProxy(envoyproxyMap[key]), patchedFields,
gatewayUnsupportedFieldsUsedInEnvoyProxy(envoyproxyMap[key]))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Merge statuses for shared proxies before deduplication

When one Gateway-level EnvoyProxy is referenced by multiple Gateways and uses StrategicMerge or JSONMerge over a GatewayClass or default config, attachEnvoyProxy constructs a separate merged ep for each Gateway, and this call writes each warning only to that transient copy. newTranslateResult then deduplicates the copies by NamespacedName (internal/gatewayapi/translator.go:247-259) without merging statuses, so the published resource retains only the first Gateway's UnsupportedField warning; accumulate status on the source EnvoyProxy or merge duplicate statuses before deduplication.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accurate, but not specific to this warning: the deprecated-field and patch-disabled warnings, and the Accepted condition, are written to the same per-Gateway merged copy, so they share the same limitation when several Gateways reference one EnvoyProxy with a merge type. Merging statuses before deduplication would change how every EnvoyProxy status is aggregated, so I'd rather keep this PR scoped and handle it separately if maintainers want it.

When Gateways are already merged, a Gateway's parametersRef is ignored
entirely and its EnvoyProxy gets no status, so the warning only applies
when Gateways are not merged.

Signed-off-by: Lakhan Yelgate <39281685+lyelgate@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 313ff3437b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}
status.SetEnvoyProxyWarnings(ep, ancestor, deprecatedFieldsUsedInEnvoyProxy(envoyproxyMap[key]), patchedFields)
status.SetEnvoyProxyWarnings(ep, ancestor, deprecatedFieldsUsedInEnvoyProxy(envoyproxyMap[key]), patchedFields,
gatewayUnsupportedFieldsUsedInEnvoyProxy(envoyproxyMap[key]))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear warnings when a Gateway reference disappears

After this warning is published, removing parametersRef, deleting its Gateway, or enabling merged mode removes the EnvoyProxy from TranslateResult instead of invoking SetEnvoyProxyWarnings with an empty list. The runner then deletes the tracked key (internal/gatewayapi/runner/runner.go:1021-1023), but the Kubernetes status subscriber explicitly ignores delete updates (internal/provider/kubernetes/status.go:668-670), so the UnsupportedField condition already written to the CR remains indefinitely even though the reference no longer applies; publish an empty or filtered status before dropping the key.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accurate, but not specific to this warning: the deprecated-field and patch-disabled warnings, and the Accepted condition, are cleared the same way, so they also stay on the CR once the EnvoyProxy drops out of the translation result. Publishing an empty status before dropping the key would change the lifecycle of every EnvoyProxy status, so I'd rather keep this PR scoped and handle it separately if maintainers want it.


This can help to efficiently utilize the infra resources in the cluster and manage them in a centralized manner, or have a single IP address for all of the listeners.
Setting the `mergeGateways` field in the EnvoyProxy resource linked to GatewayClass will result in merging all Gateway listeners under one GatewayClass resource.
The field has no effect on an EnvoyProxy referenced by a Gateway through `infrastructure.parametersRef`; that EnvoyProxy gets a `Warning` condition with reason `UnsupportedField` instead. When Gateways are already merged, the Gateway's `parametersRef` is ignored entirely, so that EnvoyProxy gets no status.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document rejection of parametersRef during class merging

In the Kubernetes provider, when merging is enabled by the GatewayClass EnvoyProxy described in the preceding sentence, processGatewayParamsRef returns an error requiring infrastructure.parametersRef to be nil (internal/provider/kubernetes/controller.go:3262-3264), and its caller marks the Gateway not accepted (internal/provider/kubernetes/controller.go:2129-2139). Thus the reference is not merely ignored in this common merged-mode path; users need to be told to remove it, with the different default-spec behavior distinguished if that is intentional.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that's correct: with merging enabled by the GatewayClass EnvoyProxy the Kubernetes provider doesn't accept a Gateway that sets parametersRef, and it's only ignored when merging comes from the default EnvoyProxy spec. The docs now say a Gateway should not set parametersRef when Gateways are merged and describe both cases, in 402a8d3.

When merging is enabled by the GatewayClass EnvoyProxy, the Kubernetes
provider does not accept a Gateway that sets infrastructure.parametersRef;
the reference is only ignored when merging comes from the default
EnvoyProxy spec in the EnvoyGateway configuration.

Signed-off-by: Lakhan Yelgate <39281685+lyelgate@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 402a8d38a8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

strings.Join(patchedFields, ", ")))
}
if len(unsupportedFields) > 0 {
addWarning(EnvoyProxyReasonUnsupportedField, fmt.Sprintf(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve patch warnings when appending unsupported fields

When a Gateway-referenced EnvoyProxy has enough deprecated telemetry entries to fill the 32-KiB condition, and it also has ignored Kubernetes patch fields plus mergeGateways, the patch warning is first preserved at the end by mergeBoundedWarningMessages, but this later addWarning truncates that end to reserve space for UnsupportedField. The resulting Warnings condition no longer says that the patch was ignored, regressing the invariant covered by TestSetEnvoyProxyWarningKeepsLaterWarningWhenFull; reserve space for every non-deprecation warning category instead of repeatedly truncating the accumulated message.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, confirmed with a test: with a deprecated-fields list that fills the message, the UnsupportedField warning cut off the patch-disabled one. The warnings are now collected first, the later ones merged together, and only then fitted after the first, so only the deprecated-fields list can be truncated. With one or two warnings the message is unchanged. Fixed in e0918a6, with TestSetEnvoyProxyWarningsKeepsLaterWarningsWhenTruncating.

Each warning was merged into the message in turn, and
mergeBoundedWarningMessages cuts the existing message short to fit the
next one. With three warnings and a deprecated-fields list that fills
the condition message, adding the UnsupportedField warning cut off the
patch-disabled warning that had been kept before it.

Merge the later warnings first and then fit them after the first one,
so only the first warning can be cut short. With one or two warnings
the message is unchanged.

Signed-off-by: Lakhan Yelgate <39281685+lyelgate@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CEL Validation to disable MergeGateways from being set when EnvoyProxy targets a Gateway

1 participant