Pulse/scripts/tests/test-toggle-mock.sh
rcourtman 7938f28de4 platforms: scale K8s clusters to 3 + fix VMware storage source matching
Two specific platform-page quality issues from the audit:

1. **/kubernetes/overview only had 1 cluster.** Bumping the K8s cluster
   count past 1 had been deferred because the prior
   monitor-broadcast equivalence test compared the raw snapshot count
   to the broadcast count exactly, and broadcast's
   `coalesceBroadcastResources` + second-pass coalesce inside
   `convertResourcesForBroadcast` legitimately drops merge candidates
   that the raw snapshot keeps. Switch the test to compare against
   the canonical snapshot count within a ±5% tolerance so future
   fixture bumps stay green without loosening any of the test's
   exact-name and exact-identity assertions. With that in place, bump
   `K8sClusterCount` 1 → 3 in `internal/mock/generator.go`,
   `scripts/toggle-mock.sh`, and the matching
   `scripts/tests/test-toggle-mock.sh` so the canonical mock estate
   ships with production + staging + edge clusters end-to-end.

   Live mock survey: k8s-cluster: 3, k8s-deployment: 42, pod: 120,
   plus 15 K8s nodes merged onto their agent hosts.

2. **/vmware/storage looked empty under platform-page chrome.**
   `resolveStorageSourceKey` was reading only `storage.type` (the
   on-disk technology like `vsan`, `vmfs`, `nfs41`, `zfs-pool`) and
   never consulted `storage.platform` (the canonical platform key
   like `vmware-vsphere` or `truenas`). Source filter chip options
   were therefore generated as `vsan`, `vmfs`, `nfs41`, etc., and
   `forcedSourceFilter='vmware-vsphere'` had nothing to match.
   Prefer the canonical `storage.platform` tag when set, so VMware
   datastores group under `vmware-vsphere`, TrueNAS pools group under
   `truenas`, PBS datastores under `proxmox-pbs`, etc., for both the
   chip options and the embedded platform-page filter.

Browser verification (Playwright, chromium, live mock-mode dev runtime):
- 9 tests pass.

Targeted vitest:
- `src/features/storageBackups` + `src/utils/__tests__/sourcePlatforms.test.ts` +
  `src/components/Storage/__tests__/storageSourceOptions.test.ts` (31
  files / 141 tests) green.

Go tests:
- `go test ./internal/mock/... ./internal/monitoring/... ./internal/vmware/...`
  all green.

Contracts updated:
- `monitoring.md` Shared Boundaries: new K8s multi-cluster default,
  ±5% tolerance for the broadcast equivalence assertion.
- `deployment-installability.md` Shared Boundaries: toggle-mock.sh /
  DefaultConfig parity updated for the K8sClusterCount=3 baseline.
2026-05-16 11:43:41 +01:00

275 lines
9.1 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Smoke test for scripts/toggle-mock.sh managed runtime helpers.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
TOGGLE_MOCK="${ROOT_DIR}/scripts/toggle-mock.sh"
if [[ ! -f "${TOGGLE_MOCK}" ]]; then
echo "toggle-mock.sh not found at ${TOGGLE_MOCK}" >&2
exit 1
fi
failures=0
temp_dirs=()
cleanup() {
local dir
for dir in "${temp_dirs[@]:-}"; do
rm -rf "${dir}" 2>/dev/null || true
done
}
trap cleanup EXIT
assert_contains() {
local desc="$1"
local haystack="$2"
local needle="$3"
if [[ "${haystack}" == *"${needle}"* ]]; then
echo "[PASS] ${desc}"
else
echo "[FAIL] ${desc}" >&2
echo "Expected to find: ${needle}" >&2
((failures++))
fi
}
assert_file_absent() {
local desc="$1"
local path="$2"
if [[ ! -e "${path}" ]]; then
echo "[PASS] ${desc}"
else
echo "[FAIL] ${desc}" >&2
echo "Did not expect file to exist: ${path}" >&2
((failures++))
fi
}
make_stub_hot_dev_bg() {
local dir
dir="$(mktemp -d)"
temp_dirs+=("${dir}")
cat > "${dir}/hot-dev-bg.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
COMMAND="${1:-}"
shift || true
printf "%s %s\n" "${COMMAND}" "$*" >> "${HOT_DEV_BG_STUB_LOG}"
case "${COMMAND}" in
status)
if [[ "${HOT_DEV_BG_STUB_RUNNING:-false}" == "true" ]]; then
echo "[hot-dev-bg] Running (pid: 12345)"
echo "[hot-dev-bg] Frontend shell HTTP: 200"
echo "[hot-dev-bg] Frontend proxy /api/health: 200"
echo "[hot-dev-bg] Backend /api/health: 200"
else
echo "[hot-dev-bg] Not running"
fi
;;
start)
echo "[hot-dev-bg] Started"
;;
stop)
echo "[hot-dev-bg] Stopped"
;;
*)
echo "[hot-dev-bg] ${COMMAND}"
;;
esac
EOF
chmod +x "${dir}/hot-dev-bg.sh"
printf "%s\n" "${dir}/hot-dev-bg.sh"
}
test_detects_managed_hot_dev_runtime() {
local stub state output
state="$(mktemp -d)"
temp_dirs+=("${state}")
stub="$(make_stub_hot_dev_bg)"
output="$(
HOT_DEV_BG_PATH="${stub}" \
HOT_DEV_BG_STUB_LOG="${state}/calls.log" \
HOT_DEV_BG_STUB_RUNNING=true \
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
printf "mode=%s\n" "$(detect_runtime_mode)"
'
)"
assert_contains "detect_runtime_mode prefers managed hot-dev" "${output}" "mode=managed-hot-dev"
}
test_managed_hot_dev_start_uses_takeover() {
local stub state output calls
state="$(mktemp -d)"
temp_dirs+=("${state}")
stub="$(make_stub_hot_dev_bg)"
output="$(
HOT_DEV_BG_PATH="${stub}" \
HOT_DEV_BG_STUB_LOG="${state}/calls.log" \
HOT_DEV_BG_STUB_RUNNING=false \
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
start_hot_dev_runtime
'
)"
calls="$(cat "${state}/calls.log")"
assert_contains "start_hot_dev_runtime announces managed startup" "${output}" "Starting managed hot-dev runtime"
assert_contains "start_hot_dev_runtime uses managed takeover start" "${calls}" "start --takeover"
}
test_managed_hot_dev_stop_uses_control_plane() {
local stub state output calls
state="$(mktemp -d)"
temp_dirs+=("${state}")
stub="$(make_stub_hot_dev_bg)"
output="$(
HOT_DEV_BG_PATH="${stub}" \
HOT_DEV_BG_STUB_LOG="${state}/calls.log" \
HOT_DEV_BG_STUB_RUNNING=true \
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
stop_hot_dev_runtime managed-hot-dev
'
)"
calls="$(cat "${state}/calls.log")"
assert_contains "stop_hot_dev_runtime announces managed stop" "${output}" "Stopping managed hot-dev runtime"
assert_contains "stop_hot_dev_runtime uses managed stop command" "${calls}" "stop "
}
test_ensure_mock_env_file_seeds_canonical_demo_defaults() {
local state output env_contents
state="$(mktemp -d)"
temp_dirs+=("${state}")
output="$(
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
MOCK_ENV_OVERRIDE="${state}/mock.env" \
LEGACY_ROOT_MOCK_ENV_OVERRIDE="${state}/legacy-root.mock.env" \
LEGACY_DEV_MOCK_ENV_OVERRIDE="${state}/legacy-dev.mock.env" \
LEGACY_RUNTIME_MOCK_ENV_OVERRIDE="${state}/legacy-runtime.mock.env" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
MOCK_ENV_FILE="${MOCK_ENV_OVERRIDE}"
LEGACY_ROOT_MOCK_ENV_FILE="${LEGACY_ROOT_MOCK_ENV_OVERRIDE}"
LEGACY_DEV_MOCK_ENV_FILE="${LEGACY_DEV_MOCK_ENV_OVERRIDE}"
LEGACY_RUNTIME_MOCK_ENV_FILE="${LEGACY_RUNTIME_MOCK_ENV_OVERRIDE}"
ensure_mock_env_file
cat "${MOCK_ENV_FILE}"
'
)"
env_contents="${output}"
assert_contains "ensure_mock_env_file seeds mock mode default" "${env_contents}" "PULSE_MOCK_MODE=false"
assert_contains "ensure_mock_env_file seeds canonical node count" "${env_contents}" "PULSE_MOCK_NODES=5"
assert_contains "ensure_mock_env_file seeds canonical vm count" "${env_contents}" "PULSE_MOCK_VMS_PER_NODE=6"
assert_contains "ensure_mock_env_file seeds canonical lxc count" "${env_contents}" "PULSE_MOCK_LXCS_PER_NODE=8"
assert_contains "ensure_mock_env_file seeds canonical docker host count" "${env_contents}" "PULSE_MOCK_DOCKER_HOSTS=5"
assert_contains "ensure_mock_env_file seeds canonical docker container count" "${env_contents}" "PULSE_MOCK_DOCKER_CONTAINERS=14"
assert_contains "ensure_mock_env_file seeds canonical generic host count" "${env_contents}" "PULSE_MOCK_GENERIC_HOSTS=4"
assert_contains "ensure_mock_env_file seeds canonical k8s cluster count" "${env_contents}" "PULSE_MOCK_K8S_CLUSTERS=3"
assert_contains "ensure_mock_env_file seeds canonical k8s node count" "${env_contents}" "PULSE_MOCK_K8S_NODES=5"
assert_contains "ensure_mock_env_file seeds canonical k8s pod count" "${env_contents}" "PULSE_MOCK_K8S_PODS=40"
assert_contains "ensure_mock_env_file seeds canonical k8s deployment count" "${env_contents}" "PULSE_MOCK_K8S_DEPLOYMENTS=14"
assert_contains "ensure_mock_env_file seeds canonical random metrics flag" "${env_contents}" "PULSE_MOCK_RANDOM_METRICS=true"
assert_contains "ensure_mock_env_file seeds canonical stopped percent" "${env_contents}" "PULSE_MOCK_STOPPED_PERCENT=6"
}
test_ensure_mock_env_file_migrates_legacy_sidecar() {
local state output env_contents
state="$(mktemp -d)"
temp_dirs+=("${state}")
cat > "${state}/legacy.mock.env" <<'EOF'
PULSE_MOCK_MODE=true
PULSE_MOCK_NODES=9
EOF
output="$(
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
MOCK_ENV_OVERRIDE="${state}/runtime.env" \
LEGACY_DEV_MOCK_ENV_OVERRIDE="${state}/legacy.mock.env" \
LEGACY_ROOT_MOCK_ENV_OVERRIDE="${state}/legacy-root.mock.env" \
LEGACY_RUNTIME_MOCK_ENV_OVERRIDE="${state}/legacy-runtime.mock.env" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
MOCK_ENV_FILE="${MOCK_ENV_OVERRIDE}"
LEGACY_DEV_MOCK_ENV_FILE="${LEGACY_DEV_MOCK_ENV_OVERRIDE}"
LEGACY_ROOT_MOCK_ENV_FILE="${LEGACY_ROOT_MOCK_ENV_OVERRIDE}"
LEGACY_RUNTIME_MOCK_ENV_FILE="${LEGACY_RUNTIME_MOCK_ENV_OVERRIDE}"
ensure_mock_env_file
cat "${MOCK_ENV_FILE}"
'
)"
env_contents="${output}"
assert_contains "ensure_mock_env_file migrates legacy mock mode" "${env_contents}" "PULSE_MOCK_MODE=true"
assert_contains "ensure_mock_env_file migrates legacy node count" "${env_contents}" "PULSE_MOCK_NODES=9"
assert_contains "ensure_mock_env_file still seeds missing defaults" "${env_contents}" "PULSE_MOCK_VMS_PER_NODE=3"
}
test_set_mock_mode_does_not_recreate_legacy_sidecars() {
local state dev_env runtime_env
state="$(mktemp -d)"
temp_dirs+=("${state}")
dev_env="${state}/dev/.env"
runtime_env="${state}/runtime/.env"
TOGGLE_MOCK_PATH="${TOGGLE_MOCK}" \
MOCK_ENV_OVERRIDE="${dev_env}" \
DEV_DATA_DIR_OVERRIDE="${state}/dev" \
RUNTIME_MOCK_ENV_OVERRIDE="${runtime_env}" \
LEGACY_DEV_MOCK_ENV_OVERRIDE="${state}/dev/mock.env" \
LEGACY_ROOT_MOCK_ENV_OVERRIDE="${state}/mock.env" \
LEGACY_RUNTIME_MOCK_ENV_OVERRIDE="${state}/runtime/mock.env" \
bash -lc '
source "${TOGGLE_MOCK_PATH}"
MOCK_ENV_FILE="${MOCK_ENV_OVERRIDE}"
DEV_DATA_DIR="${DEV_DATA_DIR_OVERRIDE}"
RUNTIME_MOCK_ENV_FILE="${RUNTIME_MOCK_ENV_OVERRIDE}"
LEGACY_DEV_MOCK_ENV_FILE="${LEGACY_DEV_MOCK_ENV_OVERRIDE}"
LEGACY_ROOT_MOCK_ENV_FILE="${LEGACY_ROOT_MOCK_ENV_OVERRIDE}"
LEGACY_RUNTIME_MOCK_ENV_FILE="${LEGACY_RUNTIME_MOCK_ENV_OVERRIDE}"
set_mock_mode true
'
assert_contains "set_mock_mode writes canonical dev env" "$(cat "${dev_env}")" "PULSE_MOCK_MODE=true"
assert_contains "set_mock_mode writes canonical runtime env" "$(cat "${runtime_env}")" "PULSE_MOCK_MODE=true"
assert_file_absent "set_mock_mode does not recreate dev legacy mock sidecar" "${state}/dev/mock.env"
assert_file_absent "set_mock_mode does not recreate root legacy mock sidecar" "${state}/mock.env"
assert_file_absent "set_mock_mode does not recreate runtime legacy mock sidecar" "${state}/runtime/mock.env"
}
main() {
test_detects_managed_hot_dev_runtime
test_managed_hot_dev_start_uses_takeover
test_managed_hot_dev_stop_uses_control_plane
test_ensure_mock_env_file_seeds_canonical_demo_defaults
test_ensure_mock_env_file_migrates_legacy_sidecar
test_set_mock_mode_does_not_recreate_legacy_sidecars
if (( failures > 0 )); then
echo "Total failures: ${failures}" >&2
exit 1
fi
echo "toggle-mock managed runtime smoke tests passed."
}
main "$@"