refractor: afgerond
This commit is contained in:
@@ -18,15 +18,55 @@ Refactoring must always:
|
|||||||
|
|
||||||
## Repository structure
|
## Repository structure
|
||||||
|
|
||||||
Backend (FastAPI)
|
Backend (FastAPI modular monolith)
|
||||||
- control/app.py (main API)
|
|
||||||
|
Bootstrap
|
||||||
|
- control/app.py (application bootstrap & router wiring ONLY)
|
||||||
|
|
||||||
|
System / platform router
|
||||||
|
- control/app_system.py
|
||||||
|
|
||||||
|
Feature routers
|
||||||
|
- control/app_containers.py
|
||||||
|
- control/app_pods.py
|
||||||
|
- control/app_networks.py
|
||||||
|
- control/app_files.py
|
||||||
- control/app_images.py
|
- control/app_images.py
|
||||||
|
|
||||||
|
Shared infrastructure
|
||||||
|
- control/common.py
|
||||||
|
|
||||||
WebUI (static Apache)
|
WebUI (static Apache)
|
||||||
- webui/html/index.html
|
- webui/html/index.html
|
||||||
- webui/html/assets/js/tabs/
|
- webui/html/assets/js/tabs/
|
||||||
- webui/conf/httpd.conf
|
- webui/conf/httpd.conf
|
||||||
|
|
||||||
|
### Backend architecture rule (HARD)
|
||||||
|
|
||||||
|
control/app.py is a bootstrap layer only.
|
||||||
|
|
||||||
|
It may:
|
||||||
|
- create FastAPI app
|
||||||
|
- include routers
|
||||||
|
- register startup events
|
||||||
|
|
||||||
|
It must NOT:
|
||||||
|
- contain feature endpoints
|
||||||
|
- contain system logic
|
||||||
|
- contain Podman or systemctl implementations
|
||||||
|
|
||||||
|
All endpoints belong in routers.
|
||||||
|
|
||||||
|
### Module ownership rule
|
||||||
|
|
||||||
|
If unsure where new logic belongs:
|
||||||
|
|
||||||
|
- shared logic → control/common.py
|
||||||
|
- system/platform logic → control/app_system.py
|
||||||
|
- feature logic → corresponding app_<feature>.py router
|
||||||
|
|
||||||
|
Never introduce new endpoints in control/app.py.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Runtime architecture (IMPORTANT)
|
## Runtime architecture (IMPORTANT)
|
||||||
@@ -123,8 +163,11 @@ New functionality must be added via:
|
|||||||
Security rules:
|
Security rules:
|
||||||
- No shell=True
|
- No shell=True
|
||||||
- subprocess must be explicit and safe
|
- subprocess must be explicit and safe
|
||||||
- Respect allowed_units.txt
|
- Never assume systemd states
|
||||||
- Never assume systemd states.
|
|
||||||
|
Legacy notice:
|
||||||
|
allow_list / allowed_units.txt functionality has been removed
|
||||||
|
and must NOT be reintroduced.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# ARCHITECTURE.md — podman-mvp (WebUI + API)
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This document describes **where code lives** and **which module owns what**.
|
||||||
|
It is a factual map of the system for reviewers and agents.
|
||||||
|
|
||||||
|
## Runtime + Test Base URLs
|
||||||
|
|
||||||
|
### WebUI
|
||||||
|
- http://127.0.0.1:8081/
|
||||||
|
|
||||||
|
### API (via WebUI reverse proxy)
|
||||||
|
- Base URL: http://127.0.0.1:8081/api
|
||||||
|
|
||||||
|
**All verification commands must target `127.0.0.1:8081` unless explicitly stated otherwise.**
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- `curl -fsS http://127.0.0.1:8081/api/health`
|
||||||
|
|
||||||
|
## Architecture Overview (Modular Monolith)
|
||||||
|
Single deployable backend service, split into modules (routers) by domain.
|
||||||
|
|
||||||
|
### Layers
|
||||||
|
1. **Bootstrap / Composition Root**
|
||||||
|
- `control/app.py`
|
||||||
|
- Responsibilities:
|
||||||
|
- create FastAPI app
|
||||||
|
- include routers
|
||||||
|
- register startup events (if needed)
|
||||||
|
- Hard rule: **no feature endpoints** and **no system logic** here.
|
||||||
|
|
||||||
|
2. **System / Platform Router**
|
||||||
|
- `control/app_system.py`
|
||||||
|
- Owns platform endpoints such as:
|
||||||
|
- `/health`
|
||||||
|
- `/daemon-reload`
|
||||||
|
- systemctl endpoints (`/{action}/{unit}`, legacy `/api/<action>/<unit>`)
|
||||||
|
- diagnostic endpoints (e.g. `/test-hybrid`, if present)
|
||||||
|
- Route ordering rule: broad patterns like `/{action}/{unit}` must be defined **last**.
|
||||||
|
|
||||||
|
3. **Feature Routers (UI Tabs / Domains)**
|
||||||
|
- `control/app_containers.py` — containers tab endpoints (dashboard, inspect, logs, stats stream)
|
||||||
|
- `control/app_pods.py` — pods tab endpoints (dashboard, pod actions)
|
||||||
|
- `control/app_networks.py` — networks tab endpoints
|
||||||
|
- `control/app_files.py` — files/workloads endpoints (tree/read/save/etc.)
|
||||||
|
- `control/app_images.py` — images endpoints
|
||||||
|
|
||||||
|
4. **Shared Infrastructure Layer**
|
||||||
|
- `control/common.py`
|
||||||
|
- Owns:
|
||||||
|
- Podman HTTP helpers (unix-socket requests)
|
||||||
|
- systemctl/subprocess helpers (when shared)
|
||||||
|
- shared parsing/normalization utilities
|
||||||
|
- Hard rule: routers should not duplicate shared helpers.
|
||||||
|
|
||||||
|
## Boundaries (Hard Rules)
|
||||||
|
- `control/app.py` is **bootstrap-only**.
|
||||||
|
- Endpoints must live in the appropriate router module:
|
||||||
|
- system/platform → `app_system.py`
|
||||||
|
- domain feature → `app_<domain>.py`
|
||||||
|
- Shared helpers belong in `common.py` (not copied into routers).
|
||||||
|
- Legacy `allow_list` / `allowed_units.txt` functionality is removed and must NOT be reintroduced.
|
||||||
|
|
||||||
|
## Contracts
|
||||||
|
API response shapes are governed by:
|
||||||
|
- `contracts/API_GOLDEN.md`
|
||||||
|
|
||||||
|
No endpoint response keys may be removed or renamed without explicit approval.
|
||||||
|
|
||||||
|
## Required Verification (Minimal)
|
||||||
|
After any change affecting backend routing or shared helpers, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m py_compile control/app.py control/common.py control/app_system.py \
|
||||||
|
control/app_containers.py control/app_pods.py control/app_networks.py \
|
||||||
|
control/app_files.py control/app_images.py
|
||||||
|
|
||||||
|
curl -fsS http://127.0.0.1:8081/api/health | jq
|
||||||
|
curl -fsS http://127.0.0.1:8081/api/pods-dashboard >/dev/null && echo OK
|
||||||
|
curl -fsS http://127.0.0.1:8081/api/containers-dashboard >/dev/null && echo OK
|
||||||
|
curl -fsS http://127.0.0.1:8081/api/files/tree >/dev/null && echo OK
|
||||||
|
curl -fsS http://127.0.0.1:8081/api/networks/meta | jq
|
||||||
@@ -47,7 +47,12 @@ Changes must be proposed first.
|
|||||||
Files requiring caution:
|
Files requiring caution:
|
||||||
|
|
||||||
control/app.py
|
control/app.py
|
||||||
|
control/app_files.py
|
||||||
control/app_images.py
|
control/app_images.py
|
||||||
|
control/app_networks.py
|
||||||
|
control/app_pods.py
|
||||||
|
control/app_system.py
|
||||||
|
control/common.py
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
- Never rewrite structure without agreement.
|
- Never rewrite structure without agreement.
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,6 @@ def _systemctl(cmd):
|
|||||||
|
|
||||||
# --- ROUTERS ---
|
# --- ROUTERS ---
|
||||||
# Images API lives in dedicated modules to keep this file from growing further.
|
# Images API lives in dedicated modules to keep this file from growing further.
|
||||||
app.include_router(init_system_router(SESSION, PODMAN_API_BASE, WORKLOADS_DIR))
|
|
||||||
app.include_router(init_images_router(SESSION, PODMAN_API_BASE))
|
app.include_router(init_images_router(SESSION, PODMAN_API_BASE))
|
||||||
app.include_router(init_files_router(SESSION, PODMAN_API_BASE, WORKLOADS_DIR))
|
app.include_router(init_files_router(SESSION, PODMAN_API_BASE, WORKLOADS_DIR))
|
||||||
app.include_router(init_networks_router(SESSION, PODMAN_API_BASE))
|
app.include_router(init_networks_router(SESSION, PODMAN_API_BASE))
|
||||||
@@ -42,6 +41,7 @@ app.include_router(init_pods_router(
|
|||||||
WORKLOADS_DIR,
|
WORKLOADS_DIR,
|
||||||
_systemctl,
|
_systemctl,
|
||||||
))
|
))
|
||||||
|
app.include_router(init_system_router(SESSION, PODMAN_API_BASE, WORKLOADS_DIR))
|
||||||
|
|
||||||
|
|
||||||
def run(cmd):
|
def run(cmd):
|
||||||
|
|||||||
Reference in New Issue
Block a user