#![allow(dead_code)]
use super::types::{InfrastructureAction, InfrastructureArgs};
use crate::context::CliContext;
use crate::services::{ConfigService, DockerService, ProjectService};
use anyhow::Result;
pub async fn handle_infrastructure(ctx: &mut CliContext, args: &InfrastructureArgs) -> Result<()> {
println!();
let docker = ctx.docker();
if docker.check_installation().is_err() || docker.check_daemon().is_err() {
anyhow::bail!("Docker is not available. Please install Docker and start the daemon.");
}
let current_dir = std::env::current_dir()?;
match ProjectService::detect(¤t_dir) {
Ok(project) => {
println!("🤖 Project Infrastructure - {}", project.name()?);
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
handle_project_infrastructure(ctx, args, &project).await?;
}
Err(_) => {
println!("🔧 Control Plane Infrastructure");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
handle_control_plane_infrastructure(docker, args).await?;
}
}
Ok(())
}
async fn handle_project_infrastructure(
_ctx: &mut CliContext,
args: &InfrastructureArgs,
project: &ProjectService,
) -> Result<()> {
let config = ConfigService::load_from(&project.config_path()).await?;
let compose_path = project.root().join(&config.docker.compose_file);
if !compose_path.exists() {
anyhow::bail!("Docker Compose file not found: {}", compose_path.display());
}
let docker = DockerService::with_compose_file(compose_path.to_string_lossy().to_string());
let services_to_manage = if args.services.is_empty() {
config.docker.robot.clone()
} else {
args.services.clone()
};
match args.action {
InfrastructureAction::Start => handle_start_project(&docker, &services_to_manage).await?,
InfrastructureAction::Stop => handle_stop(&docker, &services_to_manage).await?,
InfrastructureAction::Restart => handle_restart(&docker, &services_to_manage).await?,
InfrastructureAction::Status => handle_status(&docker, &services_to_manage).await?,
InfrastructureAction::Logs => handle_logs(&docker, &args.services).await?,
}
Ok(())
}
async fn handle_control_plane_infrastructure(docker: &DockerService, args: &InfrastructureArgs) -> Result<()> {
match args.action {
InfrastructureAction::Start => handle_start(docker, &args.services).await?,
InfrastructureAction::Stop => handle_stop(docker, &args.services).await?,
InfrastructureAction::Restart => handle_restart(docker, &args.services).await?,
InfrastructureAction::Status => handle_status(docker, &args.services).await?,
InfrastructureAction::Logs => handle_logs(docker, &args.services).await?,
}
Ok(())
}
async fn handle_start(docker: &DockerService, services: &[String]) -> Result<()> {
println!("Starting infrastructure services...\n");
if services.is_empty() {
docker.compose_up(true).await?;
println!("✅ All services started\n");
} else {
for service in services {
println!("Starting {}...", service);
docker.compose_up_service(service, true).await?;
println!("✅ {} started", service);
}
println!();
}
Ok(())
}
async fn handle_start_project(docker: &DockerService, services: &[String]) -> Result<()> {
if services.is_empty() {
println!("No services configured\n");
return Ok(());
}
println!("Starting robot infrastructure...\n");
for service in services {
println!(" Starting {}...", service);
docker.compose_up_service(service, true).await?;
println!(" ✅ {} started", service);
}
println!("\n✅ All services started successfully\n");
println!("💡 Tip: Use 'mecha10 infrastructure status' to check service health");
Ok(())
}
async fn handle_stop(docker: &DockerService, services: &[String]) -> Result<()> {
println!("Stopping infrastructure services...\n");
if services.is_empty() {
docker.compose_down().await?;
println!("✅ All services stopped\n");
} else {
for service in services {
println!("Stopping {}...", service);
docker.compose_stop(Some(service)).await?;
println!("✅ {} stopped", service);
}
println!();
}
Ok(())
}
async fn handle_restart(docker: &DockerService, services: &[String]) -> Result<()> {
println!("Restarting infrastructure services...\n");
if services.is_empty() {
docker.compose_down().await?;
docker.compose_up(true).await?;
println!("✅ All services restarted\n");
} else {
for service in services {
println!("Restarting {}...", service);
docker.compose_restart(Some(service)).await?;
println!("✅ {} restarted", service);
}
println!();
}
Ok(())
}
async fn handle_status(docker: &DockerService, services: &[String]) -> Result<()> {
println!("Infrastructure Status:\n");
let containers = docker.list_containers().await?;
if services.is_empty() {
for container in &containers {
let running = container.status.to_lowercase().contains("up");
let status = if running { "✅ Running" } else { "⬜ Stopped" };
println!(" {} {} ({})", status, container.name, container.status);
}
} else {
for service in services {
let container = containers.iter().find(|c| c.name.contains(service));
let running = container
.map(|c| c.status.to_lowercase().contains("up"))
.unwrap_or(false);
let status = if running { "✅ Running" } else { "⬜ Stopped" };
let detail = container.map(|c| c.status.as_str()).unwrap_or("Not found");
println!(" {} {} ({})", status, service, detail);
}
}
println!();
Ok(())
}
async fn handle_logs(docker: &DockerService, services: &[String]) -> Result<()> {
if services.is_empty() {
anyhow::bail!("Please specify a service to view logs.\nExample: mecha10 infrastructure logs redis");
}
let service = &services[0];
println!("Viewing logs for: {}\n", service);
docker.compose_logs(Some(service), false, Some(50))?;
Ok(())
}