xds: refactor server-side HTTP filter processing#8878
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #8878 +/- ##
==========================================
- Coverage 83.31% 83.18% -0.13%
==========================================
Files 414 416 +2
Lines 32805 32872 +67
==========================================
+ Hits 27330 27344 +14
- Misses 4069 4100 +31
- Partials 1406 1428 +22
🚀 New features to boost your workflow:
|
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request is a significant and well-executed refactoring of the server-side HTTP filter processing logic. The main goal of separating configuration from runtime state is achieved by moving logic from the xdsresource package to the server package, which will make it easier to implement filter state retention in the future. The changes are extensive but logical, with clear separation of concerns in new files like filter_chain_manager.go and routing.go. The accompanying tests are thorough and have been updated to reflect the new data structures. I've identified one critical bug in the new unmarshalling logic that needs to be addressed.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request is a significant and well-executed refactoring of the server-side HTTP filter processing logic. The primary goal of separating configuration from runtime state and moving server-specific logic into the server package has been achieved, which should make future work on state retention easier. The changes are consistent across the codebase, and the addition of new tests and updates to existing ones provide good coverage for the refactoring. I've found a few minor issues in the new test files related to variable naming and a typo in an error message, which I've commented on. Overall, this is a high-quality contribution that improves the codebase structure.
| for _, int := range r.interceptors { | ||
| errs = append(errs, int.AllowRPC(ctx).Error()) | ||
| } |
There was a problem hiding this comment.
The loop variable int shadows the built-in int type. This can be confusing and is generally considered bad practice in Go. Renaming it to something more descriptive like interceptor would improve readability and prevent potential issues.
| for _, int := range r.interceptors { | |
| errs = append(errs, int.AllowRPC(ctx).Error()) | |
| } | |
| for _, interceptor := range r.interceptors { | |
| err_s = append(errs, interceptor.AllowRPC(ctx).Error()) | |
| } |
| func cidrRangeFromAddressAndPrefixLen(address string, len int) *v3corepb.CidrRange { | ||
| return &v3corepb.CidrRange{ | ||
| AddressPrefix: address, | ||
| PrefixLen: &wrapperspb.UInt32Value{ | ||
| Value: uint32(len), | ||
| }, | ||
| } |
There was a problem hiding this comment.
The function parameter len shadows the built-in len function. This is confusing and can lead to subtle bugs if the built-in function is needed within this scope. It's best to use a more descriptive name like prefixLen.
| func cidrRangeFromAddressAndPrefixLen(address string, len int) *v3corepb.CidrRange { | |
| return &v3corepb.CidrRange{ | |
| AddressPrefix: address, | |
| PrefixLen: &wrapperspb.UInt32Value{ | |
| Value: uint32(len), | |
| }, | |
| } | |
| func cidrRangeFromAddressAndPrefixLen(address string, prefixLen int) *v3corepb.CidrRange { | |
| return &v3corepb.CidrRange{ | |
| AddressPrefix: address, | |
| PrefixLen: &wrapperspb.UInt32Value{ | |
| Value: uint32(prefixLen), | |
| }, | |
| } | |
| } |
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| if got := findBestMatchingVirtualHostServer(tt.host, tt.vHosts); !cmp.Equal(got, tt.want, cmp.AllowUnexported(virtualHostWithInterceptors{}, routeWithInterceptors{})) { | ||
| t.Errorf("FindBestMatchingxdsclient.virtualHostWithInterceptors() = %v, want %v", got, tt.want) |
There was a problem hiding this comment.
There appears to be a typo in the error message. It seems like FindBestMatchingxdsclient.virtualHostWithInterceptors() should be findBestMatchingVirtualHostServer() to match the function being tested. Correcting this will make test failures easier to debug.
| t.Errorf("FindBestMatchingxdsclient.virtualHostWithInterceptors() = %v, want %v", got, tt.want) | |
| t.Errorf("findBestMatchingVirtualHostServer() = %v, want %v", got, tt.want) |
While working on xDS HTTP filter state retention changes required for A83 and A86 in grpc#8745, I realized that the current implementation of HTTP filters on the server-side does not lend itself well to the changes we want to make to support filter state retention. The crux of the problem in the current implementation is as follows: - The `xdsresource` package builds a `FilterChainManager` type that does the following: - Keeps track of the list of Route Configuration resources to be requested based on the HTTP filters configured on the Listener resource - Updates the interceptors on the different filter chains based on Route Configuration resource updates (that contain filter config overrides) - Maintaining runtime state in a type that is supposed to represent a configuration blob seems to have been a wrong implementation choice - Everytime a Listener resource update is received, the `xdsresource` package builds a brand new `FilterChainManager` - This means that we *cannot* retain filter state across resource updates This PR makes the following changes: - Changes the layout of the `ListenerUpdate` struct to clearly separate client-side and server-side fields - Also groups information that is shared across client and server listener types into a logical struct - The `ListenerUpdate` will *only* contain information directly sourced from the listener proto - The xDS server implementation will build the runtime representation of the filter chains using the configuration update provided by the `xdsresource` package - This would move the responsibility of updating the interceptors on the filter chain to the xDS server, which is the correct place to be doing such a thing - This would make it possible for the xDS server implementation to retain filter state across listener resource updates RELEASE NOTES: none
While working on xDS HTTP filter state retention changes required for A83 and A86 in grpc#8745, I realized that the current implementation of HTTP filters on the server-side does not lend itself well to the changes we want to make to support filter state retention. The crux of the problem in the current implementation is as follows: - The `xdsresource` package builds a `FilterChainManager` type that does the following: - Keeps track of the list of Route Configuration resources to be requested based on the HTTP filters configured on the Listener resource - Updates the interceptors on the different filter chains based on Route Configuration resource updates (that contain filter config overrides) - Maintaining runtime state in a type that is supposed to represent a configuration blob seems to have been a wrong implementation choice - Everytime a Listener resource update is received, the `xdsresource` package builds a brand new `FilterChainManager` - This means that we *cannot* retain filter state across resource updates This PR makes the following changes: - Changes the layout of the `ListenerUpdate` struct to clearly separate client-side and server-side fields - Also groups information that is shared across client and server listener types into a logical struct - The `ListenerUpdate` will *only* contain information directly sourced from the listener proto - The xDS server implementation will build the runtime representation of the filter chains using the configuration update provided by the `xdsresource` package - This would move the responsibility of updating the interceptors on the filter chain to the xDS server, which is the correct place to be doing such a thing - This would make it possible for the xDS server implementation to retain filter state across listener resource updates RELEASE NOTES: none
While working on xDS HTTP filter state retention changes required for A83 and A86 in #8745, I realized that the current implementation of HTTP filters on the server-side does not lend itself well to the changes we want to make to support filter state retention. The crux of the problem in the current implementation is as follows:
xdsresourcepackage builds aFilterChainManagertype that does the following:xdsresourcepackage builds a brand newFilterChainManagerThis PR makes the following changes:
ListenerUpdatestruct to clearly separate client-side and server-side fieldsListenerUpdatewill only contain information directly sourced from the listener protoxdsresourcepackageRELEASE NOTES: none