#!/usr/bin/env bash
# tests/cloudinit-vm/run-tests.sh -- guard for modules/cloudinit-vm (D-130).
# Static assertions that the D-130 lifecycle guard is present and correctly
# placed (regression guard: removing it silently reintroduces the post-reboot
# seed-volume forced replacement, GA-F01). Runs `tofu validate` on the module
# when the binary is available; skips gracefully when it is not.
# Exit: 0 all pass | 1 any case failed. ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MOD="$(cd "$HERE/../.." && pwd)/opentofu/modules/cloudinit-vm"
PASS=0; FAIL=0
ok(){ echo " PASS $1"; PASS=$((PASS+1)); }
no(){ echo " FAIL $1"; FAIL=$((FAIL+1)); }
[ -f "$MOD/main.tf" ] && ok "T1 module main.tf present" || no "T1 module main.tf present"
# T2: the D-130 lifecycle guard lives INSIDE the seed-volume resource block --
# extract the block by brace counting from awk, then assert its content.
SEED_BLOCK="$(awk '/^resource "libvirt_volume" "seed" \{/{f=1} f{print; n+=gsub(/\{/,"{"); n-=gsub(/\}/,"}"); if(n==0 && f)exit}' "$MOD/main.tf")"
grep -q 'ignore_changes' <<<"$SEED_BLOCK" \
&& ok "T2 seed volume carries lifecycle ignore_changes (D-130)" \
|| no "T2 seed volume carries lifecycle ignore_changes (D-130)"
grep -q 'ignore_changes = \[create\]' <<<"$SEED_BLOCK" \
&& ok "T3 guard targets the create attribute exactly" \
|| no "T3 guard targets the create attribute exactly"
grep -q 'D-130' <<<"$SEED_BLOCK" \
&& ok "T4 guard cites its governing decision" \
|| no "T4 guard cites its governing decision"
# T5: the guard must NOT leak onto the data disk (only the seed volume's
# create is staging-derived; ignoring the disk's attributes would mask drift)
DISK_BLOCK="$(awk '/^resource "libvirt_volume" "disk" \{/{f=1} f{print; n+=gsub(/\{/,"{"); n-=gsub(/\}/,"}"); if(n==0 && f)exit}' "$MOD/main.tf")"
grep -q 'ignore_changes' <<<"$DISK_BLOCK" \
&& no "T5 data-disk volume has NO ignore_changes" \
|| ok "T5 data-disk volume has NO ignore_changes"
# T6: module still validates when tofu is available (init -backend=false is
# offline once the provider is in the plugin cache; skip cleanly otherwise)
if command -v tofu >/dev/null 2>&1; then
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
cp "$MOD"/*.tf "$TMP"/
if (cd "$TMP" && tofu init -backend=false -input=false >/dev/null 2>&1 \
&& tofu validate >/dev/null 2>&1); then
ok "T6 module validates (tofu validate)"
else
no "T6 module validates (tofu validate)"
fi
else
echo " SKIP T6 tofu binary not available (static checks above still bind)"
fi
echo; echo "cloudinit-vm: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ]