diff --git a/bin/cli/src/command/execute.rs b/bin/cli/src/command/execute.rs index 2b7985e3b..ccb75b331 100644 --- a/bin/cli/src/command/execute.rs +++ b/bin/cli/src/command/execute.rs @@ -221,6 +221,21 @@ pub async fn handle( Execution::SendAlert(data) => { println!("{}: {data:?}", "Data".dimmed()) } + Execution::RemoveSwarmNodes(data) => { + println!("{}: {data:?}", "Data".dimmed()) + } + Execution::RemoveSwarmStacks(data) => { + println!("{}: {data:?}", "Data".dimmed()) + } + Execution::RemoveSwarmServices(data) => { + println!("{}: {data:?}", "Data".dimmed()) + } + Execution::RemoveSwarmConfigs(data) => { + println!("{}: {data:?}", "Data".dimmed()) + } + Execution::RemoveSwarmSecrets(data) => { + println!("{}: {data:?}", "Data".dimmed()) + } Execution::ClearRepoCache(data) => { println!("{}: {data:?}", "Data".dimmed()) } @@ -488,6 +503,26 @@ pub async fn handle( .execute(request) .await .map(|u| ExecutionResult::Single(u.into())), + Execution::RemoveSwarmNodes(request) => client + .execute(request) + .await + .map(|u| ExecutionResult::Single(u.into())), + Execution::RemoveSwarmStacks(request) => client + .execute(request) + .await + .map(|u| ExecutionResult::Single(u.into())), + Execution::RemoveSwarmServices(request) => client + .execute(request) + .await + .map(|u| ExecutionResult::Single(u.into())), + Execution::RemoveSwarmConfigs(request) => client + .execute(request) + .await + .map(|u| ExecutionResult::Single(u.into())), + Execution::RemoveSwarmSecrets(request) => client + .execute(request) + .await + .map(|u| ExecutionResult::Single(u.into())), Execution::ClearRepoCache(request) => client .execute(request) .await diff --git a/bin/core/src/api/execute/mod.rs b/bin/core/src/api/execute/mod.rs index 353691a56..4e178d0b9 100644 --- a/bin/core/src/api/execute/mod.rs +++ b/bin/core/src/api/execute/mod.rs @@ -43,6 +43,7 @@ mod procedure; mod repo; mod server; mod stack; +mod swarm; mod sync; use super::Variant; @@ -69,28 +70,7 @@ pub struct ExecuteArgs { #[error(serror::Error)] #[serde(tag = "type", content = "params")] pub enum ExecuteRequest { - // ==== SERVER ==== - StartContainer(StartContainer), - RestartContainer(RestartContainer), - PauseContainer(PauseContainer), - UnpauseContainer(UnpauseContainer), - StopContainer(StopContainer), - DestroyContainer(DestroyContainer), - StartAllContainers(StartAllContainers), - RestartAllContainers(RestartAllContainers), - PauseAllContainers(PauseAllContainers), - UnpauseAllContainers(UnpauseAllContainers), - StopAllContainers(StopAllContainers), - PruneContainers(PruneContainers), - DeleteNetwork(DeleteNetwork), - PruneNetworks(PruneNetworks), - DeleteImage(DeleteImage), - PruneImages(PruneImages), - DeleteVolume(DeleteVolume), - PruneVolumes(PruneVolumes), - PruneDockerBuilders(PruneDockerBuilders), - PruneBuildx(PruneBuildx), - PruneSystem(PruneSystem), + // ==== SWARM ==== // ==== STACK ==== DeployStack(DeployStack), @@ -149,6 +129,36 @@ pub enum ExecuteRequest { TestAlerter(TestAlerter), SendAlert(SendAlert), + // ==== SERVER ==== + StartContainer(StartContainer), + RestartContainer(RestartContainer), + PauseContainer(PauseContainer), + UnpauseContainer(UnpauseContainer), + StopContainer(StopContainer), + DestroyContainer(DestroyContainer), + StartAllContainers(StartAllContainers), + RestartAllContainers(RestartAllContainers), + PauseAllContainers(PauseAllContainers), + UnpauseAllContainers(UnpauseAllContainers), + StopAllContainers(StopAllContainers), + PruneContainers(PruneContainers), + DeleteNetwork(DeleteNetwork), + PruneNetworks(PruneNetworks), + DeleteImage(DeleteImage), + PruneImages(PruneImages), + DeleteVolume(DeleteVolume), + PruneVolumes(PruneVolumes), + PruneDockerBuilders(PruneDockerBuilders), + PruneBuildx(PruneBuildx), + PruneSystem(PruneSystem), + + // ==== SWARM ==== + RemoveSwarmNodes(RemoveSwarmNodes), + RemoveSwarmStacks(RemoveSwarmStacks), + RemoveSwarmServices(RemoveSwarmServices), + RemoveSwarmConfigs(RemoveSwarmConfigs), + RemoveSwarmSecrets(RemoveSwarmSecrets), + // ==== MAINTENANCE ==== ClearRepoCache(ClearRepoCache), BackupCoreDatabase(BackupCoreDatabase), diff --git a/bin/core/src/api/execute/swarm.rs b/bin/core/src/api/execute/swarm.rs new file mode 100644 index 000000000..a07d53421 --- /dev/null +++ b/bin/core/src/api/execute/swarm.rs @@ -0,0 +1,274 @@ +use formatting::format_serror; +use komodo_client::{ + api::execute::{ + RemoveSwarmConfigs, RemoveSwarmNodes, RemoveSwarmSecrets, + RemoveSwarmServices, RemoveSwarmStacks, + }, + entities::{permission::PermissionLevel, swarm::Swarm}, +}; +use resolver_api::Resolve; + +use crate::{ + api::execute::ExecuteArgs, + helpers::{swarm::swarm_request, update::update_update}, + permission::get_check_permissions, +}; + +impl Resolve for RemoveSwarmNodes { + #[instrument( + "RemoveSwarmNodes", + skip_all, + fields( + id = id.to_string(), + operator = user.id, + update_id = update.id, + swarm = self.swarm, + nodes = serde_json::to_string(&self.nodes).unwrap_or_else(|e| e.to_string()), + force = self.force, + ) + )] + async fn resolve( + self, + ExecuteArgs { user, update, id }: &ExecuteArgs, + ) -> Result { + let swarm = get_check_permissions::( + &self.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + + update_update(update.clone()).await?; + + let mut update = update.clone(); + + match swarm_request( + &swarm.config.server_ids, + periphery_client::api::swarm::RemoveSwarmNodes { + nodes: self.nodes, + force: self.force, + }, + ) + .await + { + Ok(log) => update.logs.push(log), + Err(e) => update.push_error_log( + "Remove Swarm Nodes", + format_serror( + &e.context("Failed to remove swarm nodes").into(), + ), + ), + }; + + update.finalize(); + update_update(update.clone()).await?; + + Ok(update) + } +} + +impl Resolve for RemoveSwarmStacks { + #[instrument( + "RemoveSwarmStacks", + skip_all, + fields( + id = id.to_string(), + operator = user.id, + update_id = update.id, + swarm = self.swarm, + stacks = serde_json::to_string(&self.stacks).unwrap_or_else(|e| e.to_string()), + detach = self.detach, + ) + )] + async fn resolve( + self, + ExecuteArgs { user, update, id }: &ExecuteArgs, + ) -> Result { + let swarm = get_check_permissions::( + &self.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + + update_update(update.clone()).await?; + + let mut update = update.clone(); + + match swarm_request( + &swarm.config.server_ids, + periphery_client::api::swarm::RemoveSwarmStacks { + stacks: self.stacks, + detach: self.detach, + }, + ) + .await + { + Ok(log) => update.logs.push(log), + Err(e) => update.push_error_log( + "Remove Swarm Stacks", + format_serror( + &e.context("Failed to remove swarm stacks").into(), + ), + ), + }; + + update.finalize(); + update_update(update.clone()).await?; + + Ok(update) + } +} + +impl Resolve for RemoveSwarmServices { + #[instrument( + "RemoveSwarmServices", + skip_all, + fields( + id = id.to_string(), + operator = user.id, + update_id = update.id, + swarm = self.swarm, + services = serde_json::to_string(&self.services).unwrap_or_else(|e| e.to_string()), + ) + )] + async fn resolve( + self, + ExecuteArgs { user, update, id }: &ExecuteArgs, + ) -> Result { + let swarm = get_check_permissions::( + &self.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + + update_update(update.clone()).await?; + + let mut update = update.clone(); + + match swarm_request( + &swarm.config.server_ids, + periphery_client::api::swarm::RemoveSwarmServices { + services: self.services, + }, + ) + .await + { + Ok(log) => update.logs.push(log), + Err(e) => update.push_error_log( + "Remove Swarm Services", + format_serror( + &e.context("Failed to remove swarm services").into(), + ), + ), + }; + + update.finalize(); + update_update(update.clone()).await?; + + Ok(update) + } +} + +impl Resolve for RemoveSwarmConfigs { + #[instrument( + "RemoveSwarmConfigs", + skip_all, + fields( + id = id.to_string(), + operator = user.id, + update_id = update.id, + swarm = self.swarm, + configs = serde_json::to_string(&self.configs).unwrap_or_else(|e| e.to_string()), + ) + )] + async fn resolve( + self, + ExecuteArgs { user, update, id }: &ExecuteArgs, + ) -> Result { + let swarm = get_check_permissions::( + &self.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + + update_update(update.clone()).await?; + + let mut update = update.clone(); + + match swarm_request( + &swarm.config.server_ids, + periphery_client::api::swarm::RemoveSwarmConfigs { + configs: self.configs, + }, + ) + .await + { + Ok(log) => update.logs.push(log), + Err(e) => update.push_error_log( + "Remove Swarm Configs", + format_serror( + &e.context("Failed to remove swarm configs").into(), + ), + ), + }; + + update.finalize(); + update_update(update.clone()).await?; + + Ok(update) + } +} + +impl Resolve for RemoveSwarmSecrets { + #[instrument( + "RemoveSwarmSecrets", + skip_all, + fields( + id = id.to_string(), + operator = user.id, + update_id = update.id, + swarm = self.swarm, + secrets = serde_json::to_string(&self.secrets).unwrap_or_else(|e| e.to_string()), + ) + )] + async fn resolve( + self, + ExecuteArgs { user, update, id }: &ExecuteArgs, + ) -> Result { + let swarm = get_check_permissions::( + &self.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + + update_update(update.clone()).await?; + + let mut update = update.clone(); + + match swarm_request( + &swarm.config.server_ids, + periphery_client::api::swarm::RemoveSwarmSecrets { + secrets: self.secrets, + }, + ) + .await + { + Ok(log) => update.logs.push(log), + Err(e) => update.push_error_log( + "Remove Swarm Secrets", + format_serror( + &e.context("Failed to remove swarm secrets").into(), + ), + ), + }; + + update.finalize(); + update_update(update.clone()).await?; + + Ok(update) + } +} diff --git a/bin/core/src/helpers/procedure.rs b/bin/core/src/helpers/procedure.rs index d2f4c91ca..9360192b7 100644 --- a/bin/core/src/helpers/procedure.rs +++ b/bin/core/src/helpers/procedure.rs @@ -1162,6 +1162,91 @@ async fn execute_execution( ) .await? } + Execution::RemoveSwarmNodes(req) => { + let req = ExecuteRequest::RemoveSwarmNodes(req); + let update = init_execution_update(&req, &user).await?; + let ExecuteRequest::RemoveSwarmNodes(req) = req else { + unreachable!() + }; + let update_id = update.id.clone(); + handle_resolve_result( + req + .resolve(&ExecuteArgs { user, update, id }) + .await + .map_err(|e| e.error) + .context("Failed at RemoveSwarmNodes"), + &update_id, + ) + .await? + } + Execution::RemoveSwarmStacks(req) => { + let req = ExecuteRequest::RemoveSwarmStacks(req); + let update = init_execution_update(&req, &user).await?; + let ExecuteRequest::RemoveSwarmStacks(req) = req else { + unreachable!() + }; + let update_id = update.id.clone(); + handle_resolve_result( + req + .resolve(&ExecuteArgs { user, update, id }) + .await + .map_err(|e| e.error) + .context("Failed at RemoveSwarmStacks"), + &update_id, + ) + .await? + } + Execution::RemoveSwarmServices(req) => { + let req = ExecuteRequest::RemoveSwarmServices(req); + let update = init_execution_update(&req, &user).await?; + let ExecuteRequest::RemoveSwarmServices(req) = req else { + unreachable!() + }; + let update_id = update.id.clone(); + handle_resolve_result( + req + .resolve(&ExecuteArgs { user, update, id }) + .await + .map_err(|e| e.error) + .context("Failed at RemoveSwarmServices"), + &update_id, + ) + .await? + } + Execution::RemoveSwarmConfigs(req) => { + let req = ExecuteRequest::RemoveSwarmConfigs(req); + let update = init_execution_update(&req, &user).await?; + let ExecuteRequest::RemoveSwarmConfigs(req) = req else { + unreachable!() + }; + let update_id = update.id.clone(); + handle_resolve_result( + req + .resolve(&ExecuteArgs { user, update, id }) + .await + .map_err(|e| e.error) + .context("Failed at RemoveSwarmConfigs"), + &update_id, + ) + .await? + } + Execution::RemoveSwarmSecrets(req) => { + let req = ExecuteRequest::RemoveSwarmSecrets(req); + let update = init_execution_update(&req, &user).await?; + let ExecuteRequest::RemoveSwarmSecrets(req) = req else { + unreachable!() + }; + let update_id = update.id.clone(); + handle_resolve_result( + req + .resolve(&ExecuteArgs { user, update, id }) + .await + .map_err(|e| e.error) + .context("Failed at RemoveSwarmSecrets"), + &update_id, + ) + .await? + } Execution::ClearRepoCache(req) => { let req = ExecuteRequest::ClearRepoCache(req); let update = init_execution_update(&req, &user).await?; diff --git a/bin/core/src/helpers/update.rs b/bin/core/src/helpers/update.rs index 3b8d12b0a..4d6b8458c 100644 --- a/bin/core/src/helpers/update.rs +++ b/bin/core/src/helpers/update.rs @@ -14,6 +14,7 @@ use komodo_client::entities::{ repo::Repo, server::Server, stack::Stack, + swarm::Swarm, sync::ResourceSync, update::{Update, UpdateListItem}, user::User, @@ -121,6 +122,38 @@ pub async fn init_execution_update( user: &User, ) -> anyhow::Result { let (operation, target) = match &request { + // Swarm + ExecuteRequest::RemoveSwarmNodes(data) => ( + Operation::RemoveSwarmNodes, + ResourceTarget::Swarm( + resource::get::(&data.swarm).await?.id, + ), + ), + ExecuteRequest::RemoveSwarmStacks(data) => ( + Operation::RemoveSwarmStacks, + ResourceTarget::Swarm( + resource::get::(&data.swarm).await?.id, + ), + ), + ExecuteRequest::RemoveSwarmServices(data) => ( + Operation::RemoveSwarmServices, + ResourceTarget::Swarm( + resource::get::(&data.swarm).await?.id, + ), + ), + ExecuteRequest::RemoveSwarmConfigs(data) => ( + Operation::RemoveSwarmConfigs, + ResourceTarget::Swarm( + resource::get::(&data.swarm).await?.id, + ), + ), + ExecuteRequest::RemoveSwarmSecrets(data) => ( + Operation::RemoveSwarmSecrets, + ResourceTarget::Swarm( + resource::get::(&data.swarm).await?.id, + ), + ), + // Server ExecuteRequest::StartContainer(data) => ( Operation::StartContainer, diff --git a/bin/core/src/resource/procedure.rs b/bin/core/src/resource/procedure.rs index 38f9c3975..8f66595b2 100644 --- a/bin/core/src/resource/procedure.rs +++ b/bin/core/src/resource/procedure.rs @@ -24,6 +24,7 @@ use komodo_client::{ resource::Resource, server::Server, stack::Stack, + swarm::Swarm, sync::ResourceSync, update::Update, user::User, @@ -753,6 +754,51 @@ async fn validate_config( .try_collect::>() .await?; } + Execution::RemoveSwarmNodes(params) => { + let swarm = super::get_check_permissions::( + ¶ms.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + params.swarm = swarm.id; + } + Execution::RemoveSwarmStacks(params) => { + let swarm = super::get_check_permissions::( + ¶ms.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + params.swarm = swarm.id; + } + Execution::RemoveSwarmServices(params) => { + let swarm = super::get_check_permissions::( + ¶ms.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + params.swarm = swarm.id; + } + Execution::RemoveSwarmConfigs(params) => { + let swarm = super::get_check_permissions::( + ¶ms.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + params.swarm = swarm.id; + } + Execution::RemoveSwarmSecrets(params) => { + let swarm = super::get_check_permissions::( + ¶ms.swarm, + user, + PermissionLevel::Execute.into(), + ) + .await?; + params.swarm = swarm.id; + } Execution::ClearRepoCache(_params) => { if !user.admin { return Err(anyhow!( diff --git a/bin/core/src/sync/resources.rs b/bin/core/src/sync/resources.rs index 7de23c229..aecb3464b 100644 --- a/bin/core/src/sync/resources.rs +++ b/bin/core/src/sync/resources.rs @@ -700,6 +700,41 @@ impl ResourceSyncTrait for Procedure { }) .collect(); } + Execution::RemoveSwarmNodes(config) => { + config.swarm = resources + .swarms + .get(&config.swarm) + .map(|s| s.name.clone()) + .unwrap_or_default(); + } + Execution::RemoveSwarmStacks(config) => { + config.swarm = resources + .swarms + .get(&config.swarm) + .map(|s| s.name.clone()) + .unwrap_or_default(); + } + Execution::RemoveSwarmServices(config) => { + config.swarm = resources + .swarms + .get(&config.swarm) + .map(|s| s.name.clone()) + .unwrap_or_default(); + } + Execution::RemoveSwarmConfigs(config) => { + config.swarm = resources + .swarms + .get(&config.swarm) + .map(|s| s.name.clone()) + .unwrap_or_default(); + } + Execution::RemoveSwarmSecrets(config) => { + config.swarm = resources + .swarms + .get(&config.swarm) + .map(|s| s.name.clone()) + .unwrap_or_default(); + } Execution::ClearRepoCache(_) => {} Execution::BackupCoreDatabase(_) => {} Execution::GlobalAutoUpdate(_) => {} diff --git a/bin/core/src/sync/toml.rs b/bin/core/src/sync/toml.rs index 7092ecc1b..7c41b43df 100644 --- a/bin/core/src/sync/toml.rs +++ b/bin/core/src/sync/toml.rs @@ -843,6 +843,49 @@ impl ToToml for Procedure { ) }) } + Execution::RemoveSwarmNodes(exec) => exec.swarm.clone_from( + all + .swarms + .get(&exec.swarm) + .map(|a| &a.name) + .unwrap_or(&String::new()), + ), + Execution::RemoveSwarmStacks(exec) => { + exec.swarm.clone_from( + all + .swarms + .get(&exec.swarm) + .map(|a| &a.name) + .unwrap_or(&String::new()), + ) + } + Execution::RemoveSwarmServices(exec) => { + exec.swarm.clone_from( + all + .swarms + .get(&exec.swarm) + .map(|a| &a.name) + .unwrap_or(&String::new()), + ) + } + Execution::RemoveSwarmConfigs(exec) => { + exec.swarm.clone_from( + all + .swarms + .get(&exec.swarm) + .map(|a| &a.name) + .unwrap_or(&String::new()), + ) + } + Execution::RemoveSwarmSecrets(exec) => { + exec.swarm.clone_from( + all + .swarms + .get(&exec.swarm) + .map(|a| &a.name) + .unwrap_or(&String::new()), + ) + } Execution::None(_) | Execution::Sleep(_) | Execution::ClearRepoCache(_) diff --git a/bin/periphery/src/api/mod.rs b/bin/periphery/src/api/mod.rs index f03dfdb49..6fc76cf13 100644 --- a/bin/periphery/src/api/mod.rs +++ b/bin/periphery/src/api/mod.rs @@ -139,13 +139,19 @@ pub enum PeripheryRequest { // Swarm PollSwarmStatus(PollSwarmStatus), InspectSwarmNode(InspectSwarmNode), - InspectSwarmConfig(InspectSwarmConfig), - InspectSwarmSecret(InspectSwarmSecret), + UpdateSwarmNode(UpdateSwarmNode), + RemoveSwarmNodes(RemoveSwarmNodes), InspectSwarmStack(InspectSwarmStack), - InspectSwarmTask(InspectSwarmTask), + RemoveSwarmStacks(RemoveSwarmStacks), InspectSwarmService(InspectSwarmService), GetSwarmServiceLog(GetSwarmServiceLog), GetSwarmServiceLogSearch(GetSwarmServiceLogSearch), + RemoveSwarmServices(RemoveSwarmServices), + InspectSwarmTask(InspectSwarmTask), + InspectSwarmConfig(InspectSwarmConfig), + RemoveSwarmConfigs(RemoveSwarmConfigs), + InspectSwarmSecret(InspectSwarmSecret), + RemoveSwarmSecrets(RemoveSwarmSecrets), // Terminal ListTerminals(ListTerminals), diff --git a/bin/periphery/src/api/swarm.rs b/bin/periphery/src/api/swarm.rs index 84ebcc6c0..8a6b6a730 100644 --- a/bin/periphery/src/api/swarm.rs +++ b/bin/periphery/src/api/swarm.rs @@ -73,6 +73,104 @@ impl Resolve for InspectSwarmNode { } } +impl Resolve for UpdateSwarmNode { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker node update"); + + if let Some(role) = self.role { + command += " --role="; + command += role.as_ref(); + } + + if let Some(availability) = self.availability { + command += " --availability="; + command += availability.as_ref(); + } + + if let Some(label_add) = self.label_add { + for (key, value) in label_add { + command += " --label-add "; + command += &key; + if let Some(value) = value { + command += "="; + command += &value; + } + } + } + + if let Some(label_rm) = self.label_rm { + for key in label_rm { + command += " --label-rm "; + command += &key; + } + } + + command += " "; + command += &self.node; + + Ok( + run_komodo_standard_command("Update Swarm Node", None, command) + .await, + ) + } +} + +impl Resolve for RemoveSwarmNodes { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker node rm"); + if self.force { + command += " --force" + } + for node in self.nodes { + command += " "; + command += &node; + } + Ok( + run_komodo_standard_command( + "Remove Swarm Nodes", + None, + command, + ) + .await, + ) + } +} + +// ======= +// Stack +// ======= + +impl Resolve for InspectSwarmStack { + async fn resolve( + self, + _: &super::Args, + ) -> anyhow::Result { + inspect_swarm_stack(self.stack).await + } +} + +impl Resolve for RemoveSwarmStacks { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker stack rm"); + // This defaults to true, only need when false + if !self.detach { + command += " --detach=false" + } + for stack in self.stacks { + command += " "; + command += &stack; + } + Ok( + run_komodo_standard_command( + "Remove Swarm Stacks", + None, + command, + ) + .await, + ) + } +} + // ========= // Service // ========= @@ -182,6 +280,24 @@ impl Resolve for GetSwarmServiceLogSearch { } } +impl Resolve for RemoveSwarmServices { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker service rm"); + for service in self.services { + command += " "; + command += &service; + } + Ok( + run_komodo_standard_command( + "Remove Swarm Services", + None, + command, + ) + .await, + ) + } +} + // ====== // Task // ====== @@ -200,6 +316,37 @@ impl Resolve for InspectSwarmTask { } } +// ======== +// Config +// ======== + +impl Resolve for InspectSwarmConfig { + async fn resolve( + self, + _: &super::Args, + ) -> anyhow::Result> { + inspect_swarm_config(&self.config).await + } +} + +impl Resolve for RemoveSwarmConfigs { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker config rm"); + for config in self.configs { + command += " "; + command += &config; + } + Ok( + run_komodo_standard_command( + "Remove Swarm Configs", + None, + command, + ) + .await, + ) + } +} + // ======== // Secret // ======== @@ -218,28 +365,20 @@ impl Resolve for InspectSwarmSecret { } } -// ======== -// Config -// ======== - -impl Resolve for InspectSwarmConfig { - async fn resolve( - self, - _: &super::Args, - ) -> anyhow::Result> { - inspect_swarm_config(&self.config).await - } -} - -// ======= -// Stack -// ======= - -impl Resolve for InspectSwarmStack { - async fn resolve( - self, - _: &super::Args, - ) -> anyhow::Result { - inspect_swarm_stack(self.stack).await +impl Resolve for RemoveSwarmSecrets { + async fn resolve(self, _: &super::Args) -> anyhow::Result { + let mut command = String::from("docker secret rm"); + for secret in self.secrets { + command += " "; + command += &secret; + } + Ok( + run_komodo_standard_command( + "Remove Swarm Secrets", + None, + command, + ) + .await, + ) } } diff --git a/client/core/rs/src/api/execute/mod.rs b/client/core/rs/src/api/execute/mod.rs index 4cdef99b5..fdffcfa57 100644 --- a/client/core/rs/src/api/execute/mod.rs +++ b/client/core/rs/src/api/execute/mod.rs @@ -14,6 +14,7 @@ mod procedure; mod repo; mod server; mod stack; +mod swarm; mod sync; pub use action::*; @@ -25,6 +26,7 @@ pub use procedure::*; pub use repo::*; pub use server::*; pub use stack::*; +pub use swarm::*; pub use sync::*; use crate::{ @@ -59,83 +61,6 @@ pub enum Execution { /// The "null" execution. Does nothing. None(NoData), - // ACTION - /// Run the target action. (alias: `action`, `ac`) - #[clap(alias = "action", alias = "ac")] - RunAction(RunAction), - BatchRunAction(BatchRunAction), - - // PROCEDURE - /// Run the target procedure. (alias: `procedure`, `pr`) - #[clap(alias = "procedure", alias = "pr")] - RunProcedure(RunProcedure), - BatchRunProcedure(BatchRunProcedure), - - // BUILD - /// Run the target build. (alias: `build`, `bd`) - #[clap(alias = "build", alias = "bd")] - RunBuild(RunBuild), - BatchRunBuild(BatchRunBuild), - CancelBuild(CancelBuild), - - // DEPLOYMENT - /// Deploy the target deployment. (alias: `dp`) - #[clap(alias = "dp")] - Deploy(Deploy), - BatchDeploy(BatchDeploy), - PullDeployment(PullDeployment), - StartDeployment(StartDeployment), - RestartDeployment(RestartDeployment), - PauseDeployment(PauseDeployment), - UnpauseDeployment(UnpauseDeployment), - StopDeployment(StopDeployment), - DestroyDeployment(DestroyDeployment), - BatchDestroyDeployment(BatchDestroyDeployment), - - // REPO - /// Clone the target repo - #[clap(alias = "clone")] - CloneRepo(CloneRepo), - BatchCloneRepo(BatchCloneRepo), - PullRepo(PullRepo), - BatchPullRepo(BatchPullRepo), - BuildRepo(BuildRepo), - BatchBuildRepo(BatchBuildRepo), - CancelRepoBuild(CancelRepoBuild), - - // SERVER (Container) - StartContainer(StartContainer), - RestartContainer(RestartContainer), - PauseContainer(PauseContainer), - UnpauseContainer(UnpauseContainer), - StopContainer(StopContainer), - DestroyContainer(DestroyContainer), - StartAllContainers(StartAllContainers), - RestartAllContainers(RestartAllContainers), - PauseAllContainers(PauseAllContainers), - UnpauseAllContainers(UnpauseAllContainers), - StopAllContainers(StopAllContainers), - PruneContainers(PruneContainers), - - // SERVER (Prune) - DeleteNetwork(DeleteNetwork), - PruneNetworks(PruneNetworks), - DeleteImage(DeleteImage), - PruneImages(PruneImages), - DeleteVolume(DeleteVolume), - PruneVolumes(PruneVolumes), - PruneDockerBuilders(PruneDockerBuilders), - PruneBuildx(PruneBuildx), - PruneSystem(PruneSystem), - - // SYNC - /// Execute a Resource Sync. (alias: `sync`) - #[clap(alias = "sync")] - RunSync(RunSync), - /// Commit a Resource Sync. (alias: `commit`) - #[clap(alias = "commit")] - CommitSync(CommitSync), // This is a special case, its actually a write operation. - // STACK /// Deploy the target stack. (alias: `stack`, `st`) #[clap(alias = "stack", alias = "st")] @@ -154,11 +79,93 @@ pub enum Execution { BatchDestroyStack(BatchDestroyStack), RunStackService(RunStackService), + // DEPLOYMENT + /// Deploy the target deployment. (alias: `dp`) + #[clap(alias = "dp")] + Deploy(Deploy), + BatchDeploy(BatchDeploy), + PullDeployment(PullDeployment), + StartDeployment(StartDeployment), + RestartDeployment(RestartDeployment), + PauseDeployment(PauseDeployment), + UnpauseDeployment(UnpauseDeployment), + StopDeployment(StopDeployment), + DestroyDeployment(DestroyDeployment), + BatchDestroyDeployment(BatchDestroyDeployment), + + // BUILD + /// Run the target build. (alias: `build`, `bd`) + #[clap(alias = "build", alias = "bd")] + RunBuild(RunBuild), + BatchRunBuild(BatchRunBuild), + CancelBuild(CancelBuild), + + // REPO + /// Clone the target repo + #[clap(alias = "clone")] + CloneRepo(CloneRepo), + BatchCloneRepo(BatchCloneRepo), + PullRepo(PullRepo), + BatchPullRepo(BatchPullRepo), + BuildRepo(BuildRepo), + BatchBuildRepo(BatchBuildRepo), + CancelRepoBuild(CancelRepoBuild), + + // PROCEDURE + /// Run the target procedure. (alias: `procedure`, `pr`) + #[clap(alias = "procedure", alias = "pr")] + RunProcedure(RunProcedure), + BatchRunProcedure(BatchRunProcedure), + + // ACTION + /// Run the target action. (alias: `action`, `ac`) + #[clap(alias = "action", alias = "ac")] + RunAction(RunAction), + BatchRunAction(BatchRunAction), + + // SYNC + /// Execute a Resource Sync. (alias: `sync`) + #[clap(alias = "sync")] + RunSync(RunSync), + /// Commit a Resource Sync. (alias: `commit`) + #[clap(alias = "commit")] + CommitSync(CommitSync), // This is a special case, its actually a write operation. + // ALERTER TestAlerter(TestAlerter), #[clap(alias = "alert")] SendAlert(SendAlert), + // SERVER + StartContainer(StartContainer), + RestartContainer(RestartContainer), + PauseContainer(PauseContainer), + UnpauseContainer(UnpauseContainer), + StopContainer(StopContainer), + DestroyContainer(DestroyContainer), + StartAllContainers(StartAllContainers), + RestartAllContainers(RestartAllContainers), + PauseAllContainers(PauseAllContainers), + UnpauseAllContainers(UnpauseAllContainers), + StopAllContainers(StopAllContainers), + PruneContainers(PruneContainers), + DeleteNetwork(DeleteNetwork), + PruneNetworks(PruneNetworks), + DeleteImage(DeleteImage), + PruneImages(PruneImages), + DeleteVolume(DeleteVolume), + PruneVolumes(PruneVolumes), + PruneDockerBuilders(PruneDockerBuilders), + PruneBuildx(PruneBuildx), + PruneSystem(PruneSystem), + + // SWARM + RemoveSwarmNodes(RemoveSwarmNodes), + RemoveSwarmStacks(RemoveSwarmStacks), + RemoveSwarmServices(RemoveSwarmServices), + RemoveSwarmConfigs(RemoveSwarmConfigs), + RemoveSwarmSecrets(RemoveSwarmSecrets), + // MAINTENANCE ClearRepoCache(ClearRepoCache), #[clap( diff --git a/client/core/rs/src/api/execute/swarm.rs b/client/core/rs/src/api/execute/swarm.rs new file mode 100644 index 000000000..664f16407 --- /dev/null +++ b/client/core/rs/src/api/execute/swarm.rs @@ -0,0 +1,161 @@ +use clap::Parser; +use derive_empty_traits::EmptyTraits; +use resolver_api::Resolve; +use serde::{Deserialize, Serialize}; +use typeshare::typeshare; + +use crate::{ + api::execute::KomodoExecuteRequest, entities::update::Update, +}; + +// ======== +// = Node = +// ======== + +/// `docker node rm [OPTIONS] NODE [NODE...]` +/// +/// https://docs.docker.com/reference/cli/docker/node/rm/ +#[typeshare] +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Resolve, + EmptyTraits, + Parser, +)] +#[empty_traits(KomodoExecuteRequest)] +#[response(Update)] +#[error(serror::Error)] +pub struct RemoveSwarmNodes { + /// Name or id + pub swarm: String, + /// Node names or ids to remove + pub nodes: Vec, + /// Force remove a node from the swarm + #[serde(default)] + #[arg(long, short, default_value_t = false)] + pub force: bool, +} + +// ========= +// = Stack = +// ========= + +/// `docker stack rm [OPTIONS] STACK [STACK...]` +/// +/// https://docs.docker.com/reference/cli/docker/stack/rm/ +#[typeshare] +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Resolve, + EmptyTraits, + Parser, +)] +#[empty_traits(KomodoExecuteRequest)] +#[response(Update)] +#[error(serror::Error)] +pub struct RemoveSwarmStacks { + /// Name or id + pub swarm: String, + /// Node names to remove + pub stacks: Vec, + /// Do not wait for stack removal + #[serde(default = "default_detach")] + #[arg(long, short, default_value_t = default_detach())] + pub detach: bool, +} + +fn default_detach() -> bool { + true +} + +// =========== +// = Service = +// =========== + +/// `docker service rm SERVICE [SERVICE...]` +/// +/// https://docs.docker.com/reference/cli/docker/service/rm/ +#[typeshare] +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Resolve, + EmptyTraits, + Parser, +)] +#[empty_traits(KomodoExecuteRequest)] +#[response(Update)] +#[error(serror::Error)] +pub struct RemoveSwarmServices { + /// Name or id + pub swarm: String, + /// Service names or ids + pub services: Vec, +} + +// ========== +// = Config = +// ========== + +/// `docker config rm CONFIG [CONFIG...]` +/// +/// https://docs.docker.com/reference/cli/docker/config/rm/ +#[typeshare] +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Resolve, + EmptyTraits, + Parser, +)] +#[empty_traits(KomodoExecuteRequest)] +#[response(Update)] +#[error(serror::Error)] +pub struct RemoveSwarmConfigs { + /// Name or id + pub swarm: String, + /// Config names or ids + pub configs: Vec, +} + +// ========== +// = Secret = +// ========== + +/// `docker secret rm SECRET [SECRET...]` +/// +/// https://docs.docker.com/reference/cli/docker/secret/rm/ +#[typeshare] +#[derive( + Serialize, + Deserialize, + Debug, + Clone, + PartialEq, + Resolve, + EmptyTraits, + Parser, +)] +#[empty_traits(KomodoExecuteRequest)] +#[response(Update)] +#[error(serror::Error)] +pub struct RemoveSwarmSecrets { + /// Name or id + pub swarm: String, + /// Secret names or ids + pub secrets: Vec, +} diff --git a/client/core/rs/src/entities/docker/node.rs b/client/core/rs/src/entities/docker/node.rs index 191399c2d..958257fc6 100644 --- a/client/core/rs/src/entities/docker/node.rs +++ b/client/core/rs/src/entities/docker/node.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; +use strum::AsRefStr; use typeshare::typeshare; use super::*; @@ -111,6 +112,7 @@ pub struct NodeSpec { Default, Serialize, Deserialize, + AsRefStr, )] pub enum NodeSpecRoleEnum { #[default] @@ -134,6 +136,7 @@ pub enum NodeSpecRoleEnum { Default, Serialize, Deserialize, + AsRefStr, )] pub enum NodeSpecAvailabilityEnum { #[default] diff --git a/client/core/rs/src/entities/mod.rs b/client/core/rs/src/entities/mod.rs index 03bdbed60..b270aab8a 100644 --- a/client/core/rs/src/entities/mod.rs +++ b/client/core/rs/src/entities/mod.rs @@ -1053,6 +1053,11 @@ pub enum Operation { UpdateSwarm, RenameSwarm, DeleteSwarm, + RemoveSwarmNodes, + RemoveSwarmStacks, + RemoveSwarmServices, + RemoveSwarmConfigs, + RemoveSwarmSecrets, // Server CreateServer, diff --git a/client/core/ts/src/responses.ts b/client/core/ts/src/responses.ts index a7a595139..dff352853 100644 --- a/client/core/ts/src/responses.ts +++ b/client/core/ts/src/responses.ts @@ -359,29 +359,6 @@ export type WriteResponses = { }; export type ExecuteResponses = { - // ==== SERVER ==== - StartContainer: Types.Update; - RestartContainer: Types.Update; - PauseContainer: Types.Update; - UnpauseContainer: Types.Update; - StopContainer: Types.Update; - DestroyContainer: Types.Update; - StartAllContainers: Types.Update; - RestartAllContainers: Types.Update; - PauseAllContainers: Types.Update; - UnpauseAllContainers: Types.Update; - StopAllContainers: Types.Update; - PruneContainers: Types.Update; - DeleteNetwork: Types.Update; - PruneNetworks: Types.Update; - DeleteImage: Types.Update; - PruneImages: Types.Update; - DeleteVolume: Types.Update; - PruneVolumes: Types.Update; - PruneDockerBuilders: Types.Update; - PruneBuildx: Types.Update; - PruneSystem: Types.Update; - // ==== STACK ==== DeployStack: Types.Update; BatchDeployStack: Types.BatchExecutionResponse; @@ -439,6 +416,36 @@ export type ExecuteResponses = { TestAlerter: Types.Update; SendAlert: Types.Update; + // ==== SERVER ==== + StartContainer: Types.Update; + RestartContainer: Types.Update; + PauseContainer: Types.Update; + UnpauseContainer: Types.Update; + StopContainer: Types.Update; + DestroyContainer: Types.Update; + StartAllContainers: Types.Update; + RestartAllContainers: Types.Update; + PauseAllContainers: Types.Update; + UnpauseAllContainers: Types.Update; + StopAllContainers: Types.Update; + PruneContainers: Types.Update; + DeleteNetwork: Types.Update; + PruneNetworks: Types.Update; + DeleteImage: Types.Update; + PruneImages: Types.Update; + DeleteVolume: Types.Update; + PruneVolumes: Types.Update; + PruneDockerBuilders: Types.Update; + PruneBuildx: Types.Update; + PruneSystem: Types.Update; + + // ==== SWARM ==== + RemoveSwarmNodes: Types.Update; + RemoveSwarmStacks: Types.Update; + RemoveSwarmServices: Types.Update; + RemoveSwarmConfigs: Types.Update; + RemoveSwarmSecrets: Types.Update; + // ==== MAINTENANCE ==== ClearRepoCache: Types.Update; BackupCoreDatabase: Types.Update; diff --git a/client/core/ts/src/types.ts b/client/core/ts/src/types.ts index f6eac8b8e..a538d99e7 100644 --- a/client/core/ts/src/types.ts +++ b/client/core/ts/src/types.ts @@ -351,6 +351,11 @@ export enum Operation { UpdateSwarm = "UpdateSwarm", RenameSwarm = "RenameSwarm", DeleteSwarm = "DeleteSwarm", + RemoveSwarmNodes = "RemoveSwarmNodes", + RemoveSwarmStacks = "RemoveSwarmStacks", + RemoveSwarmServices = "RemoveSwarmServices", + RemoveSwarmConfigs = "RemoveSwarmConfigs", + RemoveSwarmSecrets = "RemoveSwarmSecrets", CreateServer = "CreateServer", UpdateServer = "UpdateServer", UpdateServerKey = "UpdateServerKey", @@ -818,16 +823,21 @@ export type BuilderQuery = ResourceQuery; export type Execution = /** The "null" execution. Does nothing. */ | { type: "None", params: NoData } - /** Run the target action. (alias: `action`, `ac`) */ - | { type: "RunAction", params: RunAction } - | { type: "BatchRunAction", params: BatchRunAction } - /** Run the target procedure. (alias: `procedure`, `pr`) */ - | { type: "RunProcedure", params: RunProcedure } - | { type: "BatchRunProcedure", params: BatchRunProcedure } - /** Run the target build. (alias: `build`, `bd`) */ - | { type: "RunBuild", params: RunBuild } - | { type: "BatchRunBuild", params: BatchRunBuild } - | { type: "CancelBuild", params: CancelBuild } + /** Deploy the target stack. (alias: `stack`, `st`) */ + | { type: "DeployStack", params: DeployStack } + | { type: "BatchDeployStack", params: BatchDeployStack } + | { type: "DeployStackIfChanged", params: DeployStackIfChanged } + | { type: "BatchDeployStackIfChanged", params: BatchDeployStackIfChanged } + | { type: "PullStack", params: PullStack } + | { type: "BatchPullStack", params: BatchPullStack } + | { type: "StartStack", params: StartStack } + | { type: "RestartStack", params: RestartStack } + | { type: "PauseStack", params: PauseStack } + | { type: "UnpauseStack", params: UnpauseStack } + | { type: "StopStack", params: StopStack } + | { type: "DestroyStack", params: DestroyStack } + | { type: "BatchDestroyStack", params: BatchDestroyStack } + | { type: "RunStackService", params: RunStackService } /** Deploy the target deployment. (alias: `dp`) */ | { type: "Deploy", params: Deploy } | { type: "BatchDeploy", params: BatchDeploy } @@ -839,6 +849,10 @@ export type Execution = | { type: "StopDeployment", params: StopDeployment } | { type: "DestroyDeployment", params: DestroyDeployment } | { type: "BatchDestroyDeployment", params: BatchDestroyDeployment } + /** Run the target build. (alias: `build`, `bd`) */ + | { type: "RunBuild", params: RunBuild } + | { type: "BatchRunBuild", params: BatchRunBuild } + | { type: "CancelBuild", params: CancelBuild } /** Clone the target repo */ | { type: "CloneRepo", params: CloneRepo } | { type: "BatchCloneRepo", params: BatchCloneRepo } @@ -847,6 +861,18 @@ export type Execution = | { type: "BuildRepo", params: BuildRepo } | { type: "BatchBuildRepo", params: BatchBuildRepo } | { type: "CancelRepoBuild", params: CancelRepoBuild } + /** Run the target procedure. (alias: `procedure`, `pr`) */ + | { type: "RunProcedure", params: RunProcedure } + | { type: "BatchRunProcedure", params: BatchRunProcedure } + /** Run the target action. (alias: `action`, `ac`) */ + | { type: "RunAction", params: RunAction } + | { type: "BatchRunAction", params: BatchRunAction } + /** Execute a Resource Sync. (alias: `sync`) */ + | { type: "RunSync", params: RunSync } + /** Commit a Resource Sync. (alias: `commit`) */ + | { type: "CommitSync", params: CommitSync } + | { type: "TestAlerter", params: TestAlerter } + | { type: "SendAlert", params: SendAlert } | { type: "StartContainer", params: StartContainer } | { type: "RestartContainer", params: RestartContainer } | { type: "PauseContainer", params: PauseContainer } @@ -868,27 +894,11 @@ export type Execution = | { type: "PruneDockerBuilders", params: PruneDockerBuilders } | { type: "PruneBuildx", params: PruneBuildx } | { type: "PruneSystem", params: PruneSystem } - /** Execute a Resource Sync. (alias: `sync`) */ - | { type: "RunSync", params: RunSync } - /** Commit a Resource Sync. (alias: `commit`) */ - | { type: "CommitSync", params: CommitSync } - /** Deploy the target stack. (alias: `stack`, `st`) */ - | { type: "DeployStack", params: DeployStack } - | { type: "BatchDeployStack", params: BatchDeployStack } - | { type: "DeployStackIfChanged", params: DeployStackIfChanged } - | { type: "BatchDeployStackIfChanged", params: BatchDeployStackIfChanged } - | { type: "PullStack", params: PullStack } - | { type: "BatchPullStack", params: BatchPullStack } - | { type: "StartStack", params: StartStack } - | { type: "RestartStack", params: RestartStack } - | { type: "PauseStack", params: PauseStack } - | { type: "UnpauseStack", params: UnpauseStack } - | { type: "StopStack", params: StopStack } - | { type: "DestroyStack", params: DestroyStack } - | { type: "BatchDestroyStack", params: BatchDestroyStack } - | { type: "RunStackService", params: RunStackService } - | { type: "TestAlerter", params: TestAlerter } - | { type: "SendAlert", params: SendAlert } + | { type: "RemoveSwarmNodes", params: RemoveSwarmNodes } + | { type: "RemoveSwarmStacks", params: RemoveSwarmStacks } + | { type: "RemoveSwarmServices", params: RemoveSwarmServices } + | { type: "RemoveSwarmConfigs", params: RemoveSwarmConfigs } + | { type: "RemoveSwarmSecrets", params: RemoveSwarmSecrets } | { type: "ClearRepoCache", params: ClearRepoCache } | { type: "BackupCoreDatabase", params: BackupCoreDatabase } | { type: "GlobalAutoUpdate", params: GlobalAutoUpdate } @@ -8711,6 +8721,70 @@ export interface RefreshStackCache { stack: string; } +/** + * `docker config rm CONFIG [CONFIG...]` + * + * https://docs.docker.com/reference/cli/docker/config/rm/ + */ +export interface RemoveSwarmConfigs { + /** Name or id */ + swarm: string; + /** Config names or ids */ + configs: string[]; +} + +/** + * `docker node rm [OPTIONS] NODE [NODE...]` + * + * https://docs.docker.com/reference/cli/docker/node/rm/ + */ +export interface RemoveSwarmNodes { + /** Name or id */ + swarm: string; + /** Node names or ids to remove */ + nodes: string[]; + /** Force remove a node from the swarm */ + force?: boolean; +} + +/** + * `docker secret rm SECRET [SECRET...]` + * + * https://docs.docker.com/reference/cli/docker/secret/rm/ + */ +export interface RemoveSwarmSecrets { + /** Name or id */ + swarm: string; + /** Secret names or ids */ + secrets: string[]; +} + +/** + * `docker service rm SERVICE [SERVICE...]` + * + * https://docs.docker.com/reference/cli/docker/service/rm/ + */ +export interface RemoveSwarmServices { + /** Name or id */ + swarm: string; + /** Service names or ids */ + services: string[]; +} + +/** + * `docker stack rm [OPTIONS] STACK [STACK...]` + * + * https://docs.docker.com/reference/cli/docker/stack/rm/ + */ +export interface RemoveSwarmStacks { + /** Name or id */ + swarm: string; + /** Node names to remove */ + stacks: string[]; + /** Do not wait for stack removal */ + detach: boolean; +} + /** **Admin only.** Remove a user from a user group. Response: [UserGroup] */ export interface RemoveUserFromUserGroup { /** The name or id of UserGroup that user should be removed from. */ @@ -9979,27 +10053,6 @@ export enum DayOfWeek { } export type ExecuteRequest = - | { type: "StartContainer", params: StartContainer } - | { type: "RestartContainer", params: RestartContainer } - | { type: "PauseContainer", params: PauseContainer } - | { type: "UnpauseContainer", params: UnpauseContainer } - | { type: "StopContainer", params: StopContainer } - | { type: "DestroyContainer", params: DestroyContainer } - | { type: "StartAllContainers", params: StartAllContainers } - | { type: "RestartAllContainers", params: RestartAllContainers } - | { type: "PauseAllContainers", params: PauseAllContainers } - | { type: "UnpauseAllContainers", params: UnpauseAllContainers } - | { type: "StopAllContainers", params: StopAllContainers } - | { type: "PruneContainers", params: PruneContainers } - | { type: "DeleteNetwork", params: DeleteNetwork } - | { type: "PruneNetworks", params: PruneNetworks } - | { type: "DeleteImage", params: DeleteImage } - | { type: "PruneImages", params: PruneImages } - | { type: "DeleteVolume", params: DeleteVolume } - | { type: "PruneVolumes", params: PruneVolumes } - | { type: "PruneDockerBuilders", params: PruneDockerBuilders } - | { type: "PruneBuildx", params: PruneBuildx } - | { type: "PruneSystem", params: PruneSystem } | { type: "DeployStack", params: DeployStack } | { type: "BatchDeployStack", params: BatchDeployStack } | { type: "DeployStackIfChanged", params: DeployStackIfChanged } @@ -10041,6 +10094,32 @@ export type ExecuteRequest = | { type: "RunSync", params: RunSync } | { type: "TestAlerter", params: TestAlerter } | { type: "SendAlert", params: SendAlert } + | { type: "StartContainer", params: StartContainer } + | { type: "RestartContainer", params: RestartContainer } + | { type: "PauseContainer", params: PauseContainer } + | { type: "UnpauseContainer", params: UnpauseContainer } + | { type: "StopContainer", params: StopContainer } + | { type: "DestroyContainer", params: DestroyContainer } + | { type: "StartAllContainers", params: StartAllContainers } + | { type: "RestartAllContainers", params: RestartAllContainers } + | { type: "PauseAllContainers", params: PauseAllContainers } + | { type: "UnpauseAllContainers", params: UnpauseAllContainers } + | { type: "StopAllContainers", params: StopAllContainers } + | { type: "PruneContainers", params: PruneContainers } + | { type: "DeleteNetwork", params: DeleteNetwork } + | { type: "PruneNetworks", params: PruneNetworks } + | { type: "DeleteImage", params: DeleteImage } + | { type: "PruneImages", params: PruneImages } + | { type: "DeleteVolume", params: DeleteVolume } + | { type: "PruneVolumes", params: PruneVolumes } + | { type: "PruneDockerBuilders", params: PruneDockerBuilders } + | { type: "PruneBuildx", params: PruneBuildx } + | { type: "PruneSystem", params: PruneSystem } + | { type: "RemoveSwarmNodes", params: RemoveSwarmNodes } + | { type: "RemoveSwarmStacks", params: RemoveSwarmStacks } + | { type: "RemoveSwarmServices", params: RemoveSwarmServices } + | { type: "RemoveSwarmConfigs", params: RemoveSwarmConfigs } + | { type: "RemoveSwarmSecrets", params: RemoveSwarmSecrets } | { type: "ClearRepoCache", params: ClearRepoCache } | { type: "BackupCoreDatabase", params: BackupCoreDatabase } | { type: "GlobalAutoUpdate", params: GlobalAutoUpdate } diff --git a/client/periphery/rs/src/api/swarm.rs b/client/periphery/rs/src/api/swarm.rs index 4cf351c56..8c22abe5c 100644 --- a/client/periphery/rs/src/api/swarm.rs +++ b/client/periphery/rs/src/api/swarm.rs @@ -46,7 +46,7 @@ pub struct InspectSwarmNode { #[derive(Debug, Clone, Serialize, Deserialize, Resolve)] #[response(Log)] #[error(anyhow::Error)] -pub struct RmSwarmNodes { +pub struct RemoveSwarmNodes { pub nodes: Vec, pub force: bool, } @@ -69,6 +69,30 @@ pub struct UpdateSwarmNode { pub role: Option, } +// ======= +// Stack +// ======= + +#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] +#[response(SwarmStackLists)] +#[error(anyhow::Error)] +pub struct InspectSwarmStack { + /// The swarm stack name + pub stack: String, +} + +/// `docker stack rm [OPTIONS] STACK [STACK...]` +/// +/// https://docs.docker.com/reference/cli/docker/stack/rm/ +#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] +#[response(Log)] +#[error(anyhow::Error)] +pub struct RemoveSwarmStacks { + pub stacks: Vec, + /// Do not wait for stack removal + pub detach: bool, +} + // ========= // Service // ========= @@ -152,7 +176,7 @@ pub struct GetSwarmServiceLogSearch { #[derive(Debug, Clone, Serialize, Deserialize, Resolve)] #[response(Log)] #[error(anyhow::Error)] -pub struct RmSwarmServices { +pub struct RemoveSwarmServices { pub services: Vec, } @@ -167,17 +191,6 @@ pub struct InspectSwarmTask { pub task: String, } -// ======== -// Secret -// ======== - -#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] -#[response(SwarmSecret)] -#[error(anyhow::Error)] -pub struct InspectSwarmSecret { - pub secret: String, -} - // ======== // Config // ======== @@ -189,26 +202,33 @@ pub struct InspectSwarmConfig { pub config: String, } -// ======= -// Stack -// ======= - -#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] -#[response(SwarmStackLists)] -#[error(anyhow::Error)] -pub struct InspectSwarmStack { - /// The swarm stack name - pub stack: String, -} - -/// `docker stack rm [OPTIONS] STACK [STACK...]` +/// `docker config rm CONFIG [CONFIG...]` /// -/// https://docs.docker.com/reference/cli/docker/stack/rm/ +/// https://docs.docker.com/reference/cli/docker/config/rm/ #[derive(Debug, Clone, Serialize, Deserialize, Resolve)] #[response(Log)] #[error(anyhow::Error)] -pub struct RmSwarmStacks { - pub stacks: Vec, - /// Do not wait for stack removal - pub detach: bool, +pub struct RemoveSwarmConfigs { + pub configs: Vec, +} + +// ======== +// Secret +// ======== + +#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] +#[response(SwarmSecret)] +#[error(anyhow::Error)] +pub struct InspectSwarmSecret { + pub secret: String, +} + +/// `docker secret rm SECRET [SECRET...]` +/// +/// https://docs.docker.com/reference/cli/docker/secret/rm/ +#[derive(Debug, Clone, Serialize, Deserialize, Resolve)] +#[response(Log)] +#[error(anyhow::Error)] +pub struct RemoveSwarmSecrets { + pub secrets: Vec, } diff --git a/frontend/public/client/responses.d.ts b/frontend/public/client/responses.d.ts index 08d6d14e8..ff5c1dc10 100644 --- a/frontend/public/client/responses.d.ts +++ b/frontend/public/client/responses.d.ts @@ -263,27 +263,6 @@ export type WriteResponses = { CloseAlert: Types.NoData; }; export type ExecuteResponses = { - StartContainer: Types.Update; - RestartContainer: Types.Update; - PauseContainer: Types.Update; - UnpauseContainer: Types.Update; - StopContainer: Types.Update; - DestroyContainer: Types.Update; - StartAllContainers: Types.Update; - RestartAllContainers: Types.Update; - PauseAllContainers: Types.Update; - UnpauseAllContainers: Types.Update; - StopAllContainers: Types.Update; - PruneContainers: Types.Update; - DeleteNetwork: Types.Update; - PruneNetworks: Types.Update; - DeleteImage: Types.Update; - PruneImages: Types.Update; - DeleteVolume: Types.Update; - PruneVolumes: Types.Update; - PruneDockerBuilders: Types.Update; - PruneBuildx: Types.Update; - PruneSystem: Types.Update; DeployStack: Types.Update; BatchDeployStack: Types.BatchExecutionResponse; DeployStackIfChanged: Types.Update; @@ -325,6 +304,32 @@ export type ExecuteResponses = { RunSync: Types.Update; TestAlerter: Types.Update; SendAlert: Types.Update; + StartContainer: Types.Update; + RestartContainer: Types.Update; + PauseContainer: Types.Update; + UnpauseContainer: Types.Update; + StopContainer: Types.Update; + DestroyContainer: Types.Update; + StartAllContainers: Types.Update; + RestartAllContainers: Types.Update; + PauseAllContainers: Types.Update; + UnpauseAllContainers: Types.Update; + StopAllContainers: Types.Update; + PruneContainers: Types.Update; + DeleteNetwork: Types.Update; + PruneNetworks: Types.Update; + DeleteImage: Types.Update; + PruneImages: Types.Update; + DeleteVolume: Types.Update; + PruneVolumes: Types.Update; + PruneDockerBuilders: Types.Update; + PruneBuildx: Types.Update; + PruneSystem: Types.Update; + RemoveSwarmNodes: Types.Update; + RemoveSwarmStacks: Types.Update; + RemoveSwarmServices: Types.Update; + RemoveSwarmConfigs: Types.Update; + RemoveSwarmSecrets: Types.Update; ClearRepoCache: Types.Update; BackupCoreDatabase: Types.Update; GlobalAutoUpdate: Types.Update; diff --git a/frontend/public/client/types.d.ts b/frontend/public/client/types.d.ts index 8bd1e1ea4..3f569f79b 100644 --- a/frontend/public/client/types.d.ts +++ b/frontend/public/client/types.d.ts @@ -358,6 +358,11 @@ export declare enum Operation { UpdateSwarm = "UpdateSwarm", RenameSwarm = "RenameSwarm", DeleteSwarm = "DeleteSwarm", + RemoveSwarmNodes = "RemoveSwarmNodes", + RemoveSwarmStacks = "RemoveSwarmStacks", + RemoveSwarmServices = "RemoveSwarmServices", + RemoveSwarmConfigs = "RemoveSwarmConfigs", + RemoveSwarmSecrets = "RemoveSwarmSecrets", CreateServer = "CreateServer", UpdateServer = "UpdateServer", UpdateServerKey = "UpdateServerKey", @@ -815,32 +820,49 @@ export type Execution = type: "None"; params: NoData; } -/** Run the target action. (alias: `action`, `ac`) */ +/** Deploy the target stack. (alias: `stack`, `st`) */ | { - type: "RunAction"; - params: RunAction; + type: "DeployStack"; + params: DeployStack; } | { - type: "BatchRunAction"; - params: BatchRunAction; -} -/** Run the target procedure. (alias: `procedure`, `pr`) */ - | { - type: "RunProcedure"; - params: RunProcedure; + type: "BatchDeployStack"; + params: BatchDeployStack; } | { - type: "BatchRunProcedure"; - params: BatchRunProcedure; -} -/** Run the target build. (alias: `build`, `bd`) */ - | { - type: "RunBuild"; - params: RunBuild; + type: "DeployStackIfChanged"; + params: DeployStackIfChanged; } | { - type: "BatchRunBuild"; - params: BatchRunBuild; + type: "BatchDeployStackIfChanged"; + params: BatchDeployStackIfChanged; } | { - type: "CancelBuild"; - params: CancelBuild; + type: "PullStack"; + params: PullStack; +} | { + type: "BatchPullStack"; + params: BatchPullStack; +} | { + type: "StartStack"; + params: StartStack; +} | { + type: "RestartStack"; + params: RestartStack; +} | { + type: "PauseStack"; + params: PauseStack; +} | { + type: "UnpauseStack"; + params: UnpauseStack; +} | { + type: "StopStack"; + params: StopStack; +} | { + type: "DestroyStack"; + params: DestroyStack; +} | { + type: "BatchDestroyStack"; + params: BatchDestroyStack; +} | { + type: "RunStackService"; + params: RunStackService; } /** Deploy the target deployment. (alias: `dp`) */ | { @@ -874,6 +896,17 @@ export type Execution = type: "BatchDestroyDeployment"; params: BatchDestroyDeployment; } +/** Run the target build. (alias: `build`, `bd`) */ + | { + type: "RunBuild"; + params: RunBuild; +} | { + type: "BatchRunBuild"; + params: BatchRunBuild; +} | { + type: "CancelBuild"; + params: CancelBuild; +} /** Clone the target repo */ | { type: "CloneRepo"; @@ -896,6 +929,38 @@ export type Execution = } | { type: "CancelRepoBuild"; params: CancelRepoBuild; +} +/** Run the target procedure. (alias: `procedure`, `pr`) */ + | { + type: "RunProcedure"; + params: RunProcedure; +} | { + type: "BatchRunProcedure"; + params: BatchRunProcedure; +} +/** Run the target action. (alias: `action`, `ac`) */ + | { + type: "RunAction"; + params: RunAction; +} | { + type: "BatchRunAction"; + params: BatchRunAction; +} +/** Execute a Resource Sync. (alias: `sync`) */ + | { + type: "RunSync"; + params: RunSync; +} +/** Commit a Resource Sync. (alias: `commit`) */ + | { + type: "CommitSync"; + params: CommitSync; +} | { + type: "TestAlerter"; + params: TestAlerter; +} | { + type: "SendAlert"; + params: SendAlert; } | { type: "StartContainer"; params: StartContainer; @@ -959,66 +1024,21 @@ export type Execution = } | { type: "PruneSystem"; params: PruneSystem; -} -/** Execute a Resource Sync. (alias: `sync`) */ - | { - type: "RunSync"; - params: RunSync; -} -/** Commit a Resource Sync. (alias: `commit`) */ - | { - type: "CommitSync"; - params: CommitSync; -} -/** Deploy the target stack. (alias: `stack`, `st`) */ - | { - type: "DeployStack"; - params: DeployStack; } | { - type: "BatchDeployStack"; - params: BatchDeployStack; + type: "RemoveSwarmNodes"; + params: RemoveSwarmNodes; } | { - type: "DeployStackIfChanged"; - params: DeployStackIfChanged; + type: "RemoveSwarmStacks"; + params: RemoveSwarmStacks; } | { - type: "BatchDeployStackIfChanged"; - params: BatchDeployStackIfChanged; + type: "RemoveSwarmServices"; + params: RemoveSwarmServices; } | { - type: "PullStack"; - params: PullStack; + type: "RemoveSwarmConfigs"; + params: RemoveSwarmConfigs; } | { - type: "BatchPullStack"; - params: BatchPullStack; -} | { - type: "StartStack"; - params: StartStack; -} | { - type: "RestartStack"; - params: RestartStack; -} | { - type: "PauseStack"; - params: PauseStack; -} | { - type: "UnpauseStack"; - params: UnpauseStack; -} | { - type: "StopStack"; - params: StopStack; -} | { - type: "DestroyStack"; - params: DestroyStack; -} | { - type: "BatchDestroyStack"; - params: BatchDestroyStack; -} | { - type: "RunStackService"; - params: RunStackService; -} | { - type: "TestAlerter"; - params: TestAlerter; -} | { - type: "SendAlert"; - params: SendAlert; + type: "RemoveSwarmSecrets"; + params: RemoveSwarmSecrets; } | { type: "ClearRepoCache"; params: ClearRepoCache; @@ -8216,6 +8236,65 @@ export interface RefreshStackCache { /** Id or name */ stack: string; } +/** + * `docker config rm CONFIG [CONFIG...]` + * + * https://docs.docker.com/reference/cli/docker/config/rm/ + */ +export interface RemoveSwarmConfigs { + /** Name or id */ + swarm: string; + /** Config names or ids */ + configs: string[]; +} +/** + * `docker node rm [OPTIONS] NODE [NODE...]` + * + * https://docs.docker.com/reference/cli/docker/node/rm/ + */ +export interface RemoveSwarmNodes { + /** Name or id */ + swarm: string; + /** Node names or ids to remove */ + nodes: string[]; + /** Force remove a node from the swarm */ + force?: boolean; +} +/** + * `docker secret rm SECRET [SECRET...]` + * + * https://docs.docker.com/reference/cli/docker/secret/rm/ + */ +export interface RemoveSwarmSecrets { + /** Name or id */ + swarm: string; + /** Secret names or ids */ + secrets: string[]; +} +/** + * `docker service rm SERVICE [SERVICE...]` + * + * https://docs.docker.com/reference/cli/docker/service/rm/ + */ +export interface RemoveSwarmServices { + /** Name or id */ + swarm: string; + /** Service names or ids */ + services: string[]; +} +/** + * `docker stack rm [OPTIONS] STACK [STACK...]` + * + * https://docs.docker.com/reference/cli/docker/stack/rm/ + */ +export interface RemoveSwarmStacks { + /** Name or id */ + swarm: string; + /** Node names to remove */ + stacks: string[]; + /** Do not wait for stack removal */ + detach: boolean; +} /** **Admin only.** Remove a user from a user group. Response: [UserGroup] */ export interface RemoveUserFromUserGroup { /** The name or id of UserGroup that user should be removed from. */ @@ -9396,69 +9475,6 @@ export declare enum DayOfWeek { Sunday = "Sunday" } export type ExecuteRequest = { - type: "StartContainer"; - params: StartContainer; -} | { - type: "RestartContainer"; - params: RestartContainer; -} | { - type: "PauseContainer"; - params: PauseContainer; -} | { - type: "UnpauseContainer"; - params: UnpauseContainer; -} | { - type: "StopContainer"; - params: StopContainer; -} | { - type: "DestroyContainer"; - params: DestroyContainer; -} | { - type: "StartAllContainers"; - params: StartAllContainers; -} | { - type: "RestartAllContainers"; - params: RestartAllContainers; -} | { - type: "PauseAllContainers"; - params: PauseAllContainers; -} | { - type: "UnpauseAllContainers"; - params: UnpauseAllContainers; -} | { - type: "StopAllContainers"; - params: StopAllContainers; -} | { - type: "PruneContainers"; - params: PruneContainers; -} | { - type: "DeleteNetwork"; - params: DeleteNetwork; -} | { - type: "PruneNetworks"; - params: PruneNetworks; -} | { - type: "DeleteImage"; - params: DeleteImage; -} | { - type: "PruneImages"; - params: PruneImages; -} | { - type: "DeleteVolume"; - params: DeleteVolume; -} | { - type: "PruneVolumes"; - params: PruneVolumes; -} | { - type: "PruneDockerBuilders"; - params: PruneDockerBuilders; -} | { - type: "PruneBuildx"; - params: PruneBuildx; -} | { - type: "PruneSystem"; - params: PruneSystem; -} | { type: "DeployStack"; params: DeployStack; } | { @@ -9581,6 +9597,84 @@ export type ExecuteRequest = { } | { type: "SendAlert"; params: SendAlert; +} | { + type: "StartContainer"; + params: StartContainer; +} | { + type: "RestartContainer"; + params: RestartContainer; +} | { + type: "PauseContainer"; + params: PauseContainer; +} | { + type: "UnpauseContainer"; + params: UnpauseContainer; +} | { + type: "StopContainer"; + params: StopContainer; +} | { + type: "DestroyContainer"; + params: DestroyContainer; +} | { + type: "StartAllContainers"; + params: StartAllContainers; +} | { + type: "RestartAllContainers"; + params: RestartAllContainers; +} | { + type: "PauseAllContainers"; + params: PauseAllContainers; +} | { + type: "UnpauseAllContainers"; + params: UnpauseAllContainers; +} | { + type: "StopAllContainers"; + params: StopAllContainers; +} | { + type: "PruneContainers"; + params: PruneContainers; +} | { + type: "DeleteNetwork"; + params: DeleteNetwork; +} | { + type: "PruneNetworks"; + params: PruneNetworks; +} | { + type: "DeleteImage"; + params: DeleteImage; +} | { + type: "PruneImages"; + params: PruneImages; +} | { + type: "DeleteVolume"; + params: DeleteVolume; +} | { + type: "PruneVolumes"; + params: PruneVolumes; +} | { + type: "PruneDockerBuilders"; + params: PruneDockerBuilders; +} | { + type: "PruneBuildx"; + params: PruneBuildx; +} | { + type: "PruneSystem"; + params: PruneSystem; +} | { + type: "RemoveSwarmNodes"; + params: RemoveSwarmNodes; +} | { + type: "RemoveSwarmStacks"; + params: RemoveSwarmStacks; +} | { + type: "RemoveSwarmServices"; + params: RemoveSwarmServices; +} | { + type: "RemoveSwarmConfigs"; + params: RemoveSwarmConfigs; +} | { + type: "RemoveSwarmSecrets"; + params: RemoveSwarmSecrets; } | { type: "ClearRepoCache"; params: ClearRepoCache; diff --git a/frontend/public/client/types.js b/frontend/public/client/types.js index 63e8af7d6..272fe51ca 100644 --- a/frontend/public/client/types.js +++ b/frontend/public/client/types.js @@ -69,6 +69,11 @@ export var Operation; Operation["UpdateSwarm"] = "UpdateSwarm"; Operation["RenameSwarm"] = "RenameSwarm"; Operation["DeleteSwarm"] = "DeleteSwarm"; + Operation["RemoveSwarmNodes"] = "RemoveSwarmNodes"; + Operation["RemoveSwarmStacks"] = "RemoveSwarmStacks"; + Operation["RemoveSwarmServices"] = "RemoveSwarmServices"; + Operation["RemoveSwarmConfigs"] = "RemoveSwarmConfigs"; + Operation["RemoveSwarmSecrets"] = "RemoveSwarmSecrets"; Operation["CreateServer"] = "CreateServer"; Operation["UpdateServer"] = "UpdateServer"; Operation["UpdateServerKey"] = "UpdateServerKey";