feat: FastAPI console with dashboard, Pulp client, healthz (stages 0-1)
- config: PULP_* env + 사내 CA(verify=) 대응 - pulp_client: Basic Auth get/post/patch, status/list_repos/get_version - BFF 라우트: GET / (대시보드), GET /repos (조각), GET /healthz - views: Pulp JSON → 표시 모델 (GPG 검증 배지 3단계, 요약 집계) - HTMX + Jinja 템플릿, vendored pico.css/htmx.js (CDN 의존 0) - 브라우저는 Pulp 직접 호출 안 함 — 모두 BFF 경유 (스펙 §2) - 테스트: pulp_client(respx), 라우트(dependency_overrides), views 순수함수 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
56
app/routes/dashboard.py
Normal file
56
app/routes/dashboard.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""대시보드 (화면 1, 읽기 전용).
|
||||
|
||||
GET / → 전체 페이지(상태 + 요약 카드 + 저장소 목록)
|
||||
GET /repos → 저장소 목록 조각 (새로고침/폴링용 partial)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
from .. import views
|
||||
from ..deps import get_pulp_client, templates
|
||||
from ..pulp_client import PulpClient
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def _load_repos(pulp: PulpClient) -> dict[str, Any]:
|
||||
"""저장소 목록을 읽어 표시 모델 + 요약 + (실패 시) 에러 메시지를 만든다."""
|
||||
try:
|
||||
repos = pulp.list_repos()
|
||||
except httpx.HTTPError as exc:
|
||||
return {"repos": [], "summary": views.summarize([]), "error": str(exc)}
|
||||
|
||||
repo_views: list[dict[str, Any]] = []
|
||||
for repo in repos:
|
||||
version = None
|
||||
vhref = repo.get("latest_version_href")
|
||||
if vhref:
|
||||
try:
|
||||
version = pulp.get_version(vhref)
|
||||
except httpx.HTTPError:
|
||||
version = None # 버전 상세 실패는 치명적이지 않음 — 행은 표시
|
||||
repo_views.append(views.build_repo_view(repo, version))
|
||||
|
||||
return {"repos": repo_views, "summary": views.summarize(repo_views), "error": None}
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def dashboard(
|
||||
request: Request, pulp: PulpClient = Depends(get_pulp_client)
|
||||
) -> HTMLResponse:
|
||||
return templates.TemplateResponse(request, "dashboard.html", _load_repos(pulp))
|
||||
|
||||
|
||||
@router.get("/repos", response_class=HTMLResponse)
|
||||
def repos_fragment(
|
||||
request: Request, pulp: PulpClient = Depends(get_pulp_client)
|
||||
) -> HTMLResponse:
|
||||
return templates.TemplateResponse(
|
||||
request, "partials/repo_list.html", _load_repos(pulp)
|
||||
)
|
||||
Reference in New Issue
Block a user