132 lines
4.9 KiB
Bash
Executable File
132 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Give each environment its own block of host ports.
|
|
#
|
|
# New versions of a system mean new clusters on ONE machine, not new machines.
|
|
# Cluster name, kubectl context, registry container and image tag already derive
|
|
# from the directory name, so two copies never collide there — but host ports are
|
|
# a single shared namespace and would.
|
|
#
|
|
# The block is derived from the directory name: stateless, stable, and requiring
|
|
# no coordination between copies that know nothing about each other.
|
|
#
|
|
# base = 20000 + (hash(slug) % 200) * 10
|
|
# +0 HTTP +1 HTTPS +2 TILT +3 REGISTRY (+4..9 reserved)
|
|
#
|
|
# 20000+ deliberately avoids the ports something is already likely to hold: 80,
|
|
# 443, 3000, 5432, 8000, 8080.
|
|
#
|
|
# Derivation is a default, not a decision. On first use the resolved block is
|
|
# written into ctrl/.env, so it becomes pinned, visible and editable rather than
|
|
# a number that appears from nowhere. Anything already in ctrl/.env wins.
|
|
#
|
|
# Usage: ports.sh show | active | derive | persist
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
source ./lib/config.sh
|
|
|
|
# derive_port_base lives in lib/config.sh so every script resolves the same block
|
|
# without going through this one.
|
|
derive_base() { derive_port_base "$1"; }
|
|
|
|
derive() {
|
|
load_config
|
|
local base; base=$(derive_base "$CLUSTER")
|
|
DERIVED_HTTP=$base
|
|
DERIVED_HTTPS=$((base + 1))
|
|
DERIVED_TILT=$((base + 2))
|
|
DERIVED_REGISTRY=$((base + 3))
|
|
}
|
|
|
|
# The resolved facts a consumer outside bash needs, machine-readable:
|
|
#
|
|
# CLUSTER KUBECONTEXT HTTP HTTPS TILT REGISTRY MANIFESTS_DIR
|
|
#
|
|
# Identity and ports together, because they are one fact set — the header above
|
|
# says so: both derive from the directory name so that copies never collide. A
|
|
# consumer needs all of them or none, and fetching them separately is how two
|
|
# end up disagreeing. MANIFESTS_DIR rides along because the one consumer that
|
|
# needs the addressing is the one that needs to know what to deploy.
|
|
#
|
|
# Space-separated, so MANIFESTS_DIR must not contain spaces. Everything else in
|
|
# rig already assumes that of paths — kind, docker and kubectl all do.
|
|
#
|
|
# `derive` answers a DIFFERENT question — what the directory name alone implies
|
|
# — and deliberately ignores ctrl/.env. Configuring anything from it would
|
|
# silently contradict this file's own rule that "anything already in ctrl/.env
|
|
# wins". `active` is what anything downstream should read.
|
|
#
|
|
# Why this exists at all: the cluster name is not the bare directory name.
|
|
# default_cluster_name() lowercases it and replaces every character outside
|
|
# [a-z0-9-], because it has to be a DNS label. Re-deriving that in another
|
|
# language is how a copy in `My_Project/` ends up guarding the wrong context.
|
|
active() {
|
|
load_config
|
|
echo "$CLUSTER $KUBECONTEXT $HTTP_PORT $HTTPS_PORT $TILT_PORT $REGISTRY_PORT $MANIFESTS_DIR"
|
|
}
|
|
|
|
show() {
|
|
derive
|
|
echo "environment $CLUSTER"
|
|
echo "derived base $(derive_base "$CLUSTER")"
|
|
echo
|
|
printf " %-14s %-8s %-8s %s\n" KEY DERIVED ACTIVE SOURCE
|
|
_row HTTP_PORT "$DERIVED_HTTP"
|
|
_row HTTPS_PORT "$DERIVED_HTTPS"
|
|
_row TILT_PORT "$DERIVED_TILT"
|
|
_row REGISTRY_PORT "$DERIVED_REGISTRY"
|
|
}
|
|
|
|
_row() {
|
|
local key="$1" derived="$2" active="${!1:-}" src="derived"
|
|
if [ -n "$active" ] && [ "$active" != "$derived" ]; then
|
|
src="override"
|
|
elif [ -z "$active" ]; then
|
|
active="$derived"
|
|
fi
|
|
printf " %-14s %-8s %-8s %s\n" "$key" "$derived" "$active" "$src"
|
|
}
|
|
|
|
# Write the derived block into ctrl/.env, once. Existing keys are never
|
|
# rewritten — an override stays an override.
|
|
persist() {
|
|
derive
|
|
[ -f ./.env ] || cp ./.env.example ./.env
|
|
|
|
local wrote=0 key val
|
|
for key in HTTP_PORT:$DERIVED_HTTP \
|
|
HTTPS_PORT:$DERIVED_HTTPS \
|
|
TILT_PORT:$DERIVED_TILT \
|
|
REGISTRY_PORT:$DERIVED_REGISTRY; do
|
|
val="${key#*:}"; key="${key%%:*}"
|
|
if grep -qE "^${key}=[0-9]" ./.env 2>/dev/null; then
|
|
continue
|
|
fi
|
|
if [ "$wrote" -eq 0 ]; then
|
|
{
|
|
echo ""
|
|
echo "# Port block for this environment, derived from the directory name"
|
|
echo "# so copies never collide. Pinned here on first use — edit freely."
|
|
} >> ./.env
|
|
wrote=1
|
|
fi
|
|
# Replace a commented/empty placeholder if present, else append.
|
|
if grep -qE "^#?\s*${key}=" ./.env 2>/dev/null; then
|
|
sed -i "s|^#\?\s*${key}=.*|${key}=${val}|" ./.env
|
|
else
|
|
echo "${key}=${val}" >> ./.env
|
|
fi
|
|
done
|
|
|
|
[ "$wrote" -eq 1 ] && echo "pinned port block into ctrl/.env" || echo "ports already set in ctrl/.env"
|
|
return 0
|
|
}
|
|
|
|
case "${1:-show}" in
|
|
show) show ;;
|
|
derive) derive; echo "$DERIVED_HTTP $DERIVED_HTTPS $DERIVED_TILT $DERIVED_REGISTRY" ;;
|
|
active) active ;;
|
|
persist) persist ;;
|
|
*) echo "usage: $0 [show|active|derive|persist]" >&2; exit 1 ;;
|
|
esac
|