fix(translator): validate EnvoyPatchPolicy targetRef based on mode (#8623)#8660
Conversation
✅ Deploy Preview for cerulean-figolla-1f9435 canceled.
|
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>
c1e4be8 to
53a651b
Compare
There was a problem hiding this comment.
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.kindvalidation logic inProcessEnvoyPatchPoliciesfor 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.
| 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 | ||
| } | ||
|
|
There was a problem hiding this comment.
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.
| 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 | |
| } |
| // GatewayClass targetRef | ||
| irKey = string(refName) | ||
| ancestorRef = gwapiv1.ParentReference{ | ||
| Group: GroupPtr(gwapiv1.GroupName), | ||
| Kind: KindPtr(targetKind), | ||
| Kind: KindPtr(resource.KindGatewayClass), | ||
| Name: refName, | ||
| } |
There was a problem hiding this comment.
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.
| 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 { |
There was a problem hiding this comment.
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.
| 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), |
There was a problem hiding this comment.
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.
| 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, |
| // In default mode, only Gateway targetRef is supported | ||
| if string(refKind) != resource.KindGateway { |
There was a problem hiding this comment.
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.
| if gwXdsIR, ok := xdsIR[irKey]; ok { | ||
| gwXdsIR.EnvoyPatchPolicies = append(gwXdsIR.EnvoyPatchPolicies, &policyIR) | ||
| } |
There was a problem hiding this comment.
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).
| 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) |
| // 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) | ||
| } |
There was a problem hiding this comment.
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).
| // 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) |
| // 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. |
There was a problem hiding this comment.
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).
| // 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, | |
| ) |
| // 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 | ||
| } | ||
|
|
There was a problem hiding this comment.
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.
| // 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 | |
| } |
| // In default mode, only Gateway targetRef is supported | ||
| if string(refKind) != resource.KindGateway { |
There was a problem hiding this comment.
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.
| - ancestorRef: | ||
| group: gateway.networking.k8s.io | ||
| kind: Gateway | ||
| kind: MyGateway |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
|
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:
I’d like to align properly with the design here before updating the PR, and avoid making assumptions this time. |
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.