Created
February 21, 2026 13:46
-
-
Save bgulla/4d577ec8bae900a445d8c28f31d2352f to your computer and use it in GitHub Desktop.
Elemental Force Removal Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Force delete stuck Elemental machines from Rancher | |
| # Assumes machines are powered off / unreachable | |
| set -euo pipefail | |
| RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' | |
| info() { echo -e "${GREEN}[INFO]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } | |
| error() { echo -e "${RED}[ERROR]${NC} $*"; } | |
| NAMESPACES=("fleet-default" "cattle-elemental-system" "cattle-system" "fleet-system") | |
| RESOURCE_TYPES=( | |
| "machineinventories.elemental.cattle.io" | |
| "machines.elemental.cattle.io" | |
| "machineregistrations.elemental.cattle.io" | |
| "elementalmachines.elemental.cattle.io" | |
| ) | |
| kubectl cluster-info &>/dev/null || { error "kubectl can't reach the cluster"; exit 1; } | |
| # ── Find all stuck Elemental resources ────────────────────────────────────── | |
| declare -A FOUND # "resource/namespace/name" => 1 | |
| find_stuck() { | |
| info "Scanning for stuck Elemental resources..." | |
| for rt in "${RESOURCE_TYPES[@]}"; do | |
| # Skip unknown CRDs silently | |
| kubectl get crd "$rt" &>/dev/null || continue | |
| for ns in "${NAMESPACES[@]}"; do | |
| kubectl get namespace "$ns" &>/dev/null || continue | |
| while IFS= read -r name; do | |
| [[ -z "$name" ]] && continue | |
| key="${rt}|${ns}|${name}" | |
| FOUND["$key"]=1 | |
| echo " STUCK: $rt/$name (ns: $ns)" | |
| done < <(kubectl get "$rt" -n "$ns" \ | |
| -o jsonpath='{range .items[?(@.metadata.deletionTimestamp)]}{.metadata.name}{"\n"}{end}' 2>/dev/null || true) | |
| done | |
| done | |
| } | |
| # ── Force-delete one resource ──────────────────────────────────────────────── | |
| force_delete() { | |
| local rt="$1" ns="$2" name="$3" | |
| info "Processing $rt/$name in $ns..." | |
| # 1. Strip finalizers | |
| kubectl patch "$rt" "$name" -n "$ns" \ | |
| --type json \ | |
| -p '[{"op":"replace","path":"/metadata/finalizers","value":[]}]' \ | |
| &>/dev/null && info " Finalizers cleared" || warn " Patch failed (may already be gone)" | |
| # 2. Force delete | |
| kubectl delete "$rt" "$name" -n "$ns" \ | |
| --force --grace-period=0 \ | |
| --ignore-not-found=true \ | |
| &>/dev/null && info " Deleted" || warn " Delete failed (may already be gone)" | |
| } | |
| # ── Main ───────────────────────────────────────────────────────────────────── | |
| main() { | |
| find_stuck | |
| if [[ ${#FOUND[@]} -eq 0 ]]; then | |
| info "No stuck Elemental machines found — you're already clean!" | |
| exit 0 | |
| fi | |
| echo "" | |
| warn "Found ${#FOUND[@]} stuck resource(s). This will force-remove them." | |
| read -rp "Continue? (yes/no): " confirm | |
| [[ "$confirm" == "yes" ]] || { info "Aborted."; exit 0; } | |
| echo "" | |
| for key in "${!FOUND[@]}"; do | |
| IFS='|' read -r rt ns name <<< "$key" | |
| force_delete "$rt" "$ns" "$name" | |
| done | |
| echo "" | |
| info "Done. Verifying..." | |
| sleep 2 | |
| find_stuck | |
| if [[ ${#FOUND[@]} -eq 0 ]]; then | |
| info "All clear! No stuck resources remain." | |
| else | |
| warn "${#FOUND[@]} resource(s) still stuck. You may need to check the Elemental operator logs:" | |
| echo " kubectl logs -n cattle-elemental-system deploy/elemental-operator" | |
| fi | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment