#!/bin/bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" [ -f "${SCRIPT_DIR}/env-buildkit_lite" ] && source "${SCRIPT_DIR}/env-buildkit_lite" [ -f "${SCRIPT_DIR}/_credentials.env" ] && source "${SCRIPT_DIR}/_credentials.env" BUILDKIT_NAMESPACE="${BUILDKIT_NAMESPACE:-build-system}" BUILDKIT_DEPLOYMENT="${BUILDKIT_DEPLOYMENT:-buildkitd}" BUILDKIT_IMAGE="${BUILDKIT_IMAGE:-moby/buildkit:v0.29.0}" BUILDKIT_PORT="${BUILDKIT_PORT:-1234}" BUILDKIT_REGISTRY_SECRET="${BUILDKIT_REGISTRY_SECRET:-zot-credentials}" CMD_TSK="${CMD_TSK:-${1:-install}}" _resolve_kubeconfig() { if [ -n "${KUBECONFIG:-}" ] && [ -f "$KUBECONFIG" ]; then return fi for candidate in \ /var/lib/k0s/pki/admin.conf \ /etc/kubernetes/admin.conf \ /root/.kube/config; do if [ -f "$candidate" ]; then export KUBECONFIG="$candidate" return fi done if command -v k0s >/dev/null 2>&1; then local tmp tmp="$(mktemp)" k0s kubeconfig admin > "$tmp" 2>/dev/null && export KUBECONFIG="$tmp" && return rm -f "$tmp" fi echo "ERROR: kubeconfig not found — set KUBECONFIG explicitly" >&2; exit 1 } _resolve_kubeconfig _kubectl() { if command -v kubectl >/dev/null 2>&1; then command kubectl "$@" elif command -v k0s >/dev/null 2>&1; then k0s kubectl "$@" else echo "ERROR: no kubectl or k0s binary found" >&2; exit 127 fi } _wait_for_deploy() { local timeout="${1:-120}" _kubectl rollout status deployment/"$BUILDKIT_DEPLOYMENT" \ --namespace "$BUILDKIT_NAMESPACE" \ --timeout="${timeout}s" } _ensure_registry_secret() { if _kubectl get secret "$BUILDKIT_REGISTRY_SECRET" \ --namespace "$BUILDKIT_NAMESPACE" >/dev/null 2>&1; then return fi if _kubectl get secret "$BUILDKIT_REGISTRY_SECRET" \ --namespace registry >/dev/null 2>&1; then _kubectl get secret "$BUILDKIT_REGISTRY_SECRET" \ --namespace registry -o yaml \ | sed "s/namespace: registry/namespace: $BUILDKIT_NAMESPACE/" \ | _kubectl apply -f - echo "Copied $BUILDKIT_REGISTRY_SECRET from registry namespace" else echo "WARNING: secret $BUILDKIT_REGISTRY_SECRET not found — buildkitd will have no registry auth" >&2 fi } _apply_if_present() { local path="$1" [ -f "$path" ] || return 0 if ! grep -q '[^[:space:]]' "$path"; then echo " [skip] $(basename "$path") is empty (template inactive)" return 0 fi _kubectl apply -f "$path" } _delete_if_present() { local path="$1" [ -f "$path" ] || return 0 if ! grep -q '[^[:space:]]' "$path"; then return 0 fi _kubectl delete -f "$path" --ignore-not-found } _wait_for_secret() { local secret="$1" local timeout="${2:-60}" local elapsed=0 while [ "$elapsed" -lt "$timeout" ]; do if _kubectl get secret "$secret" --namespace "$BUILDKIT_NAMESPACE" >/dev/null 2>&1; then return 0 fi sleep 2 elapsed=$((elapsed + 2)) done echo "WARNING: secret $secret not issued within ${timeout}s — buildkitd will fail until cert-manager catches up" >&2 return 1 } _apply_pki_if_enabled() { # Templates render empty when mtls.cert_manager.enabled is false → blank-skip. _apply_if_present "$SCRIPT_DIR/templates/mtls-clusterissuer.yaml" _apply_if_present "$SCRIPT_DIR/templates/mtls-ca-certificate.yaml" # CA Issuer depends on the CA secret being populated by cert-manager. if [ -f "$SCRIPT_DIR/templates/mtls-ca-certificate.yaml" ] \ && grep -q '[^[:space:]]' "$SCRIPT_DIR/templates/mtls-ca-certificate.yaml"; then _wait_for_secret "${BUILDKIT_MTLS_CA_SECRET:-buildkit-mtls-ca}" 60 || true fi _apply_if_present "$SCRIPT_DIR/templates/mtls-ca-issuer.yaml" _apply_if_present "$SCRIPT_DIR/templates/mtls-server-certificate.yaml" if [ -f "$SCRIPT_DIR/templates/mtls-server-certificate.yaml" ] \ && grep -q '[^[:space:]]' "$SCRIPT_DIR/templates/mtls-server-certificate.yaml"; then _wait_for_secret "${BUILDKIT_MTLS_SERVER_SECRET:-buildkit-mtls-server}" 60 || true fi } _do_install() { _kubectl apply -f "$SCRIPT_DIR/templates/namespace.yaml" _apply_pki_if_enabled _ensure_registry_secret # cache PVC (renders empty unless cache.enabled) — must exist before the Deployment mounts it _apply_if_present "$SCRIPT_DIR/templates/pvc.yaml" _kubectl apply -f "$SCRIPT_DIR/templates/buildkitd-config.yaml" _kubectl apply -f "$SCRIPT_DIR/templates/deployment.yaml" _kubectl apply -f "$SCRIPT_DIR/templates/service.yaml" _apply_if_present "$SCRIPT_DIR/templates/service-vpn.yaml" echo "Waiting for buildkitd to be ready..." _wait_for_deploy 120 echo "buildkit_lite installed in namespace $BUILDKIT_NAMESPACE" } _do_update() { _apply_pki_if_enabled _apply_if_present "$SCRIPT_DIR/templates/pvc.yaml" _kubectl apply -f "$SCRIPT_DIR/templates/buildkitd-config.yaml" _kubectl apply -f "$SCRIPT_DIR/templates/deployment.yaml" _apply_if_present "$SCRIPT_DIR/templates/service-vpn.yaml" _kubectl rollout restart deployment/"$BUILDKIT_DEPLOYMENT" --namespace "$BUILDKIT_NAMESPACE" echo "Waiting for buildkitd to restart..." _wait_for_deploy 120 echo "buildkit_lite updated" } _do_delete() { _kubectl delete -f "$SCRIPT_DIR/templates/deployment.yaml" --ignore-not-found _kubectl delete -f "$SCRIPT_DIR/templates/service.yaml" --ignore-not-found _delete_if_present "$SCRIPT_DIR/templates/service-vpn.yaml" _delete_if_present "$SCRIPT_DIR/templates/mtls-server-certificate.yaml" _delete_if_present "$SCRIPT_DIR/templates/mtls-ca-issuer.yaml" _delete_if_present "$SCRIPT_DIR/templates/mtls-ca-certificate.yaml" # mtls-clusterissuer is cluster-scoped and shareable — never delete it from a component teardown. echo "buildkit_lite removed from namespace $BUILDKIT_NAMESPACE" } _do_health() { local ready ready=$(_kubectl get deployment "$BUILDKIT_DEPLOYMENT" \ --namespace "$BUILDKIT_NAMESPACE" \ -o jsonpath='{.status.readyReplicas}' 2>/dev/null || echo "0") if [ "${ready:-0}" -ge 1 ]; then echo "HEALTHY: $BUILDKIT_DEPLOYMENT $ready/$ready ready" else echo "UNHEALTHY: $BUILDKIT_DEPLOYMENT not ready in namespace $BUILDKIT_NAMESPACE" >&2 exit 1 fi } case "$CMD_TSK" in install) _do_install ;; update) _do_update ;; delete) _do_delete ;; health) _do_health ;; *) echo "ERROR: unknown CMD_TSK='$CMD_TSK'. Valid: install|update|delete|health" >&2 exit 1 ;; esac