Pass GRPCRouteWeight conformance test - #127
codebot-robot wants to merge 4 commits into
Conversation
This change adds support for multiple backends with weights in InternalRule and implements weighted selection in the proxy. Issue gke-labs#122
This change adds support for GRPCRoute in the state and controller. Issue gke-labs#122
This change adds GRPCRouteWeight to the list of selected conformance tests. Issue gke-labs#122
|
So this is not passing e2e @codebot-robot - can you fix? |
|
I have created a |
|
I have created an |
|
I have created an |
codebot-robot
left a comment
There was a problem hiding this comment.
Thanks for the PR. While this correctly establishes the relationship between GRPCRoutes, weighted backends, and the data plane, there are critical bugs related to Gateway API spec conformance that must be addressed:
- Weight Load Balancing: Returning the first backend when all weights are 0 explicitly violates the API requirement to drop the request with a 503 Service Unavailable.
- gRPC Path Matching: Using a path prefix match for an EXACT gRPC method match is functionally incorrect and allows route leaking.
- Namespace Validation: Gateway ParentRef checks are missing namespace validation in the status condition logic.
- Controller Status: Updating the parent statuses replaces all other controllers' statuses instead of properly merging them.
- Backend App Protocol: Backend connection protocols are incorrectly derived from the frontend listener rather than the Service configuration or BackendTLSPolicy.
Please review the inline comments for actionable fixes.
(This review was generated by Overseer)
| // Check if Gateway exists and has matching listeners | ||
| var gw *GatewayState | ||
| for _, g := range gateways { | ||
| if g.Name == string(parentRef.Name) { |
There was a problem hiding this comment.
Missing namespace validation for the Gateway parent reference. If parentRef.Namespace is provided, it must be verified against g.Namespace. Without this, the route may falsely report an Accepted condition for a Gateway in a different namespace that happens to share the same name.
| } else { | ||
| matched := false | ||
| for _, listener := range gw.Spec.Listeners { | ||
| if listener.Protocol != gatewayv1.HTTPProtocolType && listener.Protocol != gatewayv1.HTTPSProtocolType && listener.Protocol != "TLS" { |
There was a problem hiding this comment.
The string literal "TLS" is used instead of the correct constant gatewayv1.TLSProtocolType. Furthermore, per the Gateway API specification, GRPCRoute is only intended to bind to HTTP or HTTPS listeners natively.
| *gatewayv1.GRPCRoute | ||
| } | ||
|
|
||
| func (s *GRPCRouteState) Validate() error { |
There was a problem hiding this comment.
The Validate() method simply returns nil without performing any structural validation of the GRPCRoute. It should validate missing required fields, negative backend weights, and unsupported filter types to prevent downstream panics and ensure early rejection.
| path += method | ||
| } | ||
| iMatch.Path = &InternalPathMatch{ | ||
| Type: gatewayv1.PathMatchPathPrefix, |
There was a problem hiding this comment.
Using PathMatchPathPrefix for a gRPC method match is incorrect when the gRPC method match type is Exact (which is the default). A prefix match on /Service/Method would inadvertently match /Service/MethodX. This should use PathMatchExact.
| service := ValueOf(match.Method.Service) | ||
| method := ValueOf(match.Method.Method) | ||
| if service != "" || method != "" { | ||
| path := "/" |
There was a problem hiding this comment.
If the gRPC service is not specified, this string concatenation creates an invalid path like "//method". This will not properly match standard gRPC requests (which look like /<Service>/<Method>). If a service is omitted, the translation needs to use a regular expression or a specialized wildcard path matcher.
| } | ||
|
|
||
| func (r *GRPCRouteReconciler) SetupWithManager(mgr ctrl.Manager) error { | ||
| return ctrl.NewControllerManagedBy(mgr). |
There was a problem hiding this comment.
The controller is only watching GRPCRoute objects. The Accepted status of a Route heavily depends on the presence and validity of the Gateway it references. The controller must also set up watches on Gateway objects so that GRPCRoutes are re-reconciled when a Gateway's listeners change.
| s.mu.Lock() | ||
| defer s.mu.Unlock() | ||
|
|
||
| s.grpcRoutes[types.NamespacedName{Namespace: route.Namespace, Name: route.Name}] = rs |
There was a problem hiding this comment.
Storing the route pointer directly into the map from the reconciler's cache without performing a .DeepCopy() can lead to data races. If the controller cache updates the object or another routine mutates it concurrently, this shared memory will be modified unsafely.
| } | ||
| } | ||
|
|
||
| r.State.UpsertGRPCRoute(route) |
There was a problem hiding this comment.
r.State.UpsertGRPCRoute(route) is called here again, but it was already called on line 52. While harmless if intended to update the cached status, it might be cleaner to only upsert it once after the final status modifications are made.
| var proxyRoutes []state.InternalRoute | ||
| for _, gw := range gateways { | ||
| proxyRoutes = append(proxyRoutes, gw.BuildInternalRoutes(routes, services, backendTLSPolicies, configMaps, ControllerName)...) | ||
| proxyRoutes = append(proxyRoutes, gw.BuildInternalRoutes(httpRoutes, grpcRoutes, services, backendTLSPolicies, configMaps, ControllerName)...) |
There was a problem hiding this comment.
The BuildInternalRoutes parameter list is growing excessively long. Consider encapsulating httpRoutes, grpcRoutes, services, backendTLSPolicies, and configMaps into a state context or options struct for better maintainability.
| Name: string(backendRef.Name), | ||
| } | ||
| var appProtocol *string | ||
| if svc, ok := services[backendSvcName]; ok { |
There was a problem hiding this comment.
If the backend Service does not exist in the services map, this logic silently proceeds and forwards traffic via DNS. Per Gateway API, if a referent Service is missing, it should properly reflect as an invalid backend, ideally contributing to a false ResolvedRefs status or yielding a 500 status in the data plane.
|
I have submitted the review generated by Overseer. I've also created an |
|
Overseer deferred investigate-failures task due to limit reached. Will retry later. |
|
Overseer has dispatched an investigate-failures task for this PR. |
- Adds grpcroutes and grpcroutes/status to gari-controller ClusterRole - Runs ap generate to fix formatting in pkg/proxy/proxy.go
|
--- INVESTIGATION REPORT ---
(This report was generated by Overseer) |
|
Thanks for the report! Acknowledged.\n\n*(This comment was generated by Overseer)* |
This PR enhances the Gateway API implementation to support GRPCRoute and weighted backends, and adds GRPCRouteWeight to the conformance test suite.
Key changes:
This PR was generated by Overseer (powered by the gemini-3-flash-preview model).
Fixes #122