use anyhow::{Context, Result};
use std::process::Command;
pub fn compose_build(compose_file: Option<&str>, service: Option<&str>) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("build");
if let Some(svc) = service {
args.push(svc);
}
let status = Command::new("docker")
.args(&args)
.status()
.context("Failed to execute 'docker compose build'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to build Docker images"));
}
Ok(())
}
pub async fn compose_up(compose_file: Option<&str>, detach: bool) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("up");
if detach {
args.push("-d");
}
let status = Command::new("docker")
.args(&args)
.status()
.context("Failed to execute 'docker compose up'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to start services"));
}
Ok(())
}
pub async fn compose_up_service(compose_file: Option<&str>, service: &str, detach: bool) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("up");
if detach {
args.push("-d");
}
args.push(service);
let status = Command::new("docker")
.args(&args)
.status()
.context(format!("Failed to start service: {}", service))?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to start service: {}", service));
}
Ok(())
}
pub async fn compose_run_service(
compose_file: Option<&str>,
service: &str,
detach: bool,
service_ports: bool,
command_args: &[String],
) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("run");
if detach {
args.push("-d");
}
if service_ports {
args.push("--service-ports");
}
if !detach {
args.push("--rm");
}
args.push(service);
let cmd_args: Vec<&str> = command_args.iter().map(|s| s.as_str()).collect();
args.extend(cmd_args);
let status = Command::new("docker")
.args(&args)
.status()
.context(format!("Failed to run service: {}", service))?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to run service: {}", service));
}
Ok(())
}
pub async fn compose_stop(compose_file: Option<&str>, service: Option<&str>) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("stop");
if let Some(svc) = service {
args.push(svc);
}
let status = Command::new("docker")
.args(&args)
.status()
.context("Failed to execute 'docker compose stop'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to stop services"));
}
Ok(())
}
pub async fn compose_down(compose_file: Option<&str>) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("down");
let status = Command::new("docker")
.args(&args)
.status()
.context("Failed to execute 'docker compose down'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to stop and remove services"));
}
Ok(())
}
pub async fn compose_restart(compose_file: Option<&str>, service: Option<&str>) -> Result<()> {
let mut args = vec!["compose"];
if let Some(file) = compose_file {
args.push("-f");
args.push(file);
}
args.push("restart");
if let Some(svc) = service {
args.push(svc);
}
let status = Command::new("docker")
.args(&args)
.status()
.context("Failed to execute 'docker compose restart'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to restart services"));
}
Ok(())
}
pub fn compose_logs(
compose_file: Option<&str>,
service: Option<&str>,
follow: bool,
tail: Option<usize>,
) -> Result<()> {
let mut cmd = Command::new("docker");
cmd.arg("compose");
if let Some(file) = compose_file {
cmd.arg("-f").arg(file);
}
cmd.arg("logs");
if follow {
cmd.arg("-f");
}
if let Some(n) = tail {
cmd.arg("--tail").arg(n.to_string());
}
if let Some(svc) = service {
cmd.arg(svc);
}
let status = cmd.status().context("Failed to execute 'docker compose logs'")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to get logs"));
}
Ok(())
}