Files
takana/scripts/farm/farm-down.sh
T
sergioandClaude Opus 4.8 5658e9337c granja: ciclo de vida EFÍMERO por hcloud API (farm-up/farm-down) + baseline €0
Migración del worker pet-24/7 a workers efímeros on-demand. farm1 (ccx23 persistente que
idleaba quemando plata) → snapshot golden 'hammer-golden-2026-07-05' (img 405120842: toolchain
+ store sellado horneados) → destruido. Baseline ahora 0 cajas / €0.

- farm-up.sh [N]: crea N workers desde el snapshot (cache-hit instantáneo del catálogo baked),
  los alinea con la cola actual del laptop, registra la flota en scripts/farm/.fleet (gitignored).
- farm-down.sh [name...]: cosecha el store (CAS, merge seguro) al laptop y DESTRUYE; promueve+firma.
  Orden seguro: sólo destruye si el pull de store salió bien.
- Validado punta a punta: up 1 → boot+cache+toolchain OK → down (cosecha+destruye) OK.
- Cron laptop harvest-go contra farm1 removido (la cosecha ahora la hace farm-down).

El worker sigue sin secretos (hub-and-spoke): compute puro y descartable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 08:23:06 -04:00

53 lines
2.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# farm-down.sh [name...] — COSECHA el store sellado de cada worker efímero al laptop y luego lo
# DESTRUYE. Sin args opera sobre toda la flota registrada en scripts/farm/.fleet. Con args, sólo
# sobre los workers nombrados (para bajar la escala parcialmente).
#
# El orden importa: primero rsync-eamos el store (CAS, merge seguro con el del laptop), y SÓLO si
# el pull salió bien destruimos el server. Tras destruir todo, promovemos+firmamos lo cosechado
# (cache-hit en los artefactos recién bajados) — el store del laptop es la fuente canónica.
#
# Uso: scripts/farm/farm-down.sh # cosecha + destruye toda la flota
# scripts/farm/farm-down.sh hworker-2 # sólo ese
# Env: SSH_KEY (def ~/.ssh/github5), REMOTE (def /opt/hammer), NO_PROMOTE=1 (sólo cosecha+destruye)
set -uo pipefail
SSH_KEY="${SSH_KEY:-$HOME/.ssh/github5}"
REMOTE="${REMOTE:-/opt/hammer}"
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
FLEET="$ROOT/scripts/farm/.fleet"
SSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10"
cd "$ROOT"
[ -s "$FLEET" ] || { echo "flota vacía (scripts/farm/.fleet)"; exit 0; }
want=" $* " # si hay args, filtrar por nombre; si no, todos
harvested=0
newfleet="$(mktemp)"
while read -r name ip; do
[ -n "${name:-}" ] || continue
if [ "$#" -gt 0 ] && [ "${want#* $name }" = "$want" ]; then
echo "$name $ip" >> "$newfleet"; continue # no seleccionado: sigue vivo
fi
echo "==> cosechando store de $name ($ip)"
if rsync -az -e "$SSH" "root@$ip:$REMOTE/store/" "$ROOT/store/"; then
echo "==> destruyendo $name"
if hcloud server delete "$name" >/dev/null 2>&1; then
harvested=$((harvested + 1))
else
echo " ⚠ no pude destruir $name — lo dejo en la flota"; echo "$name $ip" >> "$newfleet"
fi
else
echo " ⚠ falló el pull de store de $name — NO lo destruyo (queda en la flota)"
echo "$name $ip" >> "$newfleet"
fi
done < "$FLEET"
mv "$newfleet" "$FLEET"
echo "==> cosechados+destruidos: $harvested; flota restante:"; cat "$FLEET"
if [ "${NO_PROMOTE:-}" != "1" ] && [ "$harvested" -gt 0 ]; then
echo "==> promote+firma final (cache-hit en lo cosechado)"
scripts/build-farm.sh || echo " (build-farm devolvió error; revisá logs)"
fi