1use hyper::Body;
4
5use crate::{
6 conn::{tty, Headers, Payload},
7 models,
8 opts::{ExecCreateOpts, ExecResizeOpts, ExecStartOpts},
9 stream, Docker, Result,
10};
11
12api_doc! { Exec
13|
15pub struct Exec {
16 docker: Docker,
17 id: crate::Id,
18}}
19
20impl Exec {
21 fn new(docker: Docker, id: impl Into<crate::Id>) -> Self {
22 Exec {
23 docker,
24 id: id.into(),
25 }
26 }
27
28 pub fn get(docker: Docker, id: impl Into<crate::Id>) -> Exec {
34 Exec::new(docker, id)
35 }
36
37 api_doc! { Exec => Inspect
38 |
39 pub async fn inspect(&self) -> Result<models::ExecInspect200Response> {
41 Self::inspect_impl(&self.docker, self.id.as_ref()).await
42 }}
43
44 async fn inspect_impl(docker: &Docker, id: &str) -> Result<models::ExecInspect200Response> {
45 docker.get_json(&format!("/exec/{id}/json")).await
46 }
47
48 async fn create_impl(
49 docker: Docker,
50 container_id: &str,
51 opts: &ExecCreateOpts,
52 ) -> Result<crate::Id> {
53 #[derive(serde::Deserialize)]
54 #[serde(rename_all = "PascalCase")]
55 struct Response {
56 id: String,
57 }
58
59 docker
60 .post_json(
61 &format!("/containers/{}/exec", container_id),
62 Payload::Json(opts.serialize_vec()?),
63 Headers::none(),
64 )
65 .await
66 .map(|resp: Response| resp.id.into())
67 }
68
69 api_doc! { Exec => Create
70 |
71 pub async fn create(
73 docker: Docker,
74 container_id: impl AsRef<str>,
75 opts: &ExecCreateOpts,
76 ) -> Result<Exec>
77 {
78 Self::create_impl(docker.clone(), container_id.as_ref(), opts)
79 .await
80 .map(|id| Exec::new(docker, id))
81 }}
82
83 async fn start_impl(
84 docker: Docker,
85 id: &str,
86 opts: &ExecStartOpts,
87 ) -> Result<tty::Multiplexer> {
88 let endpoint = format!("/exec/{}/start", id);
89 let inspect_data = Self::inspect_impl(&docker, id).await?;
90 let is_tty = inspect_data
91 .process_config
92 .and_then(|c| c.tty)
93 .unwrap_or_default();
94
95 stream::attach(
96 docker,
97 endpoint,
98 Payload::Json(opts.serialize_vec()?.into()),
99 is_tty,
100 )
101 .await
102 }
103
104 api_doc! { Exec => Start
105 |
106 pub async fn start(&self, opts: &ExecStartOpts) -> Result<tty::Multiplexer> {
108 Self::start_impl(self.docker.clone(), self.id.as_ref(), opts).await
109 }}
110
111 pub(crate) async fn create_and_start(
112 docker: Docker,
113 container_id: impl AsRef<str>,
114 create_opts: &ExecCreateOpts,
115 start_opts: &ExecStartOpts,
116 ) -> Result<tty::Multiplexer> {
117 let container_id = container_id.as_ref();
118 let id = Self::create_impl(docker.clone(), container_id, create_opts).await?;
119
120 Self::start_impl(docker, id.as_ref(), start_opts).await
121 }
122
123 api_doc! { Exec => Resize
124 |
125 pub async fn resize(&self, opts: &ExecResizeOpts) -> Result<()> {
128 let body: Body = opts.serialize()?.into();
129
130 self.docker
131 .post_json(
132 &format!("/exec/{}/resize", &self.id),
133 Payload::Json(body),
134 Headers::none(),
135 )
136 .await
137 }}
138}