#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════════ # updates-flow.sh — Demo del flujo de actualización de alloy # Para el Episodio #834 — atareao con Linux # ═══════════════════════════════════════════════════════════════════════════ # Muestra el flujo completo: check-all → digest compare → policy apply → SSE # ═══════════════════════════════════════════════════════════════════════════ set -e VERDE='\033[0;32m' AMARILLO='\033[1;33m' AZUL='\033[0;34m' ROJO='\033[0;31m' GRIS='\033[0;90m' NC='\033[0m' echo -e "${AZUL}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${AZUL}║ 🔄 alloy — Flujo de actualización ║${NC}" echo -e "${AZUL}║ Fase 1: Check (bloqueante, devuelve respuesta) ║${NC}" echo -e "${AZUL}║ Fase 2: Policy apply (background, SSE progress) ║${NC}" echo -e "${AZUL}╚══════════════════════════════════════════════════════════════╝${NC}" echo "" # ── Fase 1: Check ──────────────────────────────────────────────────────── echo -e "${VERDE}═══ Fase 1: Check All ═══${NC}" echo "" echo -e "${GRIS}El backend:${NC}" echo " 1. Obtiene todos los contenedores (fetch_containers)" echo " 2. Para cada contenedor (en paralelo, semáforo 4 conexiones):" echo " a. Parsear referencia de imagen → (registry, repo, tag)" echo " b. Solicitar token Bearer a auth.docker.io" echo " c. Consultar manifest en registry-1.docker.io/v2/{repo}/manifests/{tag}" echo " d. Extraer config.digest del manifest" echo " e. Comparar short_digest(local) vs short_digest(remote)" echo " 3. Persistir has_update en SQLite" echo " 4. Construir lista de pendientes" echo " 5. Lanzar apply_policies_background en tokio::spawn" echo " 6. Devolver respuesta JSON con has_update flags" echo "" # ── Fase 2: Policy Apply ───────────────────────────────────────────────── echo -e "${VERDE}═══ Fase 2: Policy Apply (background) ═══${NC}" echo "" echo -e "${GRIS}Para cada contenedor pendiente:${NC}" echo "" echo " ┌─ [PullRestart] ──────────────────────────────────────────────┐" echo " │ 1. tag_backup_image() (si rollback_on_failure=true) │" echo " │ 2. pull_image() → docker.create_image() │" echo " │ 3. recreate_container() → stop + rename + create + start │" echo " │ 4. verify_container_healthy() (si rollback) │" echo " │ ├── OK → continue │" echo " │ └── FAIL → rollback_container() (restaurar imagen) │" echo " │ 5. cleanup_old_image() (si cleanup_old_image=true) │" echo " └──────────────────────────────────────────────────────────────┘" echo "" echo " ┌─ [PullRestartStack] ─────────────────────────────────────────┐" echo " │ 1. resolve_compose_file() → labels del contenedor │" echo " │ 2. docker compose -f pull │" echo " │ 3. docker compose -f up -d │" echo " └──────────────────────────────────────────────────────────────┘" echo "" echo " ┌─ [Pull] ─────────────────────────────────────────────────────┐" echo " │ 1. pull_image() → solo descargar, sin reiniciar │" echo " └──────────────────────────────────────────────────────────────┘" echo "" # ── Políticas ──────────────────────────────────────────────────────────── echo -e "${VERDE}═══ Políticas de actualización ═══${NC}" echo "" printf " %-25s %s\n" "None" "No hacer nada" printf " %-25s %s\n" "Pull" "Solo descargar imagen" printf " %-25s %s\n" "PullRestart" "Descargar + reiniciar contenedor" printf " %-25s %s\n" "PullRestartStack" "Descargar + recrear stack completo" echo "" # ── Resolución de políticas ────────────────────────────────────────────── echo -e "${VERDE}═══ Resolución de políticas ═══${NC}" echo "" echo " 1. Se mira el label del contenedor (alloy_update_policy)" echo " 2. Si no tiene label, se busca en update_policies (SQLite)" echo " 3. Si no hay política específica, se usa la política global (settings)" echo " 4. PullRestartStack resuelve el archivo compose desde los labels:" echo " a. com.docker.compose.project → nombre del proyecto" echo " b. com.docker.compose.config.files → ruta al compose file" echo " c. com.docker.compose.working_dir → directorio del proyecto" echo "" # ── Rollback ───────────────────────────────────────────────────────────── echo -e "${VERDE}═══ Rollback automático ═══${NC}" echo "" echo -e "${GRIS}Si rollback_on_failure=true y el contenedor no arranca:${NC}" echo "" echo " 1. tag_backup_image() → etiqueta la imagen actual como backup" echo " 2. pull_image() → descarga la nueva imagen" echo " 3. recreate_container() → crea contenedor con nueva imagen" echo " 4. verify_container_healthy() → espera a que responda" echo " ├── OK → todo bien, cleanup de imagen anterior" echo " └── FAIL → rollback:" echo " ├── remove contenedor nuevo" echo " ├── restaurar nombre del backup" echo " ├── restart contenedor con imagen anterior" echo " └── notificar fallo" echo "" # ── SSE Progress ───────────────────────────────────────────────────────── echo -e "${VERDE}═══ SSE Progress (tiempo real) ═══${NC}" echo "" echo -e "${GRIS}Eventos emitidos durante el proceso:${NC}" echo "" echo " event: update-progress" echo " data: {\"container\":\"nginx\",\"status\":\"🔍 PullRestart\",\"done\":false}" echo "" echo " event: update-progress" echo " data: {\"container\":\"nginx\",\"status\":\"📥 Pulling...\",\"done\":false}" echo "" echo " event: update-progress" echo " data: {\"container\":\"nginx\",\"status\":\"✅ actualizado + reiniciado\",\"done\":true}" echo "" echo " event: notification" echo " data: {\"container\":\"nginx\",\"status\":\"🔄 actualizado\",\"timestamp\":\"2026-08-29T12:00:00Z\"}" echo "" # ── Comandos curl ──────────────────────────────────────────────────────── echo -e "${VERDE}═══ Comandos para probar ═══${NC}" echo "" echo " # Check individual" echo " curl -X POST http://localhost:3066/api/check-update/nginx \\" echo " -H \"Cookie: session=TU_TOKEN\"" echo "" echo " # Update individual" echo " curl -X POST http://localhost:3066/api/update/nginx \\" echo " -H \"Cookie: session=TU_TOKEN\"" echo "" echo " # Check All (masivo)" echo " curl -X POST http://localhost:3066/api/check-all \\" echo " -H \"Cookie: session=TU_TOKEN\"" echo "" echo " # SSE updates (tiempo real)" echo " curl -N http://localhost:3066/api/updates \\" echo " -H \"Cookie: session=TU_TOKEN\"" echo "" echo " # Historial" echo " curl http://localhost:3066/api/history \\" echo " -H \"Cookie: session=TU_TOKEN\"" echo ""