Luigit
repositories / bugabinga.net

bugabinga.net

personal infrastructure for bugabinga!

owned by admin

scripts/local/test-garbage-collection.sh

Raw
#!/usr/bin/env bash
set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
tmp="$(mktemp -d "${repo_root}/.garbage-collection-test.XXXXXX")"
trap 'rm -rf "${tmp}"' EXIT

fail() {
  echo "test failed: $*" >&2
  exit 1
}

units="${tmp}/units"
dropins="${tmp}/dropins"
mkdir -p "${units}" "${dropins}" "${tmp}/bin"

fake_uid=1000
cat >"${tmp}/bin/id" <<SCRIPT
#!/usr/bin/env bash
case "\$*" in
  "-u oli") echo $((fake_uid + 1)) ;;
  "-u ci") echo $((fake_uid + 2)) ;;
  "-u toad") echo $((fake_uid + 3)) ;;
esac
SCRIPT

cat >"${tmp}/bin/getent" <<'SCRIPT'
#!/usr/bin/env bash
[[ "$1" == passwd ]] || exit 1
case "$2" in
  oli) echo "oli:x:1001:1001::/home/oli:/bin/bash" ;;
  ci) echo "ci:x:1002:1002::/home/ci:/bin/bash" ;;
  toad) echo "toad:x:1003:1003::/home/toad:/bin/bash" ;;
  *) exit 1 ;;
esac
SCRIPT

cat >"${tmp}/bin/loginctl" <<'SCRIPT'
#!/usr/bin/env bash
exit 0
SCRIPT

cat >"${tmp}/bin/mkdir" <<'SCRIPT'
#!/usr/bin/env bash
exit 0
SCRIPT

cat >"${tmp}/bin/systemctl" <<'SCRIPT'
#!/usr/bin/env bash
printf '%s\n' "$*" >>"${TEST_SYSTEMCTL_LOG}"
[[ "$1" == show ]] && printf 'Tue 2030-01-01 00:00:00 UTC\n'
exit 0
SCRIPT

cat >"${tmp}/bin/runuser" <<'SCRIPT'
#!/usr/bin/env bash
printf '%s\n' "$*" >>"${TEST_RUNUSER_LOG}"
exit 0
SCRIPT

cat >"${tmp}/bin/install" <<'SCRIPT'
#!/usr/bin/env bash
[[ " $* " == *" -d "* ]] && exit 0
args=("$@")
destination="${args[$((${#args[@]} - 1))]}"
source=''
for arg in "${args[@]}"; do
  [[ -z "${source}" && -f "${arg}" ]] && source="${arg}"
done
[[ -n "${source}" ]] || exit 0
case "${destination}" in
  /etc/systemd/system/*|/etc/systemd/journald.conf.d/*|/etc/logrotate.d/*)
    cp "${source}" "${TEST_UNITS_DIR}/$(basename "${destination}")"
    ;;
  /home/oli/*)
    cp "${source}" "${TEST_DROPIN_DIR}/$(basename "${destination}")"
    ;;
esac
exit 0
SCRIPT
chmod 0755 "${tmp}/bin/"*

PATH="${tmp}/bin:${PATH}" \
  TEST_SYSTEMCTL_LOG="${tmp}/systemctl.log" \
  TEST_RUNUSER_LOG="${tmp}/runuser.log" \
  TEST_UNITS_DIR="${units}" \
  TEST_DROPIN_DIR="${dropins}" \
  "${repo_root}/scripts/remote/setup-garbage-collection.sh" oli ci toad >/dev/null

for unit in "bugabinga-gc@.service" "bugabinga-gc@.timer" "bugabinga-gc-host.service" "bugabinga-gc-host.timer" "bugabinga-alert@.service" "bugabinga-maintenance.service" "bugabinga-maintenance.timer"; do
  [[ -f "${units}/${unit}" ]] || fail "missing unit ${unit}"
done
[[ -f "${dropins}/no-image-prune.conf" ]] || fail "missing podman-auto-update drop-in"

grep -q -- '--all' "${units}/bugabinga-gc@.service" && fail "gc service must not prune all images"
grep -q 'until=168h' "${units}/bugabinga-gc@.service" || fail "gc service lost age filter"
grep -q 'OnFailure=bugabinga-alert@%n.service' "${units}/bugabinga-gc@.service" || fail "gc service lacks failure alert"
grep -q 'runuser -u %i' "${units}/bugabinga-gc@.service" || fail "gc service must run as the instance user"
grep -q -- '--login' "${units}/bugabinga-gc@.service" && fail "gc service must not use runuser --login (incompatible with -u)"
grep -q '/data/ci/logs' "${units}/bugabinga-gc-host.service" || fail "host service lost CI log retention"
grep -q 'journalctl --vacuum-size=2G' "${units}/bugabinga-gc-host.service" || fail "host service lost journald vacuum"
grep -qx 'ExecStartPost=' "${dropins}/no-image-prune.conf" || fail "auto-update drop-in must clear ExecStartPost"
grep -q 'bugabinga-check-maintenance' "${units}/bugabinga-maintenance.service" || fail "maintenance service lost check script"

systemctl_log="$(cat "${tmp}/systemctl.log")"
grep -qx 'enable --now bugabinga-gc@oli.timer bugabinga-gc@ci.timer bugabinga-gc@toad.timer' <<<"${systemctl_log}" || fail "per-owner gc timers not enabled"
grep -qx 'enable --now bugabinga-gc-host.timer bugabinga-maintenance.timer' <<<"${systemctl_log}" || fail "host and maintenance timers not enabled"
grep -qx 'disable --now bugabinga-gc.timer' <<<"${systemctl_log}" || fail "legacy gc timer not disabled"
grep -q 'daemon-reload' "${tmp}/runuser.log" || fail "user manager was not reloaded"

echo "garbage collection test passed"

check_bin="${tmp}/check-bin"
mkdir -p "${check_bin}"
cat >"${check_bin}/getent" <<'SCRIPT'
#!/usr/bin/env bash
case "$2" in
  ci) echo "ci:x:1002:1002::/home/ci:/bin/bash" ;;
  *) echo "oli:x:1001:1001::/home/oli:/bin/bash" ;;
esac
SCRIPT

cat >"${check_bin}/systemctl" <<SCRIPT
#!/usr/bin/env bash
printf '%s\\n' "\${TEST_SYSTEMCTL_TIMESTAMP:-$(LC_ALL=C date -u -d "@$(($(date +%s) - 3600))" '+%Y-%m-%d %H:%M:%S')}"
exit 0
SCRIPT
cat >"${check_bin}/runuser" <<SCRIPT
#!/usr/bin/env bash
case "\$*" in
  *LastTriggerUSec*) printf '%s\\n' "\${TEST_UPDATE_TIMESTAMP-$(LC_ALL=C date -u -d "@$(($(date +%s) - 3600))" '+%Y-%m-%d %H:%M:%S')}" ;;
  *image\ exists*) exit "\${TEST_ROLLBACK_EXISTS:-0}" ;;
esac
exit 0
SCRIPT
cat >"${check_bin}/df" <<'SCRIPT'
#!/usr/bin/env bash
printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\ntmpfs 100000 1000 99000 1%% %s\n' "${2:-/}"
exit 0
SCRIPT
chmod 0755 "${check_bin}/"*

fresh="$(PATH="${check_bin}:${PATH}" "${repo_root}/scripts/remote/check-maintenance.sh")" || fail "fresh maintenance state reported failure:\n${fresh}"
grep -q $'^ok\tgc-oli\t' <<<"${fresh}" || fail "fresh output lacks gc-oli line:\n${fresh}"
grep -q $'^ok\tauto-update\t' <<<"${fresh}" || fail "fresh output lacks auto-update line:\n${fresh}"
grep -q $'^ok\tluci-rollback\t' <<<"${fresh}" || fail "fresh output lacks luci-rollback line:\n${fresh}"
grep -q $'^ok\tdisk-data-ci\t' <<<"${fresh}" || fail "fresh output lacks disk-data-ci line:\n${fresh}"

stale="$(PATH="${check_bin}:${PATH}" \
  TEST_SYSTEMCTL_TIMESTAMP="$(LC_ALL=C date -u -d "@$(($(date +%s) - 864000))" '+%Y-%m-%d %H:%M:%S')" \
  TEST_UPDATE_TIMESTAMP="" \
  TEST_ROLLBACK_EXISTS=1 \
  "${repo_root}/scripts/remote/check-maintenance.sh")" && fail "stale maintenance state reported success:\n${stale}"
grep -q $'^fail\tgc-oli\t' <<<"${stale}" || fail "stale output lacks gc-oli failure:\n${stale}"
grep -q $'^fail\tauto-update\t' <<<"${stale}" || fail "stale output lacks auto-update failure:\n${stale}"
grep -q $'^fail\tluci-rollback\t' <<<"${stale}" || fail "stale output lacks luci-rollback failure:\n${stale}"

echo "maintenance check test passed"