chore(hosts): Demo-Daten, Screenshots und Issue-Notizen (#008)

SSHKV_SEED_DEMO=1 legt sechs Demo-Hosts, drei Gruppen und einen Kunden an,
damit Entwicklung, Screenshots und Handbuch ohne echte Server auskommen.
Nur mit der Variable, damit eine echte Instanz nie Phantom-Hosts bekommt;
Upsert nach Name haelt den Seed idempotent.

Das Screenshot-Skript kennt jetzt Seiten mit wechselnder ID (folgen: erster
passender Link) und nimmt Hostliste und Hostdetail auf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 09:50:53 +02:00
co-authored by Claude Opus 5.5
parent 90a41dc55d
commit c8a415f1ca
7 changed files with 140 additions and 11 deletions
+81 -1
View File
@@ -5,7 +5,7 @@ import { PASSWORT_MINDESTLAENGE, passwortHashen } from "../src/lib/passwort-hash
import { EINGEBAUTE_VORLAGEN } from "./vorlagen";
/**
* Grundausstattung (#003): Notfall-Admin und eingebaute Vorlagen.
* Grundausstattung (#003): Notfall-Admin und eingebaute Vorlagen; optional Demo-Hosts (#008).
*
* Laeuft bei jedem Start des migrate-Dienstes und ist deshalb idempotent. Ein bestehender
* Notfall-Admin wird nie angefasst – sonst setzte jeder Neustart ein in der Oberflaeche
@@ -45,9 +45,89 @@ async function vorlagen(): Promise<void> {
console.log(`${EINGEBAUTE_VORLAGEN.length} eingebaute Vorlagen geprüft.`);
}
/**
* Demo-Hosts fuer Entwicklung, Screenshots und Handbuch (#008) – nur mit SSHKV_SEED_DEMO=1,
* damit eine echte Instanz nie Phantom-Hosts bekommt. Upsert nach Name: ein zweiter Lauf
* aendert nichts, und in der Oberflaeche geaenderte Demo-Hosts bleiben, wie sie sind.
* Bewusst ohne Protokolleintraege: Seed-Daten sind keine Handlung eines Menschen.
*/
const DEMO_GRUPPEN = [
{ name: "Proxmox", beschreibung: "Virtualisierungs-Cluster im Rechenzentrum" },
{ name: "DMZ", beschreibung: "Von außen erreichbare Systeme" },
{ name: "Kunde X", beschreibung: "Systeme, die wir für Kunde X betreiben" },
] as const;
const DEMO_HOSTS: {
name: string;
adresse: string;
port?: number;
tags: string[];
beschreibung?: string;
anmeldeart?: "DIENSTBENUTZER" | "ROOT";
kunde?: string;
gruppen: string[];
}[] = [
{ name: "srv-pve01", adresse: "10.0.10.11", tags: ["pve", "produktion"], gruppen: ["Proxmox"] },
{ name: "srv-pve02", adresse: "10.0.10.12", tags: ["pve", "produktion"], gruppen: ["Proxmox"] },
{
name: "srv-backup01",
adresse: "10.0.10.30",
tags: ["backup"],
beschreibung: "Proxmox Backup Server, zieht nachts von pve01/pve02",
gruppen: ["Proxmox"],
},
{
name: "srv-app01",
adresse: "app01.kunde-x.example",
port: 2222,
tags: ["web"],
kunde: "Kunde X",
gruppen: ["Kunde X"],
},
{
name: "fw-edge01",
adresse: "192.168.1.1",
tags: ["firewall"],
anmeldeart: "ROOT",
beschreibung: "Appliance ohne sudo – Anmeldung direkt als root",
gruppen: ["DMZ"],
},
{ name: "srv-rz-claude-linux", adresse: "fd00:10::42", tags: ["test"], gruppen: [] },
];
async function demoDaten(): Promise<void> {
if (process.env["SSHKV_SEED_DEMO"] !== "1") return;
const gruppen = new Map<string, string>();
for (const g of DEMO_GRUPPEN) {
const gruppe = await prisma.hostgruppe.upsert({ where: { name: g.name }, create: g, update: {} });
gruppen.set(g.name, gruppe.id);
}
for (const h of DEMO_HOSTS) {
const kunde = h.kunde
? await prisma.kunde.upsert({ where: { name: h.kunde }, create: { name: h.kunde }, update: {} })
: null;
await prisma.host.upsert({
where: { name: h.name },
update: {},
create: {
name: h.name,
adresse: h.adresse,
port: h.port ?? 22,
tags: h.tags,
beschreibung: h.beschreibung ?? null,
anmeldeart: h.anmeldeart ?? "DIENSTBENUTZER",
kundeId: kunde?.id ?? null,
gruppen: { create: h.gruppen.map((name) => ({ hostgruppeId: gruppen.get(name) ?? "" })) },
},
});
}
console.log(`Demo-Daten geprüft: ${DEMO_HOSTS.length} Hosts, ${DEMO_GRUPPEN.length} Gruppen.`);
}
try {
await notfallAdmin();
await vorlagen();
await demoDaten();
} finally {
await prisma.$disconnect();
}