112 lines
5.2 KiB
Bash
Executable File
112 lines
5.2 KiB
Bash
Executable File
#!/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"
|