Skip to content

fix(translator): validate EnvoyPatchPolicy targetRef based on mode (#8623)#8660

Open
nishantbkl3345-ship-it wants to merge 3 commits intoenvoyproxy:mainfrom
nishantbkl3345-ship-it:fix/envoypatchpolicy-targetref-validation
Open

fix(translator): validate EnvoyPatchPolicy targetRef based on mode (#8623)#8660
nishantbkl3345-ship-it wants to merge 3 commits intoenvoyproxy:mainfrom
nishantbkl3345-ship-it:fix/envoypatchpolicy-targetref-validation

Conversation

@nishantbkl3345-ship-it
Copy link
Copy Markdown

Fixes #8623

EnvoyPatchPolicy with targetRef.kind=Gateway was silently ignored in
MergeGateways mode, with no clear status indicating why patches were not applied.

This change adds mode-aware validation in ProcessEnvoyPatchPolicies so
unsupported targetRef kinds are explicitly rejected with Accepted=False
instead of being dropped silently.

  • MergeGateways mode: only GatewayClass targetRef is allowed
  • Default mode: only Gateway targetRef is allowed

@nishantbkl3345-ship-it nishantbkl3345-ship-it requested a review from a team as a code owner April 2, 2026 17:10
Copilot AI review requested due to automatic review settings April 2, 2026 17:10
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 2, 2026

Deploy Preview for cerulean-figolla-1f9435 canceled.

Name Link
🔨 Latest commit 288ea12
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/69d0268b99acb90008ae2312

EnvoyPatchPolicy with targetRef.kind=Gateway was silently ignored in
MergeGateways mode with no clear status.

Add mode-aware validation so unsupported targetRef kinds are rejected
with Accepted=False instead of being dropped.

- MergeGateways: only GatewayClass is valid
- Default mode: only Gateway is valid

Signed-off-by: Nishant <nishantbkl3345@gmail.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds mode-aware validation for EnvoyPatchPolicy.spec.targetRef so unsupported target kinds are explicitly rejected (Accepted=False) rather than being silently ignored, addressing #8623.

Changes:

  • Added mode-specific targetRef.kind validation logic in ProcessEnvoyPatchPolicies for MergeGateways vs default mode.
  • Updated invalid-target golden output to reflect the new validation message and ancestor kind.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.

File Description
internal/gatewayapi/envoypatchpolicy.go Adds mode-aware validation and status reporting for unsupported targetRef.kind/group.
internal/gatewayapi/testdata/envoypatchpolicy-invalid-target-kind.out.yaml Updates expected status output/message for invalid targetRef.kind in default mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +74
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}

message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}

// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status

status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)

// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}

continue
}

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

In MergeGateways mode the code only special-cases refKind == Gateway as invalid, but any other non-GatewayClass kind (e.g. HTTPRoute, MyGateway, etc.) will fall through and be treated as GatewayClass, which can reintroduce silent drops. Make the MergeGateways branch explicitly validate refKind == GatewayClass (and reject everything else) so unsupported kinds always get Accepted=False.

Suggested change
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}
if string(refKind) != resource.KindGatewayClass {
// Any non-GatewayClass targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(string(refKind)),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}

Copilot uses AI. Check for mistakes.
Comment on lines +75 to 81
// GatewayClass targetRef
irKey = string(refName)
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(targetKind),
Kind: KindPtr(resource.KindGatewayClass),
Name: refName,
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

In MergeGateways mode the code only special-cases refKind == Gateway as invalid, but any other non-GatewayClass kind (e.g. HTTPRoute, MyGateway, etc.) will fall through and be treated as GatewayClass, which can reintroduce silent drops. Make the MergeGateways branch explicitly validate refKind == GatewayClass (and reject everything else) so unsupported kinds always get Accepted=False.

Copilot uses AI. Check for mistakes.
Comment on lines 33 to +35
if t.MergeGateways {
targetKind = resource.KindGatewayClass
// if ref GatewayClass name is not same as t.GatewayClassName, it will be skipped in L53.
// In MergeGateways mode, only GatewayClass targetRef is supported
if string(refKind) == resource.KindGateway {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The early continue paths for kind validation run before the later TargetRef.Group validation. If both group and kind are invalid, this will report only a kind error and also hard-codes ancestorRef.Group to gwapiv1.GroupName, which is inaccurate for a user-supplied invalid group. Consider validating TargetRef.Group first (or incorporating group into these early validation branches) so the reported status is correct and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +35 to 78
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}

message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}

// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status

status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)

// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}

continue
}

// GatewayClass targetRef
irKey = string(refName)
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The early continue paths for kind validation run before the later TargetRef.Group validation. If both group and kind are invalid, this will report only a kind error and also hard-codes ancestorRef.Group to gwapiv1.GroupName, which is inaccurate for a user-supplied invalid group. Consider validating TargetRef.Group first (or incorporating group into these early validation branches) so the reported status is correct and consistent.

Suggested change
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}
// GatewayClass targetRef
irKey = string(refName)
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
group := policy.Spec.TargetRef.Group
// First validate TargetRef.Group so group-related errors are reported accurately.
if group != nil && *group != gwapiv1.GroupName {
ancestorRef = gwapiv1.ParentReference{
Group: group,
Kind: KindPtr(refKind),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Group:%s is not supported, only TargetRef.Group:%s is supported.",
*group, gwapiv1.GroupName)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
if group == nil {
group = GroupPtr(gwapiv1.GroupName)
}
ancestorRef = gwapiv1.ParentReference{
Group: group,
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}
// GatewayClass targetRef
irKey = string(refName)
if group == nil {
group = GroupPtr(gwapiv1.GroupName)
}
ancestorRef = gwapiv1.ParentReference{
Group: group,

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +84
// In default mode, only Gateway targetRef is supported
if string(refKind) != resource.KindGateway {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The early continue paths for kind validation run before the later TargetRef.Group validation. If both group and kind are invalid, this will report only a kind error and also hard-codes ancestorRef.Group to gwapiv1.GroupName, which is inaccurate for a user-supplied invalid group. Consider validating TargetRef.Group first (or incorporating group into these early validation branches) so the reported status is correct and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +70
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The new invalid-kind branches attempt to publish Accepted=False by appending a minimal policy IR to an existing xdsIR[irKey], but if that IR key is missing (common when the target is invalid/non-accepted), nothing is appended and the policy can still end up with no published status—contradicting the PR goal of avoiding silent drops. To make the rejection reliable, ensure there is always a status publication path for these invalid-kind errors (e.g., create an IR bucket for the relevant key when missing, or publish policy status independently of xdsIR existence).

Suggested change
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
gwXdsIR, ok := xdsIR[irKey]
if !ok || gwXdsIR == nil {
// Ensure there is always an IR bucket so the policy status is published
gwXdsIR = &ir.Xds{}
xdsIR[irKey] = gwXdsIR
}
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +127
// Try to find a matching Gateway IR to attach the status
irKey = t.IRKey(gatewayNN)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The new invalid-kind branches attempt to publish Accepted=False by appending a minimal policy IR to an existing xdsIR[irKey], but if that IR key is missing (common when the target is invalid/non-accepted), nothing is appended and the policy can still end up with no published status—contradicting the PR goal of avoiding silent drops. To make the rejection reliable, ensure there is always a status publication path for these invalid-kind errors (e.g., create an IR bucket for the relevant key when missing, or publish policy status independently of xdsIR existence).

Suggested change
// Try to find a matching Gateway IR to attach the status
irKey = t.IRKey(gatewayNN)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
// Try to find or create a matching Gateway IR to attach the status
irKey = t.IRKey(gatewayNN)
gwXdsIR, ok := xdsIR[irKey]
if !ok || gwXdsIR == nil {
// Ensure there is always an IR bucket so the error status is published
gwXdsIR = &ir.Xds{}
xdsIR[irKey] = gwXdsIR
}
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +144
// The TargetRef resource is not found or not accepted, skip processing without status.
// Status will not be published for policies targeting non-existent or non-accepted resources.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The new invalid-kind branches attempt to publish Accepted=False by appending a minimal policy IR to an existing xdsIR[irKey], but if that IR key is missing (common when the target is invalid/non-accepted), nothing is appended and the policy can still end up with no published status—contradicting the PR goal of avoiding silent drops. To make the rejection reliable, ensure there is always a status publication path for these invalid-kind errors (e.g., create an IR bucket for the relevant key when missing, or publish policy status independently of xdsIR existence).

Suggested change
// The TargetRef resource is not found or not accepted, skip processing without status.
// Status will not be published for policies targeting non-existent or non-accepted resources.
// The TargetRef resource is not found or not accepted, publish a rejection status.
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonTargetNotFound,
Message: "TargetRef resource is not found or not accepted by the EnvoyGateway controller",
}
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +74
// In MergeGateways mode, only GatewayClass targetRef is supported
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}

message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}

// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status

status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)

// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}

continue
}

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This PR adds separate behavior for invalid targetRef.kind in MergeGateways vs default mode, but the reviewed golden output update only covers the default-mode case. Add a test fixture (or unit test) covering MergeGateways mode rejection (e.g., targetRef.kind=Gateway) to prevent regressions back to silent ignores.

Suggested change
// In MergeGateways mode, only GatewayClass targetRef is supported
if string(refKind) == resource.KindGateway {
// Gateway targetRef is not supported in MergeGateways mode
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(resource.KindGateway),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}
// In MergeGateways mode, only GatewayClass targetRef is supported.
// Any other kind (including Gateway) is invalid and should be rejected.
if string(refKind) != resource.KindGatewayClass {
ancestorRef = gwapiv1.ParentReference{
Group: GroupPtr(gwapiv1.GroupName),
Kind: KindPtr(string(refKind)),
Name: refName,
Namespace: NamespacePtr(policy.Namespace),
}
message := fmt.Sprintf("TargetRef.Kind:%s is not supported in MergeGateways mode, only TargetRef.Kind:%s is supported.",
refKind, resource.KindGatewayClass)
resolveErr = &status.PolicyResolveError{
Reason: gwapiv1.PolicyReasonInvalid,
Message: message,
}
// Create a minimal IR entry to publish the error status
policyIR := ir.EnvoyPatchPolicy{}
policyIR.Name = policy.Name
policyIR.Namespace = policy.Namespace
policyIR.Generation = policy.Generation
policyIR.Status = &policy.Status
status.SetResolveErrorForPolicyAncestor(&policy.Status,
&ancestorRef,
t.GatewayControllerName,
policy.Generation,
resolveErr,
)
// We still need to add this to an IR so the status gets published
// Use the GatewayClassName as the key since that's the merged IR key
irKey = string(t.GatewayClassName)
if gwXdsIR, ok := xdsIR[irKey]; ok {
gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR)
}
continue
}

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +84
// In default mode, only Gateway targetRef is supported
if string(refKind) != resource.KindGateway {
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This PR adds separate behavior for invalid targetRef.kind in MergeGateways vs default mode, but the reviewed golden output update only covers the default-mode case. Add a test fixture (or unit test) covering MergeGateways mode rejection (e.g., targetRef.kind=Gateway) to prevent regressions back to silent ignores.

Copilot uses AI. Check for mistakes.
- ancestorRef:
group: gateway.networking.k8s.io
kind: Gateway
kind: MyGateway
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

MyGateway is not a kind, where is this coming from? If you're interested in helping with the approach please use the issue to discuss.

Apologies if I'm wrong but this PR looks like an LLM one-shot without understanding the context or desired changes.

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 for the feedback — that’s fair, and apologies for the confusion here.

I see that I moved too quickly to a generalized fix (including the MyGateway case) without aligning with the intended behavior.

I’ll step back and continue the discussion on the issue to align on the expected approach before making further changes here.

@nishantbkl3345-ship-it
Copy link
Copy Markdown
Author

Thanks for the feedback — that’s fair.

I realize I jumped too quickly into a generalized solution without fully aligning with the expected behavior (especially around supported kinds and how validation should be handled).

Before making further changes, I want to clarify the intended approach:

  • In MergeGateways mode, should we strictly validate only GatewayClass and reject all other kinds early?
  • And for default mode, should validation be limited to Gateway only, without trying to generalize beyond the current API expectations?

I’d like to align properly with the design here before updating the PR, and avoid making assumptions this time.

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.

EnvoyPatchPolicy with targetRef

3 participants