prole/scripts/cleanup-supabase-pvs.sh
chrisfu 20692c988d chore: enhance Supabase retained disk cleanup with project resolution and detailed skip reasons
- Updated `deploy.sh` to resolve project IDs from multiple configuration fallbacks and environment contexts for retained disk cleanup.
- Added support for `supabase_cfg_first_nonempty_value` to prioritize configuration over defaults.
- Enhanced logging with explicit reasons for skipped disk cleanup actions (e.g., missing gcloud, unresolved project).
- Updated tests to validate fallback logic and skip reason reporting.
2026-04-19 17:16:49 -07:00

110 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
PROJECT="${PROJECT:-${GCP_PROJECT_ID:-${GOOGLE_CLOUD_PROJECT:-plenary-truck-485623-p7}}}"
DRY_RUN_RAW="${SUPABASE_RETAINED_PV_CLEANUP_DRY_RUN:-false}"
DRY_RUN="false"
if [[ "${DRY_RUN_RAW,,}" =~ ^(1|true|yes|on)$ ]]; then
DRY_RUN="true"
fi
echo "==> Finding stale Supabase PVs (Released + Retain, Supabase namespace/storageClass)..."
echo "==> Dry run: ${DRY_RUN}"
echo "==> Project: ${PROJECT}"
mapfile -t CANDIDATES < <(
kubectl get pv -o json | jq -r '
.items[]
| . as $pv
| ($pv.spec.claimRef.namespace // "") as $claimNs
| ($pv.spec.storageClassName // "") as $sc
| select(
($pv.status.phase == "Released")
and (($pv.spec.persistentVolumeReclaimPolicy // "") == "Retain")
and (
$sc == "supabase-standard"
or $claimNs == "supabase"
)
)
| (
($pv.spec.csi.volumeHandle // $pv.spec.gcePersistentDisk.pdName // "")
) as $handle
| (
($pv.metadata.labels["topology.kubernetes.io/zone"]
// $pv.metadata.labels["failure-domain.beta.kubernetes.io/zone"]
// $pv.spec.csi.volumeAttributes["topology.gke.io/zone"]
// (
if ($handle | test("/zones/[^/]+/disks/[^/]+$"))
then ($handle | capture("/zones/(?<z>[^/]+)/disks/").z)
else ""
end
)
)
) as $zone
| [
($pv.metadata.name // ""),
$claimNs,
($pv.spec.claimRef.name // ""),
($pv.status.phase // ""),
($pv.spec.persistentVolumeReclaimPolicy // ""),
$sc,
$handle,
$zone
]
| @tsv
'
)
if [[ ${#CANDIDATES[@]} -eq 0 ]]; then
echo "==> No stale Supabase Released/Retain PV candidates found."
exit 0
fi
echo "==> Candidates:"
for row in "${CANDIDATES[@]}"; do
IFS=$'\t' read -r PV CLAIM_NS CLAIM_NAME PHASE RECLAIM SC DISK ZONE <<<"$row"
echo " - PV=${PV} claim=${CLAIM_NS}/${CLAIM_NAME:-<none>} phase=${PHASE} reclaim=${RECLAIM} sc=${SC} disk=${DISK:-<none>} zone=${ZONE:-<unknown>}"
done
for row in "${CANDIDATES[@]}"; do
IFS=$'\t' read -r PV CLAIM_NS CLAIM_NAME PHASE RECLAIM SC DISK ZONE <<<"$row"
NAME="${DISK##*/}"
if [[ "$DRY_RUN" == "true" ]]; then
echo "[dry-run] kubectl delete pv ${PV} --ignore-not-found"
if [[ -n "$DISK" && "$DISK" != "null" ]]; then
if [[ -n "$ZONE" ]]; then
echo "[dry-run] gcloud compute disks delete ${NAME} --zone ${ZONE} --project ${PROJECT} --quiet"
else
echo "[dry-run] skip disk delete for ${DISK} (missing zone)"
fi
else
echo "[dry-run] skip disk delete for PV ${PV} (no disk handle)"
fi
continue
fi
echo "==> Deleting PV ${PV}"
kubectl delete pv "$PV" --ignore-not-found
if [[ -z "$DISK" || "$DISK" == "null" ]]; then
echo "[WARN] PV ${PV} has no disk handle; skipped disk delete"
continue
fi
if [[ -z "$ZONE" ]]; then
echo "[WARN] Disk ${DISK} zone is unknown; skipped disk delete"
continue
fi
if ! command -v gcloud >/dev/null 2>&1; then
echo "[WARN] gcloud not found; skipped disk delete for ${DISK}"
continue
fi
echo "==> Deleting GCE disk ${NAME} (zone=${ZONE})"
gcloud compute disks delete "$NAME" --zone "$ZONE" --project "$PROJECT" --quiet \
|| echo "[WARN] disk delete failed: ${NAME}"
done
echo "==> Cleanup complete"