docker_wrapper/command/network/
rm.rs

1//! Docker network rm command implementation.
2
3use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Docker network rm command builder
8#[derive(Debug, Clone)]
9pub struct NetworkRmCommand {
10    /// Networks to remove
11    networks: Vec<String>,
12    /// Force removal
13    force: bool,
14    /// Command executor
15    pub executor: CommandExecutor,
16}
17
18impl NetworkRmCommand {
19    /// Create a new network rm command
20    #[must_use]
21    pub fn new(network: impl Into<String>) -> Self {
22        Self {
23            networks: vec![network.into()],
24            force: false,
25            executor: CommandExecutor::new(),
26        }
27    }
28
29    /// Create a new network rm command for multiple networks
30    #[must_use]
31    pub fn new_multiple(networks: Vec<String>) -> Self {
32        Self {
33            networks,
34            force: false,
35            executor: CommandExecutor::new(),
36        }
37    }
38
39    /// Add a network to remove
40    #[must_use]
41    pub fn add_network(mut self, network: impl Into<String>) -> Self {
42        self.networks.push(network.into());
43        self
44    }
45
46    /// Force removal
47    #[must_use]
48    pub fn force(mut self) -> Self {
49        self.force = true;
50        self
51    }
52
53    /// Execute the command
54    ///
55    /// # Errors
56    ///
57    /// Returns an error if the Docker daemon is not running or the command fails
58    pub async fn run(&self) -> Result<NetworkRmResult> {
59        self.execute().await.map(NetworkRmResult::from)
60    }
61}
62
63#[async_trait]
64impl DockerCommand for NetworkRmCommand {
65    type Output = CommandOutput;
66
67    fn build_command_args(&self) -> Vec<String> {
68        let mut args = vec!["network".to_string(), "rm".to_string()];
69
70        if self.force {
71            args.push("--force".to_string());
72        }
73
74        for network in &self.networks {
75            args.push(network.clone());
76        }
77
78        args.extend(self.executor.raw_args.clone());
79        args
80    }
81
82    fn get_executor(&self) -> &CommandExecutor {
83        &self.executor
84    }
85
86    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
87        &mut self.executor
88    }
89
90    async fn execute(&self) -> Result<Self::Output> {
91        let args = self.build_command_args();
92        let command_name = args[0].clone();
93        let command_args = args[1..].to_vec();
94        self.executor
95            .execute_command(&command_name, command_args)
96            .await
97    }
98}
99
100/// Result from network rm command
101#[derive(Debug, Clone)]
102pub struct NetworkRmResult {
103    /// Removed networks
104    pub removed_networks: Vec<String>,
105    /// Raw command output
106    pub raw_output: CommandOutput,
107}
108
109impl From<CommandOutput> for NetworkRmResult {
110    fn from(output: CommandOutput) -> Self {
111        let removed_networks = output
112            .stdout
113            .lines()
114            .filter(|line| !line.is_empty())
115            .map(String::from)
116            .collect();
117
118        Self {
119            removed_networks,
120            raw_output: output,
121        }
122    }
123}
124
125impl NetworkRmResult {
126    /// Check if the command was successful
127    #[must_use]
128    pub fn is_success(&self) -> bool {
129        self.raw_output.success
130    }
131
132    /// Get count of removed networks
133    #[must_use]
134    pub fn count(&self) -> usize {
135        self.removed_networks.len()
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_network_rm_single() {
145        let cmd = NetworkRmCommand::new("my-network");
146        let args = cmd.build_command_args();
147        assert_eq!(args, vec!["network", "rm", "my-network"]);
148    }
149
150    #[test]
151    fn test_network_rm_multiple() {
152        let cmd =
153            NetworkRmCommand::new_multiple(vec!["network1".to_string(), "network2".to_string()]);
154        let args = cmd.build_command_args();
155        assert_eq!(args, vec!["network", "rm", "network1", "network2"]);
156    }
157
158    #[test]
159    fn test_network_rm_force() {
160        let cmd = NetworkRmCommand::new("my-network").force();
161        let args = cmd.build_command_args();
162        assert_eq!(args, vec!["network", "rm", "--force", "my-network"]);
163    }
164}