-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
router: scoped RDS (2/4): support scoped routing configuration #5839
router: scoped RDS (2/4): support scoped routing configuration #5839
Conversation
This commit introduces: - Support for scoped routing configuration parsing. - Inline and dynamic config providers using the ConfigProvider framework. - Unit and integration testing scaffolding. This is the second step in the PR chain for envoyproxy#4704. Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
…-dynamic Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good from what I can tell, left you come comments to get you started.
api/envoy/api/v2/srds.proto
Outdated
// The Scoped RDS API is not yet fully implemented and *should not* be enabled in | ||
// :ref:`envoy_api_msg_config.filter.network.http_connection_manager.v2.HttpConnectionManager`. | ||
|
||
// The resource_names field in DiscoveryRequest specifies a set of route configuration scopes. Each |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ref link to resource_names
/DiscoveryRequest
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
api/envoy/api/v2/srds.proto
Outdated
} | ||
} | ||
|
||
// This configuration represents a set of "scopes", each containing independent routing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a set of routing "scopes"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
api/envoy/api/v2/srds.proto
Outdated
// | ||
// .. code:: | ||
// | ||
// X-Header: a,b;c,d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using a=b;c=d
in the example makes it more obvious that we're parsing key value pairs in this example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
api/envoy/api/v2/srds.proto
Outdated
// Specifies the mechanism for constructing fragments which are composed into keys. | ||
message FragmentBuilder { | ||
// Specifies how the value of a header should be extracted. | ||
// The following example maps the structure of a header to the fields in this message. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe include an example of a HeaderValueExtractor
that can be used to extract a value from the header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an example in the ScopedRouteConfigurationsSet documentation.
api/envoy/api/v2/srds.proto
Outdated
} | ||
} | ||
|
||
// The constructed key consists of the union of these fragments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does order matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, updated comment.
@@ -153,9 +200,19 @@ HttpConnectionManagerConfig::HttpConnectionManagerConfig( | |||
context_.listenerScope())), | |||
proxy_100_continue_(config.proxy_100_continue()), | |||
delayed_close_timeout_(PROTOBUF_GET_MS_OR_DEFAULT(config, delayed_close_timeout, 1000)) { | |||
// Throws an exception on failure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be more accurate to say that it throws an exception on invalid config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -74,8 +74,25 @@ class HttpConnectionManagerImplTest : public TestBase, public ConnectionManagerC | |||
std::shared_ptr<Router::MockConfig> route_config_{new NiceMock<Router::MockConfig>()}; | |||
}; | |||
|
|||
struct ScopedRouteConfigProvider : public Config::ConfigProvider { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the same as the one defined in conn_manager_impl_fuzz_test.cc
? Maybe define it in some shared file (alongside the mocks?) or maybe reuse the null provider?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I've now pulled this out into a common implementation included by both this test and the fuzz_test.
parseScopedRoutesConfigFromYaml(*resources.Add(), config_yaml); | ||
EXPECT_THROW(subscription.onConfigUpdate(resources, "1"), ProtoValidationException); | ||
|
||
// 'scope_key_builder.fragments' validation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind including comments about what is invalid about the configuration? Here and for other invalid config tests. Might also be valuable to verify the exception message to ensure that we're tickling the correct validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
~ScopedRoutesConfigProviderManagerTest() override = default; | ||
}; | ||
|
||
// Tests that the /configdump handler returns the corresponding scoped routing config. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: /config_dump
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
- name: envoy.router | ||
)EOF"; | ||
|
||
HttpConnectionManagerConfig(parseHttpConnectionManagerFromV2Yaml(config_yaml), context_, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use EXPECT_NO_THROW
to indicate that we don't expect this to throw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few high level comments from just looking at the API/docs. Thank you for working on this. Cool stuff.
api/envoy/api/v2/srds.proto
Outdated
|
||
oneof extract_type { | ||
// Specifies the index of the element to extract. | ||
int32 index = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't find mention of signed vs unsigned in Envoy's style guide so I defaulted to Google's style of using signed integers and relying on assertions to check val >= 0.
|
||
// Must be set to true when scoped RDS is enabled. | ||
// If this is enabled, RDS subscriptions will be triggered by scoped RDS config updates using | ||
// this configuration as a template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -63,6 +64,14 @@ message HttpConnectionManager { | |||
envoy.api.v2.RouteConfiguration route_config = 4; | |||
} | |||
|
|||
oneof scoped_routes_specifier { | |||
// Configuration for the Scoped RDS API which dynamically loads routing configuration scopes. | |||
ScopedRds scoped_rds = 30; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be simpler if these options were just in the route_specifier
oneof above? Why have them be orthogonal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial intention keeping them separate was to avoid confusion that SRDS and RDS are tightly coupled and require the same config source, etc.
However, based on the feedback in this review and reassessing this from the user's standpoint, I agree this is simpler if ScopedRds
becomes part of the route_specifier
, and ScopedRds
expands to include both the ConfigSource
for RDS and SRDS. This would allow me to remove scoped_rds_template
from Rds
, which avoids the confusion related to that field (I've never been quite happy with that field since I started working on this).
api/envoy/api/v2/srds.proto
Outdated
} | ||
} | ||
|
||
// This configuration represents a set of "scopes", each containing independent routing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to be honest in saying that it's very hard for me to follow the messages/documentation in this file. I read the spec a while ago but I've forgotten it. Would it be possible to add some high level documentation here that walks the end user through some examples of how the API is setup, the fragment builder works, etc. If you plan on doing this in arch overview docs that's fine too, whatever is easiest. The reason I ask for this now is I think it would make it a lot easier to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial plan was to add in-depth documentation including examples to the arch overview docs (which I wasn't planning to do until the feature is fully implemented in PR 3), but I agree better documentation in the proto definition would be helpful for this review. I am working on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a ton. I think even just some YAML examples here in the proto docs would be super helpful. You could move them to the arch overview later or just link to them here, so hopefully zero wasted effort.
@snowp @mattklein123 Thanks for the feedback and patience. I wasn't able to work on this last week but I will be actively addressing the comments and updating the PR this week. |
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Apologies for the delay responding to feedback. I have addressed most of the review comments. I am now working on removing the |
api/envoy/api/v2/srds.proto
Outdated
// which Envoy would fetch via RDS. | ||
// | ||
// [#comment:next free field: 4] | ||
message ScopedRouteConfigurationsSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon revisiting the SRDS proto in the context of Incremental xDS, I have decided to make a few changes after discussing with @htuch.
To easily enable incremental updates to the routing scopes (represented by the Scope
message) by leveraging the existing Incremental xDS API, I am going to move the ScopeKeyBuilder
specification out of the ScopedRouteConfigurationsSet
into the HttpConnectionManager
, and instead of publishing a repeated Scope scopes =
in this message, each SRDS proto (which will most likely be renamed to ScopedRouteConfiguration
) will contain a single Scope
.
This change creates much better alignment with the API/protocol already defined for incremental updates, and also simplifies the SRDS API.
I am actively working on this now and will introduce the changes discussed as part of the next few commits to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndresGuedez cool I will defer looking at the API again until this is done. Thank you for iterating on this.
/wait
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
I have made the changes to modify the SRDS API to be delta friendly; what is the best way to move forward with this review? Can this PR be reopened? |
@AndresGuedez can you merge master to resolve conflicts? |
…-dynamic Signed-off-by: Andres Guedez <aguedez@google.com>
- Refactor the framework to create a cleaner, more cohesive set of abstractions based on the ConfigProvider::ApiType of the DS API. - Rename base classes for consistency and clarity. Signed-off-by: Andres Guedez <aguedez@google.com>
Merged master and pushed commit with cleanup of the ConfigProvider framework. Actively working on addressing test coverage. |
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
@@ -329,6 +331,41 @@ class Utility { | |||
static void translateOpaqueConfig(const ProtobufWkt::Any& typed_config, | |||
const ProtobufWkt::Struct& config, | |||
Protobuf::Message& out_proto); | |||
|
|||
#if 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
@@ -178,3 +179,43 @@ message RoutesConfigDump { | |||
// The dynamically loaded route configs. | |||
repeated DynamicRouteConfig dynamic_route_configs = 3 [(gogoproto.nullable) = false]; | |||
} | |||
|
|||
// Envoy's scoped RDS implementation fills this message with all currently loaded route |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @AndresGuedez for this, my main thought looking at this is that the PR is too big to reasonably review and without diluting review bandwidth. Can we split the PR up further for review?
I think we should have this master PR kept open to show how things tie together, but then separate PRs for:
- Protos.
- Scoped RDS configuration parser and handling logic. This can just be unit tested and doesn't need to be wired up yet.
- Config subscription and wiring of scoped RDS into the rest of Envoy. The integration test can be added here.
- Optionally, other PRs to reduce the amount of renaming noise, where reasonable.
I think we can get better review velocity if we do it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack. Working on splitting this up.
Implement the scoped RDS (SRDS) API config subscription and provider based on the config protos introduced in #6675 and the ConfigProvider framework introduced in #5243 and #6781. NOTES: See parent PR #5839 for full context into these changes. PRs 2a (#6675) and 2b (#6781) have already been merged. The API is not yet fully implemented. This PR introduces static and dynamic (xDS config subscription) handling of scoped routing configuration, but the new L7 multi tenant routing logic (see #4704) has not yet been introduced. The API is not yet plumbed into the HttpConnectionManager, that will be done in the next PR. This PR includes unit tests only; integration tests will follow in the next PR. Risk Level: Low (this DS API is not yet integrated into the HCM and can not be enabled via config). Testing: Unit tests added. Docs Changes: N/A. Signed-off-by: Andres Guedez <aguedez@google.com>
#7068) Integrate the Scoped Route Discovery Service (SRDS) API into the HttpConnectionManager. NOTES: - This is the last PR in the chain originating from parent #5839. - The scoped routing logic which can be configured through this API has not yet been implemented; it will be done in follow up PRs. Risk Level: Low (API is not yet fully implemented and should not be enabled) Testing: Integration tests added. Signed-off-by: Andres Guedez <aguedez@google.com>
I think this is done and can be closed. |
This PR introduces:
This is the second PR in the chain to implement Scoped RDS (see #4704 for design).
NOTE: this PR does not actually implement the scoped routing logic; it will be introduced in the next PR in this chain.
Risk Level: Low; this API is not yet fully implemented and is config guarded (defaulting to disabled)
Testing: Unit and integration tests added
Docs Changes: SRDS (ScopedRouteConfigurationsSet) proto documentation