docker_wrapper/command/swarm/
leave.rs

1//! Docker swarm leave command implementation.
2
3use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Result of swarm leave command
8#[derive(Debug, Clone)]
9pub struct SwarmLeaveResult {
10    /// Whether the leave was successful
11    pub success: bool,
12    /// Raw output from the command
13    pub output: String,
14}
15
16impl SwarmLeaveResult {
17    /// Parse the swarm leave output
18    fn parse(output: &CommandOutput) -> Self {
19        Self {
20            success: output.success,
21            output: output.stdout.clone(),
22        }
23    }
24}
25
26/// Docker swarm leave command builder
27#[derive(Debug, Clone, Default)]
28pub struct SwarmLeaveCommand {
29    /// Force leave even if this is the last manager
30    force: bool,
31    /// Command executor
32    pub executor: CommandExecutor,
33}
34
35impl SwarmLeaveCommand {
36    /// Create a new swarm leave command
37    #[must_use]
38    pub fn new() -> Self {
39        Self::default()
40    }
41
42    /// Force leave even if this is the last manager or cluster will become unavailable
43    #[must_use]
44    pub fn force(mut self) -> Self {
45        self.force = true;
46        self
47    }
48
49    /// Build the command arguments
50    fn build_args(&self) -> Vec<String> {
51        let mut args = vec!["swarm".to_string(), "leave".to_string()];
52
53        if self.force {
54            args.push("--force".to_string());
55        }
56
57        args
58    }
59}
60
61#[async_trait]
62impl DockerCommand for SwarmLeaveCommand {
63    type Output = SwarmLeaveResult;
64
65    fn get_executor(&self) -> &CommandExecutor {
66        &self.executor
67    }
68
69    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
70        &mut self.executor
71    }
72
73    fn build_command_args(&self) -> Vec<String> {
74        self.build_args()
75    }
76
77    async fn execute(&self) -> Result<Self::Output> {
78        let args = self.build_args();
79        let output = self.execute_command(args).await?;
80        Ok(SwarmLeaveResult::parse(&output))
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_swarm_leave_basic() {
90        let cmd = SwarmLeaveCommand::new();
91        let args = cmd.build_args();
92        assert_eq!(args, vec!["swarm", "leave"]);
93    }
94
95    #[test]
96    fn test_swarm_leave_force() {
97        let cmd = SwarmLeaveCommand::new().force();
98        let args = cmd.build_args();
99        assert!(args.contains(&"--force".to_string()));
100    }
101}