who_need_help/scripts/kind-up.sh

156 lines
5.8 KiB
Bash
Executable File

#!/bin/sh
set -eu
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
"$ROOT/scripts/bootstrap-kubernetes-tools.sh"
PATH="$ROOT/.tools/bin:$PATH"
export PATH
CLUSTER=who-need-help
MARKER="$ROOT/.tools/${CLUSTER}.owned"
NAMESPACE=who-need-help
SECRET_NAME=who-need-help-local
POSTGIS_IMAGE=postgis/postgis:18-3.6-alpine
POSTGIS_SOURCE="${POSTGIS_IMAGE}@sha256:05d68c7f0f19b9aa0bf7c4a2049b2e8b38b44a63116392b95726a4c913766cf6"
MAILPIT_IMAGE=axllent/mailpit:v1.30.4
MAILPIT_SOURCE="${MAILPIT_IMAGE}@sha256:5a49a77c5bdbe7c5474450b4f46348d09949df3695257729c93a30369382d4f6"
kube() {
kubectl --context "kind-${CLUSTER}" "$@"
}
case "$(uname -m)" in
x86_64) IMAGE_ARCH=amd64 ;;
aarch64|arm64) IMAGE_ARCH=arm64 ;;
*) echo "Unsupported container architecture: $(uname -m)" >&2; exit 1 ;;
esac
load_pinned_image() {
source=$1
local_tag=$2
archive=$3
docker pull --platform "linux/${IMAGE_ARCH}" "$source"
image_id=$(docker image inspect "$source" --format '{{.Id}}')
docker tag "$image_id" "$local_tag"
docker image save --platform "linux/${IMAGE_ARCH}" --output "$archive" "$local_tag"
kind load image-archive "$archive" --name "$CLUSTER"
rm -f "$archive"
}
remove_legacy_inline_secrets() {
legacy_secret=who-need-help-who-need-help
# Older chart revisions rendered credentials from tracked Helm values. Once
# the new deployments are healthy, remove the obsolete Secret and only those
# release-history records that still contain the former inline secret keys.
kube --namespace "$NAMESPACE" delete secret "$legacy_secret" \
--ignore-not-found >/dev/null
for revision in $(
helm history who-need-help \
--kube-context "kind-${CLUSTER}" \
--namespace "$NAMESPACE" |
awk 'NR > 1 {print $1}'
); do
if helm get values who-need-help \
--revision "$revision" \
--kube-context "kind-${CLUSTER}" \
--namespace "$NAMESPACE" |
grep -Eq '^[[:space:]]*(databaseUrl|secretKeyBase|handoverSecret|releaseCookie):'; then
kube --namespace "$NAMESPACE" delete secret \
--selector="owner=helm,name=who-need-help,version=${revision}"
fi
done
}
if kind get clusters | grep -Fxq "$CLUSTER"; then
if [ ! -f "$MARKER" ]; then
echo "A kind cluster named '$CLUSTER' already exists but was not created by this project." >&2
echo "Refusing to modify it. Rename/remove it yourself or inspect it first." >&2
exit 1
fi
else
kind create cluster --config "$ROOT/deploy/kind/cluster.yaml"
touch "$MARKER"
fi
load_pinned_image "$POSTGIS_SOURCE" "$POSTGIS_IMAGE" "$ROOT/.tools/postgis-kind.tar"
load_pinned_image "$MAILPIT_SOURCE" "$MAILPIT_IMAGE" "$ROOT/.tools/mailpit-kind.tar"
docker build --tag who-need-help:local "$ROOT"
kind load docker-image who-need-help:local --name "$CLUSTER"
kube create namespace "$NAMESPACE" --dry-run=client --output=yaml | kube apply -f -
legacy_backup=
if kube --namespace "$NAMESPACE" get deployment postgis >/dev/null 2>&1; then
backup_dir="$ROOT/output/backups"
mkdir -p "$backup_dir"
umask 077
legacy_backup="$backup_dir/kind-who-need-help-$(date +%Y%m%d-%H%M%S).dump"
kube --namespace "$NAMESPACE" exec deployment/postgis -- \
pg_dump --username postgres --dbname who_need_help --format custom >"$legacy_backup"
test -s "$legacy_backup"
kube --namespace "$NAMESPACE" exec --stdin deployment/postgis -- \
pg_restore --list <"$legacy_backup" >/dev/null
echo "Validated legacy kind database backup: $legacy_backup"
fi
if ! kube --namespace "$NAMESPACE" get secret "$SECRET_NAME" >/dev/null 2>&1; then
if kube --namespace "$NAMESPACE" get statefulset postgis >/dev/null 2>&1; then
echo "Secret '$SECRET_NAME' is missing while the persistent PostGIS StatefulSet exists." >&2
echo "Refusing to generate credentials that would not match the existing database." >&2
exit 1
fi
postgres_password=$(openssl rand -hex 32)
secret_key_base=$(openssl rand -hex 64)
handover_secret=$(openssl rand -hex 64)
release_cookie=$(openssl rand -hex 64)
kube --namespace "$NAMESPACE" create secret generic "$SECRET_NAME" \
--from-literal=POSTGRES_DB=who_need_help \
--from-literal=POSTGRES_USER=postgres \
--from-literal="POSTGRES_PASSWORD=$postgres_password" \
--from-literal="DATABASE_URL=ecto://postgres:${postgres_password}@postgis/who_need_help" \
--from-literal="SECRET_KEY_BASE=$secret_key_base" \
--from-literal="HANDOVER_SECRET=$handover_secret" \
--from-literal="RELEASE_COOKIE=$release_cookie"
unset postgres_password secret_key_base handover_secret release_cookie
fi
if [ -n "$legacy_backup" ]; then
kube --namespace "$NAMESPACE" delete deployment postgis --wait=true
fi
kube --namespace "$NAMESPACE" apply -f "$ROOT/deploy/kind/dependencies.yaml"
kube --namespace "$NAMESPACE" rollout status statefulset/postgis
kube --namespace "$NAMESPACE" rollout status deployment/mailpit
if [ -n "$legacy_backup" ]; then
kube --namespace "$NAMESPACE" exec --stdin statefulset/postgis -- \
pg_restore --username postgres --dbname who_need_help \
--clean --if-exists --no-owner <"$legacy_backup"
echo "Restored legacy kind database backup."
fi
helm upgrade --install who-need-help "$ROOT/deploy/helm/who-need-help" \
--kube-context "kind-${CLUSTER}" \
--namespace "$NAMESPACE" \
--values "$ROOT/deploy/helm/who-need-help/values-kind.yaml" \
--set-string app.codexSessionId="${CODEX_SESSION_ID:-${CODEX_THREAD_ID:-not-configured}}" \
--wait
kube --namespace "$NAMESPACE" rollout restart \
deployment/who-need-help-who-need-help-web \
deployment/who-need-help-who-need-help-worker
kube --namespace "$NAMESPACE" rollout status deployment/who-need-help-who-need-help-web
kube --namespace "$NAMESPACE" rollout status deployment/who-need-help-who-need-help-worker
remove_legacy_inline_secrets
"$ROOT/scripts/verify-realtime-cluster.sh" kind
echo "Who Need Help: http://localhost:4011"
echo "Mailpit: http://localhost:8028"