docker_wrapper/command/builder/
create.rs1use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7#[derive(Debug, Clone)]
9pub struct BuildxCreateResult {
10 pub name: String,
12 pub output: String,
14 pub success: bool,
16}
17
18impl BuildxCreateResult {
19 fn parse(output: &CommandOutput) -> Self {
21 let name = output.stdout.trim().to_string();
23 Self {
24 name,
25 output: output.stdout.clone(),
26 success: output.success,
27 }
28 }
29}
30
31#[derive(Debug, Clone, Default)]
57#[allow(clippy::struct_excessive_bools)]
58pub struct BuildxCreateCommand {
59 context: Option<String>,
61 append: bool,
63 bootstrap: bool,
65 buildkitd_config: Option<String>,
67 buildkitd_flags: Option<String>,
69 driver: Option<String>,
71 driver_opts: Vec<String>,
73 leave: bool,
75 name: Option<String>,
77 node: Option<String>,
79 platforms: Vec<String>,
81 use_builder: bool,
83 pub executor: CommandExecutor,
85}
86
87impl BuildxCreateCommand {
88 #[must_use]
90 pub fn new() -> Self {
91 Self::default()
92 }
93
94 #[must_use]
96 pub fn context(mut self, context: impl Into<String>) -> Self {
97 self.context = Some(context.into());
98 self
99 }
100
101 #[must_use]
103 pub fn append(mut self) -> Self {
104 self.append = true;
105 self
106 }
107
108 #[must_use]
110 pub fn bootstrap(mut self) -> Self {
111 self.bootstrap = true;
112 self
113 }
114
115 #[must_use]
117 pub fn buildkitd_config(mut self, config: impl Into<String>) -> Self {
118 self.buildkitd_config = Some(config.into());
119 self
120 }
121
122 #[must_use]
124 pub fn buildkitd_flags(mut self, flags: impl Into<String>) -> Self {
125 self.buildkitd_flags = Some(flags.into());
126 self
127 }
128
129 #[must_use]
131 pub fn driver(mut self, driver: impl Into<String>) -> Self {
132 self.driver = Some(driver.into());
133 self
134 }
135
136 #[must_use]
138 pub fn driver_opt(mut self, opt: impl Into<String>) -> Self {
139 self.driver_opts.push(opt.into());
140 self
141 }
142
143 #[must_use]
145 pub fn leave(mut self) -> Self {
146 self.leave = true;
147 self
148 }
149
150 #[must_use]
152 pub fn name(mut self, name: impl Into<String>) -> Self {
153 self.name = Some(name.into());
154 self
155 }
156
157 #[must_use]
159 pub fn node(mut self, node: impl Into<String>) -> Self {
160 self.node = Some(node.into());
161 self
162 }
163
164 #[must_use]
166 pub fn platform(mut self, platform: impl Into<String>) -> Self {
167 self.platforms.push(platform.into());
168 self
169 }
170
171 #[must_use]
173 pub fn use_builder(mut self) -> Self {
174 self.use_builder = true;
175 self
176 }
177
178 fn build_args(&self) -> Vec<String> {
180 let mut args = vec!["buildx".to_string(), "create".to_string()];
181
182 if self.append {
183 args.push("--append".to_string());
184 }
185
186 if self.bootstrap {
187 args.push("--bootstrap".to_string());
188 }
189
190 if let Some(ref config) = self.buildkitd_config {
191 args.push("--buildkitd-config".to_string());
192 args.push(config.clone());
193 }
194
195 if let Some(ref flags) = self.buildkitd_flags {
196 args.push("--buildkitd-flags".to_string());
197 args.push(flags.clone());
198 }
199
200 if let Some(ref driver) = self.driver {
201 args.push("--driver".to_string());
202 args.push(driver.clone());
203 }
204
205 for opt in &self.driver_opts {
206 args.push("--driver-opt".to_string());
207 args.push(opt.clone());
208 }
209
210 if self.leave {
211 args.push("--leave".to_string());
212 }
213
214 if let Some(ref name) = self.name {
215 args.push("--name".to_string());
216 args.push(name.clone());
217 }
218
219 if let Some(ref node) = self.node {
220 args.push("--node".to_string());
221 args.push(node.clone());
222 }
223
224 for platform in &self.platforms {
225 args.push("--platform".to_string());
226 args.push(platform.clone());
227 }
228
229 if self.use_builder {
230 args.push("--use".to_string());
231 }
232
233 if let Some(ref context) = self.context {
234 args.push(context.clone());
235 }
236
237 args.extend(self.executor.raw_args.clone());
238
239 args
240 }
241}
242
243#[async_trait]
244impl DockerCommand for BuildxCreateCommand {
245 type Output = BuildxCreateResult;
246
247 fn get_executor(&self) -> &CommandExecutor {
248 &self.executor
249 }
250
251 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
252 &mut self.executor
253 }
254
255 fn build_command_args(&self) -> Vec<String> {
256 self.build_args()
257 }
258
259 async fn execute(&self) -> Result<Self::Output> {
260 let args = self.build_args();
261 let output = self.execute_command(args).await?;
262 Ok(BuildxCreateResult::parse(&output))
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269
270 #[test]
271 fn test_buildx_create_basic() {
272 let cmd = BuildxCreateCommand::new();
273 let args = cmd.build_args();
274 assert_eq!(args, vec!["buildx", "create"]);
275 }
276
277 #[test]
278 fn test_buildx_create_with_name() {
279 let cmd = BuildxCreateCommand::new().name("mybuilder");
280 let args = cmd.build_args();
281 assert!(args.contains(&"--name".to_string()));
282 assert!(args.contains(&"mybuilder".to_string()));
283 }
284
285 #[test]
286 fn test_buildx_create_with_driver() {
287 let cmd = BuildxCreateCommand::new().driver("docker-container");
288 let args = cmd.build_args();
289 assert!(args.contains(&"--driver".to_string()));
290 assert!(args.contains(&"docker-container".to_string()));
291 }
292
293 #[test]
294 fn test_buildx_create_with_platforms() {
295 let cmd = BuildxCreateCommand::new()
296 .platform("linux/amd64")
297 .platform("linux/arm64");
298 let args = cmd.build_args();
299 assert!(args.contains(&"--platform".to_string()));
300 assert!(args.contains(&"linux/amd64".to_string()));
301 assert!(args.contains(&"linux/arm64".to_string()));
302 }
303
304 #[test]
305 fn test_buildx_create_all_options() {
306 let cmd = BuildxCreateCommand::new()
307 .name("mybuilder")
308 .driver("docker-container")
309 .driver_opt("network=host")
310 .platform("linux/amd64")
311 .bootstrap()
312 .use_builder()
313 .append();
314 let args = cmd.build_args();
315 assert!(args.contains(&"--name".to_string()));
316 assert!(args.contains(&"--driver".to_string()));
317 assert!(args.contains(&"--driver-opt".to_string()));
318 assert!(args.contains(&"--platform".to_string()));
319 assert!(args.contains(&"--bootstrap".to_string()));
320 assert!(args.contains(&"--use".to_string()));
321 assert!(args.contains(&"--append".to_string()));
322 }
323}