From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id EB2421FF0E0 for ; Thu, 09 Jul 2026 13:59:35 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 35B4F216BA; Thu, 09 Jul 2026 13:58:04 +0200 (CEST) From: Lukas Wagner To: pbs-devel@lists.proxmox.com, pve-devel@lists.proxmox.com Subject: [PATCH proxmox 08/29] notify: matcher: add InlineSeverityMatcher Date: Thu, 9 Jul 2026 13:56:55 +0200 Message-ID: <20260709115716.299836-9-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260709115716.299836-1-l.wagner@proxmox.com> References: <20260709115716.299836-1-l.wagner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1783598238472 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.000 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: NGMMSAHR6XPNA4RJBANF7WUP7KXGMTOO X-Message-ID-Hash: NGMMSAHR6XPNA4RJBANF7WUP7KXGMTOO X-MailFrom: l.wagner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This move the inline serialization format into a new-type wrapper around SeverityMatcher. This allows us to keep the existing single-line serialization format for the old configuration keys (match-calendar), while deriving a regular Serializer for SeverityMatcher that will be used in the new expression based matcher. Signed-off-by: Lukas Wagner --- proxmox-notify/src/matcher/mod.rs | 4 +-- proxmox-notify/src/matcher/severity.rs | 41 ++++++++++++++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/proxmox-notify/src/matcher/mod.rs b/proxmox-notify/src/matcher/mod.rs index 8c9e5505..bf2efceb 100644 --- a/proxmox-notify/src/matcher/mod.rs +++ b/proxmox-notify/src/matcher/mod.rs @@ -16,7 +16,7 @@ pub mod severity; use calendar::CalendarMatcher; use field::FieldMatcher; -use severity::SeverityMatcher; +use severity::InlineSeverityMatcher; pub const MATCHER_TYPENAME: &str = "matcher"; @@ -107,7 +107,7 @@ pub struct MatcherConfig { /// List of matched severity levels. #[serde(default, skip_serializing_if = "Vec::is_empty")] #[updater(serde(skip_serializing_if = "Option::is_none"))] - pub match_severity: Vec, + pub match_severity: Vec, /// List of matched severity levels. #[serde(default, skip_serializing_if = "Vec::is_empty")] diff --git a/proxmox-notify/src/matcher/severity.rs b/proxmox-notify/src/matcher/severity.rs index 4b126d85..e12f2260 100644 --- a/proxmox-notify/src/matcher/severity.rs +++ b/proxmox-notify/src/matcher/severity.rs @@ -11,7 +11,6 @@ pub struct SeverityMatcher { severities: Vec, } -/// Common trait implemented by all matching directives impl MatchDirective for SeverityMatcher { /// Check if this directive matches a given notification fn matches(&self, notification: &Notification) -> Result { @@ -19,14 +18,29 @@ impl MatchDirective for SeverityMatcher { } } -impl fmt::Display for SeverityMatcher { +/// Match severity of the notification. +/// +/// This is a wrapper that serializes into an inline format that can be used +/// in a section config key-value pair. +#[derive(Clone, Debug)] +pub struct InlineSeverityMatcher(SeverityMatcher); + +/// Common trait implemented by all matching directives +impl MatchDirective for InlineSeverityMatcher { + /// Check if this directive matches a given notification + fn matches(&self, notification: &Notification) -> Result { + self.0.matches(notification) + } +} + +impl fmt::Display for InlineSeverityMatcher { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let severities: Vec = self.severities.iter().map(|s| format!("{s}")).collect(); + let severities: Vec = self.0.severities.iter().map(|s| format!("{s}")).collect(); f.write_str(&severities.join(",")) } } -impl FromStr for SeverityMatcher { +impl FromStr for InlineSeverityMatcher { type Err = Error; fn from_str(s: &str) -> Result { @@ -39,28 +53,31 @@ impl FromStr for SeverityMatcher { severities.push(severity) } - Ok(Self { severities }) + Ok(Self(SeverityMatcher { severities })) } } -proxmox_serde::forward_deserialize_to_from_str!(SeverityMatcher); -proxmox_serde::forward_serialize_to_display!(SeverityMatcher); +impl InlineSeverityMatcher { + pub fn into_inner(self) -> SeverityMatcher { + self.0 + } +} + +proxmox_serde::forward_deserialize_to_from_str!(InlineSeverityMatcher); +proxmox_serde::forward_serialize_to_display!(InlineSeverityMatcher); #[cfg(test)] mod test { use serde_json::Value; - use crate::{ - Notification, Severity, - matcher::{MatchDirective as _, severity::SeverityMatcher}, - }; + use super::*; #[test] fn test_severities() { let notification = Notification::from_template(Severity::Notice, "test", Value::Null, Default::default()); - let matcher: SeverityMatcher = "info,notice,warning,error".parse().unwrap(); + let matcher: InlineSeverityMatcher = "info,notice,warning,error".parse().unwrap(); assert!(matcher.matches(¬ification).unwrap()); } } -- 2.47.3