docker_wrapper/command/
compose_restart.rs1use super::{CommandExecutor, ComposeCommand, ComposeConfig, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6use std::time::Duration;
7
8#[derive(Debug, Clone)]
10pub struct ComposeRestartCommand {
11 pub executor: CommandExecutor,
13 pub config: ComposeConfig,
15 pub services: Vec<String>,
17 pub timeout: Option<Duration>,
19}
20
21#[derive(Debug, Clone)]
23pub struct ComposeRestartResult {
24 pub stdout: String,
26 pub stderr: String,
28 pub success: bool,
30 pub services: Vec<String>,
32}
33
34impl ComposeRestartCommand {
35 #[must_use]
37 pub fn new() -> Self {
38 Self {
39 executor: CommandExecutor::new(),
40 config: ComposeConfig::new(),
41 services: Vec::new(),
42 timeout: None,
43 }
44 }
45
46 #[must_use]
48 pub fn service(mut self, service: impl Into<String>) -> Self {
49 self.services.push(service.into());
50 self
51 }
52
53 #[must_use]
55 pub fn services<I, S>(mut self, services: I) -> Self
56 where
57 I: IntoIterator<Item = S>,
58 S: Into<String>,
59 {
60 self.services.extend(services.into_iter().map(Into::into));
61 self
62 }
63
64 #[must_use]
66 pub fn timeout(mut self, timeout: Duration) -> Self {
67 self.timeout = Some(timeout);
68 self
69 }
70}
71
72impl Default for ComposeRestartCommand {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78#[async_trait]
79impl DockerCommand for ComposeRestartCommand {
80 type Output = ComposeRestartResult;
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 fn build_command_args(&self) -> Vec<String> {
91 <Self as ComposeCommand>::build_command_args(self)
93 }
94
95 async fn execute(&self) -> Result<Self::Output> {
96 let args = <Self as ComposeCommand>::build_command_args(self);
97 let output = self.execute_command(args).await?;
98
99 Ok(ComposeRestartResult {
100 stdout: output.stdout,
101 stderr: output.stderr,
102 success: output.success,
103 services: self.services.clone(),
104 })
105 }
106}
107
108impl ComposeCommand for ComposeRestartCommand {
109 fn get_config(&self) -> &ComposeConfig {
110 &self.config
111 }
112
113 fn get_config_mut(&mut self) -> &mut ComposeConfig {
114 &mut self.config
115 }
116
117 fn subcommand(&self) -> &'static str {
118 "restart"
119 }
120
121 fn build_subcommand_args(&self) -> Vec<String> {
122 let mut args = Vec::new();
123
124 if let Some(timeout) = self.timeout {
125 args.push("--timeout".to_string());
126 args.push(timeout.as_secs().to_string());
127 }
128
129 args.extend(self.services.clone());
131
132 args
133 }
134}
135
136impl ComposeRestartResult {
137 #[must_use]
139 pub fn success(&self) -> bool {
140 self.success
141 }
142
143 #[must_use]
145 pub fn services(&self) -> &[String] {
146 &self.services
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_compose_restart_basic() {
156 let cmd = ComposeRestartCommand::new();
157 let args = cmd.build_subcommand_args();
158 assert!(args.is_empty());
159
160 let full_args = ComposeCommand::build_command_args(&cmd);
161 assert_eq!(full_args[0], "compose");
162 assert!(full_args.contains(&"restart".to_string()));
163 }
164
165 #[test]
166 fn test_compose_restart_with_services() {
167 let cmd = ComposeRestartCommand::new().service("web").service("db");
168 let args = cmd.build_subcommand_args();
169 assert_eq!(args, vec!["web", "db"]);
170 }
171
172 #[test]
173 fn test_compose_restart_with_timeout() {
174 let cmd = ComposeRestartCommand::new()
175 .timeout(Duration::from_secs(30))
176 .service("app");
177
178 let args = cmd.build_subcommand_args();
179 assert_eq!(args, vec!["--timeout", "30", "app"]);
180 }
181
182 #[test]
183 fn test_compose_restart_with_services_method() {
184 let cmd = ComposeRestartCommand::new().services(vec!["service1", "service2"]);
185 let args = cmd.build_subcommand_args();
186 assert_eq!(args, vec!["service1", "service2"]);
187 }
188
189 #[test]
190 fn test_compose_restart_builder_pattern() {
191 let cmd = ComposeRestartCommand::new()
192 .service("service1")
193 .service("service2")
194 .timeout(Duration::from_secs(60));
195
196 let args = cmd.build_subcommand_args();
197 assert_eq!(args, vec!["--timeout", "60", "service1", "service2"]);
198 }
199
200 #[test]
201 fn test_compose_config_integration() {
202 let cmd = ComposeRestartCommand::new()
203 .file("docker-compose.yml")
204 .project_name("myapp")
205 .timeout(Duration::from_secs(10))
206 .service("web");
207
208 let args = ComposeCommand::build_command_args(&cmd);
209 assert!(args.contains(&"--file".to_string()));
210 assert!(args.contains(&"docker-compose.yml".to_string()));
211 assert!(args.contains(&"--project-name".to_string()));
212 assert!(args.contains(&"myapp".to_string()));
213 assert!(args.contains(&"--timeout".to_string()));
214 assert!(args.contains(&"10".to_string()));
215 assert!(args.contains(&"web".to_string()));
216 }
217}