dx/dxkit/modules/network.module.sh

97 lines
No EOL
2.1 KiB
Bash

#!/usr/bin/env bash
# ============================================
# Ports
# ============================================
#function network::ports::in_use() {
# local port="$1"
#
# if command -v lsof >/dev/null 2>&1; then
# lsof -iTCP:"$port" -sTCP:LISTEN -t >/dev/null 2>&1
# else
# netstat -an | grep -q ":$port "
# fi
#}
function network::ports::in_use() {
local port="$1"
# Check Docker port bindings — reliable across platforms
if command -v docker >/dev/null 2>&1; then
docker ps --format '{{.Ports}}' | grep -q "0.0.0.0:${port}->" && return 0
docker ps --format '{{.Ports}}' | grep -q "\[::\]:${port}->" && return 0
fi
# Fallback to netstat — handles both Unix and Windows output formats
netstat -an 2>/dev/null | grep -qE ":${port}[^0-9].*LISTEN" && return 0
return 1
}
function network::ports::resolve() {
local value="$1"
# auto:X → dynamic allocation
if [[ "$value" == auto:* ]]; then
local base="${value#auto:}"
if ! [[ "$base" =~ ^[0-9]+$ ]]; then
log::network_error "Invalid auto port syntax: $value"
return 1
fi
# fallback if malformed (optional safety)
[[ -z "$base" ]] && base=8000
local p="$base"
while network::ports::in_use "$p"; do
((p++))
done
echo "$p"
return
fi
# static port
echo "$value"
}
function network::ports::resolve_many() {
local var
for var in "$@"; do
local value="${!var}"
local resolved
resolved="$(network::ports::resolve "$value")" || return 1
printf -v "$var" "%s" "$resolved"
done
}
function network::ports::persist() {
local ports_file
ports_file="$(ctx::artifact)/ports"
cat > "$ports_file" <<EOF
APP_PORT=${APP_PORT}
DB_PORT=${DB_PORT}
EOF
}
function network::ports::load() {
local ports_file
ports_file="$(ctx::artifact)/ports"
[[ -f "$ports_file" ]] || return 0
source "$ports_file"
export APP_PORT DB_PORT
}
function network::ports::prepare() {
[[ "$DB_PORT" == "auto" ]] && export DB_PORT="auto:$(docker::db::internal_port)"
network::ports::resolve_many APP_PORT DB_PORT
network::ports::persist
}