#!/usr/bin/env bash # commands/network.command.sh # # Network diagnostics, port management, and host entries. # # Usage: # dx network status — show port assignments and their status # dx network resolve — re-run port resolution and show changes # dx network hosts — manage /etc/hosts entries (delegates to hosts command) # # Hosts subcommands are also available directly: # dx hosts sync # dx hosts list # dx hosts remove # ============================================ # Lifecycle # ============================================ function cmd::network::on_load() { flag::register \ --debug } # ============================================ # Public entrypoint # ============================================ function cmd::network::run() { local subcmd="${1:-help}" shift || true case "$subcmd" in status) cmd::network::status::run "$@" ;; resolve) cmd::network::resolve::run "$@" ;; hosts) load_command hosts hosts::run "$@" ;; help) cmd::network::help ;; *) log::error "Unknown subcommand: '${subcmd}'" cmd::network::help return 1 ;; esac } # ============================================ # Help # ============================================ function cmd::network::help() { cat < Subcommands: status Show current port assignments and their status resolve Re-run port resolution and show what changed hosts Manage /etc/hosts entries Hosts subcommands: hosts sync Sync project domain to /etc/hosts hosts list Show current /etc/hosts entries for this project hosts remove Remove project entries from /etc/hosts Examples: dx network status dx network resolve dx network hosts sync dx hosts sync (shorthand) EOF } # ============================================ # Status # ============================================ function cmd::network::status::run() { log::info "Port status for ${PROJECT_NAME}..." printf "\n" printf "%-20s %-10s %s\n" "Service" "Port" "Status" printf "%-20s %-10s %s\n" "-------" "----" "------" cmd::network::status::_report "App" "$APP_PORT" cmd::network::status::_report "Database" "$(docker::db::external_port)" printf "\n" } function cmd::network::status::_report() { local label="$1" local port="$2" local status if ! network::ports::in_use "$port"; then status="✓ free" else local container container="$(docker ps --format '{{.Names}}' | grep "^${PROJECT_NAME}" | head -1)" if [[ -n "$container" ]]; then status="✓ in use by ${PROJECT_NAME}" else status="⚠️ in use by another process — run: dx network resolve" fi fi printf "%-20s %-10s %s\n" "$label" "$port" "$status" } # ============================================ # Resolve # ============================================ function cmd::network::resolve::run() { log::info "Resolving ports for ${PROJECT_NAME}..." local old_app_port="$APP_PORT" local old_db_port old_db_port="$(docker::db::external_port)" network::ports::resolve_many APP_PORT DB_PORT local new_db_port new_db_port="$(docker::db::external_port)" printf "\n" printf "%-20s %-15s %-15s %s\n" "Service" "Current" "Resolved" "Status" printf "%-20s %-15s %-15s %s\n" "-------" "-------" "--------" "------" cmd::network::resolve::_report "App" "$old_app_port" "$APP_PORT" cmd::network::resolve::_report "Database" "$old_db_port" "$new_db_port" printf "\n" if [[ "$old_app_port" != "$APP_PORT" || "$old_db_port" != "$new_db_port" ]]; then log::warn "Ports changed — run 'dx build' to apply" else log::success "No changes — all ports are available" fi } function cmd::network::resolve::_report() { local label="$1" local old="$2" local resolved="$3" local status if [[ "$old" == "$resolved" ]]; then status="✓ unchanged" else status="⚠️ remapped: ${old} → ${resolved}" fi printf "%-20s %-15s %-15s %s\n" "$label" "$old" "$resolved" "$status" }