docker_wrapper/command/
export.rs1use super::{CommandExecutor, CommandOutput, DockerCommand};
6use crate::error::Result;
7use async_trait::async_trait;
8
9#[derive(Debug, Clone)]
32pub struct ExportCommand {
33 container: String,
35 output: Option<String>,
37 pub executor: CommandExecutor,
39}
40
41impl ExportCommand {
42 #[must_use]
52 pub fn new(container: impl Into<String>) -> Self {
53 Self {
54 container: container.into(),
55 output: None,
56 executor: CommandExecutor::new(),
57 }
58 }
59
60 #[must_use]
71 pub fn output(mut self, output: impl Into<String>) -> Self {
72 self.output = Some(output.into());
73 self
74 }
75
76 pub async fn run(&self) -> Result<ExportResult> {
104 let output = self.execute().await?;
105
106 Ok(ExportResult {
107 output,
108 container: self.container.clone(),
109 output_file: self.output.clone(),
110 })
111 }
112}
113
114#[async_trait]
115impl DockerCommand for ExportCommand {
116 type Output = CommandOutput;
117
118 fn build_command_args(&self) -> Vec<String> {
119 let mut args = vec!["export".to_string()];
120
121 if let Some(ref output) = self.output {
122 args.push("--output".to_string());
123 args.push(output.clone());
124 }
125
126 args.push(self.container.clone());
127 args.extend(self.executor.raw_args.clone());
128 args
129 }
130
131 fn get_executor(&self) -> &CommandExecutor {
132 &self.executor
133 }
134
135 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
136 &mut self.executor
137 }
138
139 async fn execute(&self) -> Result<Self::Output> {
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#[derive(Debug, Clone)]
151pub struct ExportResult {
152 pub output: CommandOutput,
154 pub container: String,
156 pub output_file: Option<String>,
158}
159
160impl ExportResult {
161 #[must_use]
163 pub fn success(&self) -> bool {
164 self.output.success
165 }
166
167 #[must_use]
169 pub fn container(&self) -> &str {
170 &self.container
171 }
172
173 #[must_use]
175 pub fn output_file(&self) -> Option<&str> {
176 self.output_file.as_deref()
177 }
178
179 #[must_use]
181 pub fn output(&self) -> &CommandOutput {
182 &self.output
183 }
184
185 #[must_use]
187 pub fn exported_to_file(&self) -> bool {
188 self.output_file.is_some()
189 }
190
191 #[must_use]
193 pub fn exported_to_stdout(&self) -> bool {
194 self.output_file.is_none()
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_export_basic() {
204 let cmd = ExportCommand::new("test-container");
205 let args = cmd.build_command_args();
206 assert_eq!(args, vec!["export", "test-container"]);
207 }
208
209 #[test]
210 fn test_export_with_output() {
211 let cmd = ExportCommand::new("test-container").output("backup.tar");
212 let args = cmd.build_command_args();
213 assert_eq!(
214 args,
215 vec!["export", "--output", "backup.tar", "test-container"]
216 );
217 }
218
219 #[test]
220 fn test_export_with_path() {
221 let cmd = ExportCommand::new("web-server").output("/tmp/exports/web.tar");
222 let args = cmd.build_command_args();
223 assert_eq!(
224 args,
225 vec!["export", "--output", "/tmp/exports/web.tar", "web-server"]
226 );
227 }
228
229 #[test]
230 fn test_export_result() {
231 let result = ExportResult {
232 output: CommandOutput {
233 stdout: String::new(),
234 stderr: String::new(),
235 exit_code: 0,
236 success: true,
237 },
238 container: "my-container".to_string(),
239 output_file: Some("backup.tar".to_string()),
240 };
241
242 assert!(result.success());
243 assert_eq!(result.container(), "my-container");
244 assert_eq!(result.output_file(), Some("backup.tar"));
245 assert!(result.exported_to_file());
246 assert!(!result.exported_to_stdout());
247 }
248
249 #[test]
250 fn test_export_result_stdout() {
251 let result = ExportResult {
252 output: CommandOutput {
253 stdout: "tar data...".to_string(),
254 stderr: String::new(),
255 exit_code: 0,
256 success: true,
257 },
258 container: "my-container".to_string(),
259 output_file: None,
260 };
261
262 assert!(result.success());
263 assert_eq!(result.container(), "my-container");
264 assert_eq!(result.output_file(), None);
265 assert!(!result.exported_to_file());
266 assert!(result.exported_to_stdout());
267 }
268}