feat(templates): Profile ins Template einbacken
Beim Template-Bau lassen sich Profile wählen (nur solche ohne Pflichtvariablen). Nach dem Vorbereitungsstart laufen sie über den Guest-Agent; danach werden Maschinen-ID, SSH-Host-Keys, Docker-Engine-ID und apt-Cache entfernt. Ausrollen nimmt das Template mit den meisten passenden Profilen und überspringt, was schon eingebacken ist. Auf pve-demo: Provisionierung mit base+docker 141 s ohne, ~30 s mit Template. Dabei gefunden: docker nimmt den Benutzer per guest.user in die Gruppe auf – Profile mit guest.* laufen deshalb beim Deploy noch einmal (idempotent, schnell). Closes #022 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -147,6 +147,7 @@ async function eingabe(client: ProxmoxClient, anfrageTeil: Record<string, unknow
|
||||
anfrage.profile,
|
||||
new Map(katalog.profile.map((p) => [p.eintrag.id, p.eintrag])),
|
||||
"debian",
|
||||
anfrage.variablen,
|
||||
);
|
||||
if (!aufgeloest.ok) throw new Error("Profile");
|
||||
const angelegt: Array<Record<string, unknown>> = [];
|
||||
@@ -292,3 +293,50 @@ describe("VM ausrollen", () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Templates mit eingebackenen Profilen (#022)", () => {
|
||||
async function mitTemplates(templates: Array<{ vmid: number; tags: string }>) {
|
||||
const { mock, client, dateien } = await aufbauen();
|
||||
mock.route("GET", "/cluster/resources", () => ({
|
||||
data: [
|
||||
{ type: "node", node: "pve01", status: "online", maxmem: 64e9, mem: 8e9 },
|
||||
...templates.map((t) => ({ type: "qemu", vmid: t.vmid, node: "pve01", template: 1, tags: t.tags })),
|
||||
],
|
||||
}));
|
||||
mock.route("POST", /^\/nodes\/pve01\/qemu\/\d+\/clone$/, () => ({ data: UPID("qmclone") }));
|
||||
return { mock, client, dateien };
|
||||
}
|
||||
|
||||
it("wählt das Template mit den meisten passenden Profilen, nie eins mit ungewählten", async () => {
|
||||
const { client } = await mitTemplates([
|
||||
{ vmid: 9000, tags: "proxdeploy-template;debian-13" },
|
||||
{ vmid: 9002, tags: "proxdeploy-template;debian-13;profil-base;profil-docker" },
|
||||
{ vmid: 9003, tags: "proxdeploy-template;debian-13;profil-base;profil-docker;profil-nginx" },
|
||||
]);
|
||||
const { e } = await eingabe(client);
|
||||
const stand: VmAusrollStand = {};
|
||||
expect(await phasenAusfuehren(vmAusrollSchritte(e, stand), stumm)).toEqual({ ok: true });
|
||||
expect(stand.template).toEqual({ vmid: 9002, knoten: "pve01", eingebacken: ["base", "docker"] });
|
||||
});
|
||||
|
||||
it("überspringt gastunabhängige eingebackene Profile; docker (nutzt guest.user) läuft noch einmal", async () => {
|
||||
const { client, dateien } = await mitTemplates([
|
||||
{ vmid: 9002, tags: "proxdeploy-template;debian-13;profil-base;profil-docker" },
|
||||
]);
|
||||
const { e } = await eingabe(client);
|
||||
await phasenAusfuehren(vmAusrollSchritte(e), stumm);
|
||||
const skript = [...dateien.values()].join("");
|
||||
expect(skript).not.toContain("::proxdeploy:: profil base");
|
||||
expect(skript).toContain("::proxdeploy:: profil docker");
|
||||
expect(skript).toContain("usermod -aG docker florian");
|
||||
});
|
||||
|
||||
it("weicht eine Variable vom Standard ab, läuft auch ein eingebackenes Profil", async () => {
|
||||
const { client, dateien } = await mitTemplates([
|
||||
{ vmid: 9002, tags: "proxdeploy-template;debian-13;profil-base" },
|
||||
]);
|
||||
const { e } = await eingabe(client, { profile: ["base"], variablen: { base: { zeitzone: "UTC" } } });
|
||||
await phasenAusfuehren(vmAusrollSchritte(e), stumm);
|
||||
expect([...dateien.values()].join("")).toContain("::proxdeploy:: profil base");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user