From ec6295abe253ded5caf3a611e91f50c084635cb2 Mon Sep 17 00:00:00 2001 From: Artem Goncharov Date: Tue, 23 Sep 2025 11:56:02 +0200 Subject: [PATCH] feat: Enable security group rule deletion Implement deletion of the selected security group rule in the TUI. --- openstack_tui/.config/config.yaml | 3 ++ openstack_tui/src/action.rs | 2 + .../src/components/identity/users.rs | 5 +- openstack_tui/src/components/image/images.rs | 13 +++++ .../network/security_group_rules.rs | 48 ++++++++++++++++++- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/openstack_tui/.config/config.yaml b/openstack_tui/.config/config.yaml index f250786ed..3695f1046 100644 --- a/openstack_tui/.config/config.yaml +++ b/openstack_tui/.config/config.yaml @@ -240,6 +240,9 @@ mode_keybindings: SetNetworkSecurityGroupRuleListFilters: {} description: All type: Filter + "ctrl-d": + action: DeleteNetworkSecurityGroupRule + description: Delete # Global keybindings # : # action: diff --git a/openstack_tui/src/action.rs b/openstack_tui/src/action.rs index 8f8b4b514..39ddb775f 100644 --- a/openstack_tui/src/action.rs +++ b/openstack_tui/src/action.rs @@ -183,6 +183,8 @@ pub enum Action { SetNetworkSecurityGroupListFilters(cloud_types::NetworkSecurityGroupList), /// Switch to NetworkSecurityGroupRules ShowNetworkSecurityGroupRules, + /// Delete the security group rule. + DeleteNetworkSecurityGroupRule, /// Switch to routers view ShowNetworkRouters, /// Set Security group rule filters diff --git a/openstack_tui/src/components/identity/users.rs b/openstack_tui/src/components/identity/users.rs index 79a1814b9..b3670f73f 100644 --- a/openstack_tui/src/components/identity/users.rs +++ b/openstack_tui/src/components/identity/users.rs @@ -185,9 +185,8 @@ impl Component for IdentityUsers<'_> { self.sync_table_data()?; } self.set_loading(false); - } else if let IdentityUserApiRequest::Delete(del) = *req - && let IdentityUserDelete { id, .. } = *del - { + } else if let IdentityUserApiRequest::Delete(del) = *req { + let IdentityUserDelete { id, .. } = *del; if self.delete_item_row_by_res_id_mut(&id)?.is_none() { return Ok(Some(Action::Refresh)); } diff --git a/openstack_tui/src/components/image/images.rs b/openstack_tui/src/components/image/images.rs index c68d62802..beef37d84 100644 --- a/openstack_tui/src/components/image/images.rs +++ b/openstack_tui/src/components/image/images.rs @@ -102,6 +102,19 @@ impl Component for Images<'_> { self.set_data(data)?; } } + Action::ApiResponseData { + request: ApiRequest::Image(ImageApiRequest::Image(req)), + .. + } => { + if let ImageImageApiRequest::Delete(del) = *req { + let ImageImageDelete { ref id, .. } = *del; + if self.delete_item_row_by_res_id_mut(&id)?.is_none() { + return Ok(Some(Action::Refresh)); + } + self.sync_table_data()?; + self.set_loading(false); + } + } Action::SetImageListFilters(filters) => { self.set_filters(filters); self.set_loading(true); diff --git a/openstack_tui/src/components/network/security_group_rules.rs b/openstack_tui/src/components/network/security_group_rules.rs index 9e7b22d03..e1a14feb4 100644 --- a/openstack_tui/src/components/network/security_group_rules.rs +++ b/openstack_tui/src/components/network/security_group_rules.rs @@ -13,7 +13,7 @@ // SPDX-License-Identifier: Apache-2.0 use crossterm::event::KeyEvent; -use eyre::Result; +use eyre::{Result, WrapErr}; use ratatui::prelude::*; use tokio::sync::mpsc::UnboundedSender; @@ -22,7 +22,9 @@ use openstack_types::network::v2::security_group_rule::response::list::SecurityG use crate::{ action::Action, cloud_worker::network::v2::{ - NetworkApiRequest, NetworkSecurityGroupRuleApiRequest, NetworkSecurityGroupRuleList, + NetworkApiRequest, NetworkSecurityGroupRuleApiRequest, NetworkSecurityGroupRuleDelete, + NetworkSecurityGroupRuleDeleteBuilder, NetworkSecurityGroupRuleDeleteBuilderError, + NetworkSecurityGroupRuleList, }, cloud_worker::types::ApiRequest, components::{Component, table_view::TableViewComponentBase}, @@ -71,6 +73,17 @@ impl NetworkSecurityGroupRules<'_> { } } +impl TryFrom<&SecurityGroupRuleResponse> for NetworkSecurityGroupRuleDelete { + type Error = NetworkSecurityGroupRuleDeleteBuilderError; + fn try_from(value: &SecurityGroupRuleResponse) -> Result { + let mut builder = NetworkSecurityGroupRuleDeleteBuilder::default(); + if let Some(val) = &value.id { + builder.id(val.clone()); + } + builder.build() + } +} + impl Component for NetworkSecurityGroupRules<'_> { fn register_config_handler(&mut self, config: Config) -> Result<(), TuiError> { self.set_config(config) @@ -125,6 +138,37 @@ impl Component for NetworkSecurityGroupRules<'_> { self.set_data(data)?; } } + Action::ApiResponseData { + request: ApiRequest::Network(NetworkApiRequest::SecurityGroupRule(req)), + .. + } => { + if let NetworkSecurityGroupRuleApiRequest::Delete(del) = *req { + let NetworkSecurityGroupRuleDelete { ref id, .. } = *del; + if self.delete_item_row_by_res_id_mut(&id)?.is_none() { + return Ok(Some(Action::Refresh)); + } + self.sync_table_data()?; + self.set_loading(false); + } + } + Action::DeleteNetworkSecurityGroupRule => { + // only if we are currently in the right mode + if current_mode == Mode::NetworkSecurityGroupRules { + // and have command_tx + if let Some(command_tx) = self.get_command_tx() { + // and have a selected entry + if let Some(selected_entry) = self.get_selected() { + // send action to delete the selected SecurityGroupRule + command_tx.send(Action::Confirm(ApiRequest::from( + NetworkSecurityGroupRuleApiRequest::Delete(Box::new( + NetworkSecurityGroupRuleDelete::try_from(selected_entry) + .wrap_err("error preparing OpenStack request")?, + )), + )))?; + } + } + } + } _ => {} }; Ok(None)