#[cfg(feature = "docker")]
use crate::utils::command_exists;
use crate::{
cli::{
commands,
error::{CliResult, ErrorFactory},
},
logging::{log_error, log_info},
};
use tokio::process::Command;
#[cfg(feature = "docker")]
pub async fn handle_docker(cmd: commands::DockerCmd, debug: bool) -> CliResult<()> {
if !command_exists("docker") {
let _ = log_error("docker", "docker not installed or not in PATH", None).await;
return Err(ErrorFactory::dependency(
"docker",
"docker not installed or not in PATH",
Some("Install Docker and ensure `docker` is available in PATH."),
));
}
let args = if cmd.args.is_empty() {
vec!["--help".to_string()]
} else {
cmd.args.clone()
};
if debug {
let _ = log_info("docker", &format!("docker {}", args.join(" ")), None).await;
}
let mut process = Command::new("docker");
for arg in &args {
process.arg(arg);
}
let output = process.output().await.map_err(|e| {
ErrorFactory::operation("docker", "spawn docker process", e.to_string(), None)
})?;
let command_rendered = format!("docker {}", args.join(" "));
if !output.stdout.is_empty() {
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
print!("{}", stdout);
crate::data::athena::persist_docker_log(
None,
Some(&command_rendered),
"stdout",
&stdout,
serde_json::json!({ "source": "handle_docker" }),
)
.await;
}
if !output.stderr.is_empty() {
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
eprint!("{}", stderr);
crate::data::athena::persist_docker_log(
None,
Some(&command_rendered),
"stderr",
&stderr,
serde_json::json!({ "source": "handle_docker" }),
)
.await;
}
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let _ = log_error("docker", "docker command failed", Some(&stderr)).await;
return Err(ErrorFactory::operation(
"docker",
"execute docker command",
format!("docker exited with {}", output.status),
Some("Try re-running with `--debug` to inspect full command output."),
));
}
Ok(())
}