From bc8ad082281ce347ef8f6c28e548c73108582222 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?=
 <nicolas.jeannerod@moduscreate.com>
Date: Mon, 24 Feb 2025 18:33:44 +0100
Subject: [PATCH] Make removal script support ids or names

---
 infra/proxmox-remove.sh | 82 ++++++++++++++++++++++++++++++-----------
 1 file changed, 61 insertions(+), 21 deletions(-)

diff --git a/infra/proxmox-remove.sh b/infra/proxmox-remove.sh
index 8ab7975a..8ae410e8 100755
--- a/infra/proxmox-remove.sh
+++ b/infra/proxmox-remove.sh
@@ -18,11 +18,11 @@ mkdir $tmpdir
 api_url=
 username=
 password=
-vm_ids=
+vm_ids_or_names=
 
 help () {
   cat <<EOF
-Usage: $0 [OPTION...] ID [ID...]
+Usage: $0 [OPTION...] ID_OR_NAME [ID_OR_NAME...]
 
 Options:
   --api-url STR     Base URL of the Proxmox API (required)
@@ -35,7 +35,6 @@ Options can also be provided by adding assignments to a '.proxmox' file in the
 current working directory. For instance, it could contain:
 
   api_url=https://192.168.51.81:8006/api2/json
-  cores=7
   username=mireille@pve
   debug=true
 
@@ -64,12 +63,12 @@ while [ $# -gt 0 ]; do
 
     -*) die_with_help "Unknown argument: '%s'." "$argument" ;;
 
-    *) vm_ids="$vm_ids $argument" ;;
+    *) vm_ids_or_names="$vm_ids_or_names $argument" ;;
   esac
 done
 
-if [ -z "$vm_ids" ]; then
-  die_with_help "Required: at least one VM id.\n"
+if [ -z "$vm_ids_or_names" ]; then
+  die_with_help "Required: at least one VM id or name.\n"
 fi
 
 if [ -z "$api_url" ] || [ -z "$username" ] || [ -z "$password" ]; then
@@ -129,48 +128,89 @@ proxmox_sync () (
   done
 )
 
+################################################################################
+## Grab VM options
+##
+## Takes the name of the VM, grabs `.#vmOptions.<name>` and gets the id from it.
+
+is_integer () {
+  [ "$1" -eq "$1" ] 2>/dev/null
+}
+
+grab_vm_options () {
+  local options
+
+  if is_integer "$1"; then
+    vm_id=$1
+    vm_name="#$1"
+
+  else
+    vm_name=$1
+
+    printf 'Grabing VM options for VM %s...\n' "$vm_name"
+
+    options=$(
+      nix eval \
+        --impure --raw --expr "
+          builtins.toJSON (builtins.getFlake (builtins.toString ./.)).vmOptions.$vm_name
+        " \
+      --log-format raw --quiet
+    )
+
+    proxmox=$(echo "$options" | jq -r .proxmox)
+    vm_id=$(echo "$options" | jq -r .vmId)
+
+    if [ "$proxmox" != fediversity ]; then
+      die "I do not know how to remove things that are not Fediversity VMs,
+  but I got proxmox = '%s' for VM %s." "$proxmox" "$vm_name"
+    fi
+
+    printf 'done grabing VM options for VM %s. Got %d.\n' "$vm_name" "$vm_id"
+  fi
+}
+
 ################################################################################
 ## Stop VM
 
 stop_vm () {
-  printf 'Stopping VM %d...\n' "$1"
+  printf 'Stopping VM %s...\n' "$vm_name"
 
-  proxmox_sync POST "$api_url/nodes/$node/qemu/$1/status/stop" \
+  proxmox_sync POST "$api_url/nodes/$node/qemu/$vm_id/status/stop" \
     'overrule-shutdown'==1
 
-  printf 'done stopping VM %d.\n' "$1"
+  printf 'done stopping VM %s.\n' "$vm_name"
 }
 
 ################################################################################
 ## Delete VM
 
 delete_vm () {
-  printf 'Deleting VM %d...\n' "$1"
+  printf 'Deleting VM %s...\n' "$vm_name"
 
-  proxmox_sync DELETE "$api_url/nodes/$node/qemu/$1" \
+  proxmox_sync DELETE "$api_url/nodes/$node/qemu/$vm_id" \
     'destroy-unreferenced-disks'==1 \
     'purge'==1
 
-  printf 'done deleting VM %d.\n' "$1"
+  printf 'done deleting VM %s.\n' "$vm_name"
 }
 
 ################################################################################
 ## Main loop
 
-printf 'Removing VMs%s...\n' "$vm_ids"
+printf 'Removing VMs%s...\n' "$vm_ids_or_names"
 
-remove_vm () {
-  stop_vm "$1"
-  delete_vm "$1"
-}
+remove_vm () (
+  grab_vm_options "$1"
+  stop_vm
+  delete_vm
+)
 
-for vm_id in $vm_ids; do
-  vm_id=${vm_id%:*}
-  remove_vm "$vm_id" &
+for vm_id_or_name in $vm_ids_or_names; do
+  remove_vm "$vm_id_or_name" &
 done
 wait
 
-printf 'done removing VMs%s.\n' "$vm_ids"
+printf 'done removing VMs%s.\n' "$vm_ids_or_names"
 
 ################################################################################
 ## Cleanup