-
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: use filter type URL as the primary way to discover extensions #9618
Changes from 16 commits
7442509
aad3af2
ed020ad
151f640
f76c893
224d5cf
2e7c1fa
65113cb
6312737
a4b77ae
ac5504b
2e6515b
4b02241
0c3dba7
cff30cd
9265f8e
c0d29bd
18b57ca
5d3342b
a0445ec
d546d26
6a1d486
bc6f2bb
402a86d
7134d12
36ad6ec
df32987
858dfed
0b875dd
a338edf
9f398d3
1083c22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -332,6 +332,69 @@ The management server could respond to EDS requests with: | |
address: 127.0.0.2 | ||
port_value: 1234 | ||
|
||
.. _config_overview_v2_extension_configuration: | ||
|
||
Extension configuration | ||
----------------------- | ||
|
||
Each configuration resource in Envoy has a type URL in the `typed_config`. This | ||
type corresponds to a versioned schema. If the type URL uniquely identifies an | ||
extension capable of interpreting the configuration, then the extension is | ||
selected regardless of the `name` field. In this case the `name` field becomes | ||
optional and can be used as an identifier or as an annotation for the | ||
particular instance of the extension configuration. For example, the following | ||
filter configuration snippet is permitted: | ||
|
||
.. code-block:: yaml | ||
|
||
name: front-http-proxy | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager | ||
stat_prefix: ingress_http | ||
codec_type: AUTO | ||
rds: | ||
route_config_name: local_route | ||
config_source: | ||
api_config_source: | ||
api_type: GRPC | ||
grpc_services: | ||
envoy_grpc: | ||
cluster_name: xds_cluster | ||
http_filters: | ||
- name: front-router | ||
typed_config: | ||
"@type": type.googleapis.com/envoy.config.filter.http.router.v2.Router | ||
dynamic_stats: true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think something is injecting Protobuf::Empty when @type is specified and nothing else. Need to track that down, but that's a degenerate case. |
||
|
||
In case the control plane lacks the schema definitions for an extension, | ||
`udpa.type.v1.TypedStruct` should be used as a generic container. The type URL | ||
inside it is then used by a client to convert the contents to a typed | ||
configuration resource. For example, the above example could be written as | ||
follows: | ||
|
||
.. code-block:: yaml | ||
|
||
name: front-http-proxy | ||
typed_config: | ||
"@type": type.googleapis.com/udpa.type.v1.TypedStruct | ||
type_url: type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager | ||
value: | ||
stat_prefix: ingress_http | ||
codec_type: AUTO | ||
rds: | ||
route_config_name: local_route | ||
config_source: | ||
api_config_source: | ||
api_type: GRPC | ||
grpc_services: | ||
envoy_grpc: | ||
cluster_name: xds_cluster | ||
http_filters: | ||
- name: front-router | ||
typed_config: | ||
"@type": type.googleapis.com/udpa.type.v1.TypedStruct | ||
type_url: type.googleapis.com/envoy.config.filter.http.router.v2.Router | ||
|
||
.. _config_overview_v2_management_server: | ||
|
||
xDS API endpoints | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,8 @@ | |
#include "common/protobuf/utility.h" | ||
#include "common/singleton/const_singleton.h" | ||
|
||
#include "udpa/type/v1/typed_struct.pb.h" | ||
|
||
namespace Envoy { | ||
namespace Config { | ||
|
||
|
@@ -209,13 +211,47 @@ class Utility { | |
return *factory; | ||
} | ||
|
||
template <class Factory> static Factory& getAndCheckFactoryByType(absl::string_view type) { | ||
if (type.empty()) { | ||
throw EnvoyException("Provided type for static registration lookup was empty."); | ||
kyessenov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
Factory* factory = Registry::FactoryRegistry<Factory>::getFactoryByType(type); | ||
if (factory == nullptr) { | ||
throw EnvoyException( | ||
fmt::format("Didn't find a registered implementation for type: '{}'", type)); | ||
} | ||
return *factory; | ||
} | ||
|
||
/** | ||
* Get a Factory from the registry with error checking to ensure the name and the factory are | ||
* valid. | ||
* @param message proto that contains fields 'name' and 'typed_config'. | ||
*/ | ||
template <class Factory, class ProtoMessage> | ||
static Factory& getAndCheckFactory(const ProtoMessage& message) { | ||
const ProtobufWkt::Any& typed_config = message.typed_config(); | ||
static const std::string& struct_type = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two cases:
Both cases are abnormal IMHO. Do you want to make case 2 behave like case 1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we might want that, to make it easier for folks to move to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, made it fall back to |
||
ProtobufWkt::Struct::default_instance().GetDescriptor()->full_name(); | ||
static const std::string& typed_struct_type = | ||
udpa::type::v1::TypedStruct::default_instance().GetDescriptor()->full_name(); | ||
|
||
if (!typed_config.value().empty()) { | ||
// Unpack methods will only use the fully qualified type name after the last '/'. | ||
// https://github.com/protocolbuffers/protobuf/blob/3.6.x/src/google/protobuf/any.proto#L87 | ||
const absl::string_view type = TypeUtil::typeUrlToDescriptorFullName(typed_config.type_url()); | ||
|
||
if (type == typed_struct_type) { | ||
udpa::type::v1::TypedStruct typed_struct; | ||
MessageUtil::unpackTo(typed_config, typed_struct); | ||
// Not handling nested structs or typed structs in typed structs | ||
return Utility::getAndCheckFactoryByType<Factory>( | ||
TypeUtil::typeUrlToDescriptorFullName(typed_struct.type_url())); | ||
} else if (type != struct_type) { | ||
return Utility::getAndCheckFactoryByType<Factory>(type); | ||
} | ||
} | ||
|
||
return Utility::getAndCheckFactoryByName<Factory>(message.name()); | ||
} | ||
|
||
|
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.
Can you add some discussion in here of the UDPA typed struct also? In general I would like to see a discussion of all the various acceptable ways of configuring extensions and why a user might want to choose them.
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.
Sure. I didn't find any mention of typed struct, but can start sketching something in this section.