use foundation_netio::shared::http::SimpleHeader;
use foundation_netio::PreparedRequestBuilder;
use crate::error::DockerError;
use crate::generated::exec::{container_exec_request, ContainerExecArgs};
use crate::generated::resize::{exec_resize_request, ExecResizeArgs};
use crate::generated::shared::IDResponse;
type NoMod = fn(&mut PreparedRequestBuilder);
pub async fn exec_create(
client: &super::DockerClient,
id: &str,
cmd: &[&str],
) -> Result<IDResponse, DockerError> {
let body = serde_json::json!({
"Cmd": cmd,
"AttachStdout": true,
"AttachStderr": true,
});
let args = ContainerExecArgs {
id: id.to_string(),
};
let response = container_exec_request(
client.http(),
&args,
&client.base_url(),
Some(move |b: &mut PreparedRequestBuilder| {
b.set_header(SimpleHeader::CONTENT_TYPE, "application/json");
let _ = b.set_body_json(&body);
}),
)
.await?;
Ok(response.body)
}
pub async fn exec_start(
client: &super::DockerClient,
id: &str,
detach: bool,
) -> Result<Vec<u8>, DockerError> {
let body = serde_json::json!({ "Detach": detach });
let endpoint_url = format!("{}/exec/{}/start", client.base_url(), id);
let mut builder = PreparedRequestBuilder::post(&endpoint_url)
.map_err(|e| DockerError::Transport(e.to_string()))?;
builder.set_header(SimpleHeader::CONTENT_TYPE, "application/json");
let _ = builder.set_body_json(&body);
let response = client
.http()
.send_async(builder.build())
.await
.map_err(|e| DockerError::Transport(e.to_string()))?;
let status: usize = response.get_status().into();
if status < 200 || status >= 300 {
return Err(DockerError::Api {
status: status as u16,
message: format!("exec_start failed with status {status}"),
});
}
let body_bytes =
foundation_netio::shared::client::body_reader::collect_bytes_from_send_safe(
response.take_body(),
);
Ok(body_bytes)
}
pub async fn exec_inspect(
client: &super::DockerClient,
id: &str,
) -> Result<serde_json::Value, DockerError> {
let endpoint_url = format!("{}/exec/{}/json", client.base_url(), id);
let builder = PreparedRequestBuilder::get(&endpoint_url)
.map_err(|e| DockerError::Transport(e.to_string()))?;
let response = client
.http()
.send_async(builder.build())
.await
.map_err(|e| DockerError::Transport(e.to_string()))?;
let status: usize = response.get_status().into();
if status < 200 || status >= 300 {
return Err(DockerError::Api {
status: status as u16,
message: format!("exec_inspect failed with status {status}"),
});
}
let body_bytes =
foundation_netio::shared::client::body_reader::collect_bytes_from_send_safe(
response.take_body(),
);
let parsed: serde_json::Value = serde_json::from_slice(&body_bytes)
.map_err(|e| DockerError::JsonParse(format!("exec_inspect: {e}")))?;
Ok(parsed)
}
pub async fn exec_resize(
client: &super::DockerClient,
id: &str,
h: u32,
w: u32,
) -> Result<(), DockerError> {
let args = ExecResizeArgs {
id: id.to_string(),
h: Some(h.to_string()),
w: Some(w.to_string()),
};
exec_resize_request(client.http(), &args, &client.base_url(), None::<NoMod>).await?;
Ok(())
}