-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
xds: define base interfaces for filter factories #9391
Conversation
Signed-off-by: Kuat Yessenov <[email protected]>
@kyessenov can you look at CI? Thanks! |
Sorry, I meant to click draft button. Working on tests. |
Signed-off-by: Kuat Yessenov <[email protected]>
/cc @htuch
|
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.
@kyessenov we already have an API oracle for this, take a look at https://github.com/envoyproxy/envoy/blob/master/source/common/config/api_type_oracle.h. We leave breadcrumb links across different versions of messages. There is also a more complete API type database, which we don't link in for size reasons.
I think it would be nice to have a solution that works consistently across all forms of extension. I think that what you have uncovered is that we haven't been doing a great job at ensuring factories and extensions adopt consistent conventions, which is something that should be improved going forward.
Do you need to land this before the v3 API migration? I'm thinking it could be better to do after 1.13.0 if there are no dependencies. If there's something that you think we will need in v3 to make this tractable, would be good to know soon.
CC @envoyproxy/api-shepherds @yanavlasov (for factory naming conventions)
class TypedConfig { | ||
public: | ||
/** | ||
* @return ProtobufTypes::MessagePtr create empty config proto message for v2. The config, which |
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.
Given that folks are going to be starting to move to v3 in early 2020, do we want to do a lot of work to make this supported in v2?
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.
We need some bridge to associate a protobuf type with a factory. We probably could invert this, and just use type
to instantiate a proto. Either way works, I'm aiming for minimal disruption in 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.
What do you think about getting #8933 landed? In this world, all extensions are typed..
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, that would be wonderful. I was going to special case empty config but would be better without that.
Signed-off-by: Kuat Yessenov <[email protected]>
I don't have a strong need to land this before v3 migration. I think it would be good to make the transition smooth though, so it might be a good idea to relax the spec without breaking compatibility first. I find API-first method of detecting extensions is much better than using extension names. We could probably start a UDPA spec for a generic extension config in parallel: message ExtensionConfig {
// Resource name for the config (to be referred in the filter config discovery service)
string name = 1;
// Opaque config. The type URL is used to select an extension and upgrade the config if necessary.
google.protobuf.Any typed_config = 2;
// Transparent metadata for control plane annotations.
core.Metadata metadata = 3;
} |
To make sure I understand. The type() method of extension factory provides URL string of corresponding proto message for configuring the extensions. In this way cofig consumer can find and instantiate filters of correct type, right? |
@yanavlasov I tagged you for this comment of @kyessenov:
I'm generally in agreement with @kyessenov on API native conventions for conveying type. I'm hoping this naturally is a thing in v3 once we get rid of empty proto extensions. |
@@ -74,6 +74,7 @@ class TypedMetadataFactory { | |||
parse(const ProtobufWkt::Struct& data) const PURE; | |||
|
|||
static std::string category() { return "typed_metadata"; } | |||
static std::string type() { return ""; } |
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.
qq from a skim: what does type()
mean and why is it set to empty string everywhere?
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.
It's set to "" for factories that don't have protos defined.
type() means the protobuf message name for the config of a factory.
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 there some way to make this more obvious and less boilerplate either via templating, base class with a default, etc.?
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.
the happy case is handled by TypedConfig base class. I was thinking we may want to revisit the unhappy cases and fix them, so wasn't optimizing for that. we can provide a default base class UntypedConfig for that.
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.
Yeah something as simple as UntypedConfig IMO would make it a lot more clear, but up to you.
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 make sense to have a common base class for all factories at this point? I think there might be a critical mass of attributes common to all factories.
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.
Yeah, category, name, and type are sufficient for a base class.
include/envoy/config/typed_config.h
Outdated
/** | ||
* @return config proto full name | ||
*/ | ||
virtual std::string type() { |
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 make sense to name it config_type_url()
?
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 config_type
? I didn't want to call it URL since it's not really a type URL as in Any. Calling message name is also confusing (unless you're used to protobuf lingua).
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.
If we're going to bike shed, what about we replace the whole category and config type thing with kind
, as in https://en.wikipedia.org/wiki/Kind_(type_theory).
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.
Kind might confuse a k8s user, since in k8s the API group and version are separated from the kind. Kind means an "object kind" in that object-oriented world.
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.
Why not use the type URL as in Any?
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.
Type URL is ambiguous. It looks like proto_registry/proto_name
where proto_registry
is usually type.googleapis.com
but it doesn't have to be. It's some sort of indicator about where to fetch the descriptor, although I haven't seen anyone using it that 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.
Ok, if proto descriptor is less ambiguous than type URL then I should change corresponding field name in the Extension proto in PR #9301
Signed-off-by: Kuat Yessenov <[email protected]>
Updated the change to remove any behavioral change, since refactoring got quite large. Please take a look. |
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
There is an issue with registering factories based on proto objects. The factory registration call races ahead of the protobuf registration, which causes an issue with incomplete proto objects. There are two possible way to solve this:
I moved the code that causes it out of this PR, so it'd be easier to tackle. Let me know if this PR is good enough. |
Sent envoyproxy/envoy-filter-example#109 to fix the build error in a sister repo. |
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.
In general this approach LGTM.
include/envoy/config/typed_config.h
Outdated
if (ptr == nullptr) { | ||
return ""; | ||
} |
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.
Should this ever return nullptr? Should this be an ASSERT/RELEASE_ASSERT?
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.
Updated to use ASSERT. Seems reasonable since this interface requires a proto config.
* arrives in an opaque google.protobuf.Struct message, will be converted to JSON and then parsed | ||
* into this empty proto. | ||
*/ | ||
virtual ProtobufTypes::MessagePtr createEmptyConfigProto() PURE; |
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.
One thing we could do, and it doesn't have to be this PR, is move away from having each individual filter return empty protos. Instead, they could either return a type name or descriptor, and we could have more general machinery for assembling the empty proto. Might not be a big win, but just thought I'd throw it out there.
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.
Agree. It also helps with the registration initialization fiasco, since protobuf initializer may run after factory initializers.
Signed-off-by: Kuat Yessenov <[email protected]>
@htuch can you help merging the linked filter example PR to make tests pass here: envoyproxy/envoy-filter-example#109 |
Signed-off-by: Kuat Yessenov <[email protected]>
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.
LGTM, thanks!
@mattklein123 any final thoughts on this one? |
Nope ship it! Nice work. |
@kyessenov the CI failure is real because envoy-filter-example doesn't build with this change. Can you raise a PR there to accommodate this? |
@lizan I already did that and it got merged. How are you supposed to update both repos in tandem? |
@kyessenov https://github.com/envoyproxy/envoy/blob/master/ci/build_setup.sh#L104 update the SHA here. |
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov <[email protected]>
Signed-off-by: Kuat Yessenov [email protected]
Introduces a typed factory and an untyped factory as base types for all extension factories.
Code refactor to facilitate using the config type as the primary selection mechanism for an extension.
This change should not cause any behavioral change. The actual switch is in a follow-up PR.
Contributes to: #9358
Risk Level: low
Testing: existing tests pass
Docs Changes:
Release Notes:
[Optional Fixes #Issue]
[Optional Deprecated:]