Docgen: Infra-Doku (Mandant→Node→VM) in theProx generieren & täglich ins konfigurierbare Repo pushen #17

Closed
opened 2026-06-01 19:04:02 +00:00 by chinux · 2 comments
Owner

Fertiger Claude-Code-Prompt: einen Dokumentations-Generator in theProx selbst bauen (vom vorhandenen Scheduler getrieben), der täglich die Infra-Doku (Mandant→Node→VM) erzeugt und in ein per .env konfigurierbares Git-Repo pusht.

Vorlage existiert: Im Repo chinux/Dokumentation liegt ein lauffähiger Prototyp der Render-/Mapping-Logik (render.py, datasource.pyTheProxDbSource, generate.py). Diese Logik nach theProx portieren, nicht neu erfinden. Danach das Dokumentation-Repo auf output-only eindampfen (Generator-Code dort entfernen, nur README + mandanten/_BEISPIEL behalten).


Prompt für Claude Code

Baue in theProx (server/) einen Dokumentations-Generator "docgen", der täglich
aus der theProx-DB eine Infrastruktur-Doku erzeugt und in ein per .env
konfigurierbares Git-Repo pusht. Vorlage: chinux/Dokumentation (render.py +
datasource.py:TheProxDbSource) — diese Logik portieren.

ZIEL / ENTSCHEIDUNGEN (fix):
- Läuft IN theProx, nutzt die vorhandene async DB-Session (kein separater Dienst).
- Getriggert vom bestehenden Scheduler (server/scheduler.py), einmal täglich.
- Ziel-Repo + Token kommen aus der .env (nicht hardcoden).
- Sortierung: Mandant -> Node -> VM.
- Node/VM als Markdown (Snapshot, überschrieben; Git = Historie).
- Backups als CSV, ANGEREICHERT (append + dedupe per UPID) + lesbare backups.md.
- VM- und Node-Notizen werden mit aufgenommen.

DATEIEN:
1. server/services/docgen.py  (neu) — Kern:
   - Datenmodell (Tenant/Node/Guest/BackupRun) + async _fetch() aus der DB.
   - Render: _node_md/_vm_md/_mandant_md, _merge_backups (CSV), _backups_md.
   - Git-Orchestrierung in einem Thread (asyncio.to_thread): clone/pull des
     Ziel-Repos in DOCGEN_WORKDIR, mandanten/ neu bauen (außer _BEISPIEL),
     backups.csv mergen, `git add -A`, nur committen wenn Diff, push.
   - Public: `async run_docgen(force=False)` und `async maybe_run_docgen()`
     (prüft enabled + Stunde + "heute schon gelaufen?").
2. server/scheduler.py — im run_scheduler()-Loop (tickt eh alle 60s) ergänzen:
       try:
           from services.docgen import maybe_run_docgen
           await maybe_run_docgen()
       except Exception as e:
           log.error("Docgen tick error: %s", e)
3. server/Dockerfile — `git` zur apt-Zeile hinzufügen (Zeile mit
   "libpq-dev gcc curl" -> "... curl git ...").
4. server/.env.example — DOCGEN_*-Block ergänzen (siehe ENV unten).
5. (optional) server/routers/docgen_router.py — POST /api/docgen/run
   (require_superadmin) -> await run_docgen(force=True); in main.py registrieren.
   Praktisch zum manuellen Erst-Test statt auf die Uhrzeit zu warten.

ENV (alle os.getenv, Präfix DOCGEN_):
   DOCGEN_ENABLED=false
   DOCGEN_REPO_URL=https://git.itdata-gera.de/chinux/Dokumentation.git
   DOCGEN_GIT_USER=chinux
   DOCGEN_GIT_TOKEN=
   DOCGEN_BRANCH=main
   DOCGEN_HOUR=3
   DOCGEN_WORKDIR=/tmp/theprox-docgen
   DOCGEN_AUTHOR_NAME=theProx Docgen
   DOCGEN_AUTHOR_EMAIL=docgen@itdata-gera.de
Token zur Laufzeit in die Remote-URL einsetzen (https://user:token@host/...),
NIE committen/loggen.

DB-SCHEMA (verifiziert, models/):
- tenants            -> Tenant(id, name)
- tenant_nodes       -> TenantNode(tenant_id, node_id)   [m:n]
- nodes              -> Node(id, name, status, version, notes, last_data JSONB)
- vm_notes           -> VMNote(node_name, vmid, content)
- backup_logs        -> BackupLog(node_name, upid, vmid, storage, size, status,
                        storage_type, started_at:int(unix), ended_at:int(unix))
Nodes ohne Mandant unter Mandant "_OHNE-MANDANT" einsortieren.

last_data (JSONB, vom Agent) — relevante Keys:
   node_status: cpuinfo.model, cpuinfo.cpus, memory.total, uptime, kversion,
                cpu_temperature (erscheint erst nach #14 -> bis dahin "—")
   node_version.version
   vms[] / cts[]: vmid, name, status, cpus, maxmem, maxdisk
   storage[]: storage, type, used, total
   network[]: iface, type, address|cidr, active
   vm_qemu_scans{ "<vmid>": { ip_address, os_pretty, kernel, agent_version } }
   host_updates: available, security
Backup-Verlauf kommt aus backup_logs (NICHT aus last_data): timestamp aus
ended_at|started_at (unix->ISO UTC), duration = ended-started, dedupe per upid.

AUSGABE-STRUKTUR im Ziel-Repo:
   mandanten/<mandant-slug>/README.md
   mandanten/<mandant-slug>/<node-slug>/node.md
   mandanten/<mandant-slug>/<node-slug>/vms/<vmid>-<slug>.md
   mandanten/<mandant-slug>/<node-slug>/backups.csv   (angereichert)
   mandanten/<mandant-slug>/<node-slug>/backups.md
   _BEISPIEL/ beim Rebuild NICHT löschen.
Persistenz der CSV-Historie: das Ziel-Repo selbst (push) ist die Persistenz;
WORKDIR darf ephemer sein (clone/pull holt den letzten Stand zurück).

VERIFIKATION (ohne laufende DB nötig):
- `python3 -m py_compile server/services/docgen.py server/scheduler.py`
- Importe/Modellnamen gegen server/models/ prüfen (Tenant, TenantNode, Node,
  VMNote, BackupLog).
- Render-Funktionen ggf. mit Dummy-Daten testen.

DANACH: Repo chinux/Dokumentation auf output-only eindampfen — generate.py,
render.py, datasource.py, Dockerfile, docker-compose.yml, deploy/, requirements.txt,
.env.example entfernen; README anpassen ("wird von theProx erzeugt"); _BEISPIEL
behalten.

Branch: feat/docgen (theProx) bzw. chore/output-only (Dokumentation).

Akzeptanzkriterien

  • theProx erzeugt bei DOCGEN_ENABLED=true täglich zur DOCGEN_HOUR die Doku und pusht nur bei Änderung.
  • Ziel-Repo, Branch und Token ausschließlich über .env steuerbar.
  • Struktur Mandant→Node→VM; Backups als angereicherte CSV + MD; Notizen enthalten.
  • git im Backend-Image vorhanden; py_compile grün; keine Secrets im Code/Log.
  • Dokumentation-Repo ist output-only.

Hinweis

cpu_temperature bleibt leer, bis #14 (Temperatur-Anreicherung im Rust-Agent) gefixt ist — kein Blocker für dieses Issue.


Erweiterung (Feedback): mehr VM-Infos in der VM-Sektion

_vm_md (server/services/docgen.py:204) um vier Blöcke erweitern. Drei sind direkt aus der DB lesbar, einer braucht eine kleine Agent-Erweiterung.

Datenquellen (verifiziert)

  1. Belegter Speichernode.last_data["vm_scans"][str(vmid)]["disk"] (Gast-Scan, used/total je Mount). _vm_md zeigt aktuell nur maxdisk (Allokation); zusätzlich „Belegt" rendern.
  2. Offene Ports — Modell VMPortSnapshot (vm_port_snapshots): neuester Eintrag je (node_name,vmid) (order_by scanned_at desc), scan_data = Liste {port, protocol, process, exposure}. Als Liste/Tabelle.
  3. Offene CVEs — Modell VMCveReport (vm_cve_reports), status=="open" je (node_name,vmid): cve_id, package_name, severity, fixed_version. Plus Summary aus VMCveScan (findings_count, severities). Top-N + Gesamtzahl je Severity.
  4. Laufende Docker + Pfad — Container aus vm_scans[str(vmid)]["docker"] (name/image/status) → DB-lesbar. Compose-Pfad fehlt: collect_docker (VM-Guest-Agent/src/collect/linux.rs:194, analog FreeBSD + Windows collect.rs) erfasst per docker ps nur name/image/status/ports. Für den Pfad das Compose-Label mitnehmen, z. B. docker ps --format um {{.Label "com.docker.compose.project.working_dir"}} erweitern (oder docker inspect). → Agent-Änderung + Version-Bump; bis dahin Docker ohne Pfad rendern.

docgen-Änderungen

  • _fetch() (Z. 102): zusätzlich neuesten VMPortSnapshot + offene VMCveReport/letzten VMCveScan je (node, vmid) laden und in den Daten-Baum hängen (analog note_map).
  • _vm_md() (Z. 204): nach der Feld-Tabelle vier Abschnitte ergänzen — „## Belegter Speicher", „## Offene Ports", „## Offene CVEs", „## Docker" — jeweils leer-tolerant („— noch kein Scan/keine Daten").
  • Importe (Z. 26): VMPortSnapshot, VMCveReport, VMCveScan.

Hinweis

Ports/CVEs erscheinen nur, wenn Scans gelaufen sind (Port-Scan manuell/geplant; CVE via Scheduler _cve_scan_tick). Bei fehlendem Scan „— noch kein Scan" ausgeben.

Branch: feat/docgen-vm-details (auf feat/docgen aufsetzen).

Fertiger Claude-Code-Prompt: einen **Dokumentations-Generator in theProx selbst** bauen (vom vorhandenen Scheduler getrieben), der täglich die Infra-Doku (Mandant→Node→VM) erzeugt und in ein **per `.env` konfigurierbares Git-Repo** pusht. > **Vorlage existiert:** Im Repo `chinux/Dokumentation` liegt ein lauffähiger Prototyp der Render-/Mapping-Logik (`render.py`, `datasource.py` → `TheProxDbSource`, `generate.py`). Diese Logik **nach theProx portieren**, nicht neu erfinden. Danach das `Dokumentation`-Repo auf **output-only** eindampfen (Generator-Code dort entfernen, nur README + `mandanten/_BEISPIEL` behalten). --- ## Prompt für Claude Code ``` Baue in theProx (server/) einen Dokumentations-Generator "docgen", der täglich aus der theProx-DB eine Infrastruktur-Doku erzeugt und in ein per .env konfigurierbares Git-Repo pusht. Vorlage: chinux/Dokumentation (render.py + datasource.py:TheProxDbSource) — diese Logik portieren. ZIEL / ENTSCHEIDUNGEN (fix): - Läuft IN theProx, nutzt die vorhandene async DB-Session (kein separater Dienst). - Getriggert vom bestehenden Scheduler (server/scheduler.py), einmal täglich. - Ziel-Repo + Token kommen aus der .env (nicht hardcoden). - Sortierung: Mandant -> Node -> VM. - Node/VM als Markdown (Snapshot, überschrieben; Git = Historie). - Backups als CSV, ANGEREICHERT (append + dedupe per UPID) + lesbare backups.md. - VM- und Node-Notizen werden mit aufgenommen. DATEIEN: 1. server/services/docgen.py (neu) — Kern: - Datenmodell (Tenant/Node/Guest/BackupRun) + async _fetch() aus der DB. - Render: _node_md/_vm_md/_mandant_md, _merge_backups (CSV), _backups_md. - Git-Orchestrierung in einem Thread (asyncio.to_thread): clone/pull des Ziel-Repos in DOCGEN_WORKDIR, mandanten/ neu bauen (außer _BEISPIEL), backups.csv mergen, `git add -A`, nur committen wenn Diff, push. - Public: `async run_docgen(force=False)` und `async maybe_run_docgen()` (prüft enabled + Stunde + "heute schon gelaufen?"). 2. server/scheduler.py — im run_scheduler()-Loop (tickt eh alle 60s) ergänzen: try: from services.docgen import maybe_run_docgen await maybe_run_docgen() except Exception as e: log.error("Docgen tick error: %s", e) 3. server/Dockerfile — `git` zur apt-Zeile hinzufügen (Zeile mit "libpq-dev gcc curl" -> "... curl git ..."). 4. server/.env.example — DOCGEN_*-Block ergänzen (siehe ENV unten). 5. (optional) server/routers/docgen_router.py — POST /api/docgen/run (require_superadmin) -> await run_docgen(force=True); in main.py registrieren. Praktisch zum manuellen Erst-Test statt auf die Uhrzeit zu warten. ENV (alle os.getenv, Präfix DOCGEN_): DOCGEN_ENABLED=false DOCGEN_REPO_URL=https://git.itdata-gera.de/chinux/Dokumentation.git DOCGEN_GIT_USER=chinux DOCGEN_GIT_TOKEN= DOCGEN_BRANCH=main DOCGEN_HOUR=3 DOCGEN_WORKDIR=/tmp/theprox-docgen DOCGEN_AUTHOR_NAME=theProx Docgen DOCGEN_AUTHOR_EMAIL=docgen@itdata-gera.de Token zur Laufzeit in die Remote-URL einsetzen (https://user:token@host/...), NIE committen/loggen. DB-SCHEMA (verifiziert, models/): - tenants -> Tenant(id, name) - tenant_nodes -> TenantNode(tenant_id, node_id) [m:n] - nodes -> Node(id, name, status, version, notes, last_data JSONB) - vm_notes -> VMNote(node_name, vmid, content) - backup_logs -> BackupLog(node_name, upid, vmid, storage, size, status, storage_type, started_at:int(unix), ended_at:int(unix)) Nodes ohne Mandant unter Mandant "_OHNE-MANDANT" einsortieren. last_data (JSONB, vom Agent) — relevante Keys: node_status: cpuinfo.model, cpuinfo.cpus, memory.total, uptime, kversion, cpu_temperature (erscheint erst nach #14 -> bis dahin "—") node_version.version vms[] / cts[]: vmid, name, status, cpus, maxmem, maxdisk storage[]: storage, type, used, total network[]: iface, type, address|cidr, active vm_qemu_scans{ "<vmid>": { ip_address, os_pretty, kernel, agent_version } } host_updates: available, security Backup-Verlauf kommt aus backup_logs (NICHT aus last_data): timestamp aus ended_at|started_at (unix->ISO UTC), duration = ended-started, dedupe per upid. AUSGABE-STRUKTUR im Ziel-Repo: mandanten/<mandant-slug>/README.md mandanten/<mandant-slug>/<node-slug>/node.md mandanten/<mandant-slug>/<node-slug>/vms/<vmid>-<slug>.md mandanten/<mandant-slug>/<node-slug>/backups.csv (angereichert) mandanten/<mandant-slug>/<node-slug>/backups.md _BEISPIEL/ beim Rebuild NICHT löschen. Persistenz der CSV-Historie: das Ziel-Repo selbst (push) ist die Persistenz; WORKDIR darf ephemer sein (clone/pull holt den letzten Stand zurück). VERIFIKATION (ohne laufende DB nötig): - `python3 -m py_compile server/services/docgen.py server/scheduler.py` - Importe/Modellnamen gegen server/models/ prüfen (Tenant, TenantNode, Node, VMNote, BackupLog). - Render-Funktionen ggf. mit Dummy-Daten testen. DANACH: Repo chinux/Dokumentation auf output-only eindampfen — generate.py, render.py, datasource.py, Dockerfile, docker-compose.yml, deploy/, requirements.txt, .env.example entfernen; README anpassen ("wird von theProx erzeugt"); _BEISPIEL behalten. Branch: feat/docgen (theProx) bzw. chore/output-only (Dokumentation). ``` --- ## Akzeptanzkriterien - theProx erzeugt bei `DOCGEN_ENABLED=true` täglich zur `DOCGEN_HOUR` die Doku und pusht nur bei Änderung. - Ziel-Repo, Branch und Token ausschließlich über `.env` steuerbar. - Struktur Mandant→Node→VM; Backups als angereicherte CSV + MD; Notizen enthalten. - `git` im Backend-Image vorhanden; `py_compile` grün; keine Secrets im Code/Log. - `Dokumentation`-Repo ist output-only. ## Hinweis `cpu_temperature` bleibt leer, bis #14 (Temperatur-Anreicherung im Rust-Agent) gefixt ist — kein Blocker für dieses Issue. --- ## Erweiterung (Feedback): mehr VM-Infos in der VM-Sektion `_vm_md` (`server/services/docgen.py:204`) um vier Blöcke erweitern. Drei sind direkt aus der DB lesbar, einer braucht eine kleine Agent-Erweiterung. ### Datenquellen (verifiziert) 1. **Belegter Speicher** — `node.last_data["vm_scans"][str(vmid)]["disk"]` (Gast-Scan, used/total je Mount). `_vm_md` zeigt aktuell nur `maxdisk` (Allokation); zusätzlich „Belegt" rendern. 2. **Offene Ports** — Modell `VMPortSnapshot` (`vm_port_snapshots`): neuester Eintrag je (`node_name`,`vmid`) (`order_by scanned_at desc`), `scan_data` = Liste `{port, protocol, process, exposure}`. Als Liste/Tabelle. 3. **Offene CVEs** — Modell `VMCveReport` (`vm_cve_reports`), `status=="open"` je (`node_name`,`vmid`): `cve_id`, `package_name`, `severity`, `fixed_version`. Plus Summary aus `VMCveScan` (`findings_count`, `severities`). Top-N + Gesamtzahl je Severity. 4. **Laufende Docker + Pfad** — Container aus `vm_scans[str(vmid)]["docker"]` (name/image/status) → **DB-lesbar**. **Compose-Pfad fehlt**: `collect_docker` (`VM-Guest-Agent/src/collect/linux.rs:194`, analog FreeBSD + Windows `collect.rs`) erfasst per `docker ps` nur name/image/status/ports. Für den Pfad das Compose-Label mitnehmen, z. B. `docker ps --format` um `{{.Label "com.docker.compose.project.working_dir"}}` erweitern (oder `docker inspect`). → **Agent-Änderung + Version-Bump**; bis dahin Docker ohne Pfad rendern. ### docgen-Änderungen - `_fetch()` (Z. 102): zusätzlich neuesten `VMPortSnapshot` + offene `VMCveReport`/letzten `VMCveScan` je (node, vmid) laden und in den Daten-Baum hängen (analog `note_map`). - `_vm_md()` (Z. 204): nach der Feld-Tabelle vier Abschnitte ergänzen — „## Belegter Speicher", „## Offene Ports", „## Offene CVEs", „## Docker" — jeweils leer-tolerant („— noch kein Scan/keine Daten"). - Importe (Z. 26): `VMPortSnapshot, VMCveReport, VMCveScan`. ### Hinweis Ports/CVEs erscheinen nur, wenn Scans gelaufen sind (Port-Scan manuell/geplant; CVE via Scheduler `_cve_scan_tick`). Bei fehlendem Scan „— noch kein Scan" ausgeben. Branch: `feat/docgen-vm-details` (auf `feat/docgen` aufsetzen).
chinux reopened this issue 2026-06-01 21:31:37 +00:00
Author
Owner

Brauch mehr Infos der VM's:

  • offne Ports
  • offne CVE's
  • Belegter Speicher
  • laufen Docker + Pfad
Brauch mehr Infos der VM's: - offne Ports - offne CVE's - Belegter Speicher - laufen Docker + Pfad
Author
Owner

Hinweis: Der Block "Offene CVEs" aus der VM-Sektion-Erweiterung entfaellt — CVE wird per #45 komplett entfernt. Es bleiben drei Felder: Belegter Speicher, Offene Ports, Docker (+ Pfad via #31).

Hinweis: Der Block "Offene CVEs" aus der VM-Sektion-Erweiterung entfaellt — CVE wird per #45 komplett entfernt. Es bleiben drei Felder: Belegter Speicher, Offene Ports, Docker (+ Pfad via #31).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chinux/theProx#17
No description provided.