xds: define base interfaces for filter factories#9391
xds: define base interfaces for filter factories#9391lizan merged 18 commits intoenvoyproxy:masterfrom
Conversation
Signed-off-by: Kuat Yessenov <kuat@google.com>
|
@kyessenov can you look at CI? Thanks! |
|
Sorry, I meant to click draft button. Working on tests. |
Signed-off-by: Kuat Yessenov <kuat@google.com>
|
/cc @htuch
|
htuch
left a comment
There was a problem hiding this comment.
@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.
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.
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.
What do you think about getting #8933 landed? In this world, all extensions are typed..
There was a problem hiding this comment.
Yes, that would be wonderful. I was going to special case empty config but would be better without that.
|
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. |
| 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.
qq from a skim: what does type() mean and why is it set to empty string everywhere?
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
Would it make sense to name it config_type_url()?
There was a problem hiding this comment.
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.
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.
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.
Why not use the type URL as in Any?
There was a problem hiding this comment.
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.
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 <kuat@google.com>
|
Updated the change to remove any behavioral change, since refactoring got quite large. Please take a look. |
Signed-off-by: Kuat Yessenov <kuat@google.com>
Signed-off-by: Kuat Yessenov <kuat@google.com>
|
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. |
mattklein123
left a comment
There was a problem hiding this comment.
In general this approach LGTM.
include/envoy/config/typed_config.h
Outdated
| if (ptr == nullptr) { | ||
| return ""; | ||
| } |
There was a problem hiding this comment.
Should this ever return nullptr? Should this be an ASSERT/RELEASE_ASSERT?
There was a problem hiding this comment.
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.
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.
Agree. It also helps with the registration initialization fiasco, since protobuf initializer may run after factory initializers.
Signed-off-by: Kuat Yessenov <kuat@google.com>
|
@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 <kuat@google.com>
|
@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 <kuat@google.com>
Signed-off-by: Kuat Yessenov <kuat@google.com>
Signed-off-by: Kuat Yessenov <kuat@google.com>
Signed-off-by: Kuat Yessenov <kuat@google.com>
Signed-off-by: Kuat Yessenov kuat@google.com
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:]