Merge branch 'phase/023-feldtest-pbs'
This commit is contained in:
@@ -17,6 +17,16 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
|||||||
|
|
||||||
### Sicherheit
|
### Sicherheit
|
||||||
|
|
||||||
|
## [0.14.1] – 2026-09-18
|
||||||
|
|
||||||
|
### Behoben
|
||||||
|
- Auf Proxmox Backup Server las der Agent **keine einzige Angabe** aus: `proxmox-backup-manager subscription get` gibt eine Rahmentabelle aus, keine `feld: wert`-Zeilen. Jetzt wird für PBS `--output-format json` genutzt, und die Tabelle wird als Rückfall ausgewertet (#023)
|
||||||
|
- Die PBS-Version enthielt die laufende Fassung ein zweites Mal (#023)
|
||||||
|
- Der Agent meldete eine „neue Version“, auch wenn die installierte neuer war als die des Dashboards (#023)
|
||||||
|
|
||||||
|
### Geändert
|
||||||
|
- Agent-Version 0.2.1; die Tests prüfen die Versionsangabe jetzt gegen die Konstante des Dashboards statt gegen eine abgeschriebene Zahl (#023)
|
||||||
|
|
||||||
## [0.14.0] – 2026-09-18
|
## [0.14.0] – 2026-09-18
|
||||||
|
|
||||||
### Hinzugefügt
|
### Hinzugefügt
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Zeitübersicht
|
## Zeitübersicht
|
||||||
|
|
||||||
**Gesamt:** 9 h 08 min
|
**Gesamt:** 9 h 43 min
|
||||||
|
|
||||||
| Issue | Zeit |
|
| Issue | Zeit |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
| #021 Geheimnisse verschlüsseln | 0 h 20 min |
|
| #021 Geheimnisse verschlüsseln | 0 h 20 min |
|
||||||
| #018 Feldtest auf echten Hosts | 0 h 40 min |
|
| #018 Feldtest auf echten Hosts | 0 h 40 min |
|
||||||
| #022 Cluster-Abgleich | 0 h 25 min |
|
| #022 Cluster-Abgleich | 0 h 25 min |
|
||||||
|
| #023 Feldtest PBS | 0 h 35 min |
|
||||||
|
|
||||||
| Meilenstein | Zeit |
|
| Meilenstein | Zeit |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
|
|
||||||
## 2026-09-17 · Sitzung 1 · 19:36–laufend
|
## 2026-09-17 · Sitzung 1 · 19:36–laufend
|
||||||
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
|
**Issue:** #001–#007 (Meilensteine v0.1.0 bis v0.4.0)
|
||||||
**Version:** 0.14.0
|
**Version:** 0.14.1
|
||||||
|
|
||||||
### Erledigt
|
### Erledigt
|
||||||
- Auftrag gelesen, Rückfragen gestellt
|
- Auftrag gelesen, Rückfragen gestellt
|
||||||
@@ -133,6 +134,10 @@
|
|||||||
- #022 abgeschlossen: Cluster-Abgleich – jeder Agent meldet die Mitglieder, das Dashboard warnt bei Knoten ohne Agent
|
- #022 abgeschlossen: Cluster-Abgleich – jeder Agent meldet die Mitglieder, das Dashboard warnt bei Knoten ohne Agent
|
||||||
- **Fehler im eigenen Werkzeug gefunden:** Alle Handbuch-Bilder waren in Wahrheit die Anmeldeseite. Firefox verwirft eine selbst angelegte Cookie-Datei stillschweigend. Jetzt läuft ein lokaler Vermittler mit, und das Skript bricht ab, wenn alle Aufnahmen gleich groß sind.
|
- **Fehler im eigenen Werkzeug gefunden:** Alle Handbuch-Bilder waren in Wahrheit die Anmeldeseite. Firefox verwirft eine selbst angelegte Cookie-Datei stillschweigend. Jetzt läuft ein lokaler Vermittler mit, und das Skript bricht ab, wenn alle Aufnahmen gleich groß sind.
|
||||||
|
|
||||||
|
- Feldtest auf einem echten Proxmox Backup Server (#023): der Agent hätte dort **nichts** gelesen – PBS gibt eine Rahmentabelle aus, kein `feld: wert`. Behoben, mit den echten Ausgaben als Testfälle
|
||||||
|
- Der erfundene PBS-Testfall hatte den Fehler verdeckt. Lehre: ausgedachte Testdaten bestätigen nur die eigene Annahme
|
||||||
|
- Uninstall zum ersten Mal auf einem echten Host geprüft – restlos sauber, damit ist #018 vollständig
|
||||||
|
|
||||||
### Nächster Schritt
|
### Nächster Schritt
|
||||||
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline
|
- #016 Benutzerhandbuch mit Screenshots, danach #017 Favicons und #019 CI-Pipeline
|
||||||
- Für 1.0.0 fehlen noch: Feldtest auf PBS und PMG, Uninstall auf einem echten Host
|
- Für 1.0.0 fehlt noch: PMG (kein Host verfügbar) und der Fall „aktive Subscription auf PBS“ (#023)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
AGENT_VERSION="0.2.0"
|
AGENT_VERSION="0.2.1"
|
||||||
CONFIG_DATEI="${PROXLEDGER_CONFIG:-/etc/proxledger/agent.conf}"
|
CONFIG_DATEI="${PROXLEDGER_CONFIG:-/etc/proxledger/agent.conf}"
|
||||||
SPOOL_VERZEICHNIS="${PROXLEDGER_SPOOL:-/var/lib/proxledger/spool}"
|
SPOOL_VERZEICHNIS="${PROXLEDGER_SPOOL:-/var/lib/proxledger/spool}"
|
||||||
SPOOL_MAXIMUM=30
|
SPOOL_MAXIMUM=30
|
||||||
@@ -106,15 +106,24 @@ produkt_erkennen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
subscription_ausgabe() {
|
subscription_ausgabe() {
|
||||||
|
local ausgabe=""
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
# PVE kennt --output-format nicht (geprueft auf 9.2), liefert aber "feld: wert".
|
||||||
pve) pvesubscription get 2>/dev/null ;;
|
pve) pvesubscription get 2>/dev/null ;;
|
||||||
pbs) proxmox-backup-manager subscription get 2>/dev/null ;;
|
# PBS gibt ohne --output-format eine Rahmentabelle aus, aus der sich schlecht lesen laesst.
|
||||||
|
# JSON kann es (geprueft auf 4.2); aeltere Fassungen faengt die Tabellenauswertung ab.
|
||||||
|
pbs)
|
||||||
|
ausgabe=$(proxmox-backup-manager subscription get --output-format json 2>/dev/null)
|
||||||
|
[ -n "$ausgabe" ] || ausgabe=$(proxmox-backup-manager subscription get 2>/dev/null)
|
||||||
|
printf '%s' "$ausgabe"
|
||||||
|
;;
|
||||||
pmg) pmgsubscription get 2>/dev/null ;;
|
pmg) pmgsubscription get 2>/dev/null ;;
|
||||||
*) printf '' ;;
|
*) printf '' ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Liest ein Feld aus der Subscription-Ausgabe. Unterstützt "feld: wert" und JSON.
|
# Liest ein Feld aus der Subscription-Ausgabe. Unterstuetzt "feld: wert", JSON und die
|
||||||
|
# Rahmentabelle von PBS ("| feld | wert |" mit Unicode-Strichen).
|
||||||
feld_lesen() {
|
feld_lesen() {
|
||||||
local feld="$1" text="$2" wert
|
local feld="$1" text="$2" wert
|
||||||
wert=$(printf '%s\n' "$text" | sed -n "s/^[[:space:]]*${feld}[[:space:]]*:[[:space:]]*//p" | head -n1)
|
wert=$(printf '%s\n' "$text" | sed -n "s/^[[:space:]]*${feld}[[:space:]]*:[[:space:]]*//p" | head -n1)
|
||||||
@@ -122,6 +131,15 @@ feld_lesen() {
|
|||||||
wert=$(printf '%s\n' "$text" |
|
wert=$(printf '%s\n' "$text" |
|
||||||
sed -n "s/.*\"${feld}\"[[:space:]]*:[[:space:]]*\"\{0,1\}\([^\",}]*\)\"\{0,1\}.*/\1/p" | head -n1)
|
sed -n "s/.*\"${feld}\"[[:space:]]*:[[:space:]]*\"\{0,1\}\([^\",}]*\)\"\{0,1\}.*/\1/p" | head -n1)
|
||||||
fi
|
fi
|
||||||
|
if [ -z "$wert" ]; then
|
||||||
|
# Tabellenzeile: Trennzeichen ist U+2502; awk zerlegt daran und liefert die zweite Spalte.
|
||||||
|
wert=$(printf '%s\n' "$text" |
|
||||||
|
awk -F'\xe2\x94\x82' -v feld="$feld" '
|
||||||
|
NF >= 3 {
|
||||||
|
name = $2; gsub(/^[ \t]+|[ \t]+$/, "", name)
|
||||||
|
if (name == feld) { wert = $3; gsub(/^[ \t]+|[ \t]+$/, "", wert); print wert; exit }
|
||||||
|
}')
|
||||||
|
fi
|
||||||
# Umschließende Anführungszeichen und Leerzeichen entfernen.
|
# Umschließende Anführungszeichen und Leerzeichen entfernen.
|
||||||
wert=${wert%\"}
|
wert=${wert%\"}
|
||||||
wert=${wert#\"}
|
wert=${wert#\"}
|
||||||
@@ -133,7 +151,9 @@ produkt_version() {
|
|||||||
# Der Kernel wird separat gemeldet, deshalb hier abschneiden.
|
# Der Kernel wird separat gemeldet, deshalb hier abschneiden.
|
||||||
case "$1" in
|
case "$1" in
|
||||||
pve) pveversion 2>/dev/null | head -n1 | sed 's/ (running kernel.*//' ;;
|
pve) pveversion 2>/dev/null | head -n1 | sed 's/ (running kernel.*//' ;;
|
||||||
pbs) proxmox-backup-manager version 2>/dev/null | head -n1 ;;
|
# PBS haengt die laufende Fassung an ("… 4.2.6-1 running version: 4.2.1");
|
||||||
|
# gemeldet wird die installierte.
|
||||||
|
pbs) proxmox-backup-manager version 2>/dev/null | head -n1 | sed 's/ running version.*//' ;;
|
||||||
pmg) pmgversion 2>/dev/null | head -n1 ;;
|
pmg) pmgversion 2>/dev/null | head -n1 ;;
|
||||||
*) printf '' ;;
|
*) printf '' ;;
|
||||||
esac
|
esac
|
||||||
@@ -395,8 +415,15 @@ aktion_test() {
|
|||||||
[ "$(printf '%s' "$antwort" | tail -n1)" = "200" ]
|
[ "$(printf '%s' "$antwort" | tail -n1)" = "200" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ist $1 eine neuere Fassung als $2? `sort -V` vergleicht Versionsnummern der Reihe nach.
|
||||||
|
version_neuer() {
|
||||||
|
[ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
|
||||||
|
}
|
||||||
|
|
||||||
version_pruefen() {
|
version_pruefen() {
|
||||||
if [ -n "${NEUESTE_VERSION:-}" ] && [ "$NEUESTE_VERSION" != "$AGENT_VERSION" ]; then
|
# Nur melden, wenn das Dashboard wirklich eine neuere Fassung kennt. Sonst warnt ein Agent,
|
||||||
|
# der einer Testinstallation vorauseilt, gegen sich selbst (im Feldtest #023 aufgefallen).
|
||||||
|
if [ -n "${NEUESTE_VERSION:-}" ] && version_neuer "$NEUESTE_VERSION" "$AGENT_VERSION"; then
|
||||||
protokoll notice "Neue Agent-Version verfügbar: ${NEUESTE_VERSION} (installiert: ${AGENT_VERSION})."
|
protokoll notice "Neue Agent-Version verfügbar: ${NEUESTE_VERSION} (installiert: ${AGENT_VERSION})."
|
||||||
if [ "$AUTO_UPDATE" = "yes" ]; then
|
if [ "$AUTO_UPDATE" = "yes" ]; then
|
||||||
aktion_update
|
aktion_update
|
||||||
|
|||||||
@@ -113,6 +113,12 @@ Der Installer erkennt selbst, ob es sich um Proxmox VE, Backup Server oder Mail
|
|||||||
registriert den Host, legt die Konfiguration unter `/etc/proxledger/agent.conf` (Rechte 600) ab,
|
registriert den Host, legt die Konfiguration unter `/etc/proxledger/agent.conf` (Rechte 600) ab,
|
||||||
richtet einen systemd-Timer ein und schickt sofort den ersten Report.
|
richtet einen systemd-Timer ein und schickt sofort den ersten Report.
|
||||||
|
|
||||||
|
> **Stand der Erprobung:** Proxmox VE (9.2, mit und ohne Subscription, einzeln und im Cluster) und
|
||||||
|
> Proxmox Backup Server (4.2, ohne Subscription) sind auf echten Hosts geprüft. Für **Mail Gateway**
|
||||||
|
> stand bisher kein Host zur Verfügung – dort beruht die Auswertung noch auf Annahmen, und bei PBS hat
|
||||||
|
> sich genau so eine Annahme als falsch erwiesen. Bitte den ersten PMG-Host nach der Installation
|
||||||
|
> kurz gegenprüfen (`proxledger-agent --dry-run` zeigt, was gemeldet würde).
|
||||||
|
|
||||||
Nützliche Befehle auf dem Host:
|
Nützliche Befehle auf dem Host:
|
||||||
|
|
||||||
| Befehl | Zweck |
|
| Befehl | Zweck |
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ auf echten Hosts laufen.
|
|||||||
- [x] Ausgabeformate von `pvesubscription get`, `proxmox-backup-manager subscription get` und
|
- [x] Ausgabeformate von `pvesubscription get`, `proxmox-backup-manager subscription get` und
|
||||||
`pmgsubscription get` mit den Annahmen im Skript abgleichen
|
`pmgsubscription get` mit den Annahmen im Skript abgleichen
|
||||||
- [x] Verhalten ohne Subscription geprüft (Status `notfound`, alle übrigen Felder fehlen und werden zu null)
|
- [x] Verhalten ohne Subscription geprüft (Status `notfound`, alle übrigen Felder fehlen und werden zu null)
|
||||||
- [x] Timer und Spool-Nachsendung geprüft; Uninstall steht noch aus (Agents laufen vorerst weiter)
|
- [x] Timer, Spool-Nachsendung und Uninstall geprüft (Uninstall am 18.09.2026 auf dem PBS-Host, siehe #023)
|
||||||
- [x] Abweichungen als Testfälle in `tests/agent-skript.test.ts` übernehmen
|
- [x] Abweichungen als Testfälle in `tests/agent-skript.test.ts` übernehmen
|
||||||
|
|
||||||
## Akzeptanzkriterien
|
## Akzeptanzkriterien
|
||||||
@@ -60,4 +60,4 @@ funktioniert (Report gepuffert bei unerreichbarem Dashboard, beim nächsten Lauf
|
|||||||
6. **Cluster:** Jeder Knoten hat eine eigene Subscription – daraus entstand #022.
|
6. **Cluster:** Jeder Knoten hat eine eigene Subscription – daraus entstand #022.
|
||||||
|
|
||||||
**Noch offen:** PBS und PMG – dafür ist #023 angelegt. PBS-Hosts stellt Florian bereit, allerdings nur
|
**Noch offen:** PBS und PMG – dafür ist #023 angelegt. PBS-Hosts stellt Florian bereit, allerdings nur
|
||||||
unlizenziert; für PMG gibt es derzeit keinen Host. Ebenfalls offen: ein echter Uninstall-Durchlauf.
|
unlizenziert; für PMG gibt es derzeit keinen Host. Der Uninstall-Durchlauf ist inzwischen erledigt (#023).
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
**Status:** offen
|
**Status:** offen
|
||||||
**Meilenstein:** v1.0.0
|
**Meilenstein:** v1.0.0
|
||||||
**Labels:** agent, feldtest
|
**Labels:** agent, feldtest
|
||||||
**Geschätzt:** 2 h **Tatsächlich:** –
|
**Geschätzt:** 2 h **Tatsächlich:** 0 h 35 min (PBS erledigt, PMG offen)
|
||||||
|
|
||||||
## Ziel
|
## Ziel
|
||||||
Der Feldtest in #018 lief auf zwei Proxmox-VE-Hosts. Für Backup Server und Mail Gateway beruht die
|
Der Feldtest in #018 lief auf zwei Proxmox-VE-Hosts. Für Backup Server und Mail Gateway beruht die
|
||||||
@@ -16,15 +16,54 @@ falsch erwiesen (`--output-format json` gibt es dort nicht). Das gehört vor 1.0
|
|||||||
- **PMG:** derzeit kein Host verfügbar. Der Zweig bleibt ungeprüft; das ist im Handbuch zu vermerken.
|
- **PMG:** derzeit kein Host verfügbar. Der Zweig bleibt ungeprüft; das ist im Handbuch zu vermerken.
|
||||||
|
|
||||||
## Aufgaben
|
## Aufgaben
|
||||||
- [ ] `scripts/feldtest-erheben.sh` auf einem PBS-Host laufen lassen (liest nur, ändert nichts)
|
- [x] `scripts/feldtest-erheben.sh` auf einem PBS-Host laufen lassen (liest nur, ändert nichts)
|
||||||
- [ ] Prüfen, ob `proxmox-backup-manager subscription get` Text oder JSON liefert und welche Felder
|
- [x] Prüfen, ob `proxmox-backup-manager subscription get` Text oder JSON liefert und welche Felder
|
||||||
ohne Subscription überhaupt erscheinen
|
ohne Subscription überhaupt erscheinen
|
||||||
- [ ] Ausgabe von `proxmox-backup-manager version` gegen `produkt_version()` prüfen
|
- [x] Ausgabe von `proxmox-backup-manager version` gegen `produkt_version()` prüfen
|
||||||
- [ ] Erhobene Ausgaben als Testfälle in `tests/agent-skript.test.ts` aufnehmen – der heutige
|
- [x] Erhobene Ausgaben als Testfälle in `tests/agent-skript.test.ts` aufnehmen – der heutige
|
||||||
PBS-Testfall ist erfunden (JSON) und damit womöglich am echten Verhalten vorbei
|
PBS-Testfall ist erfunden (JSON) und damit womöglich am echten Verhalten vorbei
|
||||||
- [ ] Agent auf einem PBS-Host installieren, einen Report abwarten, wieder deinstallieren
|
- [x] Agent auf einem PBS-Host installieren, einen Report abwarten, wieder deinstallieren
|
||||||
- [ ] PMG offen lassen und die Lücke im Handbuch benennen
|
- [ ] PMG offen lassen und die Lücke im Handbuch benennen
|
||||||
|
|
||||||
## Notizen
|
## Notizen
|
||||||
Der Cluster-Abgleich aus #022 betrifft nur PVE: PBS und PMG kennen kein `pvecm`, dort bleibt die
|
Der Cluster-Abgleich aus #022 betrifft nur PVE: PBS und PMG kennen kein `pvecm`, dort bleibt die
|
||||||
Mitgliederliste leer.
|
Mitgliederliste leer.
|
||||||
|
|
||||||
|
## Ergebnis (18.09.2026, `bup-ste-pbs-01`, PBS 4.2 auf Debian 13, ohne Subscription)
|
||||||
|
|
||||||
|
**Ein echter Fehler gefunden – und er war kein kleiner.** `proxmox-backup-manager subscription get`
|
||||||
|
gibt ohne weitere Angabe eine **Rahmentabelle** aus:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────┬────────────────────────────────┐
|
||||||
|
│ Name │ Value │
|
||||||
|
╞══════════╪════════════════════════════════╡
|
||||||
|
│ status │ notfound │
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Agent suchte nach `feld: wert` oder JSON – beides passt nicht. Auf einem echten PBS hätte er
|
||||||
|
**alle Felder als null gemeldet, nicht einmal die Server-ID**. Der erfundene Testfall hatte genau das
|
||||||
|
verdeckt, weil er JSON unterstellte.
|
||||||
|
|
||||||
|
Behoben in drei Schritten:
|
||||||
|
|
||||||
|
1. Für PBS wird `--output-format json` verwendet. Anders als PVE **kann** PBS das (auf 4.2 geprüft).
|
||||||
|
2. Bleibt die Ausgabe leer, wird die Textform genommen und die Rahmentabelle ausgewertet
|
||||||
|
(`awk -F'│'`) – für Fassungen, die das JSON-Format nicht kennen.
|
||||||
|
3. `proxmox-backup-manager version` liefert „proxmox-backup-server 4.2.6-1 running version: 4.2.1“;
|
||||||
|
gemeldet wird jetzt die installierte Fassung ohne den Zusatz.
|
||||||
|
|
||||||
|
Beide Formen sind als Testfälle hinterlegt, mit den echten Ausgaben des Hosts.
|
||||||
|
|
||||||
|
**Nebenbefund:** Der Agent meldete „Neue Agent-Version verfügbar: 0.2.0 (installiert: 0.2.1)“ – er
|
||||||
|
verglich nur auf Ungleichheit. Jetzt wird mit `sort -V` geprüft, ob die Fassung wirklich neuer ist.
|
||||||
|
|
||||||
|
**Ende-zu-Ende geprüft:** Installation → Registrierung → erster Report → Warnungen. Im Dashboard kamen
|
||||||
|
an: Produkt `PBS`, Version `proxmox-backup-server 4.2.6-1`, Server-ID `69AED6…`, 1 Sockel, 106
|
||||||
|
ausstehende Pakete, leere Cluster-Liste (PBS kennt kein `pvecm`), Warnungen „Keine Subscription
|
||||||
|
gefunden“ und „Host ist keinem Kunden zugewiesen“. Anschließend `--uninstall`: Timer, Dienst,
|
||||||
|
`/usr/local/bin/proxledger-agent`, `/etc/proxledger` und `/var/lib/proxledger` restlos entfernt. Damit
|
||||||
|
ist auch der letzte offene Punkt aus #018 erledigt.
|
||||||
|
|
||||||
|
**Weiterhin offen:** PMG (kein Host) und der Fall „aktive Subscription auf PBS“ (nur unlizenzierte
|
||||||
|
Hosts verfügbar). Dieses Issue bleibt deshalb offen.
|
||||||
|
|||||||
@@ -26,5 +26,5 @@ Details und Architektur: [../architektur.md](../architektur.md). Zeiten werden a
|
|||||||
| [#020](020-gitea-issue-abgleich.md) | Issues nach Gitea übertragen | erledigt | v0.4.1 | 2 h | 0 h 10 min |
|
| [#020](020-gitea-issue-abgleich.md) | Issues nach Gitea übertragen | erledigt | v0.4.1 | 2 h | 0 h 10 min |
|
||||||
| [#021](021-geheimnisse-verschluesseln.md) | Zugangsdaten verschlüsselt speichern | erledigt | v0.13.1 | 2 h | 0 h 20 min |
|
| [#021](021-geheimnisse-verschluesseln.md) | Zugangsdaten verschlüsselt speichern | erledigt | v0.13.1 | 2 h | 0 h 20 min |
|
||||||
| [#022](022-cluster-abgleich.md) | Cluster-Abgleich | erledigt | v0.14.0 | 3 h | 0 h 25 min |
|
| [#022](022-cluster-abgleich.md) | Cluster-Abgleich | erledigt | v0.14.0 | 3 h | 0 h 25 min |
|
||||||
| [#023](023-feldtest-pbs-pmg.md) | Feldtest auf PBS und PMG | offen | v1.0.0 | 2 h | – |
|
| [#023](023-feldtest-pbs-pmg.md) | Feldtest auf PBS und PMG | offen | v1.0.0 | 2 h | 0 h 35 min (PBS erledigt, PMG offen) |
|
||||||
| | **Summe** | | | **121 h** | **9 h 08 min** |
|
| | **Summe** | | | **121 h** | **9 h 43 min** |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "proxledger",
|
"name": "proxledger",
|
||||||
"version": "0.14.0",
|
"version": "0.14.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { tokenAusHeader } from "@/lib/tokens";
|
|||||||
import { AgentApiFehler } from "./service";
|
import { AgentApiFehler } from "./service";
|
||||||
|
|
||||||
/** Version des Agent-Skripts, die das Dashboard ausliefert (siehe #005). */
|
/** Version des Agent-Skripts, die das Dashboard ausliefert (siehe #005). */
|
||||||
export const AGENT_VERSION = "0.2.0";
|
export const AGENT_VERSION = "0.2.1";
|
||||||
|
|
||||||
export function fehlerAntwort(status: number, code: string, nachricht: string, extra?: HeadersInit) {
|
export function fehlerAntwort(status: number, code: string, nachricht: string, extra?: HeadersInit) {
|
||||||
return Response.json({ ok: false, code, fehler: nachricht }, { status, headers: extra });
|
return Response.json({ ok: false, code, fehler: nachricht }, { status, headers: extra });
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { afterAll, afterEach, beforeEach, describe, expect, it } from "vitest";
|
import { afterAll, afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||||
import { POST as enrollPost } from "@/app/api/agent/v1/enroll/route";
|
import { POST as enrollPost } from "@/app/api/agent/v1/enroll/route";
|
||||||
|
import { AGENT_VERSION } from "@/server/agent/http";
|
||||||
import { POST as reportPost } from "@/app/api/agent/v1/report/route";
|
import { POST as reportPost } from "@/app/api/agent/v1/report/route";
|
||||||
import { agentRateLimit, enrollRateLimit } from "@/lib/ratelimit";
|
import { agentRateLimit, enrollRateLimit } from "@/lib/ratelimit";
|
||||||
import { erzeugeToken } from "@/lib/tokens";
|
import { erzeugeToken } from "@/lib/tokens";
|
||||||
@@ -20,6 +21,36 @@ function befehlErsetzen(name: string, ausgabe: string) {
|
|||||||
chmodSync(datei, 0o755);
|
chmodSync(datei, 0o755);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ahmt `proxmox-backup-manager` nach: Das Werkzeug beantwortet `version` anders als
|
||||||
|
* `subscription get`, und auf `--output-format json` antwortet es anders als ohne.
|
||||||
|
* Genau daran hängt die Auswertung im Agent.
|
||||||
|
*/
|
||||||
|
function pbsErsetzen(antworten: { json: string; tabelle: string; version: string }) {
|
||||||
|
const datei = path.join(stubVerzeichnis, "proxmox-backup-manager");
|
||||||
|
writeFileSync(
|
||||||
|
datei,
|
||||||
|
[
|
||||||
|
"#!/usr/bin/env bash",
|
||||||
|
'if [ "$1" = "version" ]; then',
|
||||||
|
"cat <<'VERSION'",
|
||||||
|
antworten.version,
|
||||||
|
"VERSION",
|
||||||
|
'elif [[ "$*" == *--output-format*json* ]]; then',
|
||||||
|
"cat <<'JSON'",
|
||||||
|
antworten.json,
|
||||||
|
"JSON",
|
||||||
|
"else",
|
||||||
|
"cat <<'TEXT'",
|
||||||
|
antworten.tabelle,
|
||||||
|
"TEXT",
|
||||||
|
"fi",
|
||||||
|
"",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
chmodSync(datei, 0o755);
|
||||||
|
}
|
||||||
|
|
||||||
/** Führt den Agent mit den vorbereiteten Befehlen aus und liefert den Report. */
|
/** Führt den Agent mit den vorbereiteten Befehlen aus und liefert den Report. */
|
||||||
function reportErzeugen(): Record<string, never> | Record<string, unknown> {
|
function reportErzeugen(): Record<string, never> | Record<string, unknown> {
|
||||||
const ausgabe = execFileSync("bash", [AGENT, "--dry-run"], {
|
const ausgabe = execFileSync("bash", [AGENT, "--dry-run"], {
|
||||||
@@ -43,6 +74,23 @@ nextduedate: 2026-09-24
|
|||||||
sockets: 1
|
sockets: 1
|
||||||
level: c`;
|
level: c`;
|
||||||
|
|
||||||
|
// Echte Ausgaben von einem Proxmox Backup Server 4.2 ohne Subscription (Feldtest #023).
|
||||||
|
const PBS_TABELLE = `┌──────────┬──────────────────────────────────────────────────────────┐
|
||||||
|
│ Name │ Value │
|
||||||
|
╞══════════╪══════════════════════════════════════════════════════════╡
|
||||||
|
│ status │ notfound │
|
||||||
|
├──────────┼──────────────────────────────────────────────────────────┤
|
||||||
|
│ message │ There is no subscription key │
|
||||||
|
├──────────┼──────────────────────────────────────────────────────────┤
|
||||||
|
│ serverid │ 69AED6ABA8A34EBE9AE1075333BBF8FE │
|
||||||
|
├──────────┼──────────────────────────────────────────────────────────┤
|
||||||
|
│ url │ https://www.proxmox.com/en/proxmox-backup-server/pricing │
|
||||||
|
└──────────┴──────────────────────────────────────────────────────────┘`;
|
||||||
|
|
||||||
|
const PBS_VERSION = "proxmox-backup-server 4.2.6-1 running version: 4.2.1";
|
||||||
|
|
||||||
|
const PBS_JSON = `{"message":"There is no subscription key","serverid":"69AED6ABA8A34EBE9AE1075333BBF8FE","status":"notfound","url":"https://www.proxmox.com/en/proxmox-backup-server/pricing"}`;
|
||||||
|
|
||||||
describe("Agent-Skript", () => {
|
describe("Agent-Skript", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stubVerzeichnis = mkdtempSync(path.join(tmpdir(), "proxledger-agent-test-"));
|
stubVerzeichnis = mkdtempSync(path.join(tmpdir(), "proxledger-agent-test-"));
|
||||||
@@ -75,7 +123,7 @@ describe("Agent-Skript", () => {
|
|||||||
host: Record<string, unknown>;
|
host: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(report.agentVersion).toBe("0.2.0");
|
expect(report.agentVersion).toBe(AGENT_VERSION);
|
||||||
expect(report.reportId).toMatch(/.{8,}/);
|
expect(report.reportId).toMatch(/.{8,}/);
|
||||||
expect(report.erhobenAm).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/);
|
expect(report.erhobenAm).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/);
|
||||||
expect(report.produkt).toEqual({ typ: "pve", version: "pve-manager/8.3.2/dc2b2f4e" });
|
expect(report.produkt).toEqual({ typ: "pve", version: "pve-manager/8.3.2/dc2b2f4e" });
|
||||||
@@ -144,6 +192,39 @@ productname: Proxmox "VE" \\ Subscription mit Tab`,
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("liest einen PBS ohne Subscription (echte Ausgaben, JSON bevorzugt)", () => {
|
||||||
|
pbsErsetzen({ json: PBS_JSON, tabelle: PBS_TABELLE, version: PBS_VERSION });
|
||||||
|
|
||||||
|
const report = reportErzeugen() as {
|
||||||
|
produkt: { typ: string };
|
||||||
|
subscription: Record<string, unknown>;
|
||||||
|
host: { clusterMitglieder: string[] };
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(report.produkt.typ).toBe("pbs");
|
||||||
|
expect(report.subscription.status).toBe("notfound");
|
||||||
|
expect(report.subscription.serverid).toBe("69AED6ABA8A34EBE9AE1075333BBF8FE");
|
||||||
|
expect(report.subscription.key).toBeNull();
|
||||||
|
expect(report.subscription.sockets).toBeNull();
|
||||||
|
// Ohne pvecm bleibt die Mitgliederliste leer – PBS kennt keinen Cluster in diesem Sinne.
|
||||||
|
expect(report.host.clusterMitglieder).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("liest die Rahmentabelle, falls ein PBS kein JSON ausgibt", () => {
|
||||||
|
// Ältere Fassungen könnten das JSON-Format nicht kennen; dann bleibt nur die Tabelle.
|
||||||
|
befehlErsetzen("proxmox-backup-manager", PBS_TABELLE);
|
||||||
|
|
||||||
|
const report = reportErzeugen() as { subscription: Record<string, unknown> };
|
||||||
|
expect(report.subscription.status).toBe("notfound");
|
||||||
|
expect(report.subscription.serverid).toBe("69AED6ABA8A34EBE9AE1075333BBF8FE");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("meldet die PBS-Version ohne die laufende Fassung", () => {
|
||||||
|
pbsErsetzen({ json: PBS_JSON, tabelle: PBS_TABELLE, version: PBS_VERSION });
|
||||||
|
const report = reportErzeugen() as { produkt: { version: string } };
|
||||||
|
expect(report.produkt.version).toBe("proxmox-backup-server 4.2.6-1");
|
||||||
|
});
|
||||||
|
|
||||||
it("meldet die Cluster-Mitglieder", () => {
|
it("meldet die Cluster-Mitglieder", () => {
|
||||||
befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION);
|
befehlErsetzen("pvesubscription", PVE_SUBSCRIPTION);
|
||||||
befehlErsetzen(
|
befehlErsetzen(
|
||||||
@@ -169,7 +250,7 @@ productname: Proxmox "VE" \\ Subscription mit Tab`,
|
|||||||
|
|
||||||
it("gibt die Version aus", () => {
|
it("gibt die Version aus", () => {
|
||||||
const ausgabe = execFileSync("bash", [AGENT, "--version"], { encoding: "utf8" }).trim();
|
const ausgabe = execFileSync("bash", [AGENT, "--version"], { encoding: "utf8" }).trim();
|
||||||
expect(ausgabe).toBe("0.2.0");
|
expect(ausgabe).toBe(AGENT_VERSION);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.runIf(datenbankVerfuegbar)("Zusammenspiel mit der Agent-API", () => {
|
describe.runIf(datenbankVerfuegbar)("Zusammenspiel mit der Agent-API", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user