prole/install.sh
chrisfu 4f3280002c fix(k3s): repair iscsi-pvs node names and kubectl context after prole→knoe rename
k8s/knoe/iscsi-pvs.yaml had *.knoe.org nodeAffinity after the rename, but the
live k3s cluster nodes are still *.prole.org — causing immutable field errors on
Bound PVs during kubectl apply. Revert to *.prole.org to match live state.

conf/k3s.cfg KUBECTL_CONTEXT was renamed to knoe-service-cluster, but both the
system kubeconfig and etc/secrets/k3s.kubeconfig still use prole-service-cluster.

install.sh _check_gcp_tools() now skips gcloud check for k3s mode and any non-gke
config path (only GKE deploys need gcloud/kubectl pre-flight).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 02:48:48 -07:00

135 lines
5.1 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Thin launch vehicle for the Knoe installer.
#
# Local execution (from a repo checkout):
# ./install.sh [args...]
#
# Bootstrap via curl (first-time install):
# curl -fsSL https://knoey.com/install.sh | bash
#
# ---------------------------------------------------------------------------
# Dual-cluster GKE architecture (prod / k8s mode)
# ---------------------------------------------------------------------------
# knoe-dev-0 — Autopilot cluster: app workloads (GitLab, platform), service mesh knoe-0
# knoe-cnpg-0 — Standard GKE cluster: CloudNative-PG only (rw/ro/r pod separation)
# 3 nodes × e2-standard-2, node pool: cnpg-db-pool
#
# GCP quota requirements (project: plenary-truck-485623-p7, region: us-west3):
# pd-standard : node boot disks (3 × 50 GB = 150 GB — does NOT count against pd-ssd quota)
# pd-ssd : PGDATA PVCs (3 × 50 Gi = 150 Gi)
# WAL PVCs (3 × 50 Gi = 150 Gi)
# Total pd-ssd = 300 Gi (requires 300 GB pd-ssd regional quota)
#
# To patch an existing knoe-cnpg-0 cluster with wrong boot disk type:
# ./scripts/patch_clusters.sh # dry-run first: DRY_RUN=true ./scripts/patch_clusters.sh
# ---------------------------------------------------------------------------
set -euo pipefail
# Repo URL used only during bootstrap (curl-pipe) installs.
KNOE_REPO_URL="${KNOE_REPO_URL:-https://gitlab.knoey.com/knoe/knoe.git}"
# Default install directory for bootstrap installs.
_INSTALL_DIR="${KNOE_HOME:-$HOME/knoe}"
_check_gcp_tools() {
# gcloud is only required for GKE (k8s) deploys — skip for k3d, k3s, and min modes
for arg in "$@"; do
if [[ "$arg" == "--min" || "$arg" == "--k3d" || "$arg" == "--k3s" ]]; then
return 0
fi
done
# Skip when a non-GKE config is explicitly passed (only gke.cfg needs gcloud)
local prev=""
for arg in "$@"; do
if [[ ("$prev" == "-c" || "$prev" == "--config") && "$arg" != *gke* ]]; then
return 0
fi
prev="$arg"
done
local missing=0
if ! command -v gcloud >/dev/null 2>&1; then
echo "Error: gcloud CLI is required for GKE cluster management." >&2
echo " Install: https://cloud.google.com/sdk/docs/install" >&2
missing=1
fi
if ! command -v kubectl >/dev/null 2>&1; then
echo "Error: kubectl is required for Kubernetes cluster operations." >&2
echo " Install: https://kubernetes.io/docs/tasks/tools/" >&2
missing=1
fi
if [[ "$missing" -ne 0 ]]; then
echo "" >&2
echo "Install missing tools and re-run install.sh." >&2
exit 1
fi
}
_bootstrap() {
echo "==> Bootstrapping Knoe installer..."
command -v git >/dev/null 2>&1 || { echo "Error: git is required." >&2; exit 1; }
command -v python3 >/dev/null 2>&1 || { echo "Error: python3 is required." >&2; exit 1; }
if [[ -d "${_INSTALL_DIR}/.git" ]]; then
echo "==> Updating existing checkout at ${_INSTALL_DIR} ..."
git -C "${_INSTALL_DIR}" pull --ff-only
else
echo "==> Cloning to ${_INSTALL_DIR} ..."
git clone "${KNOE_REPO_URL}" "${_INSTALL_DIR}"
fi
exec "${_INSTALL_DIR}/install.sh" "$@"
}
# Resolve script directory; empty when running via curl pipe.
_src="${BASH_SOURCE[0]:-}"
_script_dir="$(cd "$(dirname "${_src:-/}")" 2>/dev/null && pwd || echo "")"
if [[ -n "${_script_dir}" && -d "${_script_dir}/knoe" ]]; then
# Local checkout: delegate to the Python installer module.
cd "${_script_dir}"
# kubectl-context notice. install.sh defers mode selection to the Python
# TUI, so we can't strictly verify here — but printing the inherited
# context up-front gives the user a chance to abort before the TUI
# launches if it looks wrong (e.g. shell on GKE while planning a k3d
# install). Filed against docs/TODO.md queue item #1 (drift R4); the
# mode-aware strict guard runs in deploy.sh (which knows its config) and
# should also run Python-side once the welcome screen records a mode.
if [[ -f "${_script_dir}/etc/preflight_kubecontext.sh" ]]; then
_is_min=0
for arg in "$@"; do
if [[ "$arg" == "--min" ]]; then _is_min=1; break; fi
done
if [[ "$_is_min" -eq 0 ]]; then
# shellcheck source=etc/preflight_kubecontext.sh
source "${_script_dir}/etc/preflight_kubecontext.sh"
print_kubecontext_notice
fi
unset _is_min
fi
# 1Password preflight — sign in, create 'knoey' vault, ensure 'administrator' item.
# Skipped in --min mode (init_1password.sh handles the flag check itself).
if [[ -f "${_script_dir}/etc/init_1password.sh" ]]; then
bash "${_script_dir}/etc/init_1password.sh" "$@" || true
fi
# If a built binary exists, prefer it.
if [[ -x "dist/knoe" ]]; then
exec "./dist/knoe" "$@"
fi
# Prefer the venv Python at KNOE_HOME (or the repo root) when available;
# it carries all knoe_requirements.txt dependencies.
_VENV_PYTHON="${KNOE_HOME:-${_script_dir}}/bin/python3"
_check_gcp_tools "$@"
if [[ -x "${_VENV_PYTHON}" ]]; then
exec "${_VENV_PYTHON}" -m knoe.ui.screens "$@"
fi
exec python3 -m knoe.ui.screens "$@"
else
# No local checkout found — bootstrap from the remote repo.
_bootstrap "$@"
fi