Files
probo/contrib/lima/sandbox.sh
Ludovic Vielle 570395c4ac Add opt-in shell lint and format targets
Introduce make lint-shell / fmt-shell with shellcheck and
shfmt (-i 2 -ci -bn), normalize first-party scripts, and
document the new targets. Keep them out of make lint / fmt.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-28 17:37:34 +02:00

195 lines
4.6 KiB
Bash
Executable File

#!/bin/bash
# Copyright (c) 2025-2026 Probo Inc <hello@probo.com>.
# SPDX-License-Identifier: MIT
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TEMPLATE="${SCRIPT_DIR}/probo.yaml"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
WORKTREE_NAME="$(basename "${REPO_ROOT}")"
VM_NAME="probo-${WORKTREE_NAME}"
usage() {
cat <<EOF
Usage: $(basename "$0") <command> [options]
Commands:
create [--cpus C] [--memory M] [--disk D] Create a new sandbox VM
start Start a stopped sandbox
boot-logs Show boot logs
stop Stop the sandbox
restart Stop + start the sandbox
delete Delete the sandbox entirely
ssh Open interactive shell in /workspace
exec -- CMD Run a command in the sandbox
status Show sandbox state, IP, and services
list List all probo-* VMs
VM name: ${VM_NAME} (derived from worktree directory)
EOF
exit 1
}
get_vm_ip() {
limactl shell "${VM_NAME}" ip -4 -j addr show dev lima0 2>/dev/null \
| jq -r '.[0].addr_info[0].local // empty' 2>/dev/null || true
}
get_vm_status() {
local status
status=$(limactl list --json 2>/dev/null \
| jq -r "select(.name == \"${VM_NAME}\") | .status" 2>/dev/null) || true
echo "${status:-NotFound}"
}
cmd_create() {
local cpus="" memory="" disk=""
while [[ $# -gt 0 ]]; do
case "$1" in
--cpus)
cpus="$2"
shift 2
;;
--memory)
memory="$2"
shift 2
;;
--disk)
disk="$2"
shift 2
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done
echo "Creating sandbox: ${VM_NAME}"
echo "Worktree: ${REPO_ROOT}"
local -a create_args=(
--name "${VM_NAME}"
--tty=false
--set ".mounts = [{\"location\": \"${REPO_ROOT}\", \"mountPoint\": \"/workspace\", \"writable\": true},{\"location\": \"${HOME}/go\", \"mountPoint\": \"/home/${USER}.guest/go\", \"writable\": true}]"
--mount-type virtiofs
)
if [[ -n "${cpus}" ]]; then
create_args+=(--cpus "${cpus}")
fi
if [[ -n "${memory}" ]]; then
create_args+=(--memory "${memory}")
fi
if [[ -n "${disk}" ]]; then
create_args+=(--disk "${disk}")
fi
limactl create "${create_args[@]}" "${TEMPLATE}"
}
cmd_start() {
echo "Starting sandbox: ${VM_NAME}"
limactl start "${VM_NAME}"
echo ""
cmd_status
}
cmd_boot_logs() {
limactl shell "${VM_NAME}" -- sudo tail -f /var/log/cloud-init-output.log
}
cmd_stop() {
echo "Stopping sandbox: ${VM_NAME}"
limactl stop "${VM_NAME}"
echo "Sandbox stopped."
}
cmd_restart() {
cmd_stop
echo ""
cmd_start
}
cmd_delete() {
echo "Deleting sandbox: ${VM_NAME}"
limactl delete --force "${VM_NAME}"
echo "Sandbox deleted."
}
cmd_ssh() {
exec limactl shell --workdir /workspace "${VM_NAME}"
}
cmd_exec() {
limactl shell --workdir /workspace "${VM_NAME}" "$@"
}
cmd_status() {
local status ip
status="$(get_vm_status)"
ip="$(get_vm_ip)"
echo "Sandbox: ${VM_NAME}"
echo "State: ${status}"
echo "IP: ${ip:-"-"}"
if [[ "${status}" == "Running" && -n "${ip}" ]]; then
echo ""
echo "Services (use VM IP to access from host):"
echo " Console: http://${ip}:5173"
echo " Compliance Portal: http://${ip}:5174"
echo " API: http://${ip}:8080"
echo " Grafana: http://${ip}:3001"
echo " Mailpit: http://${ip}:8025"
echo " Keycloak: http://${ip}:8082"
echo " PostgreSQL: psql -h ${ip} -U probod"
fi
}
cmd_list() {
printf "%-25s %-12s %s\n" "NAME" "STATE" "IP"
limactl list --json 2>/dev/null | jq -r '
select(.name | startswith("probo-")) |
[.name, .status] | @tsv
' | while IFS=$'\t' read -r name status; do
local ip="-"
if [[ "${status}" == "Running" ]]; then
ip=$(limactl shell "${name}" ip -4 -j addr show dev lima0 2>/dev/null \
| jq -r '.[0].addr_info[0].local // "-"' 2>/dev/null || echo "-")
fi
printf "%-25s %-12s %s\n" "${name}" "${status}" "${ip}"
done
}
if [[ $# -lt 1 ]]; then
usage
fi
command="$1"
shift
case "${command}" in
create) cmd_create "$@" ;;
start) cmd_start ;;
boot-logs) cmd_boot_logs ;;
stop) cmd_stop ;;
restart) cmd_restart ;;
delete) cmd_delete ;;
ssh) cmd_ssh ;;
exec)
if [[ "${1:-}" == "--" ]]; then shift; fi
cmd_exec "$@"
;;
status) cmd_status ;;
list) cmd_list ;;
*)
echo "Unknown command: ${command}"
usage
;;
esac