#!/usr/bin/env bash
# tests/dc-cache-proxy/run-tests.sh -- guard for scripts/dc-cache-proxy.sh
# (D-135 amendment 2026-07-24: the INTERIM per-DC apt CACHING PROXY, apt-cacher-ng,
# the DC1-unblock path). Static: syntax, both sites' identity values (the utility
# .4 the deploy expects + the ruled edge gateways -- changing one silently breaks
# the proxy address or upstream egress), stable-identity keying (libvirt net
# names, never virbrN), proxy-mode port pin, the MEASURED-tag discipline on site
# rows, arg/site validation, and that the net layer is REUSED (not re-created).
# Exit: 0 all pass | 1 any case failed. ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT="$(cd "$HERE/../.." && pwd)/scripts/dc-cache-proxy.sh"
PASS=0; FAIL=0
ok(){ echo " PASS $1"; PASS=$((PASS+1)); }
no(){ echo " FAIL $1"; FAIL=$((FAIL+1)); }
[ -f "$SCRIPT" ] && ok "T1 script present" || { no "T1 script present"; echo; echo "dc-cache-proxy: $PASS passed, $FAIL failed"; exit 1; }
bash -n "$SCRIPT" 2>/dev/null && ok "T2 bash -n clean" || no "T2 bash -n clean"
# T3-T4: dc0 identity values (utility .4 + ruled edge gw) -- parity row
grep -q 'LISTEN_CIDR="10.12.8.4/22"' "$SCRIPT" \
&& grep -q 'UTIL_NET="vr1-dc0-metal-admin"' "$SCRIPT" \
&& ok "T3 dc0 LISTEN 10.12.8.4/22 on metal-admin (utility .4)" \
|| no "T3 dc0 LISTEN 10.12.8.4/22 on metal-admin (utility .4)"
awk '/^ dc0\)/{f=1} f{print} f&&/;;/{exit}' "$SCRIPT" | grep -q 'EDGE_GW="10.12.4.1"' \
&& ok "T4 dc0 edge gw 10.12.4.1" || no "T4 dc0 edge gw 10.12.4.1"
# T5-T6: dc1 identity values (the INTERIM cache-proxy site)
grep -q 'LISTEN_CIDR="10.12.68.4/22"' "$SCRIPT" \
&& grep -q 'UTIL_NET="vr1-dc1-metal-admin"' "$SCRIPT" \
&& ok "T5 dc1 LISTEN 10.12.68.4/22 on metal-admin (utility .4)" \
|| no "T5 dc1 LISTEN 10.12.68.4/22 on metal-admin (utility .4)"
awk '/^ dc1\)/{f=1} f{print} f&&/;;/{exit}' "$SCRIPT" | grep -q 'EDGE_GW="10.12.64.1"' \
&& ok "T6 dc1 edge gw 10.12.64.1" || no "T6 dc1 edge gw 10.12.64.1"
# T7: stable-identity keying -- no virbrN literal; bridge from the net name
grep -q 'net-dumpxml' "$SCRIPT" && ! grep -qE 'virbr[0-9]' "$SCRIPT" \
&& ok "T7 bridge resolved from net name; no virbrN literal" \
|| no "T7 bridge resolved from net name; no virbrN literal"
# T8: proxy-mode port pinned to 3142
grep -q 'PROXY_PORT="3142"' "$SCRIPT" && grep -q 'Port: ${PROXY_PORT}' "$SCRIPT" \
&& ok "T8 apt-cacher-ng port pinned 3142" || no "T8 apt-cacher-ng port pinned 3142"
# T9: consumption documented as proxy mode (apt-http-proxy), not apt-mirror
grep -q 'apt-http-proxy=http://' "$SCRIPT" \
&& ok "T9 documents proxy-mode consumption (apt-http-proxy)" \
|| no "T9 documents proxy-mode consumption (apt-http-proxy)"
# T10: behavioral smoke test covers BOTH archive and UCA through the proxy
grep -q 'archive.ubuntu.com' "$SCRIPT" && grep -q 'ubuntu-cloud.archive.canonical.com' "$SCRIPT" \
&& grep -q -- '-x "http://${LISTEN}:${PROXY_PORT}"' "$SCRIPT" \
&& ok "T10 smoke test proxies archive + UCA" || no "T10 smoke test proxies archive + UCA"
# T11: install requires root
grep -q 'install requires root' "$SCRIPT" && ok "T11 install requires root" || no "T11 install requires root"
# T12 (REPLACED 2026-07-27 -- it asserted the SUPERSEDED design). It used to require
# that this script REUSE dc-mirror.sh's net layer and write no ip addr/route itself.
# That coupling was a measured trap: on a proxy-only DC, three `*-mirror-*` files were
# load-bearing for the PROXY, so the recorded mirror-removal procedure would have killed
# it, and the proxy could not be rebuilt without reinstalling the whole mirror apparatus.
# Operator ruled the net layer moves here (2026-07-27), so the test is INVERTED rather
# than dropped -- the old assertion is now the defect it protected against.
# T12: this script OWNS the net layer -- it writes the address and route itself...
grep -qE 'ip addr replace' "$SCRIPT" && grep -qE 'ip route replace default' "$SCRIPT" \
&& ok "T12 net layer is OWNED here (writes its own addr + default route)" \
|| no "T12 net layer is OWNED here (writes its own addr + default route)"
# T12b: ...and no longer defers to dc-mirror.sh for it. A lingering "run dc-mirror.sh
# install" instruction would send an operator to re-create the very apparatus a
# proxy-only DC is meant not to have. Scoped to NON-COMMENT lines on purpose: the
# header's account of WHY the coupling was removed cites that command, and deleting
# the history to satisfy a grep would lose the reason the trap existed. What must not
# survive is an OPERATIVE referral -- one reachable at runtime in an echo/miss string.
grep -vE '^[[:space:]]*#' "$SCRIPT" | grep -q 'dc-mirror.sh install' \
&& no "T12b no OPERATIVE dc-mirror.sh referral remains (header history is exempt)" \
|| ok "T12b no OPERATIVE dc-mirror.sh referral remains (header history is exempt)"
# T12c: the owned artifacts are named for the PROXY, never "mirror". The whole point
# is that a proxy-only DC carries no mirror-named dependency for someone to tidy away.
grep -q 'cache-proxy-net.service' "$SCRIPT" \
&& grep -q 'cache-proxy-net-apply' "$SCRIPT" \
&& ! grep -qE '(NET_UNIT|NET_HELPER|RESOLVED_DROPIN)=.*mirror' "$SCRIPT" \
&& ok "T12c owned net artifacts are proxy-named, not mirror-named" \
|| no "T12c owned net artifacts are proxy-named, not mirror-named"
# T12d: the net layer must be ENABLED, not merely started -- otherwise the proxy's
# LISTEN address and egress vanish on the next rack reboot. This rack has rebooted
# before (the D-126/D-128 base-leg machinery exists for exactly that reason).
grep -qE 'systemctl enable "\$\{SITE\}-cache-proxy-net.service"' "$SCRIPT" \
&& grep -q 'cache-proxy-net.service enabled' "$SCRIPT" \
&& ok "T12d net unit is enabled at install and asserted by check (reboot-persistent)" \
|| no "T12d net unit is enabled at install and asserted by check (reboot-persistent)"
# T12e: check must assert the ARTIFACTS, not just the live address/route. Asserting
# only the live effect would PASS while the layer was really provided by
# <site>-mirror-net.service -- it would look independent and break on mirror teardown,
# which is the exact failure this change exists to prevent.
grep -q 'gen_net_helper' "$SCRIPT" && grep -q 'gen_net_unit' "$SCRIPT" \
&& grep -q 'this script owns the net layer now' "$SCRIPT" \
&& ok "T12e check asserts the owned net artifacts, not only their live effect" \
|| no "T12e check asserts the owned net artifacts, not only their live effect"
# T12f: idempotent verbs only. `ip addr replace`/`ip route replace` let this unit and
# a surviving <site>-mirror-net.service coexist on a site running both (dc0 keeps its
# mirror), setting identical MEASURED values instead of fighting.
! grep -qE 'ip (addr|route) add ' "$SCRIPT" \
&& ok "T12f net writes use idempotent replace (safe to coexist with the mirror unit)" \
|| no "T12f net writes use idempotent replace (safe to coexist with the mirror unit)"
# T13: MEASURED/RULED-tag discipline on every site row (hard rule 2)
MR="$(grep -cE 'MEASURED/RULED' "$SCRIPT")"
[ "$MR" -ge 2 ] && ok "T13 both site rows carry a MEASURED/RULED tag" \
|| no "T13 both site rows carry a MEASURED/RULED tag (found $MR)"
# T14: bad args / unknown site -> exit 2
out="$(bash "$SCRIPT" bogus dc1 2>&1)"; [ "$?" = "2" ] || out="$out RC!=2"
grep -q 'usage:' <<<"$out" && ok "T14 bad mode -> usage, exit 2" || no "T14 bad mode -> usage, exit 2"
bash "$SCRIPT" check zz >/dev/null 2>&1; [ "$?" = "2" ] \
&& ok "T15 unknown site -> exit 2" || no "T15 unknown site -> exit 2"
echo; echo "dc-cache-proxy: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] && exit 0 || exit 1