[pve-devel] [PATCH v3 proxmox 20/66] notify: on deletion, check if a filter/endp. is still used by anything
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Jul 18 15:20:09 CEST 2023
On Mon, Jul 17, 2023 at 05:00:05PM +0200, Lukas Wagner wrote:
> Signed-off-by: Lukas Wagner <l.wagner at proxmox.com>
> ---
> proxmox-notify/src/api/filter.rs | 1 +
> proxmox-notify/src/api/gotify.rs | 1 +
> proxmox-notify/src/api/mod.rs | 113 ++++++++++++++++++++++++++---
> proxmox-notify/src/api/sendmail.rs | 1 +
> 4 files changed, 106 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 d8a44bf2..81c182c7 100644
> --- a/proxmox-notify/src/api/mod.rs
> +++ b/proxmox-notify/src/api/mod.rs
> @@ -102,6 +102,59 @@ 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)? {
> + for endpoint in group.endpoint {
> + if endpoint == entity {
> + referrers.insert(group.name.clone());
We could `break` here, since `group` comes from the outer loop.
Or, in fact, replace the inner for loop with:
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(", ");
*sigh*...
iterators vs join...
Some day this can hopefully be
refererrs
.into_iter()
.map(Cow::Owned)
.intersperse(Cow::Borrowed(", "))
.collect::<String>();
Yeah okay fine, the ergonomics with `String` vs the `&'static str`
aren't great either... exactly as long as the for loop variant, but w/e.
Could also just be
referrers.iter().map(String::as_str).intersperse(", ").collect::<String>();
... Oh well ...
> +
> + 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();
(...)
More information about the pve-devel
mailing list