contain_rs_core/client/
podman.rs

1use std::process::Command;
2
3use crate::{container::*, error::ContainerResult, rt::DetailedContainerInfo};
4
5use super::{
6    shared::{
7        build_rm_command, build_run_command, build_stop_command, do_log, inspect,
8        run_and_wait_for_command, wait_for,
9    },
10    Client, ContainerHandle, Log,
11};
12
13///
14/// The Podman struct is used for acessing the podman cli.
15///
16/// ```
17/// use contain_rs_core::{
18///     client::{podman::Podman, Client, Handle},
19///     container::{Container, Image, HealthCheck, WaitStrategy},
20/// };
21/// use std::str::FromStr;
22///
23/// let client = Podman::new();
24///
25/// let mut container = Container::from_image(Image::from_str("docker.io/library/nginx").unwrap());
26///
27/// container.health_check(HealthCheck::new("curl http://localhost || exit 1"))
28///     .wait_for(WaitStrategy::HealthCheck);
29///
30/// client.run(&container).unwrap();
31/// client.wait(&container).unwrap();
32/// client.rm(&container).unwrap();
33/// ```
34///
35#[allow(dead_code)]
36#[derive(Clone)]
37pub struct Podman {
38    host: Option<String>,
39}
40
41impl Podman {
42    const BINARY: &'static str = "podman";
43
44    pub fn new() -> Self {
45        Self { host: None }
46    }
47
48    fn build_command(&self) -> Command {
49        Command::new(Self::BINARY)
50    }
51}
52
53impl Default for Podman {
54    fn default() -> Self {
55        Self::new()
56    }
57}
58
59impl Client for Podman {
60    type ClientType = Self;
61
62    fn command(&self) -> Command {
63        self.build_command()
64    }
65
66    fn create<C: IntoContainer>(&self, container: C) -> ContainerHandle<Podman> {
67        ContainerHandle {
68            client: self.to_owned(),
69            container: container.into_container(),
70        }
71    }
72
73    fn run(&self, container: &Container) -> ContainerResult<()> {
74        let mut command = self.build_command();
75
76        build_run_command(&mut command, container);
77        run_and_wait_for_command(&mut command)?;
78
79        Ok(())
80    }
81
82    fn stop(&self, container: &Container) -> ContainerResult<()> {
83        let mut command = self.build_command();
84
85        build_stop_command(&mut command, container);
86        run_and_wait_for_command(&mut command)?;
87
88        Ok(())
89    }
90
91    fn rm(&self, container: &Container) -> ContainerResult<()> {
92        let mut command = self.build_command();
93
94        build_rm_command(&mut command, container);
95        run_and_wait_for_command(&mut command)?;
96
97        Ok(())
98    }
99
100    fn log(&self, container: &Container) -> ContainerResult<Option<Log>> {
101        if self.runs(container)? {
102            Ok(Some(do_log(self, container)?))
103        } else {
104            Ok(None)
105        }
106    }
107
108    fn inspect(&self, container: &Container) -> ContainerResult<Option<DetailedContainerInfo>> {
109        inspect(self, container)
110    }
111
112    fn exists(&self, container: &Container) -> ContainerResult<bool> {
113        Ok(self.inspect(container)?.is_some())
114    }
115
116    fn runs(&self, container: &Container) -> ContainerResult<bool> {
117        match self.inspect(container)? {
118            Some(detail) => Ok(detail.state.running),
119            None => Ok(false),
120        }
121    }
122
123    fn wait(&self, container: &Container) -> ContainerResult<()> {
124        wait_for(self, container)
125    }
126}