-
Notifications
You must be signed in to change notification settings - Fork 24
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
Using stackrox/storage/ResourceCollection #1622
Changes from all commits
a7489fc
faa22e7
0fb715e
ec6737a
08637af
a5aeffb
84f7055
1edd8df
77f752b
1344b40
287a194
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 | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,133 @@ | ||||||||
// | ||||||||
// Created by Robby Cochran on 3/28/24. | ||||||||
// | ||||||||
|
||||||||
#include "ResourceSelector.h" | ||||||||
|
||||||||
#include <regex> | ||||||||
|
||||||||
#include "Hash.h" | ||||||||
|
||||||||
namespace collector { | ||||||||
|
||||||||
UnorderedMap<std::string, std::regex> ResourceSelector::regexMap_; | ||||||||
|
||||||||
std::regex ResourceSelector::GetOrCompileRegex(const std::string& str) { | ||||||||
auto pair = regexMap_.find(str); | ||||||||
if (pair != regexMap_.end()) { | ||||||||
return pair->second; | ||||||||
} else { | ||||||||
std::regex pattern(str); | ||||||||
regexMap_[str] = pattern; | ||||||||
return pattern; | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsRuleValueFollowed(const storage::RuleValue& value, const std::string& resource_name) { | ||||||||
if (value.match_type() == storage::REGEX) { | ||||||||
std::regex pattern = GetOrCompileRegex(value.value()); | ||||||||
return std::regex_match(resource_name, pattern); | ||||||||
} else { | ||||||||
return (resource_name == value.value()); | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsRuleFollowed(const storage::SelectorRule& rule, const std::string& resource_name) { | ||||||||
const auto& values = rule.values(); | ||||||||
|
||||||||
if (values.size() == 0) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
auto op = [resource_name](const auto& value) -> bool { | ||||||||
return IsRuleValueFollowed(value, resource_name); | ||||||||
}; | ||||||||
|
||||||||
if (rule.operator_() == storage::BooleanOperator::OR) { | ||||||||
return std::any_of(values.begin(), values.end(), op); | ||||||||
} else if (rule.operator_() == storage::BooleanOperator::AND) { | ||||||||
return std::all_of(values.begin(), values.end(), op); | ||||||||
} | ||||||||
|
||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsResourceInResourceSelector(const storage::ResourceSelector& rs, const std::string& resource_type, const std::string& resource_name) { | ||||||||
const auto& rules = rs.rules(); | ||||||||
|
||||||||
if (rules.size() == 0) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
return std::all_of(rules.begin(), rules.end(), [resource_type, resource_name](const auto& rule) -> bool { | ||||||||
return rule.field_name() != resource_type || IsRuleFollowed(rule, resource_name); | ||||||||
}); | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsNamespaceInResourceSelector(const storage::ResourceSelector& rs, const std::string& ns) { | ||||||||
return IsResourceInResourceSelector(rs, "Namespace", ns); | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsClusterInResourceSelector(const storage::ResourceSelector& rs, const std::string& cluster) { | ||||||||
return IsResourceInResourceSelector(rs, "Cluster", cluster); | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::IsNamespaceSelected(const storage::ResourceCollection& rc, const std::string& ns) { | ||||||||
const auto& resource_selectors = rc.resource_selectors(); | ||||||||
|
||||||||
if (resource_selectors.size() == 0) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
return std::any_of(resource_selectors.begin(), resource_selectors.end(), [ns](const auto& rs) -> bool { | ||||||||
return IsNamespaceInResourceSelector(rs, ns); | ||||||||
}); | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::AreClusterAndNamespaceSelected(const storage::ResourceCollection& rc, const std::string& cluster, const std::string& ns) { | ||||||||
const auto& resource_selectors = rc.resource_selectors(); | ||||||||
|
||||||||
if (resource_selectors.size() == 0) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
return std::any_of(resource_selectors.begin(), resource_selectors.end(), [cluster, ns](const auto& rs) -> bool { | ||||||||
return IsClusterInResourceSelector(rs, cluster) && IsNamespaceInResourceSelector(rs, ns); | ||||||||
}); | ||||||||
} | ||||||||
|
||||||||
bool ResourceSelector::AreClusterAndNamespaceSelected(const storage::ResourceCollection& rc, const UnorderedMap<std::string, storage::ResourceCollection> rcMap, const std::string& cluster, const std::string& ns) { | ||||||||
if (AreClusterAndNamespaceSelected(rc, cluster, ns)) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
for (const auto& embeddedCollection : rc.embedded_collections()) { | ||||||||
auto embeddedRc = rcMap.find(embeddedCollection.id()); | ||||||||
if (embeddedRc != rcMap.end()) { | ||||||||
bool inEmbeddedRc = AreClusterAndNamespaceSelected(embeddedRc->second, rcMap, cluster, ns); | ||||||||
if (inEmbeddedRc) { | ||||||||
Comment on lines
+107
to
+108
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.
Suggested change
|
||||||||
return true; | ||||||||
} | ||||||||
} | ||||||||
} | ||||||||
return false; | ||||||||
Comment on lines
+104
to
+113
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. Can this be |
||||||||
} | ||||||||
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. Possible improvements to this function include checks for cycles and stopping at a maximum depth. |
||||||||
|
||||||||
// Applies multiple rules for ResourceCollections. Starts with a default status and applies the rules one by one. | ||||||||
// If a cluster/namespace is in a collection the status becomes the status for that collection. | ||||||||
bool ResourceSelector::IsFeatureEnabledForClusterAndNamespace(const std::vector<FilteringRule>& filteringRules, const UnorderedMap<std::string, storage::ResourceCollection> rcMap, bool defaultStatus, const std::string& cluster, const std::string& ns) { | ||||||||
bool status = defaultStatus; | ||||||||
|
||||||||
for (auto filteringRule : filteringRules) { | ||||||||
auto rc = rcMap.find(filteringRule.collectionId()); | ||||||||
if (rc != rcMap.end()) { | ||||||||
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. Need to decide what to do if the key is not in the map. |
||||||||
if (AreClusterAndNamespaceSelected(rc->second, rcMap, cluster, ns)) { | ||||||||
status = filteringRule.status(); | ||||||||
} | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
return status; | ||||||||
} | ||||||||
|
||||||||
} // namespace collector |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// Created by Robby Cochran on 3/28/24. | ||
// | ||
|
||
#ifndef RESOURCESELECTOR_H | ||
#define RESOURCESELECTOR_H | ||
#include <regex> | ||
#include <string> | ||
|
||
#include "storage/resource_collection.pb.h" | ||
|
||
#include "Hash.h" | ||
|
||
namespace collector { | ||
|
||
class FilteringRule { | ||
public: | ||
FilteringRule(std::string collectionId, bool status) { | ||
collectionId_ = collectionId; | ||
status_ = status; | ||
} | ||
|
||
std::string collectionId() { | ||
return collectionId_; | ||
} | ||
|
||
bool status() { | ||
return status_; | ||
} | ||
|
||
private: | ||
std::string collectionId_; | ||
bool status_; | ||
}; | ||
|
||
class ResourceSelector { | ||
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. The use of a class here feels a little redundant since everything is static anyway. A namespace might be a better fit |
||
public: | ||
static bool IsNamespaceSelected(const storage::ResourceCollection& rc, const std::string& ns); | ||
static bool AreClusterAndNamespaceSelected(const storage::ResourceCollection& rc, const std::string& cluster, const std::string& ns); | ||
static bool AreClusterAndNamespaceSelected(const storage::ResourceCollection& rc, const UnorderedMap<std::string, storage::ResourceCollection> rcMap, const std::string& cluster, const std::string& ns); | ||
static bool IsFeatureEnabledForClusterAndNamespace(const std::vector<FilteringRule>& filteringRules, const UnorderedMap<std::string, storage::ResourceCollection> rcMap, bool defaultStatus, const std::string& cluster, const std::string& ns); | ||
|
||
private: | ||
static bool IsRuleFollowed(const storage::SelectorRule& rule, const std::string& ns); | ||
static bool IsRuleValueFollowed(const storage::RuleValue& value, const std::string& ns); | ||
Comment on lines
+44
to
+45
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. Could also use overloading here and call both functions |
||
static bool IsResourceInResourceSelector(const storage::ResourceSelector& rs, const std::string& resource_type, const std::string& resource_name); | ||
Molter73 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static bool IsNamespaceInResourceSelector(const storage::ResourceSelector& rs, const std::string& ns); | ||
static bool IsClusterInResourceSelector(const storage::ResourceSelector& rs, const std::string& cluster); | ||
Comment on lines
+46
to
+48
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. [nit] these are pretty verbose and the type name suffix is unnecessary - perhaps |
||
static std::regex GetOrCompileRegex(const std::string& str); | ||
|
||
static UnorderedMap<std::string, std::regex> regexMap_; | ||
}; | ||
|
||
} // namespace collector | ||
|
||
#endif // RESOURCESELECTOR_H |
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.
One alternative could be to have a function that strips out all of the ResourceSelectors where the cluster does not match collector's cluster.