From: Pritha Srivastava Date: Sat, 5 Jun 2021 15:42:02 +0000 (+0530) Subject: rgw/sts: code changes to store multi-valued tags X-Git-Tag: v16.2.11~244^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f935c5d2d2c5895f337bde3e4b73691570638ed2;p=ceph.git rgw/sts: code changes to store multi-valued tags for objects and buckets (to be used as s3:ResourceTags in Identity and Resource policies). Test code changes as suggested by Yuval Lifshitz. Signed-off-by: Pritha Srivastava (cherry picked from commit b682db4f6cf9aba4b09d8b323a6593c65c20eff1) --- diff --git a/src/rgw/rgw_notify.cc b/src/rgw/rgw_notify.cc index 31e2034d5d5..8d86b493bd3 100644 --- a/src/rgw/rgw_notify.cc +++ b/src/rgw/rgw_notify.cc @@ -646,7 +646,7 @@ void metadata_from_attributes(const req_state* s, rgw::sal::RGWObject* obj, KeyV } } -void tags_from_attributes(const req_state* s, rgw::sal::RGWObject* obj, KeyValueMap& tags) { +void tags_from_attributes(const req_state* s, rgw::sal::RGWObject* obj, KeyMultiValueMap& tags) { const auto src_obj = get_object_with_atttributes(s, obj); if (!src_obj) { return; @@ -747,7 +747,7 @@ bool notification_match(reservation_t& res, const rgw_pubsub_topic_filter& filte } } else { // try to fetch tags from the attributes - KeyValueMap tags; + KeyMultiValueMap tags; tags_from_attributes(s, obj, tags); if (!match(filter.s3_filter.tag_filter, tags)) { return false; diff --git a/src/rgw/rgw_pubsub.cc b/src/rgw/rgw_pubsub.cc index 17d9ae221f6..8a6341e6e98 100644 --- a/src/rgw/rgw_pubsub.cc +++ b/src/rgw/rgw_pubsub.cc @@ -172,6 +172,19 @@ bool match(const rgw_s3_key_value_filter& filter, const KeyValueMap& kv) { return std::includes(kv.begin(), kv.end(), filter.kv.begin(), filter.kv.end()); } +bool match(const rgw_s3_key_value_filter& filter, const KeyMultiValueMap& kv) { + // all filter pairs must exist with the same value in the object's metadata/tags + // object metadata/tags may include items not in the filter + for (auto& filter : filter.kv) { + auto result = kv.equal_range(filter.first); + if (std::any_of(result.first, result.second, [&filter](const pair& p) { return p.second == filter.second;})) + continue; + else + return false; + } + return true; +} + bool match(const rgw::notify::EventTypeList& events, rgw::notify::EventType event) { // if event list exists, and none of the events in the list matches the event type, filter the message if (!events.empty() && std::find(events.begin(), events.end(), event) == events.end()) { diff --git a/src/rgw/rgw_pubsub.h b/src/rgw/rgw_pubsub.h index 958fb9ce2e2..096ff3ea626 100644 --- a/src/rgw/rgw_pubsub.h +++ b/src/rgw/rgw_pubsub.h @@ -42,6 +42,7 @@ struct rgw_s3_key_filter { WRITE_CLASS_ENCODER(rgw_s3_key_filter) using KeyValueMap = boost::container::flat_map; +using KeyMultiValueMap = std::multimap; struct rgw_s3_key_value_filter { KeyValueMap kv; @@ -148,8 +149,13 @@ struct rgw_pubsub_s3_notification { // return true if the key matches the prefix/suffix/regex rules of the key filter bool match(const rgw_s3_key_filter& filter, const std::string& key); -// return true if the key matches the metadata/tags rules of the metadata/tags filter + +// return true if the key matches the metadata rules of the metadata filter bool match(const rgw_s3_key_value_filter& filter, const KeyValueMap& kv); + +// return true if the key matches the tag rules of the tag filter +bool match(const rgw_s3_key_value_filter& filter, const KeyMultiValueMap& kv); + // return true if the event type matches (equal or contained in) one of the events in the list bool match(const rgw::notify::EventTypeList& events, rgw::notify::EventType event); @@ -252,7 +258,7 @@ struct rgw_pubsub_s3_event { // meta data KeyValueMap x_meta_map; // tags - KeyValueMap tags; + KeyMultiValueMap tags; // opaque data received from the topic // could be used to identify the gateway std::string opaque_data; diff --git a/src/rgw/rgw_tag.cc b/src/rgw/rgw_tag.cc index f43a1824868..e60a265e738 100644 --- a/src/rgw/rgw_tag.cc +++ b/src/rgw/rgw_tag.cc @@ -10,12 +10,12 @@ #include "rgw_tag.h" #include "rgw_common.h" -bool RGWObjTags::add_tag(const string&key, const string& val){ - return tag_map.emplace(std::make_pair(key,val)).second; +void RGWObjTags::add_tag(const string& key, const string& val){ + tag_map.emplace(std::make_pair(key,val)); } -bool RGWObjTags::emplace_tag(std::string&& key, std::string&& val){ - return tag_map.emplace(std::move(key), std::move(val)).second; +void RGWObjTags::emplace_tag(std::string&& key, std::string&& val){ + tag_map.emplace(std::move(key), std::move(val)); } int RGWObjTags::check_and_add_tag(const string&key, const string& val){ @@ -26,10 +26,7 @@ int RGWObjTags::check_and_add_tag(const string&key, const string& val){ return -ERR_INVALID_TAG; } - // if we get a conflicting key, either the XML is malformed or the user - // supplied an invalid string - if (!add_tag(key,val)) - return -EINVAL; + add_tag(key,val); return 0; } diff --git a/src/rgw/rgw_tag.h b/src/rgw/rgw_tag.h index e8531031dbf..88a4e665228 100644 --- a/src/rgw/rgw_tag.h +++ b/src/rgw/rgw_tag.h @@ -6,12 +6,12 @@ #include #include -#include +#include class RGWObjTags { public: - using tag_map_t = boost::container::flat_map ; + using tag_map_t = std::multimap ; protected: tag_map_t tag_map; @@ -37,8 +37,8 @@ protected: } void dump(Formatter *f) const; - bool add_tag(const std::string& key, const std::string& val=""); - bool emplace_tag(std::string&& key, std::string&& val); + void add_tag(const std::string& key, const std::string& val=""); + void emplace_tag(std::string&& key, std::string&& val); int check_and_add_tag(const std::string& key, const std::string& val=""); size_t count() const {return tag_map.size();} int set_from_string(const std::string& input); diff --git a/src/rgw/rgw_tag_s3.cc b/src/rgw/rgw_tag_s3.cc index b03607f73a7..2c352c59203 100644 --- a/src/rgw/rgw_tag_s3.cc +++ b/src/rgw/rgw_tag_s3.cc @@ -35,9 +35,7 @@ void RGWObjTagSet_S3::decode_xml(XMLObj *obj) { for (auto& entry : entries) { const std::string& key = entry.get_key(); const std::string& val = entry.get_val(); - if (!add_tag(key,val)) { - throw RGWXMLDecoder::err("failed to add tag"); - } + add_tag(key,val); } }