97 lines
3.7 KiB
Python
97 lines
3.7 KiB
Python
import html
|
|
|
|
from fastapi import APIRouter, Depends, 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 PREFLIGHT_SCRIPT, get_latest_preflight_job, summarize_readiness
|
|
from app.routes.jobs import render_job_status
|
|
from app.templates.layout import page
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def render_readiness_pill(ready: bool) -> str:
|
|
if ready:
|
|
return '<span class="pill pill-success">READY</span>'
|
|
return '<span class="pill pill-danger">NOT READY</span>'
|
|
|
|
|
|
@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)
|
|
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 = '<tr><td colspan="2">Zatím není uložený žádný výsledek preflight kontroly.</td></tr>'
|
|
if job:
|
|
job_id = html.escape(str(job.get("id", "")))
|
|
job_rows = f"""
|
|
<tr><th>Úloha</th><td><a href="/portal/jobs/{job_id}">#{job_id}</a></td></tr>
|
|
<tr><th>Stav úlohy</th><td>{render_job_status(job.get("status"))}</td></tr>
|
|
<tr><th>Vytvořeno</th><td>{html.escape(job.get("created_at", "") or "")}</td></tr>
|
|
<tr><th>Spuštěno</th><td>{html.escape(job.get("started_at", "") or "")}</td></tr>
|
|
<tr><th>Dokončeno</th><td>{html.escape(job.get("finished_at", "") or "")}</td></tr>
|
|
<tr><th>Worker</th><td>{html.escape(job.get("worker_id", "") or "")}</td></tr>
|
|
"""
|
|
|
|
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"""
|
|
<div class="card">
|
|
<h2>Migration Readiness</h2>
|
|
<p class="muted">Poslední výsledek maintenance skriptu {html.escape(PREFLIGHT_SCRIPT)} uložený v databázi.</p>
|
|
<form method="post" action="/portal/migration-readiness/run">
|
|
<button type="submit">Spustit preflight kontrolu</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="stats-grid">
|
|
<div class="stat-card {"stat-success" if summary["ready"] else "stat-danger"}"><span>Stav</span><strong>{render_readiness_pill(summary["ready"])}</strong></div>
|
|
<div class="stat-card stat-success"><span>OK</span><strong>{html.escape(str(summary["ok_count"]))}</strong></div>
|
|
<div class="stat-card stat-warning"><span>WARN</span><strong>{html.escape(str(summary["warn_count"]))}</strong></div>
|
|
<div class="stat-card stat-danger"><span>FAIL</span><strong>{html.escape(str(summary["fail_count"]))}</strong></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Poslední úloha</h2>
|
|
<table>
|
|
{job_rows}
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Raw log výstup</h2>
|
|
<pre class="log-viewer log-stdout">{raw_output}</pre>
|
|
</div>
|
|
""",
|
|
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)
|