-
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
router: vhost/route/w.cluster local filter configuration #3045
Changes from all commits
636e605
b2d0263
134734b
0cc834f
35f37f7
4820c48
d76ad4d
6309d41
9897138
118c728
711f59f
472f7ae
c2f915b
cbd19d4
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 |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
|
||
#include "envoy/http/header_map.h" | ||
#include "envoy/runtime/runtime.h" | ||
#include "envoy/server/filter_config.h" // TODO(rodaine): break dependency on server | ||
#include "envoy/upstream/cluster_manager.h" | ||
#include "envoy/upstream/upstream.h" | ||
|
||
|
@@ -21,6 +22,8 @@ | |
#include "common/common/utility.h" | ||
#include "common/config/metadata.h" | ||
#include "common/config/rds_json.h" | ||
#include "common/config/utility.h" | ||
#include "common/config/well_known_names.h" | ||
#include "common/http/headers.h" | ||
#include "common/http/utility.h" | ||
#include "common/protobuf/utility.h" | ||
|
@@ -244,7 +247,8 @@ RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, | |
route.route().response_headers_to_remove())), | ||
opaque_config_(parseOpaqueConfig(route)), decorator_(parseDecorator(route)), | ||
direct_response_code_(ConfigUtility::parseDirectResponseCode(route)), | ||
direct_response_body_(ConfigUtility::parseDirectResponseBody(route)) { | ||
direct_response_body_(ConfigUtility::parseDirectResponseBody(route)), | ||
per_filter_configs_(route.per_filter_config()) { | ||
if (route.route().has_metadata_match()) { | ||
const auto filter_it = route.route().metadata_match().filter_metadata().find( | ||
Envoy::Config::MetadataFilters::get().ENVOY_LB); | ||
|
@@ -520,14 +524,19 @@ void RouteEntryImplBase::validateClusters(Upstream::ClusterManager& cm) const { | |
} | ||
} | ||
|
||
const Protobuf::Message* RouteEntryImplBase::perFilterConfig(const std::string& name) const { | ||
return per_filter_configs_.get(name); | ||
} | ||
|
||
RouteEntryImplBase::WeightedClusterEntry::WeightedClusterEntry( | ||
const RouteEntryImplBase* parent, const std::string runtime_key, Runtime::Loader& loader, | ||
const envoy::api::v2::route::WeightedCluster_ClusterWeight& cluster) | ||
: DynamicRouteEntry(parent, cluster.name()), runtime_key_(runtime_key), loader_(loader), | ||
cluster_weight_(PROTOBUF_GET_WRAPPED_REQUIRED(cluster, weight)), | ||
request_headers_parser_(HeaderParser::configure(cluster.request_headers_to_add())), | ||
response_headers_parser_(HeaderParser::configure(cluster.response_headers_to_add(), | ||
cluster.response_headers_to_remove())) { | ||
cluster.response_headers_to_remove())), | ||
per_filter_configs_(cluster.per_filter_config()) { | ||
if (cluster.has_metadata_match()) { | ||
const auto filter_it = cluster.metadata_match().filter_metadata().find( | ||
Envoy::Config::MetadataFilters::get().ENVOY_LB); | ||
|
@@ -542,6 +551,15 @@ RouteEntryImplBase::WeightedClusterEntry::WeightedClusterEntry( | |
} | ||
} | ||
|
||
const Protobuf::Message* | ||
RouteEntryImplBase::WeightedClusterEntry::perFilterConfig(const std::string& name) const { | ||
const Protobuf::Message* cfg = per_filter_configs_.get(name); | ||
if (cfg != nullptr) { | ||
return cfg; | ||
} | ||
return DynamicRouteEntry::perFilterConfig(name); | ||
} | ||
|
||
PrefixRouteEntryImpl::PrefixRouteEntryImpl(const VirtualHostImpl& vhost, | ||
const envoy::api::v2::route::Route& route, | ||
Runtime::Loader& loader) | ||
|
@@ -652,7 +670,8 @@ VirtualHostImpl::VirtualHostImpl(const envoy::api::v2::route::VirtualHost& virtu | |
global_route_config_(global_route_config), | ||
request_headers_parser_(HeaderParser::configure(virtual_host.request_headers_to_add())), | ||
response_headers_parser_(HeaderParser::configure(virtual_host.response_headers_to_add(), | ||
virtual_host.response_headers_to_remove())) { | ||
virtual_host.response_headers_to_remove())), | ||
per_filter_configs_(virtual_host.per_filter_config()) { | ||
switch (virtual_host.require_tls()) { | ||
case envoy::api::v2::route::VirtualHost::NONE: | ||
ssl_requirements_ = SslRequirements::NONE; | ||
|
@@ -716,6 +735,10 @@ VirtualHostImpl::VirtualClusterEntry::VirtualClusterEntry( | |
|
||
const Config& VirtualHostImpl::routeConfig() const { return global_route_config_; } | ||
|
||
const Protobuf::Message* VirtualHostImpl::perFilterConfig(const std::string& name) const { | ||
return per_filter_configs_.get(name); | ||
} | ||
|
||
const VirtualHostImpl* RouteMatcher::findWildcardVirtualHost(const std::string& host) const { | ||
// We do a longest wildcard suffix match against the host that's passed in. | ||
// (e.g. foo-bar.baz.com should match *-bar.baz.com before matching *.baz.com) | ||
|
@@ -855,5 +878,22 @@ ConfigImpl::ConfigImpl(const envoy::api::v2::RouteConfiguration& config, Runtime | |
config.response_headers_to_remove()); | ||
} | ||
|
||
PerFilterConfigs::PerFilterConfigs(const Protobuf::Map<std::string, ProtobufWkt::Struct>& configs) { | ||
for (const auto& cfg : configs) { | ||
const std::string& name = cfg.first; | ||
const ProtobufWkt::Struct& struct_config = cfg.second; | ||
|
||
auto& factory = Envoy::Config::Utility::getAndCheckFactory< | ||
Server::Configuration::NamedHttpFilterConfigFactory>(name); | ||
|
||
configs_[name] = Envoy::Config::Utility::translateToFactoryRouteConfig(struct_config, factory); | ||
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. create another map config_hash_ to store hash of config The hash can be calculated by 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. Same comment as above. I don't think this is very helpful and I would rather sort out filter update callbacks as a separate feature? |
||
} | ||
} | ||
|
||
const Protobuf::Message* PerFilterConfigs::get(const std::string& name) const { | ||
auto cfg = configs_.find(name); | ||
return cfg == configs_.end() ? nullptr : cfg->second.get(); | ||
} | ||
|
||
} // namespace Router | ||
} // namespace Envoy |
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.
This suggestion is trying to address this issue: #3008
We can do it in a separate PR. But it is so simple, you can also put in in this PR too.
In these VHost/Route/Cluster, add another function
// If perFitlerConfig exists for this filter, get its config hash value to detect if config is updated.
// return 0 if no config for the filter.
size_t perFitlerConfigHash(const std::string& name) const 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.
I don't quite understand how this will help you. In the filter are you going to check this on a per-route basis? What you really want is another callback which allows a filter to update global structures on a route update.
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.
This is to help filters need to pre-process per_route_config. per_route_config can be dynamically changed anytime. But you don't want to pre-process the config for each request. This hash will help to detect config change, and skip pre_processing step:
This is how it can be used, For each request in decodeHeader()
This will also achieve: different routes with same config can share the same pre_processed object.
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.
This is not how I would recommend implementing this. (The above is not thread safe.). I have a pretty good idea of how to efficiently implement this and give you the functionality you need. Let's do this in a follow up.
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 istio mixer-client filter, the "global_map" actually is per_thread_global_map. so this approach works for us.
the filter_factory callback approach is better, the global_map can be used by all worker threads. But it is not easy for Istio to use it since its "object_map" object is way deep inside a per_thread object.
My request is: can we support both: 1) calculate the hash of per_route_config at config update time and filter can access it. 2) implements factory callback to support a config change update.