-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Support ListValue for metadata matcher #3964
Conversation
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
/cc @rodaine |
source/common/common/matchers.cc
Outdated
@@ -78,6 +78,18 @@ bool MetadataMatcher::match(const envoy::api::v2::core::Metadata& metadata) cons | |||
case ProtobufWkt::Value::kBoolValue: | |||
return (bool_matcher_.has_value() && *bool_matcher_ == value.bool_value()); | |||
case ProtobufWkt::Value::kListValue: | |||
for (int i = 0; i < value.list_value().values_size(); ++i) { | |||
const auto& lv = value.list_value().values(i); | |||
if ((double_matcher_.has_value() && lv.kind_case() == ProtobufWkt::Value::kNumberValue && |
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 think you should also check null_matcher_
unless you mention it in the doc that null_matcher_
is not supported in list.
Another Nit: as the matcher is stable so you should be able to decide the expected value and type from the matcher outside the for-loop, and during the for-loop just check if lv
has the value and type. This should make it faster.
@@ -68,8 +68,6 @@ import "validate/validate.proto"; | |||
// <envoy_api_msg_config.rbac.v2alpha.Principal>`. | |||
message MetadataMatcher { | |||
// Specifies the segment in a path to retrieve value from Metadata. | |||
// Note: Currently it's not supported to retrieve a value from a list in Metadata. This means it |
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 think this comment should remain, we still don't support to retrieve a value from a list.
And the comment in line 80 should be updated that it now supports to compare a value to a list, but such comparison only supports primitive values in a list, embedded values in a list are still not supported.
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.
@liminw can we revert the comment?
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 already support list value. The current match method is one_of, as documented in API. I don't think we need the comments here. BTW, list embedded in another list is supported with the new change.
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.
@liminw these comment are still valid for PathSegment
, with this PR it will support matching to a list, doesn't mean we can specify a PathSegment that retrieve a value from a list.
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 modified the origin comment to make it more accurate.
source/common/common/matchers.cc
Outdated
@@ -78,6 +78,18 @@ bool MetadataMatcher::match(const envoy::api::v2::core::Metadata& metadata) cons | |||
case ProtobufWkt::Value::kBoolValue: | |||
return (bool_matcher_.has_value() && *bool_matcher_ == value.bool_value()); | |||
case ProtobufWkt::Value::kListValue: | |||
for (int i = 0; i < value.list_value().values_size(); ++i) { |
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 think we should automatically extend the value matchers to list (and treat it is matched when one of the list element matches to it), can we make a ListMatch
in matcher/metadata.proto, and make this behavior explicitly from the API? In future we may want to do more than oneof match for lists.
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.
+1
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.
Please make the oneof ListMatch explicit in API.
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
@lizan @yangminzhu @mattklein123 I refactored the matcher code. The comments you mentioned should be addressed. PTAL. |
source/common/common/matchers.cc
Outdated
for (int i = 0; i < value.list_value().values_size(); ++i) { | ||
const auto& lv = value.list_value().values(i); | ||
|
||
if (oneof_value_matcher_ && oneof_value_matcher_->match(lv)) { |
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.
You can check oneof_value_matcher_
outside the loop.
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.
Moved if (oneof_value_matcher) to outside the loop.
@@ -68,8 +68,6 @@ import "validate/validate.proto"; | |||
// <envoy_api_msg_config.rbac.v2alpha.Principal>`. | |||
message MetadataMatcher { | |||
// Specifies the segment in a path to retrieve value from Metadata. | |||
// Note: Currently it's not supported to retrieve a value from a list in Metadata. This means it |
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.
@liminw can we revert the comment?
source/common/common/matchers.cc
Outdated
MatcherPtr ValueMatcher::create(const envoy::type::matcher::ValueMatcher& v) { | ||
switch (v.match_pattern_case()) { | ||
case envoy::type::matcher::ValueMatcher::kNullMatch: | ||
return std::make_shared<const NullMatcher>(); |
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 we use unique_ptr here?
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 feel using shared_ptr is safer because a ValueMatcher instance could be referred in multiple places.
default: | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
}; | ||
} | ||
|
||
bool StringMatcher::match(const std::string& value) const { | ||
bool StringMatcher::match(const ProtobufWkt::Value& value) const { |
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.
Previously, the StringMatcher accepts a simple string so it could be used in anywhere with a string value, now it only can be only used with Value? is this expected?
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, match() is a virtual function defined in the parent class ValueMatcher. StringMatcher just implements the overrides here. If in the future, there is a need to use the primitive string as the parameter, we can always add that function.
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
test/common/common/matchers_test.cc
Outdated
@@ -162,6 +162,145 @@ TEST(MetadataTest, MatchPresentValue) { | |||
EXPECT_FALSE(Envoy::Matchers::MetadataMatcher(matcher).match(metadata)); | |||
} | |||
|
|||
TEST(MetadataTest, MatchStringListValue) { | |||
envoy::api::v2::core::Metadata metadata; |
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 make a utility function like this https://github.com/envoyproxy/envoy/blob/master/test/common/http/header_utility_test.cc#L17 and use it to construct those test fixtures from YAML? It is hard to read from the code with multiple mutable_*
.
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.
Added a utility function.
* @return true if it's matched otherwise false. | ||
*/ | ||
bool match(const std::string& value) const; | ||
bool match(const ProtobufWkt::Value& value) const override; |
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.
not remove the comment?
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 think the comments here is needed. It's overriding match() defined in parent class ValueMatcher. If we add the comment back, it would just repeats the one in ValueMatcher class.
source/common/common/matchers.h
Outdated
|
||
namespace Envoy { | ||
namespace Matchers { | ||
|
||
class DoubleMatcher { | ||
class ValueMatcher; | ||
typedef std::shared_ptr<const ValueMatcher> MatcherPtr; |
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.
You should name this ValueMatcherConstSharedPtr
per style guide
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.
Done.
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[email protected]>
@lizan @mattklein123 @yangminzhu All your comments are addressed. Let me know if you have further comments. Thanks. |
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.
seems the docs CI is failed, can you take a look?
source/common/common/matchers.cc
Outdated
} | ||
|
||
if (oneof_value_matcher_) { | ||
for (int i = 0; i < value.list_value().values_size(); ++i) { |
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.
doesn't for (const auto& lv : value.list_value().values())
work?
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.
Changed to what you suggested.
@@ -68,8 +68,6 @@ import "validate/validate.proto"; | |||
// <envoy_api_msg_config.rbac.v2alpha.Principal>`. | |||
message MetadataMatcher { | |||
// Specifies the segment in a path to retrieve value from Metadata. | |||
// Note: Currently it's not supported to retrieve a value from a list in Metadata. This means it |
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.
@liminw these comment are still valid for PathSegment
, with this PR it will support matching to a list, doesn't mean we can specify a PathSegment that retrieve a value from a list.
Signed-off-by: Limin Wang <[email protected]>
Signed-off-by: Limin Wang <[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! one comment left for other reviewers.
|
||
// Specifies the way to match a ProtobufWkt::Value. Primitive values and ListValue are supported. | ||
// StructValue is not supported and is always not matched. | ||
message ValueMatcher { |
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.
Although the diff looks a bit scary, IIUC this refactoring out Value
-> ValueMatcher
shouldn't break backward compatibility of those protos, right?
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 from my eye LGTM, but would like if @htuch could double check.
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, some small nits. Thank you!
source/common/common/matchers.cc
Outdated
return false; | ||
} | ||
|
||
double v = value.number_value(); |
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.
nit: const
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.
Done.
source/common/common/matchers.cc
Outdated
default: | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
} | ||
} | ||
|
||
ListMatcher::ListMatcher(const envoy::type::matcher::ListMatcher& matcher) : matcher_(matcher) { | ||
if (matcher_.match_pattern_case() != envoy::type::matcher::ListMatcher::kOneOf) { |
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.
nit: This should just be an 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.
Done.
source/common/common/matchers.cc
Outdated
NOT_REACHED_GCOVR_EXCL_LINE; | ||
} | ||
|
||
const auto& oneof = matcher_.one_of(); |
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.
nit: local var not needed
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.
Done.
source/common/common/matchers.h
Outdated
|
||
class NullMatcher : public ValueMatcher { | ||
public: | ||
NullMatcher() {} |
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.
nit: not needed
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.
Done.
source/common/common/matchers.h
Outdated
bool match(const ProtobufWkt::Value& value) const override; | ||
|
||
private: | ||
bool matcher_; |
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.
nit: const
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.
Done.
source/common/common/matchers.h
Outdated
bool match(const ProtobufWkt::Value& value) const override; | ||
|
||
private: | ||
bool matcher_; |
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.
nit: const
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.
Done.
Signed-off-by: Limin Wang <[email protected]>
Thanks @mattklein123! All comments are addressed. |
Description: This change added support for ListValue type in MetadataMatcher.
Risk Level: Low
Testing: Added unit tests.
Docs Changes: N/A.
Release Notes: N/A.