/** * Network diagnostic CLI commands. * * Inspects Docker container networking, DNS, proxy, and connectivity. * * @module */ import { chalk, getCliSdk } from "../actions.js"; import { resolveUuid } from "../coolify-state.js"; /** Inspect container network environment. */ export async function networkInspectCommand( uuid: string | undefined, options: { services?: string } = {}, ): Promise { const resolved = resolveUuid(uuid); if (!resolved) { console.error( chalk.red("Error: No UUID provided and no .coolify.json found"), ); return; } const servicesToTest = options.services ? options.services.split(",").map((s) => s.trim()) : []; console.log(chalk.cyan(`Inspecting network for ${resolved}...\n`)); try { const info = await getCliSdk().network.inspect(resolved, servicesToTest); // Hosts console.log(chalk.bold("Container Hosts (/etc/hosts):")); if (info.hosts.length > 0) { for (const h of info.hosts) { console.log(` ${chalk.gray(h)}`); } } else { console.log(chalk.yellow(" No entries")); } // Network interfaces if (info.interfaces.length > 0) { console.log(chalk.bold("\nNetwork Interfaces:")); for (const iface of info.interfaces) { console.log(` ${chalk.gray(iface.trim())}`); } } // Network env vars const envEntries = Object.entries(info.networkEnv); if (envEntries.length > 0) { console.log(chalk.bold("\nNetwork Environment Variables:")); for (const [key, val] of envEntries) { console.log(` ${chalk.green(key)} = ${chalk.gray(val)}`); } } // DNS resolution if (info.dns.length > 0) { console.log(chalk.bold("\nDNS Resolution:")); for (const d of info.dns) { const status = d.resolved ? chalk.green(`✓ ${d.ip}`) : chalk.red("✗ FAILED"); console.log(` ${chalk.white(d.hostname)} → ${status}`); } } // Connectivity if (info.connectivity.length > 0) { console.log(chalk.bold("\nService Connectivity:")); for (const c of info.connectivity) { const status = c.reachable ? chalk.green(`✓ reachable (${c.responseTime}ms)`) : chalk.red("✗ unreachable"); console.log(` ${chalk.white(c.target)} → ${status}`); } } // Trace console.log(chalk.bold("\nTrace:")); for (const step of info.trace.steps) { console.log( ` ${chalk.gray(step.step)} ${chalk.yellow(step.durationMs + "ms")}${step.detail ? chalk.gray(` (${step.detail})`) : ""}`, ); } console.log(chalk.gray(` Total: ${info.trace.totalMs}ms`)); } catch (error) { console.error( chalk.red( `Error: ${error instanceof Error ? error.message : String(error)}`, ), ); } } /** Analyze a failed deployment. */ export async function analyzeDeployCommand( deploymentUuid: string, ): Promise { console.log(chalk.cyan(`Analyzing deployment ${deploymentUuid}...\n`)); try { const analysis = await getCliSdk().diagnose.deployFailure(deploymentUuid); console.log(chalk.bold("Deployment:")); console.log(` ${chalk.gray("UUID:")} ${analysis.deploymentUuid}`); console.log(` ${chalk.gray("Status:")} ${analysis.status}`); console.log( ` ${chalk.gray("Category:")} ${chalk.yellow(analysis.category)}`, ); console.log(chalk.bold.red(`\nDiagnosis: ${analysis.summary}`)); console.log(chalk.cyan(`Suggestion: ${analysis.suggestion}`)); if (analysis.errors.length > 0) { console.log(chalk.bold(`\nError Lines (${analysis.errors.length}):`)); for (const line of analysis.errors.slice(0, 10)) { console.log(` ${chalk.red(line.trim())}`); } if (analysis.errors.length > 10) { console.log( chalk.gray(` ... and ${analysis.errors.length - 10} more`), ); } } // Trace console.log(chalk.bold("\nTrace:")); for (const step of analysis.trace.steps) { console.log( ` ${chalk.gray(step.step)} ${chalk.yellow(step.durationMs + "ms")}${step.detail ? chalk.gray(` (${step.detail})`) : ""}`, ); } } catch (error) { console.error( chalk.red( `Error: ${error instanceof Error ? error.message : String(error)}`, ), ); } }