[pve-devel] [PATCH v4 proxmox 22/69] notify: on deletion, check if a filter/endp. is still used by anything

Lukas Wagner l.wagner at proxmox.com
Thu Jul 20 16:31:49 CEST 2023


Signed-off-by: Lukas Wagner <l.wagner at proxmox.com>
---

Notes:
    Changes since v3:
        - get_referrers: minor stylistic touchups

 proxmox-notify/src/api/filter.rs   |   1 +
 proxmox-notify/src/api/gotify.rs   |   1 +
 proxmox-notify/src/api/mod.rs      | 111 ++++++++++++++++++++++++++---
 proxmox-notify/src/api/sendmail.rs |   1 +
 4 files changed, 104 insertions(+), 10 deletions(-)

diff --git a/proxmox-notify/src/api/filter.rs b/proxmox-notify/src/api/filter.rs
index 3fcff6b9..824f802d 100644
--- a/proxmox-notify/src/api/filter.rs
+++ b/proxmox-notify/src/api/filter.rs
@@ -115,6 +115,7 @@ pub fn update_filter(
 pub fn delete_filter(config: &mut Config, name: &str) -> Result<(), ApiError> {
     // Check if the filter exists
     let _ = get_filter(config, name)?;
+    super::ensure_unused(config, name)?;
 
     config.config.sections.remove(name);
 
diff --git a/proxmox-notify/src/api/gotify.rs b/proxmox-notify/src/api/gotify.rs
index d6f33064..5c4db4be 100644
--- a/proxmox-notify/src/api/gotify.rs
+++ b/proxmox-notify/src/api/gotify.rs
@@ -145,6 +145,7 @@ pub fn update_endpoint(
 pub fn delete_gotify_endpoint(config: &mut Config, name: &str) -> Result<(), ApiError> {
     // Check if the endpoint exists
     let _ = get_endpoint(config, name)?;
+    super::ensure_unused(config, name)?;
 
     remove_private_config_entry(config, name)?;
     config.config.sections.remove(name);
diff --git a/proxmox-notify/src/api/mod.rs b/proxmox-notify/src/api/mod.rs
index 1d9aaca7..e064b607 100644
--- a/proxmox-notify/src/api/mod.rs
+++ b/proxmox-notify/src/api/mod.rs
@@ -102,6 +102,57 @@ fn endpoint_exists(config: &Config, name: &str) -> bool {
     exists
 }
 
+fn get_referrers(config: &Config, entity: &str) -> Result<HashSet<String>, ApiError> {
+    let mut referrers = HashSet::new();
+
+    for group in group::get_groups(config)? {
+        if group.endpoint.iter().any(|endpoint| endpoint == entity) {
+            referrers.insert(group.name.clone());
+        }
+
+        if let Some(filter) = group.filter {
+            if filter == entity {
+                referrers.insert(group.name);
+            }
+        }
+    }
+
+    #[cfg(feature = "sendmail")]
+    for endpoint in sendmail::get_endpoints(config)? {
+        if let Some(filter) = endpoint.filter {
+            if filter == entity {
+                referrers.insert(endpoint.name);
+            }
+        }
+    }
+
+    #[cfg(feature = "gotify")]
+    for endpoint in gotify::get_endpoints(config)? {
+        if let Some(filter) = endpoint.filter {
+            if filter == entity {
+                referrers.insert(endpoint.name);
+            }
+        }
+    }
+
+    Ok(referrers)
+}
+
+fn ensure_unused(config: &Config, entity: &str) -> Result<(), ApiError> {
+    let referrers = get_referrers(config, entity)?;
+
+    if !referrers.is_empty() {
+        let used_by = referrers.into_iter().collect::<Vec<_>>().join(", ");
+
+        return Err(ApiError::bad_request(
+            format!("cannot delete '{entity}', referenced by: {used_by}"),
+            None,
+        ));
+    }
+
+    Ok(())
+}
+
 fn get_referenced_entities(config: &Config, entity: &str) -> HashSet<String> {
     let mut to_expand = HashSet::new();
     let mut expanded = HashSet::new();
@@ -161,8 +212,7 @@ mod tests {
     use crate::filter::FilterConfig;
     use crate::group::GroupConfig;
 
-    #[test]
-    fn test_get_referenced_entities() {
+    fn prepare_config() -> Result<Config, ApiError> {
         let mut config = super::test_helpers::empty_config();
 
         filter::add_filter(
@@ -171,8 +221,7 @@ mod tests {
                 name: "filter".to_string(),
                 ..Default::default()
             },
-        )
-        .unwrap();
+        )?;
 
         sendmail::add_endpoint(
             &mut config,
@@ -182,8 +231,7 @@ mod tests {
                 filter: Some("filter".to_string()),
                 ..Default::default()
             },
-        )
-        .unwrap();
+        )?;
 
         gotify::add_endpoint(
             &mut config,
@@ -197,8 +245,7 @@ mod tests {
                 name: "gotify".to_string(),
                 token: "foo".to_string(),
             },
-        )
-        .unwrap();
+        )?;
 
         group::add_group(
             &mut config,
@@ -208,8 +255,14 @@ mod tests {
                 filter: Some("filter".to_string()),
                 ..Default::default()
             },
-        )
-        .unwrap();
+        )?;
+
+        Ok(config)
+    }
+
+    #[test]
+    fn test_get_referenced_entities() {
+        let config = prepare_config().unwrap();
 
         assert_eq!(
             get_referenced_entities(&config, "filter"),
@@ -233,4 +286,42 @@ mod tests {
             ])
         );
     }
+
+    #[test]
+    fn test_get_referrers_for_entity() -> Result<(), ApiError> {
+        let config = prepare_config().unwrap();
+
+        assert_eq!(
+            get_referrers(&config, "filter")?,
+            HashSet::from([
+                "gotify".to_string(),
+                "sendmail".to_string(),
+                "group".to_string()
+            ])
+        );
+
+        assert_eq!(
+            get_referrers(&config, "sendmail")?,
+            HashSet::from(["group".to_string()])
+        );
+
+        assert_eq!(
+            get_referrers(&config, "gotify")?,
+            HashSet::from(["group".to_string()])
+        );
+
+        assert!(get_referrers(&config, "group")?.is_empty(),);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_ensure_unused() {
+        let config = prepare_config().unwrap();
+
+        assert!(ensure_unused(&config, "filter").is_err());
+        assert!(ensure_unused(&config, "gotify").is_err());
+        assert!(ensure_unused(&config, "sendmail").is_err());
+        assert!(ensure_unused(&config, "group").is_ok());
+    }
 }
diff --git a/proxmox-notify/src/api/sendmail.rs b/proxmox-notify/src/api/sendmail.rs
index 070ed6e7..bf225f29 100644
--- a/proxmox-notify/src/api/sendmail.rs
+++ b/proxmox-notify/src/api/sendmail.rs
@@ -147,6 +147,7 @@ pub fn update_endpoint(
 pub fn delete_endpoint(config: &mut Config, name: &str) -> Result<(), ApiError> {
     // Check if the endpoint exists
     let _ = get_endpoint(config, name)?;
+    super::ensure_unused(config, name)?;
 
     config.config.sections.remove(name);
 
-- 
2.39.2






More information about the pve-devel mailing list