Skip to content

Commit be1cd7b

Browse files
author
Snow Pettersen
authored
alpha matching: support generic action factory context (#17025)
Prior to this PR the MatchTreeFactory requried a ServerFactoryContext in order to pass this to the action factories. This is not available in all contexts, and there are other possible use cases where we might need to pass additional information to the match tree factory (e.g. the router might need to pass the parent vhost configuration). This PR introduces a paramterized action context, allowing each usage of the MatchTree to define its own data that should be presented to the action factories. This also has the nice benefit of partitioning the action factories per context: each unique ActionFactoryContext defines a new factory type, ensuring that actions defined for a HTTP filter context won't be conflated with actions defined for another context. Signed-off-by: Snow Pettersen <[email protected]>
1 parent 3d9c533 commit be1cd7b

File tree

19 files changed

+97
-90
lines changed

19 files changed

+97
-90
lines changed

envoy/matcher/matcher.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ class Action {
7676
using ActionPtr = std::unique_ptr<Action>;
7777
using ActionFactoryCb = std::function<ActionPtr()>;
7878

79-
class ActionFactory : public Config::TypedFactory {
79+
template <class ActionFactoryContext> class ActionFactory : public Config::TypedFactory {
8080
public:
8181
virtual ActionFactoryCb
82-
createActionFactoryCb(const Protobuf::Message& config, const std::string& stats_prefix,
83-
Server::Configuration::FactoryContext& context) PURE;
82+
createActionFactoryCb(const Protobuf::Message& config,
83+
ActionFactoryContext& action_factory_context,
84+
ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
8485

8586
std::string category() const override { return "envoy.matching.action"; }
8687
};
@@ -155,7 +156,7 @@ class InputMatcherFactory : public Config::TypedFactory {
155156
public:
156157
virtual InputMatcherFactoryCb
157158
createInputMatcherFactoryCb(const Protobuf::Message& config,
158-
Server::Configuration::FactoryContext& factory_context) PURE;
159+
ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
159160

160161
std::string category() const override { return "envoy.matching.input_matchers"; }
161162
};
@@ -226,7 +227,7 @@ template <class DataType> class DataInputFactory : public Config::TypedFactory {
226227
*/
227228
virtual DataInputFactoryCb<DataType>
228229
createDataInputFactoryCb(const Protobuf::Message& config,
229-
Server::Configuration::FactoryContext& factory_context) PURE;
230+
ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
230231

231232
/**
232233
* The category of this factory depends on the DataType, so we require a name() function to exist
@@ -262,7 +263,7 @@ class CommonProtocolInputFactory : public Config::TypedFactory {
262263
*/
263264
virtual CommonProtocolInputFactoryCb
264265
createCommonProtocolInputFactoryCb(const Protobuf::Message& config,
265-
Server::Configuration::FactoryContext& factory_context) PURE;
266+
ProtobufMessage::ValidationVisitor& validation_visitor) PURE;
266267

267268
std::string category() const override { return "envoy.matching.common_inputs"; }
268269
};

source/common/http/filter_manager.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
#include "source/common/http/header_utility.h"
1414
#include "source/common/http/utility.h"
1515

16+
#include "matching/data_impl.h"
17+
1618
namespace Envoy {
1719
namespace Http {
1820

1921
namespace {
20-
REGISTER_FACTORY(SkipActionFactory, Matcher::ActionFactory);
22+
REGISTER_FACTORY(SkipActionFactory, Matcher::ActionFactory<Matching::HttpFilterActionContext>);
2123

2224
template <class T> using FilterList = std::list<std::unique_ptr<T>>;
2325

source/common/http/filter_manager.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@ class FilterMatchState {
6868

6969
using FilterMatchStateSharedPtr = std::shared_ptr<FilterMatchState>;
7070

71-
class SkipActionFactory : public Matcher::ActionFactory {
71+
class SkipActionFactory : public Matcher::ActionFactory<Matching::HttpFilterActionContext> {
7272
public:
7373
std::string name() const override { return "skip"; }
74-
Matcher::ActionFactoryCb createActionFactoryCb(const Protobuf::Message&, const std::string&,
75-
Server::Configuration::FactoryContext&) override {
74+
Matcher::ActionFactoryCb createActionFactoryCb(const Protobuf::Message&,
75+
Matching::HttpFilterActionContext&,
76+
ProtobufMessage::ValidationVisitor&) override {
7677
return []() { return std::make_unique<SkipAction>(); };
7778
}
7879
ProtobufTypes::MessagePtr createEmptyConfigProto() override {

source/common/http/match_wrapper/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ envoy_cc_library(
1515
deps = [
1616
"//envoy/registry",
1717
"//envoy/server:filter_config_interface",
18+
"//source/common/http/matching:data_impl_lib",
1819
"//source/common/matcher:matcher_lib",
1920
"//source/extensions/filters/http/common:factory_base_lib",
2021
"@envoy_api//envoy/extensions/common/matching/v3:pkg_cc_proto",

source/common/http/match_wrapper/config.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "envoy/registry/registry.h"
66

77
#include "source/common/config/utility.h"
8+
#include "source/common/http/matching/data_impl.h"
89
#include "source/common/matcher/matcher.h"
910

1011
#include "absl/status/status.h"
@@ -103,9 +104,11 @@ Envoy::Http::FilterFactoryCb MatchWrapperConfig::createFilterFactoryFromProtoTyp
103104

104105
MatchTreeValidationVisitor validation_visitor(*factory.matchingRequirements());
105106

106-
auto match_tree =
107-
Matcher::MatchTreeFactory<Envoy::Http::HttpMatchingData>(prefix, context, validation_visitor)
108-
.create(proto_config.matcher());
107+
Envoy::Http::Matching::HttpFilterActionContext action_context{prefix, context};
108+
auto match_tree = Matcher::MatchTreeFactory<Envoy::Http::HttpMatchingData,
109+
Envoy::Http::Matching::HttpFilterActionContext>(
110+
action_context, context.messageValidationVisitor(), validation_visitor)
111+
.create(proto_config.matcher());
109112

110113
if (!validation_visitor.errors().empty()) {
111114
// TODO(snowp): Output all violations.

source/common/http/matching/data_impl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class HttpMatchingDataImpl : public HttpMatchingData {
5555

5656
using HttpMatchingDataImplSharedPtr = std::shared_ptr<HttpMatchingDataImpl>;
5757

58+
struct HttpFilterActionContext {
59+
const std::string& stat_prefix_;
60+
Server::Configuration::FactoryContext& factory_context_;
61+
};
5862
} // namespace Matching
5963
} // namespace Http
6064
} // namespace Envoy

source/common/http/matching/inputs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ class HttpHeadersDataInputFactoryBase : public Matcher::DataInputFactory<HttpMat
5555

5656
Matcher::DataInputFactoryCb<HttpMatchingData>
5757
createDataInputFactoryCb(const Protobuf::Message& config,
58-
Server::Configuration::FactoryContext& factory_context) override {
59-
const auto& typed_config = MessageUtil::downcastAndValidate<const ProtoType&>(
60-
config, factory_context.messageValidationVisitor());
58+
ProtobufMessage::ValidationVisitor& validation_visitor) override {
59+
const auto& typed_config =
60+
MessageUtil::downcastAndValidate<const ProtoType&>(config, validation_visitor);
6161

6262
return [header_name = typed_config.header_name()] {
6363
return std::make_unique<DataInputType>(header_name);

source/common/matcher/matcher.h

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,15 @@ template <class DataType> using DataInputFactoryCb = std::function<DataInputPtr<
6666

6767
/**
6868
* Recursively constructs a MatchTree from a protobuf configuration.
69+
* @param DataType the type used as a source for DataInputs
70+
* @param ActionFactoryContext the context provided to Action factories
6971
*/
70-
template <class DataType> class MatchTreeFactory {
72+
template <class DataType, class ActionFactoryContext> class MatchTreeFactory {
7173
public:
72-
MatchTreeFactory(const std::string& stats_prefix,
73-
Server::Configuration::FactoryContext& factory_context,
74+
MatchTreeFactory(ActionFactoryContext& context,
75+
ProtobufMessage::ValidationVisitor& proto_validation_visitor,
7476
MatchTreeValidationVisitor<DataType>& validation_visitor)
75-
: stats_prefix_(stats_prefix), factory_context_(factory_context),
77+
: action_factory_context_(context), proto_validation_visitor_(proto_validation_visitor),
7678
validation_visitor_(validation_visitor) {}
7779

7880
MatchTreeFactoryCb<DataType> create(const envoy::config::common::matcher::v3::Matcher& config) {
@@ -200,12 +202,13 @@ template <class DataType> class MatchTreeFactory {
200202
return OnMatch<DataType>{{}, matcher_factory()};
201203
};
202204
} else if (on_match.has_action()) {
203-
auto& factory = Config::Utility::getAndCheckFactory<ActionFactory>(on_match.action());
205+
auto& factory = Config::Utility::getAndCheckFactory<ActionFactory<ActionFactoryContext>>(
206+
on_match.action());
204207
ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
205-
on_match.action().typed_config(), factory_context_.messageValidationVisitor(), factory);
208+
on_match.action().typed_config(), proto_validation_visitor_, factory);
206209

207-
auto action_factory =
208-
factory.createActionFactoryCb(*message, stats_prefix_, factory_context_);
210+
auto action_factory = factory.createActionFactoryCb(*message, action_factory_context_,
211+
proto_validation_visitor_);
209212
return [action_factory] { return OnMatch<DataType>{action_factory, {}}; };
210213
}
211214

@@ -234,8 +237,8 @@ template <class DataType> class MatchTreeFactory {
234237
validation_visitor_.validateDataInput(*factory, config.typed_config().type_url());
235238

236239
ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
237-
config.typed_config(), factory_context_.messageValidationVisitor(), *factory);
238-
auto data_input = factory->createDataInputFactoryCb(*message, factory_context_);
240+
config.typed_config(), proto_validation_visitor_, *factory);
241+
auto data_input = factory->createDataInputFactoryCb(*message, proto_validation_visitor_);
239242
return data_input;
240243
}
241244

@@ -244,9 +247,9 @@ template <class DataType> class MatchTreeFactory {
244247
auto& common_input_factory =
245248
Config::Utility::getAndCheckFactory<CommonProtocolInputFactory>(config);
246249
ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
247-
config.typed_config(), factory_context_.messageValidationVisitor(), common_input_factory);
248-
auto common_input =
249-
common_input_factory.createCommonProtocolInputFactoryCb(*message, factory_context_);
250+
config.typed_config(), proto_validation_visitor_, common_input_factory);
251+
auto common_input = common_input_factory.createCommonProtocolInputFactoryCb(
252+
*message, proto_validation_visitor_);
250253
return
251254
[common_input]() { return std::make_unique<CommonProtocolInputWrapper>(common_input()); };
252255
}
@@ -265,17 +268,17 @@ template <class DataType> class MatchTreeFactory {
265268
auto& factory =
266269
Config::Utility::getAndCheckFactory<InputMatcherFactory>(predicate.custom_match());
267270
ProtobufTypes::MessagePtr message = Config::Utility::translateAnyToFactoryConfig(
268-
predicate.custom_match().typed_config(), factory_context_.messageValidationVisitor(),
269-
factory);
270-
return factory.createInputMatcherFactoryCb(*message, factory_context_);
271+
predicate.custom_match().typed_config(), proto_validation_visitor_, factory);
272+
return factory.createInputMatcherFactoryCb(*message, proto_validation_visitor_);
271273
}
272274
default:
273275
NOT_REACHED_GCOVR_EXCL_LINE;
274276
}
275277
}
276278

277279
const std::string stats_prefix_;
278-
Server::Configuration::FactoryContext& factory_context_;
280+
ActionFactoryContext& action_factory_context_;
281+
ProtobufMessage::ValidationVisitor& proto_validation_visitor_;
279282
MatchTreeValidationVisitor<DataType>& validation_visitor_;
280283
};
281284
} // namespace Matcher

source/extensions/filters/http/composite/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ envoy_cc_library(
1616
srcs = ["action.cc"],
1717
hdrs = ["action.h"],
1818
deps = [
19+
"//source/common/http/matching:data_impl_lib",
1920
"//source/common/matcher:matcher_lib",
2021
"@envoy_api//envoy/extensions/filters/http/composite/v3:pkg_cc_proto",
2122
],

source/extensions/filters/http/composite/action.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ namespace Composite {
77
void ExecuteFilterAction::createFilters(Http::FilterChainFactoryCallbacks& callbacks) const {
88
cb_(callbacks);
99
}
10-
REGISTER_FACTORY(ExecuteFilterActionFactory, Matcher::ActionFactory);
10+
REGISTER_FACTORY(ExecuteFilterActionFactory,
11+
Matcher::ActionFactory<Http::Matching::HttpFilterActionContext>);
1112
} // namespace Composite
1213
} // namespace HttpFilters
1314
} // namespace Extensions

0 commit comments

Comments
 (0)