podman_api/api/exec.rs
1use crate::{
2 conn::{tty, Headers, Payload},
3 opts, Result, Value,
4};
5
6use containers_api::url;
7
8#[derive(Debug)]
9/// [Api Reference](https://docs.podman.io/en/latest/_static/api.html?version=v4.3.1#tag/Exec)
10pub struct Exec {
11 podman: crate::Podman,
12 id: crate::Id,
13 is_tty: bool,
14 is_unchecked: bool,
15}
16
17impl Exec {
18 ///Exports an interface exposing operations against a Exec instance with TTY
19 pub(crate) fn new_tty(podman: crate::Podman, id: impl Into<crate::Id>) -> Self {
20 Exec {
21 podman,
22 id: id.into(),
23 is_tty: true,
24 is_unchecked: false,
25 }
26 }
27
28 ///Exports an interface exposing operations against a Exec instance without TTY
29 pub(crate) fn new_raw(podman: crate::Podman, id: impl Into<crate::Id>) -> Self {
30 Exec {
31 podman,
32 id: id.into(),
33 is_tty: false,
34 is_unchecked: false,
35 }
36 }
37
38 ///Exports an interface exposing operations against a Exec instance with unchecked TTY state
39 pub(crate) fn new_unchecked(podman: crate::Podman, id: impl Into<crate::Id>) -> Self {
40 Exec {
41 podman,
42 id: id.into(),
43 is_tty: false,
44 is_unchecked: true,
45 }
46 }
47
48 ///A getter for Exec id
49 pub fn id(&self) -> &crate::Id {
50 &self.id
51 }
52}
53
54#[derive(Debug)]
55/// Handle for Podman Execs.
56pub struct Execs {
57 podman: crate::Podman,
58}
59
60impl Execs {
61 ///Exports an interface for interacting with Podman Execs.
62 pub fn new(podman: crate::Podman) -> Self {
63 Execs { podman }
64 }
65
66 ///Returns a reference to a set of operations available to a specific Exec.
67 pub fn get(&self, id: impl Into<crate::Id>) -> Exec {
68 Exec::new_unchecked(self.podman.clone(), id)
69 }
70}
71
72impl Exec {
73 api_doc! {
74 Exec => StartLibpod
75 |
76 /// Starts a previously set up exec instance. If `detach` is true, this endpoint returns
77 /// immediately after starting the command. Otherwise, it sets up an interactive session
78 /// with the command.
79 ///
80 /// To create an exec instance use [`Container::create_exec`](crate::api::Container::create_exec).
81 ///
82 /// Examples:
83 ///
84 /// ```no_run
85 /// async {
86 /// use podman_api::Podman;
87 /// use futures_util::StreamExt;
88 /// let podman = Podman::unix("/run/user/1000/podman/podman.sock");
89 /// let container = podman.containers().get("451b27c6b9d3");
90 ///
91 /// let exec = container
92 /// .create_exec(
93 /// &podman_api::opts::ExecCreateOpts::builder()
94 /// .command(["cat", "/some/path/in/container"])
95 /// .build(),
96 /// )
97 /// .await
98 /// .unwrap();
99 ///
100 /// let opts = Default::default();
101 /// let mut stream = exec.start(&opts).await.unwrap().unwrap();
102 ///
103 /// while let Some(chunk) = stream.next().await {
104 /// println!("{:?}", chunk.unwrap());
105 /// }
106 /// };
107 /// ```
108 pub async fn start<'exec>(
109 &'exec self,
110 opts: &'exec opts::ExecStartOpts,
111 ) -> Result<Option<tty::Multiplexer<'exec>>> {
112 if self.is_unchecked {
113 return Err(crate::Error::UncheckedExec);
114 }
115
116 let ep = format!("/libpod/exec/{}/start", &self.id);
117
118 let payload = Payload::Json(
119 opts.serialize()
120 .map_err(|e| crate::conn::Error::Any(Box::new(e)))?,
121 );
122
123 let detach = opts.params.get("Detach").and_then(|value| value.as_bool()).unwrap_or(false);
124
125 if !detach {
126 self.podman.post_upgrade_stream(ep, payload).await.map(|x| {
127 if self.is_tty {
128 Some(tty::Multiplexer::new(x, tty::decode_raw))
129 } else {
130 Some(tty::Multiplexer::new(x, tty::decode_chunk))
131 }
132 })
133 } else {
134 self.podman.post(ep, payload, None).await.map(|_| None)
135 }
136 }}
137
138 api_doc! {
139 Exec => InspectLibpod
140 |
141 /// Returns low-level information about an exec instance.
142 ///
143 /// Examples:
144 ///
145 /// ```no_run
146 /// async {
147 /// use podman_api::Podman;
148 /// use futures_util::StreamExt;
149 /// let podman = Podman::unix("/run/user/1000/podman/podman.sock");
150 /// let container = podman.containers().get("451b27c6b9d3");
151 ///
152 /// let exec = container
153 /// .create_exec(
154 /// &podman_api::opts::ExecCreateOpts::builder()
155 /// .command(["cat", "/some/path/in/container"])
156 /// .build(),
157 /// )
158 /// .await
159 /// .unwrap();
160 ///
161 /// match exec.inspect().await {
162 /// Ok(info) => println!("{:?}", info),
163 /// Err(e) => eprintln!("{}", e)
164 /// }
165 /// };
166 /// ```
167 pub async fn inspect(&self) -> Result<Value> {
168 let ep = format!("/libpod/exec/{}/json", &self.id);
169 self.podman.get_json(&ep).await
170 }}
171
172 api_doc! {
173 Exec => ResizeLibpod
174 |
175 /// Resize the TTY session used by an exec instance. This endpoint only works if
176 /// tty was specified as part of creating and starting the exec instance.
177 ///
178 /// Examples:
179 ///
180 /// ```no_run
181 /// use futures_util::StreamExt;
182 /// async {
183 /// use podman_api::Podman;
184 /// let podman = Podman::unix("/run/user/1000/podman/podman.sock");
185 /// let container = podman.containers().get("451b27c6b9d3");
186 ///
187 /// let exec = container
188 /// .create_exec(
189 /// &podman_api::opts::ExecCreateOpts::builder()
190 /// .command(["cat", "/some/path/in/container"])
191 /// .build(),
192 /// )
193 /// .await
194 /// .unwrap();
195 ///
196 /// if let Err(e) = exec.resize(1280, 720).await {
197 /// eprintln!("{}", e);
198 /// }
199 /// };
200 /// ```
201 pub async fn resize(&self, width: usize, heigth: usize) -> Result<()> {
202 let ep = url::construct_ep(
203 format!("/libpod/exec/{}/resize", &self.id),
204 Some(url::encoded_pairs([
205 ("h", heigth.to_string()),
206 ("w", width.to_string()),
207 ])),
208 );
209 self.podman.post(&ep, Payload::None::<&str>, Headers::none()).await.map(|_| ())
210 }}
211}