Skip to content
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

Closed

Conversation

AndresGuedez
Copy link
Contributor

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

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>
@htuch htuch self-assigned this Feb 5, 2019
Signed-off-by: Andres Guedez <aguedez@google.com>
@mattklein123 mattklein123 self-assigned this Feb 6, 2019
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
@htuch htuch requested a review from snowp February 7, 2019 17:06
Copy link
Contributor

@snowp snowp left a 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.

// 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
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}

// This configuration represents a set of "scopes", each containing independent routing
Copy link
Contributor

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"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

//
// .. code::
//
// X-Header: a,b;c,d
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// 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.
Copy link
Contributor

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

Copy link
Contributor Author

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.

}
}

// The constructed key consists of the union of these fragments.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does order matter?

Copy link
Contributor Author

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.
Copy link
Contributor

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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

Copy link
Contributor Author

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: /config_dump

Copy link
Contributor Author

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_,
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@junr03 junr03 self-assigned this Feb 11, 2019
Copy link
Member

@mattklein123 mattklein123 left a 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.


oneof extract_type {
// Specifies the index of the element to extract.
int32 index = 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsigned?

Copy link
Contributor Author

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.
Copy link
Member

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;
Copy link
Member

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?

Copy link
Contributor Author

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).

}
}

// This configuration represents a set of "scopes", each containing independent routing
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

@AndresGuedez
Copy link
Contributor Author

AndresGuedez commented Feb 19, 2019

@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.

@stale
Copy link

stale bot commented Feb 26, 2019

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!

@stale stale bot added the stale stalebot believes this issue/PR has not been touched recently label Feb 26, 2019
Signed-off-by: Andres Guedez <aguedez@google.com>
Signed-off-by: Andres Guedez <aguedez@google.com>
@stale stale bot removed the stale stalebot believes this issue/PR has not been touched recently label Feb 27, 2019
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>
@AndresGuedez
Copy link
Contributor Author

Apologies for the delay responding to feedback.

I have addressed most of the review comments. I am now working on removing the scoped_rds_template per #5839 (comment). This should simplify the logic in HttpConnectionManager and also greatly clarify the interaction between SRDS and RDS ConfigSource configuration.

// which Envoy would fetch via RDS.
//
// [#comment:next free field: 4]
message ScopedRouteConfigurationsSet {
Copy link
Contributor Author

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.

Copy link
Member

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>
@AndresGuedez
Copy link
Contributor Author

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?

Signed-off-by: Andres Guedez <aguedez@google.com>
@htuch htuch reopened this Apr 15, 2019
@stale stale bot removed the stale stalebot believes this issue/PR has not been touched recently label Apr 15, 2019
@htuch
Copy link
Member

htuch commented Apr 15, 2019

@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>
@AndresGuedez
Copy link
Contributor Author

@AndresGuedez can you merge master to resolve conflicts?

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
Copy link
Member

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
Copy link
Member

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:

  1. Protos.
  2. Scoped RDS configuration parser and handling logic. This can just be unit tested and doesn't need to be wired up yet.
  3. Config subscription and wiring of scoped RDS into the rest of Envoy. The integration test can be added here.
  4. 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.

Copy link
Contributor Author

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.

@snowp snowp removed their assignment Apr 19, 2019
@mattklein123 mattklein123 added no stalebot Disables stalebot from closing an issue waiting labels Apr 24, 2019
htuch pushed a commit that referenced this pull request May 22, 2019
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>
htuch pushed a commit that referenced this pull request Jun 4, 2019
#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>
@mattklein123
Copy link
Member

I think this is done and can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no stalebot Disables stalebot from closing an issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants