prole/etc/init_nginx_ingress.sh

176 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck disable=SC1090
source "$SCRIPT_DIR/knoe_cfg.sh"
usage() {
cat <<USAGE
Usage: init_nginx_ingress.sh [--mode MODE] [--config-file FILE] [apply|update|initialize]
Generates/updates ingress-nginx TCP mappings from conf/port-mapping.cfg.
USAGE
}
MODE_OVERRIDE=""
CFG_FILE=""
while [ $# -gt 0 ]; do
case "$1" in
-m|--mode)
shift
MODE_OVERRIDE="${1:-}"
shift
;;
-m=*|--mode=*)
MODE_OVERRIDE="${1#*=}"
shift
;;
-c|--config-file)
shift
CFG_FILE="${1:-}"
shift
;;
-c=*|--config-file=*)
CFG_FILE="${1#*=}"
shift
;;
apply|update|initialize|start|reload)
shift
;;
-h|--help)
usage
exit 0
;;
*)
usage
exit 2
;;
esac
done
MODE="${MODE_OVERRIDE:-${KNOE_MODE:-${DEPLOYMENT_MODE:-${CLUSTER_ENV:-}}}}"
if command -v knoe_normalize_mode >/dev/null 2>&1; then
MODE=$(knoe_normalize_mode "$MODE")
fi
if [[ -n "$MODE" && "$MODE" != "k3d" ]]; then
echo "[INFO] nginx ingress host-port mappings are only applied for k3d (mode=$MODE)."
exit 0
fi
knoe_ensure_kubeconfig >/dev/null 2>&1 || true
ensure_kube_context || exit 1
PORT_MAPPING_FILE_PATH="${PORT_MAPPING_FILE:-}"
if [[ -z "$PORT_MAPPING_FILE_PATH" ]]; then
if [[ -n "${KNOE_CONF:-}" && -f "$KNOE_CONF/port-mapping.cfg" ]]; then
PORT_MAPPING_FILE_PATH="$KNOE_CONF/port-mapping.cfg"
elif [[ -f "$SCRIPT_DIR/../conf/port-mapping.cfg" ]]; then
PORT_MAPPING_FILE_PATH="$SCRIPT_DIR/../conf/port-mapping.cfg"
fi
fi
if [[ -n "$CFG_FILE" && -f "$CFG_FILE" ]]; then
PORT_MAPPING_FILE_PATH="$CFG_FILE"
fi
if [[ -z "$PORT_MAPPING_FILE_PATH" || ! -f "$PORT_MAPPING_FILE_PATH" ]]; then
echo "ERROR: port-mapping.cfg not found (set PORT_MAPPING_FILE or use --config-file)." >&2
exit 1
fi
trim() {
_knoe_trim "$1"
}
# Parse legacy conf/port-mapping.cfg style entries.
declare -A PORT_MAP
PORT_MAP[_dummy_]=1; unset "PORT_MAP[_dummy_]" # keep array "bound" under set -u
while IFS= read -r line; do
line="$(trim "$line")"
[[ -z "$line" ]] && continue
case "$line" in
\#*|\;*) continue ;;
esac
id="${line%%:*}"
rest="${line#*:}"
if [[ "$id" == "$line" ]]; then
continue
fi
id="$(trim "$id")"
rest="$(trim "$rest")"
hostPort="" servicePort="" ns="" target=""
for token in $rest; do
key="$(trim "${token%%=*}")"
value="$(trim "${token#*=}")"
case "$key" in
local|host|hostPort|host_port) hostPort="$value" ;;
remote|servicePort|service_port) servicePort="$value" ;;
ns|namespace) ns="$value" ;;
svc|service) target="svc/$value" ;;
target) target="$value" ;;
desc|description) ;;
esac
done
if [[ -z "$hostPort" || -z "$servicePort" || -z "$ns" || -z "$target" ]]; then
echo "[WARN] Skipping mapping '$id': missing required fields." >&2
continue
fi
if [[ "$target" == svc/* ]]; then
svc="${target#svc/}"
else
echo "[WARN] Skipping mapping '$id': target '$target' is not a service." >&2
continue
fi
PORT_MAP["$hostPort"]="$ns/$svc:$servicePort"
done <"$PORT_MAPPING_FILE_PATH"
if [[ "${#PORT_MAP[@]}" -eq 0 ]]; then
echo "ERROR: No mappings found in $PORT_MAPPING_FILE_PATH" >&2
exit 1
fi
INGRESS_NS="${INGRESS_NGINX_NAMESPACE:-ingress-nginx}"
TCP_CONFIGMAP="${INGRESS_NGINX_TCP_CONFIGMAP:-tcp-services}"
# Ensure namespace exists
kubectl get namespace "$INGRESS_NS" >/dev/null 2>&1 || kubectl create namespace "$INGRESS_NS" >/dev/null
# Build ConfigMap for ingress-nginx TCP services
TMP_CM=$(mktemp)
{
echo "apiVersion: v1"
echo "kind: ConfigMap"
echo "metadata:"
echo " name: ${TCP_CONFIGMAP}"
echo " namespace: ${INGRESS_NS}"
echo "data:"
for port in $(printf '%s\n' "${!PORT_MAP[@]}" | sort -n); do
echo " \"${port}\": \"${PORT_MAP[$port]}\""
done
} >"$TMP_CM"
kubectl apply -f "$TMP_CM"
rm -f "$TMP_CM"
# Patch ingress-nginx controller service to expose TCP ports, if present.
if kubectl -n "$INGRESS_NS" get svc ingress-nginx-controller >/dev/null 2>&1; then
existing_ports=$(kubectl -n "$INGRESS_NS" get svc ingress-nginx-controller -o jsonpath='{.spec.ports[*].port}')
for port in $(printf '%s\n' "${!PORT_MAP[@]}" | sort -n); do
if ! echo " $existing_ports " | grep -q " $port "; then
kubectl -n "$INGRESS_NS" patch svc ingress-nginx-controller --type json \
-p "[{\"op\":\"add\",\"path\":\"/spec/ports/-\",\"value\":{\"name\":\"tcp-${port}\",\"port\":${port},\"protocol\":\"TCP\",\"targetPort\":${port}}}]" >/dev/null
fi
done
echo "[OK] nginx ingress TCP mappings applied."
else
echo "[WARN] ingress-nginx-controller service not found in namespace '$INGRESS_NS'."
echo " Install ingress-nginx and rerun init_nginx_ingress.sh to expose host ports."
fi