notify: matcher: support lists of values for 'exact' match-field mode

For example, one can now use:
  match-field exact:type=vzdump,replication
to match on vzdump AND replication events.

Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
This commit is contained in:
Lukas Wagner 2023-12-13 17:37:42 +01:00 committed by Wolfgang Bumiller
parent 39c4d7d85e
commit ead4190e7b

View File

@ -160,7 +160,7 @@ trait MatchDirective {
pub enum FieldMatcher { pub enum FieldMatcher {
Exact { Exact {
field: String, field: String,
matched_value: String, matched_values: Vec<String>,
}, },
Regex { Regex {
field: String, field: String,
@ -176,12 +176,12 @@ impl MatchDirective for FieldMatcher {
Ok(match self { Ok(match self {
FieldMatcher::Exact { FieldMatcher::Exact {
field, field,
matched_value, matched_values,
} => { } => {
let value = notification.metadata.additional_fields.get(field); let value = notification.metadata.additional_fields.get(field);
if let Some(value) = value { if let Some(value) = value {
matched_value == value matched_values.contains(value)
} else { } else {
// Metadata field does not exist, so we do not match // Metadata field does not exist, so we do not match
false false
@ -212,9 +212,10 @@ impl fmt::Display for FieldMatcher {
match self { match self {
FieldMatcher::Exact { FieldMatcher::Exact {
field, field,
matched_value, matched_values,
} => { } => {
write!(f, "exact:{field}={matched_value}") let values = matched_values.join(",");
write!(f, "exact:{field}={values}")
} }
FieldMatcher::Regex { FieldMatcher::Regex {
field, field,
@ -256,10 +257,17 @@ impl FromStr for FieldMatcher {
None => Err(Error::FilterFailed(format!( None => Err(Error::FilterFailed(format!(
"invalid match-field statement: {s}" "invalid match-field statement: {s}"
))), ))),
Some((field, expected_value)) => Ok(Self::Exact { Some((field, expected_values)) => {
field: field.into(), let values: Vec<String> = expected_values
matched_value: expected_value.into(), .split(',')
}), .map(str::trim)
.map(String::from)
.collect();
Ok(Self::Exact {
field: field.into(),
matched_values: values,
})
}
} }
} else { } else {
Err(Error::FilterFailed(format!( Err(Error::FilterFailed(format!(
@ -460,6 +468,23 @@ mod tests {
let matcher: FieldMatcher = "regex:notthere=b.*".parse().unwrap(); let matcher: FieldMatcher = "regex:notthere=b.*".parse().unwrap();
assert!(!matcher.matches(&notification).unwrap()); assert!(!matcher.matches(&notification).unwrap());
let matcher: FieldMatcher = "exact:foo=bar,test".parse().unwrap();
assert!(matcher.matches(&notification).unwrap());
let mut fields = HashMap::new();
fields.insert("foo".into(), "test".into());
let notification =
Notification::new_templated(Severity::Notice, "test", "test", Value::Null, fields);
assert!(matcher.matches(&notification).unwrap());
let mut fields = HashMap::new();
fields.insert("foo".into(), "notthere".into());
let notification =
Notification::new_templated(Severity::Notice, "test", "test", Value::Null, fields);
assert!(!matcher.matches(&notification).unwrap());
assert!("regex:'3=b.*".parse::<FieldMatcher>().is_err()); assert!("regex:'3=b.*".parse::<FieldMatcher>().is_err());
assert!("invalid:'bar=b.*".parse::<FieldMatcher>().is_err()); assert!("invalid:'bar=b.*".parse::<FieldMatcher>().is_err());
} }