212 lines
7.2 KiB
Bash
Executable file
212 lines
7.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -uo pipefail
|
|
|
|
DEFAULT_MIN_PORT=8000
|
|
DEFAULT_MAX_PORT=64000
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") [OPTIONS] [COMMAND]
|
|
|
|
Manage and check ports for LoadBalancer services in k8s yaml files.
|
|
|
|
Commands:
|
|
next Find the next available port greater than MIN (default: 8000)
|
|
check PORT Check if a specific port is available
|
|
list List all ports in use
|
|
|
|
Options:
|
|
--from MIN Minimum port to check from (default: $DEFAULT_MIN_PORT)
|
|
--to MAX Maximum port to check to (default: $DEFAULT_MAX_PORT)
|
|
-h, --help Show this help message
|
|
-v Verbose output
|
|
|
|
Examples:
|
|
$(basename "$0") next # Find next available port > 8000
|
|
$(basename "$0") next --from 8200 --to 8300 # Find next available port in range
|
|
$(basename "$0") check 8008 # Check if port 8008 is available
|
|
$(basename "$0") check 9000 --from 9000 # Check if port 9000 is available in range
|
|
$(basename "$0") list # List all ports in use
|
|
EOF
|
|
}
|
|
|
|
VERBOSE=0
|
|
COMMAND=""
|
|
MIN_PORT=$DEFAULT_MIN_PORT
|
|
MAX_PORT=$DEFAULT_MAX_PORT
|
|
CHECK_PORT=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
-v)
|
|
VERBOSE=1
|
|
shift
|
|
;;
|
|
--from)
|
|
MIN_PORT="$2"
|
|
shift 2
|
|
;;
|
|
--to)
|
|
MAX_PORT="$2"
|
|
shift 2
|
|
;;
|
|
next|check|list)
|
|
COMMAND="$1"
|
|
shift
|
|
;;
|
|
-*)
|
|
echo "Error: Unknown option: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
if [[ "$1" =~ ^[0-9]+$ ]]; then
|
|
if [[ "$COMMAND" == "check" ]] || [[ -z "$COMMAND" ]]; then
|
|
CHECK_PORT="$1"
|
|
COMMAND="check"
|
|
else
|
|
echo "Error: Unexpected argument: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Error: Unexpected argument: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$COMMAND" ]]; then
|
|
echo "Error: No command specified" >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
K8S_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
collect_ports() {
|
|
PORTS=()
|
|
|
|
while IFS= read -r file || [[ -n "$file" ]]; do
|
|
if [[ ! -f "$file" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if ! grep -q "LoadBalancer" "$file" 2>/dev/null; then
|
|
continue
|
|
fi
|
|
|
|
lb_port=$(yq -r '.. | objects | select(.type == "LoadBalancer") | select(.port != null) | .port // empty' "$file" 2>/dev/null || true)
|
|
if [[ -n "$lb_port" ]] && [[ "$lb_port" != "null" ]] && [[ "$lb_port" =~ ^[0-9]+$ ]]; then
|
|
PORTS+=("$lb_port")
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Found .port $lb_port in $file"
|
|
fi
|
|
|
|
service_port_http=$(yq -r '.. | objects | select(.type == "LoadBalancer") | .servicePortHttp // empty' "$file" 2>/dev/null || true)
|
|
if [[ -n "$service_port_http" ]] && [[ "$service_port_http" != "null" ]] && [[ "$service_port_http" =~ ^[0-9]+$ ]]; then
|
|
PORTS+=("$service_port_http")
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Found servicePortHttp $service_port_http in $file"
|
|
fi
|
|
|
|
service_port_https=$(yq -r '.. | objects | select(.type == "LoadBalancer") | .servicePortHttps // empty' "$file" 2>/dev/null || true)
|
|
if [[ -n "$service_port_https" ]] && [[ "$service_port_https" != "null" ]] && [[ "$service_port_https" =~ ^[0-9]+$ ]]; then
|
|
PORTS+=("$service_port_https")
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Found servicePortHttps $service_port_https in $file"
|
|
fi
|
|
|
|
service_dns_port=$(yq -r '.. | objects | select(.type == "LoadBalancer") | .dns.port // empty' "$file" 2>/dev/null || true)
|
|
if [[ -n "$service_dns_port" ]] && [[ "$service_dns_port" != "null" ]] && [[ "$service_dns_port" =~ ^[0-9]+$ ]]; then
|
|
PORTS+=("$service_dns_port")
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Found dns.port $service_dns_port in $file"
|
|
fi
|
|
done < <(find "$K8S_DIR/k8s" -name "*.yaml" -type f 2>/dev/null) || true
|
|
|
|
if command -v kubectl &>/dev/null && kubectl cluster-info &>/dev/null 2>&1; then
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Querying kubectl for LoadBalancer services..."
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
ports_str=$(echo "$line" | awk '{print $6}')
|
|
svc_name=$(echo "$line" | awk '{print $2}')
|
|
while IFS=',' read -ra port_entries || [[ -n "${port_entries[*]}" ]]; do
|
|
for entry in "${port_entries[@]}"; do
|
|
port=$(echo "$entry" | cut -d: -f1 | cut -d/ -f1)
|
|
if [[ -n "$port" ]] && [[ "$port" =~ ^[0-9]+$ ]]; then
|
|
PORTS+=("$port")
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Found kubectl port $port for $svc_name"
|
|
fi
|
|
done
|
|
done <<< "$ports_str"
|
|
done < <(kubectl get svc -A --no-headers 2>/dev/null | grep LoadBalancer || true)
|
|
fi
|
|
}
|
|
|
|
is_port_in_use() {
|
|
local port="$1"
|
|
[[ " ${PORTS[*]} " =~ ${port} ]]
|
|
}
|
|
|
|
run_command() {
|
|
collect_ports
|
|
|
|
if [[ ${#PORTS[@]} -eq 0 ]]; then
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] No ports found in use"
|
|
else
|
|
[[ $VERBOSE -eq 1 ]] && echo "[DEBUG] Ports in use: ${PORTS[*]}"
|
|
fi
|
|
|
|
case "$COMMAND" in
|
|
next)
|
|
next_port=$MIN_PORT
|
|
while [[ $next_port -le $MAX_PORT ]]; do
|
|
if ! is_port_in_use "$next_port"; then
|
|
echo "$next_port"
|
|
return 0
|
|
fi
|
|
next_port=$((next_port + 1))
|
|
done
|
|
echo "Error: No available port found between $MIN_PORT and $MAX_PORT" >&2
|
|
return 1
|
|
;;
|
|
check)
|
|
if [[ -z "$CHECK_PORT" ]]; then
|
|
echo "Error: PORT is required for check command" >&2
|
|
return 1
|
|
fi
|
|
if ! [[ "$CHECK_PORT" =~ ^[0-9]+$ ]]; then
|
|
echo "Error: PORT must be a number" >&2
|
|
return 1
|
|
fi
|
|
if [[ "$CHECK_PORT" -lt 1 ]] || [[ "$CHECK_PORT" -gt 65535 ]]; then
|
|
echo "Error: PORT must be between 1 and 65535" >&2
|
|
return 1
|
|
fi
|
|
if [[ "$CHECK_PORT" -lt "$MIN_PORT" ]] || [[ "$CHECK_PORT" -gt "$MAX_PORT" ]]; then
|
|
echo "Error: PORT $CHECK_PORT is outside the check range ($MIN_PORT - $MAX_PORT)" >&2
|
|
return 1
|
|
fi
|
|
if is_port_in_use "$CHECK_PORT"; then
|
|
echo "PORT $CHECK_PORT IS IN USE"
|
|
return 1
|
|
else
|
|
echo "PORT $CHECK_PORT IS AVAILABLE"
|
|
return 0
|
|
fi
|
|
;;
|
|
list)
|
|
if [[ ${#PORTS[@]} -eq 0 ]]; then
|
|
echo "No ports in use"
|
|
else
|
|
printf '%s\n' "${PORTS[@]}" | sort -n -u
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
run_command
|