huskies: merge 811
This commit is contained in:
Executable
+101
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env bash
|
||||
# fly_multitenant_poc.sh — Proof of concept for Spike 811.
|
||||
#
|
||||
# Demonstrates the Fly.io Machines API calls that the huskies gateway
|
||||
# will eventually make to provision and tear down a per-tenant project
|
||||
# machine. Run against a real Fly org with FLY_API_TOKEN set, or read it
|
||||
# as a commented sketch — the calls are the contract.
|
||||
#
|
||||
# This is NOT production code. Production will issue these requests
|
||||
# from Rust (see server::service::cloud::fly) with retries, structured
|
||||
# errors, and CRDT writes to record machine_id/volume_id. The shell
|
||||
# script exists so the spec is verifiable end-to-end.
|
||||
#
|
||||
# Required env:
|
||||
# FLY_API_TOKEN - org-scoped Fly token
|
||||
# FLY_APP - name of the huskies-projects Fly app (must exist)
|
||||
# TENANT_ID - identifier used to tag and name the machine
|
||||
# REGION - Fly region code, e.g. "iad" (default: iad)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: "${FLY_API_TOKEN:?FLY_API_TOKEN must be set}"
|
||||
: "${FLY_APP:?FLY_APP must be set}"
|
||||
: "${TENANT_ID:?TENANT_ID must be set}"
|
||||
REGION="${REGION:-iad}"
|
||||
IMAGE="registry.fly.io/huskies-projects:latest"
|
||||
|
||||
API="https://api.machines.dev/v1"
|
||||
AUTH=(-H "Authorization: Bearer ${FLY_API_TOKEN}" -H "Content-Type: application/json")
|
||||
|
||||
echo "==> 1. Create a 1 GiB persistent volume for tenant ${TENANT_ID}"
|
||||
VOLUME_JSON=$(curl -sS -X POST "${API}/apps/${FLY_APP}/volumes" "${AUTH[@]}" --data @- <<EOF
|
||||
{
|
||||
"name": "huskies_${TENANT_ID}",
|
||||
"region": "${REGION}",
|
||||
"size_gb": 1
|
||||
}
|
||||
EOF
|
||||
)
|
||||
VOLUME_ID=$(echo "${VOLUME_JSON}" | jq -r .id)
|
||||
echo " volume_id = ${VOLUME_ID}"
|
||||
|
||||
echo "==> 2. Create a machine attached to the volume, with auto-suspend"
|
||||
MACHINE_JSON=$(curl -sS -X POST "${API}/apps/${FLY_APP}/machines" "${AUTH[@]}" --data @- <<EOF
|
||||
{
|
||||
"name": "huskies-${TENANT_ID}",
|
||||
"region": "${REGION}",
|
||||
"config": {
|
||||
"image": "${IMAGE}",
|
||||
"env": {
|
||||
"TENANT_ID": "${TENANT_ID}",
|
||||
"HUSKIES_PORT": "3001",
|
||||
"PRIMARY_REGION": "${REGION}"
|
||||
},
|
||||
"guest": { "cpu_kind": "shared", "cpus": 2, "memory_mb": 2048 },
|
||||
"mounts": [ { "volume": "${VOLUME_ID}", "path": "/data" } ],
|
||||
"services": [ {
|
||||
"ports": [
|
||||
{ "port": 443, "handlers": ["tls","http"] },
|
||||
{ "port": 80, "handlers": ["http"] }
|
||||
],
|
||||
"protocol": "tcp",
|
||||
"internal_port": 3001,
|
||||
"auto_stop_machines": "suspend",
|
||||
"auto_start_machines": true,
|
||||
"min_machines_running": 0
|
||||
} ],
|
||||
"metadata": { "tenant": "${TENANT_ID}", "managed_by": "huskies-gw" },
|
||||
"restart": { "policy": "on-failure", "max_retries": 5 }
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
MACHINE_ID=$(echo "${MACHINE_JSON}" | jq -r .id)
|
||||
PRIVATE_IP=$(echo "${MACHINE_JSON}" | jq -r .private_ip)
|
||||
echo " machine_id = ${MACHINE_ID}"
|
||||
echo " private_ip = ${PRIVATE_IP}"
|
||||
|
||||
echo "==> 3. Wait for the machine to reach 'started' (long-poll, 60s timeout)"
|
||||
curl -sS "${API}/apps/${FLY_APP}/machines/${MACHINE_ID}/wait?state=started&timeout=60" "${AUTH[@]}" \
|
||||
| jq -r '" state = " + .ok'
|
||||
|
||||
echo " machine reachable at ${MACHINE_ID}.vm.${FLY_APP}.internal:3001"
|
||||
|
||||
# ----- At this point the gateway would record (tenant, machine_id, volume_id)
|
||||
# ----- into the CRDT and start proxying traffic. We pause here.
|
||||
sleep 2
|
||||
|
||||
echo "==> 4. Graceful stop (lets sled flush; idle-suspend uses the same path)"
|
||||
curl -sS -X POST "${API}/apps/${FLY_APP}/machines/${MACHINE_ID}/stop" "${AUTH[@]}" \
|
||||
--data '{"signal":"SIGTERM","timeout":"30s"}' > /dev/null
|
||||
|
||||
echo "==> 5. Destroy the machine"
|
||||
curl -sS -X DELETE "${API}/apps/${FLY_APP}/machines/${MACHINE_ID}?force=true" "${AUTH[@]}" > /dev/null
|
||||
echo " machine destroyed"
|
||||
|
||||
echo "==> 6. Reclaim the volume (only when the tenant deletes the project)"
|
||||
curl -sS -X DELETE "${API}/apps/${FLY_APP}/volumes/${VOLUME_ID}" "${AUTH[@]}" > /dev/null
|
||||
echo " volume reclaimed"
|
||||
|
||||
echo "==> done."
|
||||
Reference in New Issue
Block a user