#!/usr/bin/env bash # The host templates, rendered the way install.sh renders them, checked # without installing anything. # # ./tests/test_vm_host_render.sh # # WHY THIS EXISTS # # vm/host is full of @PLACEHOLDER@ tokens now, so that no machine's pool # path, memory ceiling or LAN address is baked into the repo. That moves # a whole class of mistake to install time: a token added to a template # and not to install.sh's render() produces a systemd unit with a literal # @VM_MEMORY_MAX@ in it, which fails when the unit is STARTED - long # after the install said it succeeded. # # So this renders every template with sample values that are nothing like # this machine's, and asserts the results are complete and valid. It # touches /etc nowhere and needs no root. set -uo pipefail cd "$(dirname "$0")/.." HOST=vm/host FAILS=0 check() { if [ "$2" -eq 0 ]; then echo "ok $1"; else echo "FAIL $1"; FAILS=$((FAILS+1)); fi; } WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT # Deliberately unlike this host: a different pool, different sizing, a # different operator, so a value that leaked through as a default shows up. POOL_ROOT=/tank OPERATOR=someone VM_MEMORY_MAX=6G VM_CPU_QUOTA=300% MAINT_CPU_QUOTA=400% TOOLS_SUBNET=10.9.0.0/24 GITEA_ALLOW="IPAddressAllow=10.9.9.9/32" VM_ALLOWED_CPUS="" render() { # the same transformation install.sh applies local src="$1" dst="$2" allow="$WORK/allow" printf '%s\n' "$GITEA_ALLOW" > "$allow" sed -e "/@GITEA_ALLOW@/{r $allow" -e "d;}" "$src" > "$dst" sed -i -e "s|@POOL_ROOT@|$POOL_ROOT|g" -e "s|@OPERATOR@|$OPERATOR|g" \ -e "s|@VM_MEMORY_MAX@|$VM_MEMORY_MAX|g" -e "s|@VM_CPU_QUOTA@|$VM_CPU_QUOTA|g" \ -e "s|@MAINT_CPU_QUOTA@|$MAINT_CPU_QUOTA|g" -e "s|@TOOLS_SUBNET@|$TOOLS_SUBNET|g" "$dst" if [ -z "$VM_ALLOWED_CPUS" ]; then sed -i '/^AllowedCPUs=@VM_ALLOWED_CPUS@$/d' "$dst" else sed -i "s|@VM_ALLOWED_CPUS@|$VM_ALLOWED_CPUS|g" "$dst" fi } TEMPLATES="owuivm.service owuivmd.service owuivm-maint@.service owuivm-ctl owuivm-launch owuivm-teardown owuivm-maint-prepare 50-owuivm.rules owuivm-tmpfiles.conf owuivm-insert@.service owuivm-rename@.service owuivm-thaw@.service owuivm-freeze@.service owuivm-detach@.service owuivm-nft-guard.service" # --- every template renders completely -------------------------------- for t in $TEMPLATES; do [ -f "$HOST/$t" ] || { echo "FAIL $t is missing"; FAILS=$((FAILS+1)); continue; } render "$HOST/$t" "$WORK/$t" left=$(grep -o '@[A-Z_]\+@' "$WORK/$t" | sort -u | tr '\n' ' ') [ -z "$left" ]; check "$t renders with nothing left over${left:+ (found: $left)}" $? done # --- nothing of THIS machine survives, in the parts that DO something -- # Rendered with someone else's values, no line that systemd or bash acts # on may still carry ours. # # Comments are excluded deliberately. They cite the measurements the # defaults came from - "qemu sat at 697% of the 700% ceiling, with 1,792 # throttle events" - and that evidence is the reason anyone could change # a number safely. Stripping it to satisfy a grep would make the files # portable and useless. strip_comments() { grep -rhvE '^[[:space:]]*(#|//)' "$WORK" ; } for pattern in '/Pool' '20-27' '11G' '700%' '800%' '172\.22\.0\.0' '(^|[^a-zA-Z])operator([^a-zA-Z]|$)'; do ! strip_comments | grep -qE "$pattern" check "no '$pattern' in any line that is acted on" $? done # --- and the sample values did arrive --------------------------------- grep -q '/tank/vmrun' "$WORK/owuivm.service"; check "the pool reached owuivm.service" $? grep -q '/tank/vmprojects' "$WORK/owuivmd.service"; check "the pool reached owuivmd.service" $? grep -q '/tank/vmprojects' "$WORK/owuivm-ctl"; check "the pool reached owuivm-ctl" $? grep -q 'MemoryMax=6G' "$WORK/owuivm.service"; check "the memory ceiling was substituted" $? grep -q 'CPUQuota=300%' "$WORK/owuivm.service"; check "the cpu quota was substituted" $? grep -q 'IPAddressAllow=10.9.9.9/32' "$WORK/owuivmd.service"; check "the gitea allowlist was inserted" $? grep -q 'subject.user == "someone"' "$WORK/50-owuivm.rules"; check "the operator reached polkit" $? ! grep -q '^AllowedCPUs=' "$WORK/owuivm.service" check "with no pinning, AllowedCPUs is REMOVED rather than left empty" $? # --- the results are valid --------------------------------------------- # An empty AllowedCPUs= would RESET the property rather than leave it # alone, which is why the line is deleted; systemd-analyze is what says # the rest of the file is still a unit. if command -v systemd-analyze >/dev/null 2>&1; then for u in owuivm.service owuivmd.service "owuivm-maint@.service" owuivm-insert@.service owuivm-rename@.service; do out=$(systemd-analyze verify "$WORK/$u" 2>&1 | grep -viE 'Unknown key|command .* is not executable|Failed to (resolve|open)|/usr/local|not found' || true) [ -z "$out" ]; check "systemd accepts $u${out:+ -- $out}" $? done else echo "skip systemd-analyze is not here; unit validity not checked" fi for sh in owuivm-ctl owuivm-launch owuivm-teardown owuivm-maint-prepare; do bash -n "$WORK/$sh"; check "$sh is still valid bash after rendering" $? done echo if [ "$FAILS" -gt 0 ]; then echo "$FAILS FAILED"; exit 1; fi echo "every host template renders into something valid, with no trace of this machine"