Ctrl K
ComunidadGuías…

scripts/local-vm.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
VM=devpush-test
command="${1:-help}"
if [[ "$command" == "--" ]]; then shift; command="${1:-help}"; fi

usage() {
  cat <<'USAGE'
Local devpush VM:
  pnpm vm:setup          Create/start the VM with Docker and a reachable local IP.
  pnpm vm:install URL    Enroll this VM using a generated installer, pinning its IP.
  pnpm vm:test           Set up the VM and run real Compose/Traefik tests directly.
  pnpm vm:stop           Stop the VM, keeping its disk.
  pnpm vm:destroy       Delete the dedicated test VM and all its data.
Requires macOS and Lima; tests also require Go on the host. VM name: devpush-test.
USAGE
}
if [[ "$command" == install ]]; then
  [[ $# -eq 2 ]] || { usage >&2; exit 2; }
else
  [[ $# -le 1 ]] || { usage >&2; exit 2; }
fi
guest() { limactl shell "$VM" -- "$@"; }
status() { limactl list --format '{{.Name}} {{.Status}}' | awk -v name="$VM" '$1 == name {print $2}'; }
setup() {
  [[ "$(uname -s)" == Darwin ]] || { echo 'This local VM setup uses macOS Lima vzNAT networking.' >&2; exit 1; }
  local current network
  current="$(status)"
  if [[ -z "$current" ]]; then
    limactl create --tty=false --name "$VM" "$ROOT/scripts/local-vm.yaml"
  fi
  if [[ "$current" != Running ]]; then limactl start --tty=false "$VM"; fi
  guest test -f /etc/devpush-test-vm
  # Check the marker before changing an existing VM's networking.
  network="$(limactl list --json | node --input-type=module -e '
    let raw = ""; for await (const chunk of process.stdin) raw += chunk;
    const vm = raw.trim().split("\n").filter(Boolean).map(JSON.parse).find(vm => vm.name === "devpush-test");
    if (!vm || vm.vmType !== "vz") process.exit(1);
    console.log((vm.config?.networks ?? []).some(network => network.vzNAT) ? "ready" : "missing");
  ')" || { echo 'The test VM must use the vz driver. Recreate it with vm:destroy then vm:setup.' >&2; exit 1; }
  if [[ "$network" != ready ]]; then
    limactl stop "$VM"
    limactl edit --tty=false --network=vzNAT "$VM"
    limactl start --tty=false "$VM"
  fi
  guest sudo docker info >/dev/null
  guest sudo docker compose version
  echo 'Local VM IPv4:'
  guest ip -4 -o addr show dev lima0 scope global | awk '{sub(/\/.*/, "", $4); print $4}'
}

case "$command" in
  help|--help|-h) usage; exit 0 ;;
  setup) setup; exit 0 ;;
  install)
    installer="${2:-}"
    [[ "$installer" == http://* || "$installer" == https://* ]] || { echo 'Pass the generated installer URL from devpush.' >&2; exit 2; }
    setup
    address="$(guest ip -4 -o addr show dev lima0 scope global | awk '{sub(/\/.*/, "", $4); print $4; exit}')"
    [[ -n "$address" ]] || { echo 'VM has no reachable IPv4 address.' >&2; exit 1; }
    guest bash -s -- "$installer" "$address" <<'INSTALL'
set -euo pipefail
script="$(mktemp)"
trap 'rm -f "$script"' EXIT
curl -fsSL -o "$script" -- "$1"
sudo bash "$script" --address "$2"
INSTALL
    exit 0 ;;

  stop) [[ -z "$(status)" ]] || limactl stop "$VM"; exit 0 ;;
  destroy)
    [[ -n "$(status)" ]] || { echo "$VM does not exist."; exit 0; }
    # Validate ownership before deleting a VM with this name.
    [[ "$(status)" == Running ]] || limactl start --tty=false "$VM"
    guest test -f /etc/devpush-test-vm
    limactl stop "$VM"
    limactl delete --tty=false "$VM"
    exit 0 ;;
  test) ;;
  *) usage >&2; exit 2 ;;
esac

command -v go >/dev/null
setup
# An enrolled VM belongs to a different testing flow; don't alter its ingress.
guest bash -s <<'CHECK'
set -euo pipefail
if systemctl is-active --quiet devpush-agent || sudo docker inspect devpush-traefik >/dev/null 2>&1 || sudo docker inspect devpush-docker-socket-proxy >/dev/null 2>&1; then
  echo 'This VM already has an agent or ingress. Use vm:destroy then vm:test for a clean test VM.' >&2
  exit 1
fi
CHECK
case "$(guest uname -m)" in aarch64) arch=arm64 ;; x86_64) arch=amd64 ;; *) echo 'Unsupported VM architecture.' >&2; exit 1 ;; esac
mkdir -p "$ROOT/.tmp"
temporary="$(mktemp -d "$ROOT/.tmp/vm-test.XXXXXX")"
trap 'rm -rf "$temporary"' EXIT
cd "$ROOT"
GOOS=linux GOARCH="$arch" CGO_ENABLED=0 GOCACHE="$ROOT/.tmp/go-build-cache" \
  go test -c -o "$temporary/agent.test" ./agent/internal/agent
# Lima mounts the host home read-only; copy the binary to writable guest storage.
guest sudo bash -s -- "$temporary/agent.test" <<'TEST' | tee "$temporary/results.log"
set -euo pipefail
work="$(mktemp -d /tmp/devpush-test.XXXXXX)"
cleanup() {
  docker rm -f devpush-docker-socket-proxy >/dev/null 2>&1 || true
  docker network rm devpush-docker-api devpush-proxy >/dev/null 2>&1 || true
  rm -rf "$work"
}
trap cleanup EXIT
cp "$1" "$work/agent.test"
mkdir -p "$work/internal/agent"
cd "$work/internal/agent"
DEVPUSH_RUN_DOCKER_SMOKE=1 "$work/agent.test" -test.v -test.timeout=8m \
  '-test.run=^TestRunDeploymentJob(RunsRealDockerCompose|RoutesThroughRealTraefik)$'
TEST
if grep -q -- '--- SKIP:' "$temporary/results.log"; then echo 'Tests must not be skipped.' >&2; exit 1; fi
for test in RunsRealDockerCompose RoutesThroughRealTraefik; do
  grep -q -- "--- PASS: TestRunDeploymentJob$test" "$temporary/results.log"
done
echo "VM tests passed. $VM remains running; use pnpm vm:stop or pnpm vm:destroy."