prole/mock_val/init_gitlab.sh

175 lines
5.9 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
PROG="init_gitlab"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1090
source "$SCRIPT_DIR/knoe_cfg.sh"
MODE="$(knoe_normalize_mode "${KNOE_MODE:-${DEPLOYMENT_MODE:-k3d}}")"
NAMESPACE="${GITLAB_NAMESPACE:-}"
CFG_PATH=""
FORCE=0
usage() {
cat <<EOF
Usage:
$PROG [options] [deploy]
Options:
--mode <k3d|k3s|k8s|local> Deployment mode (default: ${MODE:-k3d})
-n, --namespace <name> Target namespace (default: gitlab)
-c, --config <knoe.cfg> Path to knoe.cfg (defaults to detected)
--force Uninstall existing GitLab release before deploy
--help Show this help
Behavior:
- Installs self-hosted GitLab via the official Helm chart.
- Uses CloudNativePG (CNPG) Postgres as the database backend (external DB).
EOF
}
die() { echo "[ERROR] $*" >&2; exit 2; }
log() { echo "[INFO] $*"; }
warn() { echo "[WARN] $*" >&2; }
while [[ $# -gt 0 ]]; do
case "$1" in
--mode) MODE="$(knoe_normalize_mode "${2:-}")"; shift 2 ;;
--mode=*) MODE="$(knoe_normalize_mode "${1#*=}")"; shift 1 ;;
-n|--namespace) NAMESPACE="${2:-}"; shift 2 ;;
--namespace=*) NAMESPACE="${1#*=}"; shift 1 ;;
-c|--config) CFG_PATH="${2:-}"; shift 2 ;;
--config=*) CFG_PATH="${1#*=}"; shift 1 ;;
--force) FORCE=1; shift 1 ;;
-h|--help) usage; exit 0 ;;
*) break ;;
esac
done
# Resolve config path and namespace defaults from knoe.cfg when present
if [[ -z "$CFG_PATH" && -n "${KNOE_CONF:-}" && -f "${KNOE_CONF}/knoe.cfg" ]]; then
CFG_PATH="${KNOE_CONF}/knoe.cfg"
elif [[ -z "$CFG_PATH" && -f "$SCRIPT_DIR/../conf/knoe.cfg" ]]; then
CFG_PATH="$SCRIPT_DIR/../conf/knoe.cfg"
fi
if [[ -z "$NAMESPACE" && -n "$CFG_PATH" ]]; then
maybe_ns="$(_knoe_cfg_extract_key "$CFG_PATH" "GITOPS_NAMESPACE")"
[[ -z "$maybe_ns" ]] && maybe_ns="$(_knoe_cfg_extract_key "$CFG_PATH" "GITLAB_NAMESPACE")"
NAMESPACE="$maybe_ns"
fi
NAMESPACE="${NAMESPACE:-gitlab}"
export GITLAB_NAMESPACE="$NAMESPACE"
case "$MODE" in
k3d|k3s|k8s|local) ;;
*) die "Unsupported mode '$MODE' (use k3d, k3s, k8s, or local)" ;;
esac
export KNOE_MODE="$MODE"
command -v kubectl >/dev/null || die "kubectl not found"
command -v helm >/dev/null || die "helm not found (required for GitLab install)"
DB_NAMESPACE="${PROLE_NAMESPACE:-}"
if [[ -z "$DB_NAMESPACE" && -n "$CFG_PATH" ]]; then
DB_NAMESPACE="$(_knoe_cfg_extract_key "$CFG_PATH" "NAMESPACE")"
fi
DB_NAMESPACE="${DB_NAMESPACE:-default}"
CNPG_CLUSTER_NAME="${CNPG_CLUSTER_NAME:-knoe-db}"
GITLAB_DB_NAME="${GITLAB_DB_NAME:-gitlabhq_production}"
GITLAB_DB_USER="${GITLAB_DB_USER:-gitlab}"
GITLAB_DB_PASSWORD="${GITLAB_DB_PASSWORD:-}"
if [[ -z "$GITLAB_DB_PASSWORD" ]]; then
GITLAB_DB_PASSWORD=$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom 2>/dev/null | head -c 32 || true)
fi
DB_HOST="${CNPG_CLUSTER_NAME}-rw.${DB_NAMESPACE}.svc.cluster.local"
DB_PORT="${GITLAB_DB_PORT:-5432}"
kubectl get ns "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE" >/dev/null 2>&1
ensure_db() {
local primary_pod=""
primary_pod=$(kubectl -n "$DB_NAMESPACE" get pods \
-l "cnpg.io/cluster=${CNPG_CLUSTER_NAME},role=primary" \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
if [[ -z "$primary_pod" ]]; then
primary_pod=$(kubectl -n "$DB_NAMESPACE" get pods \
-l "cnpg.io/cluster=${CNPG_CLUSTER_NAME}" \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
fi
if [[ -z "$primary_pod" ]]; then
die "Could not find CNPG pod for cluster '${CNPG_CLUSTER_NAME}' in namespace '${DB_NAMESPACE}'"
fi
log "Ensuring database '${GITLAB_DB_NAME}' and role '${GITLAB_DB_USER}' exist in CNPG cluster '${CNPG_CLUSTER_NAME}' (ns=${DB_NAMESPACE})"
kubectl -n "$DB_NAMESPACE" exec "$primary_pod" -- bash -lc "psql -v ON_ERROR_STOP=1 -U postgres -d postgres" <<SQL
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = '${GITLAB_DB_USER}') THEN
CREATE ROLE ${GITLAB_DB_USER} LOGIN PASSWORD '${GITLAB_DB_PASSWORD}';
END IF;
END
\$\$;
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = '${GITLAB_DB_NAME}') THEN
CREATE DATABASE ${GITLAB_DB_NAME} OWNER ${GITLAB_DB_USER};
END IF;
END
\$\$;
SQL
kubectl -n "$NAMESPACE" create secret generic gitlab-db \
--from-literal=host="$DB_HOST" \
--from-literal=port="$DB_PORT" \
--from-literal=database="$GITLAB_DB_NAME" \
--from-literal=username="$GITLAB_DB_USER" \
--from-literal=password="$GITLAB_DB_PASSWORD" \
--dry-run=client -o yaml | kubectl apply -f - >/dev/null
}
ensure_db
RELEASE_NAME="${GITLAB_RELEASE_NAME:-gitlab}"
if [[ "$FORCE" -eq 1 ]]; then
warn "--force specified; uninstalling existing release '$RELEASE_NAME' in namespace '$NAMESPACE' (if present)"
helm -n "$NAMESPACE" uninstall "$RELEASE_NAME" >/dev/null 2>&1 || true
fi
GITLAB_DOMAIN="${GITLAB_DOMAIN:-${DOMAIN:-${PROLE_DOMAIN:-}}}"
GITLAB_DOMAIN="${GITLAB_DOMAIN:-example.local}"
log "Adding/updating GitLab Helm repo"
helm repo add gitlab https://charts.gitlab.io/ >/dev/null 2>&1 || true
helm repo update >/dev/null
log "Installing GitLab (release=$RELEASE_NAME, ns=$NAMESPACE, domain=$GITLAB_DOMAIN)"
# Notes:
# - We keep the chart install minimal to avoid assuming ingress/cert-manager setup.
# - We disable the bundled PostgreSQL and point GitLab to CNPG.
helm upgrade --install "$RELEASE_NAME" gitlab/gitlab \
-n "$NAMESPACE" \
--timeout 30m \
--wait \
--set global.hosts.domain="$GITLAB_DOMAIN" \
--set global.hosts.https=false \
--set certmanager.install=false \
--set prometheus.install=false \
--set postgresql.install=false \
--set global.psql.host="$DB_HOST" \
--set global.psql.port="$DB_PORT" \
--set global.psql.username="$GITLAB_DB_USER" \
--set global.psql.database="$GITLAB_DB_NAME" \
--set global.psql.password.secret=gitlab-db \
--set global.psql.password.key=password
log "Done. Inspect services/pods with: kubectl -n $NAMESPACE get pods,svc"