Eine VM aus dem ProxDeploy-Template ausrollen, vollständig per API: Klonen, Hardware, cloud-init, Start, Guest-Agent und Provisionierung der Profile über den Agent – ohne SSH. Der Fortschritt kommt aus der Logdatei im Gast, je Profil eine Marke. Der Dry-Run läuft durch dieselben Phasen mit einem Trocken-Client und zeigt jeden geplanten Proxmox-Aufruf und den passenden CLI-Befehl. Der Assistent hat 9 Schritte, den Zustand in der URL und bietet an, ein fehlendes Template im selben Auftrag zu bauen. Auf pve-demo abgenommen: pd-test01 (base, docker) per API, pd-test02 (base, zabbix-agent) über den Assistenten, beide per SSH geprüft. Dabei gefunden: file-write scheitert an Umlauten – Skripte gehen jetzt base64-kodiert hinüber. Closes #008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
90 lines
3.4 KiB
TypeScript
90 lines
3.4 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import { POST as ausrollenPost } from "@/app/api/v1/auftraege/route";
|
|
import { verschluesseln } from "@/lib/geheimnisse";
|
|
import { cliBefehl, AusrollAnfrage } from "@/lib/schemas/ausrollen";
|
|
import { katalogSynchronisieren } from "@/server/services/katalog";
|
|
import { datenbankLeeren, datenbankVerfuegbar, testPrisma } from "./helpers/db";
|
|
import { angemeldet, anfrage } from "./helpers/anfragen";
|
|
|
|
const SCHLUESSEL =
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFTdkCuqQ6mF7I8QzmkNaQpKj7S/I2+yuxWeYasJjLd florian@test";
|
|
const gueltig = {
|
|
typ: "vm",
|
|
server: "rz1",
|
|
distribution: "debian-13",
|
|
name: "web01",
|
|
storage: "local-zfs",
|
|
netz: { bridge: "vmbr0" },
|
|
zugang: { benutzer: "florian", sshSchluessel: [SCHLUESSEL] },
|
|
profile: ["docker"],
|
|
};
|
|
|
|
describe("CLI-Befehl aus der Anfrage", () => {
|
|
it("nennt nur Abweichungen vom Standard und entspricht der Vorgabe", () => {
|
|
const a = AusrollAnfrage.parse({
|
|
...gueltig,
|
|
profile: ["base", "docker"],
|
|
netz: { bridge: "vmbr0", vlan: 20, modus: "statisch", ip: "10.0.20.15/24", gateway: "10.0.20.1" },
|
|
cores: 2,
|
|
speicherMb: 4096,
|
|
diskGb: 40,
|
|
});
|
|
expect(cliBefehl(a)).toBe(
|
|
"proxdeploy vm web01 --server rz1 --distro debian-13 --profile base,docker --ip 10.0.20.15/24 --gw 10.0.20.1 --vlan 20 --memory 4096 --disk 40G --storage local-zfs --user florian",
|
|
);
|
|
});
|
|
|
|
it("quotet Variablenwerte mit Leerzeichen", () => {
|
|
const a = AusrollAnfrage.parse({ ...gueltig, variablen: { "zabbix-agent": { server: "a b" } } });
|
|
expect(cliBefehl(a)).toContain("--var zabbix-agent.server='a b'");
|
|
});
|
|
});
|
|
|
|
describe.runIf(datenbankVerfuegbar)("POST /api/v1/auftraege", () => {
|
|
let cookie: string;
|
|
beforeEach(async () => {
|
|
await datenbankLeeren();
|
|
await katalogSynchronisieren();
|
|
cookie = (await angemeldet("OPERATOR")).cookie;
|
|
await testPrisma.server.create({
|
|
data: {
|
|
name: "rz1",
|
|
titel: "RZ 1",
|
|
url: "https://127.0.0.1:8006",
|
|
tokenId: "a@pve!b",
|
|
tokenGeheimnis: verschluesseln("x"),
|
|
fingerabdruck: "AA",
|
|
},
|
|
});
|
|
});
|
|
|
|
const senden = async (rumpf: unknown) => {
|
|
const antwort = await ausrollenPost(anfrage("POST", "/api/v1/auftraege", cookie, rumpf));
|
|
return { status: antwort.status, inhalt: await antwort.json() };
|
|
};
|
|
|
|
it("meldet Feldfehler einzeln: Name, Schlüssel, root", async () => {
|
|
const { status, inhalt } = await senden({
|
|
...gueltig,
|
|
name: "Web_01",
|
|
zugang: { benutzer: "root", sshSchluessel: ["kein schlüssel"] },
|
|
});
|
|
expect(status).toBe(400);
|
|
expect(Object.keys(inhalt.fehler.felder)).toEqual(
|
|
expect.arrayContaining(["name", "zugang.benutzer", "zugang.sshSchluessel.0"]),
|
|
);
|
|
});
|
|
|
|
it("fehlende Profil-Variable landet am richtigen Feld", async () => {
|
|
const { status, inhalt } = await senden({ ...gueltig, profile: ["zabbix-agent"] });
|
|
expect(status).toBe(400);
|
|
expect(inhalt.fehler.felder).toEqual({ "variablen.zabbix-agent.server": "Zabbix-Server fehlt." });
|
|
});
|
|
|
|
it("deaktivierte Distribution und unbekannter Server werden abgewiesen", async () => {
|
|
await testPrisma.distribution.update({ where: { id: "debian-13" }, data: { aktiv: false } });
|
|
expect((await senden(gueltig)).status).toBe(400);
|
|
expect((await senden({ ...gueltig, server: "gibtsnicht" })).status).toBe(404);
|
|
});
|
|
});
|