mecha10-cli 0.1.47

Mecha10 CLI tool
Documentation
//! Docker installation and daemon checks

use crate::services::docker::types::DockerInfo;
use anyhow::{Context, Result};
use std::process::Command;

/// Check if Docker is installed and accessible
///
/// # Errors
///
/// Returns an error if Docker is not found or not executable.
pub fn check_installation() -> Result<DockerInfo> {
    let output = Command::new("docker")
        .arg("--version")
        .output()
        .context("Failed to execute 'docker --version'. Is Docker installed?")?;

    if !output.status.success() {
        return Err(anyhow::anyhow!(
            "Docker is not installed or not accessible. Please install Docker: https://docs.docker.com/get-docker/"
        ));
    }

    let version = String::from_utf8_lossy(&output.stdout).trim().to_string();

    // Check Docker Compose
    let compose_version = check_compose_version()?;

    Ok(DockerInfo {
        version,
        compose_version,
    })
}

/// Check Docker Compose version
///
/// Checks both Docker Compose V2 (built-in) and V1 (standalone).
pub fn check_compose_version() -> Result<String> {
    // Try 'docker compose' (Docker Compose V2)
    if let Ok(output) = Command::new("docker").args(["compose", "version"]).output() {
        if output.status.success() {
            return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
        }
    }

    // Try 'docker-compose' (Docker Compose V1)
    if let Ok(output) = Command::new("docker-compose").arg("--version").output() {
        if output.status.success() {
            return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
        }
    }

    Err(anyhow::anyhow!(
        "Docker Compose is not installed. Please install Docker Compose: https://docs.docker.com/compose/install/"
    ))
}

/// Check if Docker daemon is running
///
/// # Errors
///
/// Returns an error if the daemon is not running or unreachable.
pub fn check_daemon() -> Result<()> {
    let output = Command::new("docker")
        .arg("info")
        .output()
        .context("Failed to execute 'docker info'")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        if stderr.contains("Cannot connect to the Docker daemon") {
            return Err(anyhow::anyhow!(
                "Docker daemon is not running. Please start Docker and try again."
            ));
        } else {
            return Err(anyhow::anyhow!("Docker daemon check failed: {}", stderr));
        }
    }

    Ok(())
}