sal_virt/buildah/builder.rs
1use crate::buildah::{
2 execute_buildah_command, set_thread_local_debug, thread_local_debug, BuildahError, Image,
3};
4use sal_process::CommandResult;
5use std::collections::HashMap;
6
7/// Builder struct for buildah operations
8#[derive(Clone)]
9pub struct Builder {
10 /// Name of the container
11 name: String,
12 /// Container ID
13 container_id: Option<String>,
14 /// Base image
15 image: String,
16 /// Debug mode
17 debug: bool,
18}
19
20impl Builder {
21 /// Create a new builder with a container from the specified image
22 ///
23 /// # Arguments
24 ///
25 /// * `name` - Name for the container
26 /// * `image` - Image to create the container from
27 ///
28 /// # Returns
29 ///
30 /// * `Result<Self, BuildahError>` - Builder instance or error
31 pub fn new(name: &str, image: &str) -> Result<Self, BuildahError> {
32 // Try to create a new container
33 let result = execute_buildah_command(&["from", "--name", name, image]);
34
35 match result {
36 Ok(success_result) => {
37 // Container created successfully
38 let container_id = success_result.stdout.trim().to_string();
39
40 Ok(Self {
41 name: name.to_string(),
42 container_id: Some(container_id),
43 image: image.to_string(),
44 debug: false,
45 })
46 }
47 Err(BuildahError::CommandFailed(error_msg)) => {
48 // Check if the error is because the container already exists
49 if error_msg.contains("that name is already in use") {
50 // Extract the container ID from the error message
51 // Error format: "the container name "name" is already in use by container_id. You have to remove that container to be able to reuse that name: that name is already in use"
52 let container_id = error_msg
53 .split("already in use by ")
54 .nth(1)
55 .and_then(|s| s.split('.').next())
56 .unwrap_or("")
57 .trim()
58 .to_string();
59
60 if !container_id.is_empty() {
61 // Container already exists, continue with it
62 Ok(Self {
63 name: name.to_string(),
64 container_id: Some(container_id),
65 image: image.to_string(),
66 debug: false,
67 })
68 } else {
69 // Couldn't extract container ID
70 Err(BuildahError::Other(
71 "Failed to extract container ID from error message".to_string(),
72 ))
73 }
74 } else {
75 // Other command failure
76 Err(BuildahError::CommandFailed(error_msg))
77 }
78 }
79 Err(e) => {
80 // Other error
81 Err(e)
82 }
83 }
84 }
85
86 /// Get the container ID
87 pub fn container_id(&self) -> Option<&String> {
88 self.container_id.as_ref()
89 }
90
91 /// Get the container name
92 pub fn name(&self) -> &str {
93 &self.name
94 }
95
96 /// Get the debug mode
97 pub fn debug(&self) -> bool {
98 self.debug
99 }
100
101 /// Set the debug mode
102 pub fn set_debug(&mut self, debug: bool) -> &mut Self {
103 self.debug = debug;
104 self
105 }
106
107 /// Get the base image
108 pub fn image(&self) -> &str {
109 &self.image
110 }
111
112 /// Run a command in the container
113 ///
114 /// # Arguments
115 ///
116 /// * `command` - The command to run
117 ///
118 /// # Returns
119 ///
120 /// * `Result<CommandResult, BuildahError>` - Command result or error
121 pub fn run(&self, command: &str) -> Result<CommandResult, BuildahError> {
122 if let Some(container_id) = &self.container_id {
123 // Save the current debug flag
124 let previous_debug = thread_local_debug();
125
126 // Set the thread-local debug flag from the Builder's debug flag
127 set_thread_local_debug(self.debug);
128
129 // Execute the command
130 let result = execute_buildah_command(&["run", container_id, "sh", "-c", command]);
131
132 // Restore the previous debug flag
133 set_thread_local_debug(previous_debug);
134
135 result
136 } else {
137 Err(BuildahError::Other("No container ID available".to_string()))
138 }
139 }
140
141 /// Run a command in the container with specified isolation
142 ///
143 /// # Arguments
144 ///
145 /// * `command` - The command to run
146 /// * `isolation` - Isolation method (e.g., "chroot", "rootless", "oci")
147 ///
148 /// # Returns
149 ///
150 /// * `Result<CommandResult, BuildahError>` - Command result or error
151 pub fn run_with_isolation(
152 &self,
153 command: &str,
154 isolation: &str,
155 ) -> Result<CommandResult, BuildahError> {
156 if let Some(container_id) = &self.container_id {
157 // Save the current debug flag
158 let previous_debug = thread_local_debug();
159
160 // Set the thread-local debug flag from the Builder's debug flag
161 set_thread_local_debug(self.debug);
162
163 // Execute the command
164 let result = execute_buildah_command(&[
165 "run",
166 "--isolation",
167 isolation,
168 container_id,
169 "sh",
170 "-c",
171 command,
172 ]);
173
174 // Restore the previous debug flag
175 set_thread_local_debug(previous_debug);
176
177 result
178 } else {
179 Err(BuildahError::Other("No container ID available".to_string()))
180 }
181 }
182
183 /// Copy files into the container
184 ///
185 /// # Arguments
186 ///
187 /// * `source` - Source path
188 /// * `dest` - Destination path in the container
189 ///
190 /// # Returns
191 ///
192 /// * `Result<CommandResult, BuildahError>` - Command result or error
193 pub fn copy(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
194 if let Some(container_id) = &self.container_id {
195 // Save the current debug flag
196 let previous_debug = thread_local_debug();
197
198 // Set the thread-local debug flag from the Builder's debug flag
199 set_thread_local_debug(self.debug);
200
201 // Execute the command
202 let result = execute_buildah_command(&["copy", container_id, source, dest]);
203
204 // Restore the previous debug flag
205 set_thread_local_debug(previous_debug);
206
207 result
208 } else {
209 Err(BuildahError::Other("No container ID available".to_string()))
210 }
211 }
212
213 /// Add files into the container
214 ///
215 /// # Arguments
216 ///
217 /// * `source` - Source path
218 /// * `dest` - Destination path in the container
219 ///
220 /// # Returns
221 ///
222 /// * `Result<CommandResult, BuildahError>` - Command result or error
223 pub fn add(&self, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
224 if let Some(container_id) = &self.container_id {
225 // Save the current debug flag
226 let previous_debug = thread_local_debug();
227
228 // Set the thread-local debug flag from the Builder's debug flag
229 set_thread_local_debug(self.debug);
230
231 // Execute the command
232 let result = execute_buildah_command(&["add", container_id, source, dest]);
233
234 // Restore the previous debug flag
235 set_thread_local_debug(previous_debug);
236
237 result
238 } else {
239 Err(BuildahError::Other("No container ID available".to_string()))
240 }
241 }
242
243 /// Commit the container to an image
244 ///
245 /// # Arguments
246 ///
247 /// * `image_name` - Name for the new image
248 ///
249 /// # Returns
250 ///
251 /// * `Result<CommandResult, BuildahError>` - Command result or error
252 pub fn commit(&self, image_name: &str) -> Result<CommandResult, BuildahError> {
253 if let Some(container_id) = &self.container_id {
254 // Save the current debug flag
255 let previous_debug = thread_local_debug();
256
257 // Set the thread-local debug flag from the Builder's debug flag
258 set_thread_local_debug(self.debug);
259
260 // Execute the command
261 let result = execute_buildah_command(&["commit", container_id, image_name]);
262
263 // Restore the previous debug flag
264 set_thread_local_debug(previous_debug);
265
266 result
267 } else {
268 Err(BuildahError::Other("No container ID available".to_string()))
269 }
270 }
271
272 /// Remove the container
273 ///
274 /// # Returns
275 ///
276 /// * `Result<CommandResult, BuildahError>` - Command result or error
277 pub fn remove(&self) -> Result<CommandResult, BuildahError> {
278 if let Some(container_id) = &self.container_id {
279 // Save the current debug flag
280 let previous_debug = thread_local_debug();
281
282 // Set the thread-local debug flag from the Builder's debug flag
283 set_thread_local_debug(self.debug);
284
285 // Execute the command
286 let result = execute_buildah_command(&["rm", container_id]);
287
288 // Restore the previous debug flag
289 set_thread_local_debug(previous_debug);
290
291 result
292 } else {
293 Err(BuildahError::Other("No container ID available".to_string()))
294 }
295 }
296
297 /// Reset the builder by removing the container and clearing the container_id
298 ///
299 /// # Returns
300 ///
301 /// * `Result<(), BuildahError>` - Success or error
302 pub fn reset(&mut self) -> Result<(), BuildahError> {
303 if let Some(container_id) = &self.container_id {
304 // Save the current debug flag
305 let previous_debug = thread_local_debug();
306
307 // Set the thread-local debug flag from the Builder's debug flag
308 set_thread_local_debug(self.debug);
309
310 // Try to remove the container
311 let result = execute_buildah_command(&["rm", container_id]);
312
313 // Restore the previous debug flag
314 set_thread_local_debug(previous_debug);
315
316 // Clear the container_id regardless of whether the removal succeeded
317 self.container_id = None;
318
319 // Return the result of the removal operation
320 match result {
321 Ok(_) => Ok(()),
322 Err(e) => Err(e),
323 }
324 } else {
325 // No container to remove
326 Ok(())
327 }
328 }
329
330 /// Configure container metadata
331 ///
332 /// # Arguments
333 ///
334 /// * `options` - Map of configuration options
335 ///
336 /// # Returns
337 ///
338 /// * `Result<CommandResult, BuildahError>` - Command result or error
339 pub fn config(&self, options: HashMap<String, String>) -> Result<CommandResult, BuildahError> {
340 if let Some(container_id) = &self.container_id {
341 let mut args_owned: Vec<String> = Vec::new();
342 args_owned.push("config".to_string());
343
344 // Process options map
345 for (key, value) in options.iter() {
346 let option_name = format!("--{}", key);
347 args_owned.push(option_name);
348 args_owned.push(value.clone());
349 }
350
351 args_owned.push(container_id.clone());
352
353 // Convert Vec<String> to Vec<&str> for execute_buildah_command
354 let args: Vec<&str> = args_owned.iter().map(|s| s.as_str()).collect();
355
356 // Save the current debug flag
357 let previous_debug = thread_local_debug();
358
359 // Set the thread-local debug flag from the Builder's debug flag
360 set_thread_local_debug(self.debug);
361
362 // Execute the command
363 let result = execute_buildah_command(&args);
364
365 // Restore the previous debug flag
366 set_thread_local_debug(previous_debug);
367
368 result
369 } else {
370 Err(BuildahError::Other("No container ID available".to_string()))
371 }
372 }
373
374 /// Set the entrypoint for the container
375 ///
376 /// # Arguments
377 ///
378 /// * `entrypoint` - The entrypoint command
379 ///
380 /// # Returns
381 ///
382 /// * `Result<CommandResult, BuildahError>` - Command result or error
383 pub fn set_entrypoint(&self, entrypoint: &str) -> Result<CommandResult, BuildahError> {
384 if let Some(container_id) = &self.container_id {
385 // Save the current debug flag
386 let previous_debug = thread_local_debug();
387
388 // Set the thread-local debug flag from the Builder's debug flag
389 set_thread_local_debug(self.debug);
390
391 // Execute the command
392 let result =
393 execute_buildah_command(&["config", "--entrypoint", entrypoint, container_id]);
394
395 // Restore the previous debug flag
396 set_thread_local_debug(previous_debug);
397
398 result
399 } else {
400 Err(BuildahError::Other("No container ID available".to_string()))
401 }
402 }
403
404 /// Set the default command for the container
405 ///
406 /// # Arguments
407 ///
408 /// * `cmd` - The default command
409 ///
410 /// # Returns
411 ///
412 /// * `Result<CommandResult, BuildahError>` - Command result or error
413 pub fn set_cmd(&self, cmd: &str) -> Result<CommandResult, BuildahError> {
414 if let Some(container_id) = &self.container_id {
415 // Save the current debug flag
416 let previous_debug = thread_local_debug();
417
418 // Set the thread-local debug flag from the Builder's debug flag
419 set_thread_local_debug(self.debug);
420
421 // Execute the command
422 let result = execute_buildah_command(&["config", "--cmd", cmd, container_id]);
423
424 // Restore the previous debug flag
425 set_thread_local_debug(previous_debug);
426
427 result
428 } else {
429 Err(BuildahError::Other("No container ID available".to_string()))
430 }
431 }
432
433 /// List images in local storage
434 ///
435 /// # Returns
436 ///
437 /// * `Result<Vec<Image>, BuildahError>` - List of images or error
438 pub fn images() -> Result<Vec<Image>, BuildahError> {
439 // Use default debug value (false) for static method
440 let result = execute_buildah_command(&["images", "--json"])?;
441
442 // Try to parse the JSON output
443 match serde_json::from_str::<serde_json::Value>(&result.stdout) {
444 Ok(json) => {
445 if let serde_json::Value::Array(images_json) = json {
446 let mut images = Vec::new();
447
448 for image_json in images_json {
449 // Extract image ID
450 let id = match image_json.get("id").and_then(|v| v.as_str()) {
451 Some(id) => id.to_string(),
452 None => {
453 return Err(BuildahError::ConversionError(
454 "Missing image ID".to_string(),
455 ))
456 }
457 };
458
459 // Extract image names
460 let names = match image_json.get("names").and_then(|v| v.as_array()) {
461 Some(names_array) => {
462 let mut names_vec = Vec::new();
463 for name_value in names_array {
464 if let Some(name_str) = name_value.as_str() {
465 names_vec.push(name_str.to_string());
466 }
467 }
468 names_vec
469 }
470 None => Vec::new(), // Empty vector if no names found
471 };
472
473 // Extract image size
474 let size = match image_json.get("size").and_then(|v| v.as_str()) {
475 Some(size) => size.to_string(),
476 None => "Unknown".to_string(), // Default value if size not found
477 };
478
479 // Extract creation timestamp
480 let created = match image_json.get("created").and_then(|v| v.as_str()) {
481 Some(created) => created.to_string(),
482 None => "Unknown".to_string(), // Default value if created not found
483 };
484
485 // Create Image struct and add to vector
486 images.push(Image {
487 id,
488 names,
489 size,
490 created,
491 });
492 }
493
494 Ok(images)
495 } else {
496 Err(BuildahError::JsonParseError(
497 "Expected JSON array".to_string(),
498 ))
499 }
500 }
501 Err(e) => Err(BuildahError::JsonParseError(format!(
502 "Failed to parse image list JSON: {}",
503 e
504 ))),
505 }
506 }
507
508 /// Remove an image
509 ///
510 /// # Arguments
511 ///
512 /// * `image` - Image ID or name
513 ///
514 /// # Returns
515 ///
516 /// * `Result<CommandResult, BuildahError>` - Command result or error
517 pub fn image_remove(image: &str) -> Result<CommandResult, BuildahError> {
518 // Use default debug value (false) for static method
519 execute_buildah_command(&["rmi", image])
520 }
521
522 /// Remove an image with debug output
523 ///
524 /// # Arguments
525 ///
526 /// * `image` - Image ID or name
527 /// * `debug` - Whether to enable debug output
528 ///
529 /// # Returns
530 ///
531 /// * `Result<CommandResult, BuildahError>` - Command result or error
532 pub fn image_remove_with_debug(
533 image: &str,
534 debug: bool,
535 ) -> Result<CommandResult, BuildahError> {
536 // Save the current debug flag
537 let previous_debug = thread_local_debug();
538
539 // Set the thread-local debug flag
540 set_thread_local_debug(debug);
541
542 // Execute the command
543 let result = execute_buildah_command(&["rmi", image]);
544
545 // Restore the previous debug flag
546 set_thread_local_debug(previous_debug);
547
548 result
549 }
550
551 /// Pull an image from a registry
552 ///
553 /// # Arguments
554 ///
555 /// * `image` - Image name
556 /// * `tls_verify` - Whether to verify TLS
557 ///
558 /// # Returns
559 ///
560 /// * `Result<CommandResult, BuildahError>` - Command result or error
561 pub fn image_pull(image: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
562 // Use default debug value (false) for static method
563 let mut args = vec!["pull"];
564
565 if !tls_verify {
566 args.push("--tls-verify=false");
567 }
568
569 args.push(image);
570
571 execute_buildah_command(&args)
572 }
573
574 /// Pull an image from a registry with debug output
575 ///
576 /// # Arguments
577 ///
578 /// * `image` - Image name
579 /// * `tls_verify` - Whether to verify TLS
580 /// * `debug` - Whether to enable debug output
581 ///
582 /// # Returns
583 ///
584 /// * `Result<CommandResult, BuildahError>` - Command result or error
585 pub fn image_pull_with_debug(
586 image: &str,
587 tls_verify: bool,
588 debug: bool,
589 ) -> Result<CommandResult, BuildahError> {
590 // Save the current debug flag
591 let previous_debug = thread_local_debug();
592
593 // Set the thread-local debug flag
594 set_thread_local_debug(debug);
595
596 let mut args = vec!["pull"];
597
598 if !tls_verify {
599 args.push("--tls-verify=false");
600 }
601
602 args.push(image);
603
604 // Execute the command
605 let result = execute_buildah_command(&args);
606
607 // Restore the previous debug flag
608 set_thread_local_debug(previous_debug);
609
610 result
611 }
612
613 /// Push an image to a registry
614 ///
615 /// # Arguments
616 ///
617 /// * `image` - Image name
618 /// * `destination` - Destination registry
619 /// * `tls_verify` - Whether to verify TLS
620 ///
621 /// # Returns
622 ///
623 /// * `Result<CommandResult, BuildahError>` - Command result or error
624 pub fn image_push(
625 image: &str,
626 destination: &str,
627 tls_verify: bool,
628 ) -> Result<CommandResult, BuildahError> {
629 // Use default debug value (false) for static method
630 let mut args = vec!["push"];
631
632 if !tls_verify {
633 args.push("--tls-verify=false");
634 }
635
636 args.push(image);
637 args.push(destination);
638
639 execute_buildah_command(&args)
640 }
641
642 /// Push an image to a registry with debug output
643 ///
644 /// # Arguments
645 ///
646 /// * `image` - Image name
647 /// * `destination` - Destination registry
648 /// * `tls_verify` - Whether to verify TLS
649 /// * `debug` - Whether to enable debug output
650 ///
651 /// # Returns
652 ///
653 /// * `Result<CommandResult, BuildahError>` - Command result or error
654 pub fn image_push_with_debug(
655 image: &str,
656 destination: &str,
657 tls_verify: bool,
658 debug: bool,
659 ) -> Result<CommandResult, BuildahError> {
660 // Save the current debug flag
661 let previous_debug = thread_local_debug();
662
663 // Set the thread-local debug flag
664 set_thread_local_debug(debug);
665
666 let mut args = vec!["push"];
667
668 if !tls_verify {
669 args.push("--tls-verify=false");
670 }
671
672 args.push(image);
673 args.push(destination);
674
675 // Execute the command
676 let result = execute_buildah_command(&args);
677
678 // Restore the previous debug flag
679 set_thread_local_debug(previous_debug);
680
681 result
682 }
683
684 /// Tag an image
685 ///
686 /// # Arguments
687 ///
688 /// * `image` - Image ID or name
689 /// * `new_name` - New tag for the image
690 ///
691 /// # Returns
692 ///
693 /// * `Result<CommandResult, BuildahError>` - Command result or error
694 pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, BuildahError> {
695 // Use default debug value (false) for static method
696 execute_buildah_command(&["tag", image, new_name])
697 }
698
699 /// Tag an image with debug output
700 ///
701 /// # Arguments
702 ///
703 /// * `image` - Image ID or name
704 /// * `new_name` - New tag for the image
705 /// * `debug` - Whether to enable debug output
706 ///
707 /// # Returns
708 ///
709 /// * `Result<CommandResult, BuildahError>` - Command result or error
710 pub fn image_tag_with_debug(
711 image: &str,
712 new_name: &str,
713 debug: bool,
714 ) -> Result<CommandResult, BuildahError> {
715 // Save the current debug flag
716 let previous_debug = thread_local_debug();
717
718 // Set the thread-local debug flag
719 set_thread_local_debug(debug);
720
721 // Execute the command
722 let result = execute_buildah_command(&["tag", image, new_name]);
723
724 // Restore the previous debug flag
725 set_thread_local_debug(previous_debug);
726
727 result
728 }
729
730 /// Commit a container to an image with advanced options
731 ///
732 /// # Arguments
733 ///
734 /// * `container` - Container ID or name
735 /// * `image_name` - Name for the new image
736 /// * `format` - Optional format (oci or docker)
737 /// * `squash` - Whether to squash layers
738 /// * `rm` - Whether to remove the container after commit
739 ///
740 /// # Returns
741 ///
742 /// * `Result<CommandResult, BuildahError>` - Command result or error
743 pub fn image_commit(
744 container: &str,
745 image_name: &str,
746 format: Option<&str>,
747 squash: bool,
748 rm: bool,
749 ) -> Result<CommandResult, BuildahError> {
750 // Use default debug value (false) for static method
751 let mut args = vec!["commit"];
752
753 if let Some(format_str) = format {
754 args.push("--format");
755 args.push(format_str);
756 }
757
758 if squash {
759 args.push("--squash");
760 }
761
762 if rm {
763 args.push("--rm");
764 }
765
766 args.push(container);
767 args.push(image_name);
768
769 execute_buildah_command(&args)
770 }
771
772 /// Commit a container to an image with advanced options and debug output
773 ///
774 /// # Arguments
775 ///
776 /// * `container` - Container ID or name
777 /// * `image_name` - Name for the new image
778 /// * `format` - Optional format (oci or docker)
779 /// * `squash` - Whether to squash layers
780 /// * `rm` - Whether to remove the container after commit
781 /// * `debug` - Whether to enable debug output
782 ///
783 /// # Returns
784 ///
785 /// * `Result<CommandResult, BuildahError>` - Command result or error
786 pub fn image_commit_with_debug(
787 container: &str,
788 image_name: &str,
789 format: Option<&str>,
790 squash: bool,
791 rm: bool,
792 debug: bool,
793 ) -> Result<CommandResult, BuildahError> {
794 // Save the current debug flag
795 let previous_debug = thread_local_debug();
796
797 // Set the thread-local debug flag
798 set_thread_local_debug(debug);
799
800 let mut args = vec!["commit"];
801
802 if let Some(format_str) = format {
803 args.push("--format");
804 args.push(format_str);
805 }
806
807 if squash {
808 args.push("--squash");
809 }
810
811 if rm {
812 args.push("--rm");
813 }
814
815 args.push(container);
816 args.push(image_name);
817
818 // Execute the command
819 let result = execute_buildah_command(&args);
820
821 // Restore the previous debug flag
822 set_thread_local_debug(previous_debug);
823
824 result
825 }
826
827 /// Build an image from a Containerfile/Dockerfile
828 ///
829 /// # Arguments
830 ///
831 /// * `tag` - Optional tag for the image
832 /// * `context_dir` - Directory containing the Containerfile/Dockerfile
833 /// * `file` - Path to the Containerfile/Dockerfile
834 /// * `isolation` - Optional isolation method
835 ///
836 /// # Returns
837 ///
838 /// * `Result<CommandResult, BuildahError>` - Command result or error
839 pub fn build(
840 tag: Option<&str>,
841 context_dir: &str,
842 file: &str,
843 isolation: Option<&str>,
844 ) -> Result<CommandResult, BuildahError> {
845 // Use default debug value (false) for static method
846 let mut args = Vec::new();
847 args.push("build");
848
849 if let Some(tag_value) = tag {
850 args.push("-t");
851 args.push(tag_value);
852 }
853
854 if let Some(isolation_value) = isolation {
855 args.push("--isolation");
856 args.push(isolation_value);
857 }
858
859 args.push("-f");
860 args.push(file);
861
862 args.push(context_dir);
863
864 execute_buildah_command(&args)
865 }
866
867 /// Build an image from a Containerfile/Dockerfile with debug output
868 ///
869 /// # Arguments
870 ///
871 /// * `tag` - Optional tag for the image
872 /// * `context_dir` - Directory containing the Containerfile/Dockerfile
873 /// * `file` - Path to the Containerfile/Dockerfile
874 /// * `isolation` - Optional isolation method
875 /// * `debug` - Whether to enable debug output
876 ///
877 /// # Returns
878 ///
879 /// * `Result<CommandResult, BuildahError>` - Command result or error
880 pub fn build_with_debug(
881 tag: Option<&str>,
882 context_dir: &str,
883 file: &str,
884 isolation: Option<&str>,
885 debug: bool,
886 ) -> Result<CommandResult, BuildahError> {
887 // Save the current debug flag
888 let previous_debug = thread_local_debug();
889
890 // Set the thread-local debug flag
891 set_thread_local_debug(debug);
892
893 let mut args = Vec::new();
894 args.push("build");
895
896 if let Some(tag_value) = tag {
897 args.push("-t");
898 args.push(tag_value);
899 }
900
901 if let Some(isolation_value) = isolation {
902 args.push("--isolation");
903 args.push(isolation_value);
904 }
905
906 args.push("-f");
907 args.push(file);
908
909 args.push(context_dir);
910
911 // Execute the command
912 let result = execute_buildah_command(&args);
913
914 // Restore the previous debug flag
915 set_thread_local_debug(previous_debug);
916
917 result
918 }
919}