init rig
This commit is contained in:
148
rig/ctrl/lib/config.sh
Normal file
148
rig/ctrl/lib/config.sh
Normal file
@@ -0,0 +1,148 @@
|
||||
# Shared config loading. Sourced, never executed.
|
||||
#
|
||||
# The ecosystem convention is that scripts are standalone with no shared log
|
||||
# library — that still holds. This file is not a logging lib; it is the single
|
||||
# definition of how the config layers compose, which every script has to agree
|
||||
# on exactly. Precedence, weakest first:
|
||||
#
|
||||
# ctrl/versions.env pinned toolchain + image digests (committed)
|
||||
# ctrl/env.d/<profile> cluster shape (committed)
|
||||
# ctrl/.env machine-local values and secrets (gitignored)
|
||||
# the caller's env `make cluster up PROFILE=client` (always wins)
|
||||
#
|
||||
# That last rule is why this is more than a few `source` lines: .env sets
|
||||
# PROFILE, so without snapshotting it would silently override the PROFILE the
|
||||
# user just typed on the command line.
|
||||
#
|
||||
# Run from ctrl/.
|
||||
|
||||
# Values a user can reasonably override per-invocation. Anything set in the
|
||||
# environment when load_config runs is restored after the files are read.
|
||||
# NODES and AUDIT are deliberately NOT here: they are properties of the chosen
|
||||
# ctrl/k8s/kind-config*.yaml.tpl and are read back out of it below, so there is
|
||||
# one place that decides the shape of the cluster rather than two that can drift.
|
||||
CONFIG_OVERRIDABLE="PROFILE CLUSTER K8S_VERSION KIND_CONFIG ADDONS
|
||||
REGISTRY_MODE INGRESS_MODE DNS_MODE TILT_PORT
|
||||
SOURCE ARCH DEPS_SOURCE HTTP_PORT HTTPS_PORT"
|
||||
|
||||
# The containing folder's name, reduced to something kind accepts as a cluster
|
||||
# name (a DNS label: lowercase alphanumerics and dashes). Run from ctrl/, so the
|
||||
# repo root is the parent.
|
||||
default_cluster_name() {
|
||||
local n
|
||||
n=$(basename "$(cd .. && pwd)")
|
||||
n=$(echo "$n" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9-' '-')
|
||||
n=$(echo "$n" | sed 's/^-*//; s/-*$//')
|
||||
echo "${n:-rig}"
|
||||
}
|
||||
|
||||
# Base of this environment's 10-port block. cksum is used rather than $RANDOM or
|
||||
# bash hashing because it is POSIX and returns the same value on every machine,
|
||||
# which is what makes the block reproducible instead of merely unique.
|
||||
derive_port_base() {
|
||||
local h; h=$(printf '%s' "$1" | cksum | awk '{print $1}')
|
||||
echo $((20000 + (h % 200) * 10))
|
||||
}
|
||||
|
||||
load_config() {
|
||||
local k saved=""
|
||||
for k in $CONFIG_OVERRIDABLE; do
|
||||
# ${!k+x} distinguishes "set but empty" from "unset" — an explicit
|
||||
# FOO= on the command line is a real choice and must survive.
|
||||
if [ -n "${!k+x}" ]; then
|
||||
saved+="$k=$(printf '%q' "${!k}")"$'\n'
|
||||
fi
|
||||
done
|
||||
|
||||
set -a
|
||||
source ./versions.env
|
||||
[ -f ./.env ] && source ./.env
|
||||
set +a
|
||||
|
||||
# Re-apply overrides now so PROFILE is the caller's before we pick the file.
|
||||
_config_restore "$saved"
|
||||
|
||||
local profile="${PROFILE:-minimal}"
|
||||
if [ ! -f "./env.d/${profile}.env" ]; then
|
||||
echo "no such profile: env.d/${profile}.env" >&2
|
||||
echo "available: $(ls env.d/*.env 2>/dev/null | xargs -n1 basename | sed 's/\.env$//' | tr '\n' ' ')" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "./env.d/${profile}.env"
|
||||
[ -f ./.env ] && source ./.env
|
||||
set +a
|
||||
|
||||
_config_restore "$saved"
|
||||
|
||||
# Identity follows the FOLDER, so copying this directory somewhere else and
|
||||
# renaming it yields a distinct environment with no further edits. Without
|
||||
# this, two copies would share one cluster and `make cluster down` in either
|
||||
# would destroy the other's.
|
||||
CLUSTER="${CLUSTER:-$(default_cluster_name)}"
|
||||
KUBECONTEXT="kind-${CLUSTER}"
|
||||
|
||||
# Host ports are a single shared namespace, so unlike the cluster name they
|
||||
# cannot just follow the directory — they have to be spread out. Anything
|
||||
# already set (ctrl/.env, a profile, the command line) wins; only the gaps
|
||||
# are filled. See ports.sh for the reasoning.
|
||||
local base; base=$(derive_port_base "$CLUSTER")
|
||||
HTTP_PORT="${HTTP_PORT:-$base}"
|
||||
HTTPS_PORT="${HTTPS_PORT:-$((base + 1))}"
|
||||
TILT_PORT="${TILT_PORT:-$((base + 2))}"
|
||||
REGISTRY_PORT="${REGISTRY_PORT:-$((base + 3))}"
|
||||
|
||||
# Profiles name a k8s minor (v1_36); versions.env holds the pinned digest.
|
||||
local var="NODE_IMAGE_${K8S_VERSION}"
|
||||
NODE_IMAGE="${!var:-}"
|
||||
if [ -z "$NODE_IMAGE" ]; then
|
||||
echo "K8S_VERSION='${K8S_VERSION}' has no NODE_IMAGE_${K8S_VERSION} in versions.env" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The cluster's shape is a file in ctrl/k8s/, named by the profile. Adding a
|
||||
# shape is adding a file; there is no dispatcher to edit.
|
||||
KIND_CONFIG="${KIND_CONFIG:-kind-config.yaml.tpl}"
|
||||
KIND_CONFIG_PATH="./k8s/${KIND_CONFIG}"
|
||||
if [ ! -f "$KIND_CONFIG_PATH" ]; then
|
||||
echo "no such cluster shape: ctrl/k8s/${KIND_CONFIG}" >&2
|
||||
echo "available: $(ls k8s/kind-config*.yaml.tpl 2>/dev/null | xargs -n1 basename | tr '\n' ' ')" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read the shape back out of the YAML rather than trusting a profile to
|
||||
# restate it. station.sh sizes the memory warning on NODES, and cluster.sh
|
||||
# prints AUDIT before spending minutes building something that cannot be
|
||||
# changed afterwards — both would mislead if the numbers drifted.
|
||||
NODES=$(grep -c '^ - role:' "$KIND_CONFIG_PATH")
|
||||
if grep -q 'audit-policy-file' "$KIND_CONFIG_PATH"; then AUDIT=on; else AUDIT=off; fi
|
||||
}
|
||||
|
||||
# Render a cluster shape to stdout. sed rather than envsubst: envsubst is
|
||||
# gettext-base, absent from a minimal Debian, and Docker is meant to be the only
|
||||
# prerequisite. The variable list is explicit so a template cannot quietly start
|
||||
# depending on something the caller does not set.
|
||||
#
|
||||
# hostPath entries are resolved by the HOST dockerd, so HOST_WORKDIR must stay a
|
||||
# host path even when this runs inside the wizard container.
|
||||
render_kind_config() {
|
||||
local host_workdir="${HOST_WORKDIR:-$(cd .. && pwd)}"
|
||||
sed -e "s|\${CLUSTER}|${CLUSTER}|g" \
|
||||
-e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" \
|
||||
-e "s|\${HTTP_PORT}|${HTTP_PORT}|g" \
|
||||
-e "s|\${HOST_WORKDIR}|${host_workdir}|g" \
|
||||
"$KIND_CONFIG_PATH"
|
||||
}
|
||||
|
||||
_config_restore() {
|
||||
local line
|
||||
while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
eval "export $line"
|
||||
fi
|
||||
done <<< "$1"
|
||||
# A while loop returns its last body command's status; the trailing empty
|
||||
# line would otherwise make this return 1 and trip `set -e` in the caller.
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user