contain_rs_core/client/
docker.rs

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