import html from fastapi import APIRouter, Depends, Form, HTTPException, Request from fastapi.responses import HTMLResponse, RedirectResponse from app.auth import require_user from app.db.audit import log_audit_event from app.db.jobs import create_job from app.db.migration_readiness import ( BOOTSTRAP_SCRIPT, PREFLIGHT_SCRIPT, get_latest_bootstrap_job, get_latest_preflight_job, summarize_readiness, summarize_script_run, ) from app.routes.jobs import render_job_status from app.templates.layout import page router = APIRouter() BOOTSTRAP_MODES = {"check", "repair", "deploy"} def render_readiness_pill(ready: bool) -> str: if ready: return 'READY' return 'NOT READY' def render_script_result(title: str, script_name: str, summary: dict) -> str: job = summary.get("job") job_rows = f'Zatím není uložený žádný výsledek skriptu {html.escape(script_name)}.' if job: job_id = html.escape(str(job.get("id", ""))) return_code = summary.get("return_code") return_code_label = "" if return_code is None else html.escape(str(return_code)) job_rows = f""" Úloha#{job_id} Status{render_job_status(job.get("status"))} Return code{return_code_label} Started at{html.escape(job.get("started_at", "") or "")} Finished at{html.escape(job.get("finished_at", "") or "")} """ stdout = html.escape(summary.get("stdout") or "Zatím není uložený žádný stdout log.") stderr = html.escape(summary.get("stderr") or "Zatím není uložený žádný stderr log.") return f"""

{html.escape(title)}

Poslední výsledek maintenance skriptu {html.escape(script_name)} uložený v databázi.

{job_rows}

Raw stdout log

{stdout}

Raw stderr log

{stderr}
""" @router.get("/migration-readiness", response_class=HTMLResponse) def migration_readiness_page(request: Request, user=Depends(require_user)): latest_job = get_latest_preflight_job() summary = summarize_readiness(latest_job) bootstrap_summary = summarize_script_run(get_latest_bootstrap_job()) job = summary["job"] log_audit_event( user, action="migration_readiness.viewed", target_type="migration_readiness", target_id=PREFLIGHT_SCRIPT, metadata={"job_id": job.get("id") if job else None}, ) job_rows = 'Zatím není uložený žádný výsledek preflight kontroly.' if job: job_id = html.escape(str(job.get("id", ""))) job_rows = f""" Úloha#{job_id} Stav úlohy{render_job_status(job.get("status"))} Vytvořeno{html.escape(job.get("created_at", "") or "")} Spuštěno{html.escape(job.get("started_at", "") or "")} Dokončeno{html.escape(job.get("finished_at", "") or "")} Worker{html.escape(job.get("worker_id", "") or "")} """ raw_output = html.escape(summary.get("raw_output") or "") if not raw_output: raw_output = "Zatím není uložený žádný log výstup." return page( "Migration Readiness", f"""

Migration Readiness

Poslední výsledek maintenance skriptu {html.escape(PREFLIGHT_SCRIPT)} uložený v databázi. Stav vychází pouze z výstupu skriptu.

Bootstrap v2 má explicitní režimy.

Portál bootstrap nespouští přímo přes shell. Pouze založí maintenance job pro {html.escape(BOOTSTRAP_SCRIPT)}.

Plný Bootstrap Deploy není výchozí akce.

Režim deploy deployuje core services a může změnit stav systému. Spouštějte ho jen po kontrole dopadu.

Stav{render_readiness_pill(summary["ready"])}
OK{html.escape(str(summary["ok_count"]))}
WARN{html.escape(str(summary["warn_count"]))}
FAIL{html.escape(str(summary["fail_count"]))}

Poslední preflight úloha

{job_rows}

Raw preflight log výstup

{raw_output}
{render_script_result("Poslední výsledek Bootstrap v2", BOOTSTRAP_SCRIPT, bootstrap_summary)} """, user=user, ) @router.post("/migration-readiness/run") def run_migration_readiness(user=Depends(require_user)): job_id = create_job( job_type="run_script", target_type="maintenance_script", target_id=PREFLIGHT_SCRIPT, payload={"script_name": PREFLIGHT_SCRIPT}, user=user, source="portal_manual", ) return RedirectResponse(url=f"/portal/jobs/{job_id}", status_code=303) @router.post("/migration-readiness/bootstrap") def run_bootstrap_v2(mode: str = Form(...), user=Depends(require_user)): mode = (mode or "").strip().lower() if mode not in BOOTSTRAP_MODES: raise HTTPException(status_code=400, detail="Neplatný režim bootstrapu") job_id = create_job( job_type="run_script", target_type="maintenance_script", target_id=BOOTSTRAP_SCRIPT, payload={ "script_name": BOOTSTRAP_SCRIPT, "args": [mode], "arguments": [mode], "mode": mode, }, user=user, source="portal_manual", ) return RedirectResponse(url=f"/portal/jobs/{job_id}", status_code=303)