feat: move proxmox discovery/import/sync into a first-party plugin

This commit is contained in:
LukeGus committed 2026-09-21 19:20:17 -05:00
1 parent 9db66d5780
commit d440ce9073
21 files changed
+290 -36

No files matched your search

@@ -1,58 +0,0 @@
import { describe, expect, it } from "vitest";
import { resolveProxmoxImportAuth } from "../../../database/routes/proxmox-import-auth.js";
// The frontend carries its own copy of this decision in
// src/ui/components/proxmox/proxmox-import-auth.ts. The two drifting apart is
// what produced the reported bug, so both are held to the same matrix.
describe("resolveProxmoxImportAuth", () => {
it("uses the default credential for key auth when one is configured", () => {
expect(resolveProxmoxImportAuth("key", 7)).toEqual({
authType: "credential",
credentialId: 7,
overrideCredentialUsername: 0,
});
});
it("uses the default credential for password auth when one is configured", () => {
expect(resolveProxmoxImportAuth("password", 7)).toEqual({
authType: "credential",
credentialId: 7,
overrideCredentialUsername: 0,
});
});
it("falls back to none when a secret-backed default has no credential", () => {
for (const authType of ["password", "key", "credential"]) {
expect(resolveProxmoxImportAuth(authType, null)).toEqual({
authType: "none",
credentialId: null,
overrideCredentialUsername: 0,
});
}
});
it("uses the credential when no default auth type is configured", () => {
expect(resolveProxmoxImportAuth(undefined, 42)).toEqual({
authType: "credential",
credentialId: 42,
overrideCredentialUsername: 0,
});
expect(resolveProxmoxImportAuth(undefined, null)).toEqual({
authType: "none",
credentialId: null,
overrideCredentialUsername: 0,
});
});
it("keeps secretless auth types, with or without a credential", () => {
for (const authType of ["none", "agent", "opkssh", "tailscale", "vault"]) {
for (const credentialId of [null, 7]) {
expect(resolveProxmoxImportAuth(authType, credentialId)).toEqual({
authType,
credentialId: null,
overrideCredentialUsername: 0,
});
}
}
});
});
@@ -1,26 +0,0 @@
import { describe, expect, it } from "vitest";
import {
parseProxmoxJumpHosts,
serializeProxmoxJumpHosts,
} from "../../../database/routes/proxmox-jump-hosts.js";
describe("Proxmox jump-host persistence", () => {
const jumpHosts = [{ hostId: 7 }, { hostId: 9 }];
it("serializes resolved arrays before inserting a synced guest", () => {
expect(serializeProxmoxJumpHosts(jumpHosts)).toBe(
'[{"hostId":7},{"hostId":9}]',
);
});
it("keeps stored JSON strings stable", () => {
const stored = '[{"hostId":7}]';
expect(serializeProxmoxJumpHosts(stored)).toBe(stored);
expect(parseProxmoxJumpHosts(stored)).toEqual([{ hostId: 7 }]);
});
it("turns missing or malformed values into null", () => {
expect(serializeProxmoxJumpHosts(null)).toBeNull();
expect(serializeProxmoxJumpHosts("invalid")).toBeNull();
});
});
@@ -1,49 +0,0 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { Client } from "ssh2";
const execElevated = vi.fn();
vi.mock("../../../hosts/metrics-shared/exec-elevated.js", () => ({
execElevated: (...args: unknown[]) => execElevated(...args),
}));
import { execPveshCommand } from "../../../database/routes/proxmox.js";
const client = {} as Client;
describe("Proxmox discovery sudo execution", () => {
beforeEach(() => {
execElevated.mockReset();
});
it("forces pvesh through the stored sudo credentials", async () => {
execElevated.mockResolvedValue({
stdout: '[{"type":"qemu"}]',
stderr: "",
code: 0,
usedSudo: true,
});
await expect(
execPveshCommand(client, "pvesh get /cluster/resources", "secret", 12000),
).resolves.toBe('[{"type":"qemu"}]');
expect(execElevated).toHaveBeenCalledWith(
client,
"pvesh get /cluster/resources",
"secret",
{ forceSudo: true, timeoutMs: 12000 },
);
});
it("surfaces a failed elevated pvesh command", async () => {
execElevated.mockResolvedValue({
stdout: "",
stderr: "pvesh failed",
code: 255,
usedSudo: true,
});
await expect(
execPveshCommand(client, "pvesh get /cluster/resources", "secret"),
).rejects.toThrow("pvesh failed");
});
});