fix(gateway): correct BackendRef matching and canary header build#342
fix(gateway): correct BackendRef matching and canary header build#342marcoma2018 wants to merge 2 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
1c52fc9 to
42470de
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #342 +/- ##
==========================================
+ Coverage 51.38% 51.87% +0.49%
==========================================
Files 66 66
Lines 8559 8559
==========================================
+ Hits 4398 4440 +42
+ Misses 3575 3530 -45
- Partials 586 589 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Fixes in pkg/trafficrouting/network/gateway/gateway.go: * getServiceBackendRef: per the Gateway API spec, BackendObjectReference.Kind defaults to "Service" when nil. The previous check `ref.Kind != nil && *ref.Kind == "Service"` skipped refs without an explicit Kind, so HTTPRoutes emitted by controllers that omit the field (e.g. Envoy Gateway) were never recognised as stable/canary backends and the rollout silently failed to inject canary traffic. Treat nil Kind as Service. Also return (-1, nil) on miss instead of (0, nil) to remove the ambiguity between "not found" and "found at index 0". * setServiceBackendRef: symmetric fix — refuse only when an explicit Kind other than Service is set, so canary BackendRefs derived from a stable ref with nil Kind can be written back. Replace the manual slice rebuild with an in-place assignment. * buildCanaryHeaderHttpRoutes: the inner loop indexed `matches[k]` while `k` ranged over `nonPathMatches`. The two slices have different lengths whenever a path-bearing match is not the first element, so headers and query params from the wrong match were grafted onto canary rules. Index `nonPathMatches[k]` instead. * buildCanaryHeaderHttpRoutes: the shallow copy `canaryRuleMatchBase := *canaryRuleMatch` shares the underlying arrays of Headers/QueryParams with the original rule. Subsequent appends could mutate the original HTTPRoute when its slices had spare capacity. Clone the slices before extending; preserve nil-ness to keep output identical to the previous implementation when nothing is appended. * EnsureRoutes: surface the error from intstr.GetScaledValueFromIntOrPercent rather than silently coercing malformed traffic strings to 0 %. * EnsureRoutes / Finalise: pass the inbound ctx to client Get/Update inside the retry closure instead of context.TODO(), so cancellation and deadlines propagate. Tests in pkg/trafficrouting/network/gateway/gateway_test.go: * Added regression cases covering BackendRefs with nil Kind across the weight, header, and finalise code paths. * Added a case where matches mix path and non-path entries so that pathMatches and nonPathMatches diverge in length, exercising the index-correctness fix. * Added a clean-state weight canary case; the existing weight-20 case fed in the final 80/20 shape and only proved idempotence. * Added TestInitialize, TestEnsureRoutesAndFinalise, and TestEnsureRoutesInvalidTraffic to drive the controller end-to-end against a fake client, covering happy path, idempotence, finalise, rollback, and invalid-input rejection. Signed-off-by: Marco Ma <qingjin_ma@163.com>
42470de to
23b577f
Compare
Signed-off-by: Marco Ma <qingjin_ma@163.com>
Fixes in pkg/trafficrouting/network/gateway/gateway.go:
getServiceBackendRef: per the Gateway API spec, BackendObjectReference.Kind defaults to "Service" when nil. The previous check
ref.Kind != nil && *ref.Kind == "Service"skipped refs without an explicit Kind, so HTTPRoutes emitted by controllers that omit the field (e.g. Envoy Gateway) were never recognised as stable/canary backends and the rollout silently failed to inject canary traffic. Treat nil Kind as Service. Also return (-1, nil) on miss instead of (0, nil) to remove the ambiguity between "not found" and "found at index 0".setServiceBackendRef: symmetric fix — refuse only when an explicit Kind other than Service is set, so canary BackendRefs derived from a stable ref with nil Kind can be written back. Replace the manual slice rebuild with an in-place assignment.
buildCanaryHeaderHttpRoutes: the inner loop indexed
matches[k]whilekranged overnonPathMatches. The two slices have different lengths whenever a path-bearing match is not the first element, so headers and query params from the wrong match were grafted onto canary rules. IndexnonPathMatches[k]instead.buildCanaryHeaderHttpRoutes: the shallow copy
canaryRuleMatchBase := *canaryRuleMatchshares the underlying arrays of Headers/QueryParams with the original rule. Subsequent appends could mutate the original HTTPRoute when its slices had spare capacity. Clone the slices before extending; preserve nil-ness to keep output identical to the previous implementation when nothing is appended.EnsureRoutes: surface the error from intstr.GetScaledValueFromIntOrPercent rather than silently coercing malformed traffic strings to 0 %.
EnsureRoutes / Finalise: pass the inbound ctx to client Get/Update inside the retry closure instead of context.TODO(), so cancellation and deadlines propagate.
Tests in pkg/trafficrouting/network/gateway/gateway_test.go: