#!/usr/bin/env bash # Readiness check: is this machine ready to run rig? # # Reports and instructs; never silently fixes anything. Everything it finds is # either already fine, or something a human has to decide on. # # Runs ctrl/deps.sh host detection in a container when Docker is the only thing # installed, or directly when the toolchain is already present. Then adds the # checks that need this repo's config: profile sanity, CA trust, port clashes. set -euo pipefail cd "$(dirname "$0")" DEPS_IMAGE="${DEPS_IMAGE:-$(basename "$(cd .. && pwd)")-deps}" # Host detection. Prefer running it bare — it needs no dependencies beyond # coreutils — and fall back to the container only if this shell can't. bash ./deps.sh detect # ── repo-level checks ────────────────────────────────────────────────────── source ./lib/config.sh load_config echo echo "config" echo " profile ${PROFILE_NAME} (nodes=${NODES} audit=${AUDIT})" echo " cluster ${CLUSTER} (context ${KUBECONTEXT})" echo " registry ${REGISTRY_MODE}" echo " ingress ${INGRESS_MODE}" if [ ! -f ./.env ]; then echo " ! ctrl/.env missing — copy it: cp ctrl/.env.example ctrl/.env" fi # A 3-node profile on a box that's already full is the most common first # failure, and it presents as pods stuck Pending rather than anything obvious. avail=$(awk '/^MemAvailable:/{printf "%d", $2/1024/1024}' /proc/meminfo) need=$((NODES * 2)) if [ "$avail" -lt "$need" ]; then echo " ! profile '${PROFILE_NAME}' wants ~${need} GB, ${avail} GB available" echo " 'make cluster list' shows what else is running; 'make cluster free' stops it" fi # The CA reaches three places and only one of them is ours. Report the other two. if [ -n "${REGISTRY_CA_FILE:-}" ]; then echo echo "registry CA" if [ ! -r "$REGISTRY_CA_FILE" ]; then echo " ! REGISTRY_CA_FILE not readable: $REGISTRY_CA_FILE" else echo " file $REGISTRY_CA_FILE" host="${REGISTRY_REMOTE_URL#*://}"; host="${host%%/*}" if [ -n "$host" ] && [ ! -f "/etc/docker/certs.d/${host}/ca.crt" ]; then echo " ! the HOST docker daemon does not trust it yet:" echo " sudo mkdir -p /etc/docker/certs.d/${host}" echo " sudo cp ${REGISTRY_CA_FILE} /etc/docker/certs.d/${host}/ca.crt" echo " (kind nodes are handled by registry.sh; in-cluster clients are the workload's job)" fi fi fi # Host ports this environment will try to bind. Checked before cluster creation # because docker reports a clash halfway through, as an opaque # "failed to bind host port ...: address already in use". echo echo "ports (block derived from the directory name — see 'make ports')" port_busy() { if command -v ss >/dev/null 2>&1; then ss -ltn "sport = :$1" 2>/dev/null | grep -q LISTEN && return 0 || return 1 fi # iproute2 is absent from a minimal Debian, so fall back to procfs rather # than silently reporting everything as free. local hex; hex=$(printf ':%04X' "$1") grep -qi "^ *[0-9]*: [0-9A-F]*$hex " /proc/net/tcp /proc/net/tcp6 2>/dev/null } # A port held by THIS environment's own cluster is not a clash — it is the thing # working. Reporting it as a problem every time the cluster is up would train # people to ignore this section, which is the opposite of the point. # Extract with a second grep rather than `tr -d ':->'`: in tr, ':->' is the # character RANGE ':' to '>', which does not contain '-', so the trailing dash # survives and nothing ever matches. ours=$(docker ps --filter "label=io.x-k8s.kind.cluster=${CLUSTER}" \ --format '{{.Ports}}' 2>/dev/null | tr ',' '\n' \ | grep -oE ':[0-9]+->' | grep -oE '[0-9]+' || true) clash=0 for entry in "HTTP:${HTTP_PORT}" "HTTPS:${HTTPS_PORT}" \ "TILT:${TILT_PORT}" "REGISTRY:${REGISTRY_PORT}"; do name="${entry%%:*}"; p="${entry#*:}" [ -n "$p" ] || continue if ! port_busy "$p"; then printf " %-9s %-6s free\n" "$name" "$p" elif echo "$ours" | grep -qx "$p"; then printf " %-9s %-6s in use by this environment's cluster\n" "$name" "$p" else printf " ! %-9s %-6s IN USE by something else\n" "$name" "$p" clash=1 fi done if [ "$clash" -eq 1 ]; then echo " override the clashing one in ctrl/.env, e.g. HTTP_PORT=21080" echo " (or rename this directory — the whole block follows the name)" fi