contain_rs_core/client/
mod.rs1use std::{
8 io::{BufRead, BufReader},
9 process::Command,
10};
11
12use os_pipe::PipeReader;
13
14use crate::{
15 container::{Container, IntoContainer},
16 error::ContainerResult,
17 rt::DetailedContainerInfo,
18};
19
20pub mod docker;
21pub mod podman;
22pub mod shared;
23
24pub trait Client: Clone {
32 type ClientType: Client;
33
34 fn command(&self) -> Command;
35 fn create<C: IntoContainer>(&self, container: C) -> ContainerHandle<Self::ClientType>;
36 fn run(&self, container: &Container) -> ContainerResult<()>;
37 fn stop(&self, container: &Container) -> ContainerResult<()>;
38 fn rm(&self, container: &Container) -> ContainerResult<()>;
39 fn log(&self, container: &Container) -> ContainerResult<Option<Log>>;
40 fn inspect(&self, container: &Container) -> ContainerResult<Option<DetailedContainerInfo>>;
41 fn exists(&self, container: &Container) -> ContainerResult<bool>;
42 fn runs(&self, container: &Container) -> ContainerResult<bool>;
43 fn wait(&self, container: &Container) -> ContainerResult<()>;
44}
45
46pub trait Handle {
53 fn run(&self) -> ContainerResult<()>;
54 fn wait(&self) -> ContainerResult<()>;
55 fn run_and_wait(&self) -> ContainerResult<()>;
56 fn stop(&self) -> ContainerResult<()>;
57 fn rm(&self) -> ContainerResult<()>;
58 fn log(&self) -> ContainerResult<Option<Log>>;
59 fn container(&self) -> &Container;
60 fn is_running(&self) -> ContainerResult<bool>;
61 fn exists(&self) -> ContainerResult<bool>;
62}
63
64pub struct Log {
65 pub reader: PipeReader,
66}
67
68impl Log {
69 fn stream(&mut self) -> impl BufRead {
70 BufReader::new(self.reader.try_clone().unwrap())
71 }
72}
73
74pub struct ContainerHandle<T: Client> {
75 client: T,
76 container: Container,
77}
78
79impl<T: Client> Handle for ContainerHandle<T> {
80 fn run(&self) -> ContainerResult<()> {
81 if !self.is_running()? {
82 self.client.run(&self.container)?;
83 }
84
85 Ok(())
86 }
87
88 fn wait(&self) -> ContainerResult<()> {
89 self.client.wait(&self.container)?;
90
91 Ok(())
92 }
93
94 fn run_and_wait(&self) -> ContainerResult<()> {
95 if !self.is_running()? {
96 self.run()?;
97 self.wait()?;
98 }
99
100 Ok(())
101 }
102
103 fn stop(&self) -> ContainerResult<()> {
104 if self.is_running()? {
105 self.client.stop(&self.container)?
106 }
107
108 Ok(())
109 }
110
111 fn rm(&self) -> ContainerResult<()> {
112 self.stop()?;
113
114 if self.exists()? {
115 self.client.rm(&self.container)?
116 }
117
118 Ok(())
119 }
120
121 fn log(&self) -> ContainerResult<Option<Log>> {
122 if self.is_running()? {
123 Ok(self.client.log(&self.container)?)
124 } else {
125 Ok(None)
126 }
127 }
128
129 fn container(&self) -> &Container {
130 &self.container
131 }
132
133 fn is_running(&self) -> ContainerResult<bool> {
134 Ok(self.exists()? && self.client.runs(&self.container)?)
135 }
136
137 fn exists(&self) -> ContainerResult<bool> {
138 self.client.exists(&self.container)
139 }
140}
141
142impl<T: Client> Drop for ContainerHandle<T> {
143 fn drop(&mut self) {
144 self.rm().unwrap();
145 }
146}