docker_wrapper/command/
pause.rs

1//! Docker pause command implementation.
2//!
3//! This module provides the `docker pause` command for pausing all processes within containers.
4
5use super::{CommandExecutor, CommandOutput, DockerCommand};
6use crate::error::Result;
7use async_trait::async_trait;
8
9/// Docker pause command builder
10///
11/// Pause all processes within one or more containers.
12///
13/// # Example
14///
15/// ```no_run
16/// use docker_wrapper::PauseCommand;
17///
18/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
19/// // Pause a single container
20/// PauseCommand::new("my-container")
21///     .run()
22///     .await?;
23///
24/// // Pause multiple containers
25/// PauseCommand::new_multiple(vec!["web", "db", "cache"])
26///     .run()
27///     .await?;
28/// # Ok(())
29/// # }
30/// ```
31#[derive(Debug, Clone)]
32pub struct PauseCommand {
33    /// Container names or IDs to pause
34    containers: Vec<String>,
35    /// Command executor
36    pub executor: CommandExecutor,
37}
38
39impl PauseCommand {
40    /// Create a new pause command for a single container
41    ///
42    /// # Example
43    ///
44    /// ```
45    /// use docker_wrapper::PauseCommand;
46    ///
47    /// let cmd = PauseCommand::new("my-container");
48    /// ```
49    #[must_use]
50    pub fn new(container: impl Into<String>) -> Self {
51        Self {
52            containers: vec![container.into()],
53            executor: CommandExecutor::new(),
54        }
55    }
56
57    /// Create a new pause command for multiple containers
58    ///
59    /// # Example
60    ///
61    /// ```
62    /// use docker_wrapper::PauseCommand;
63    ///
64    /// let cmd = PauseCommand::new_multiple(vec!["web", "db", "cache"]);
65    /// ```
66    #[must_use]
67    pub fn new_multiple(containers: Vec<impl Into<String>>) -> Self {
68        Self {
69            containers: containers.into_iter().map(Into::into).collect(),
70            executor: CommandExecutor::new(),
71        }
72    }
73
74    /// Add another container to pause
75    #[must_use]
76    pub fn container(mut self, container: impl Into<String>) -> Self {
77        self.containers.push(container.into());
78        self
79    }
80
81    /// Execute the pause command
82    ///
83    /// # Errors
84    /// Returns an error if:
85    /// - The Docker daemon is not running
86    /// - Any of the specified containers don't exist
87    /// - Any container is not running
88    ///
89    /// # Example
90    ///
91    /// ```no_run
92    /// use docker_wrapper::PauseCommand;
93    ///
94    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
95    /// let result = PauseCommand::new("my-container")
96    ///     .run()
97    ///     .await?;
98    ///
99    /// if result.success() {
100    ///     println!("Paused {} containers", result.paused_containers().len());
101    /// }
102    /// # Ok(())
103    /// # }
104    /// ```
105    pub async fn run(&self) -> Result<PauseResult> {
106        let output = self.execute().await?;
107        Ok(PauseResult {
108            output,
109            containers: self.containers.clone(),
110        })
111    }
112}
113
114#[async_trait]
115impl DockerCommand for PauseCommand {
116    type Output = CommandOutput;
117
118    fn get_executor(&self) -> &CommandExecutor {
119        &self.executor
120    }
121
122    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
123        &mut self.executor
124    }
125
126    fn build_command_args(&self) -> Vec<String> {
127        let mut args = vec!["pause".to_string()];
128        args.extend(self.containers.clone());
129        args.extend(self.executor.raw_args.clone());
130        args
131    }
132
133    async fn execute(&self) -> Result<Self::Output> {
134        if self.containers.is_empty() {
135            return Err(crate::error::Error::invalid_config(
136                "No containers specified for pausing",
137            ));
138        }
139
140        let args = self.build_command_args();
141        let command_name = args[0].clone();
142        let command_args = args[1..].to_vec();
143        self.executor
144            .execute_command(&command_name, command_args)
145            .await
146    }
147}
148
149/// Result from the pause command
150#[derive(Debug, Clone)]
151pub struct PauseResult {
152    /// Raw command output
153    pub output: CommandOutput,
154    /// Containers that were paused
155    pub containers: Vec<String>,
156}
157
158impl PauseResult {
159    /// Check if the pause was successful
160    #[must_use]
161    pub fn success(&self) -> bool {
162        self.output.success
163    }
164
165    /// Get the paused container names
166    #[must_use]
167    pub fn paused_containers(&self) -> &[String] {
168        &self.containers
169    }
170
171    /// Get the count of paused containers
172    #[must_use]
173    pub fn paused_count(&self) -> usize {
174        self.containers.len()
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use super::*;
181
182    #[test]
183    fn test_pause_single_container() {
184        let cmd = PauseCommand::new("test-container");
185        let args = cmd.build_command_args();
186        assert_eq!(args, vec!["pause", "test-container"]);
187    }
188
189    #[test]
190    fn test_pause_multiple_containers() {
191        let cmd = PauseCommand::new_multiple(vec!["web", "db", "cache"]);
192        let args = cmd.build_command_args();
193        assert_eq!(args, vec!["pause", "web", "db", "cache"]);
194    }
195
196    #[test]
197    fn test_pause_add_container() {
198        let cmd = PauseCommand::new("web").container("db").container("cache");
199        let args = cmd.build_command_args();
200        assert_eq!(args, vec!["pause", "web", "db", "cache"]);
201    }
202}