mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-29 18:31:33 +00:00
Fix Proxmox sync jump host persistence (#1303)
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
export function parseProxmoxJumpHosts(raw: unknown): unknown[] | null {
|
||||||
|
if (!raw) return null;
|
||||||
|
if (Array.isArray(raw)) return raw;
|
||||||
|
if (typeof raw !== "string") return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(raw);
|
||||||
|
return Array.isArray(parsed) ? parsed : null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serializeProxmoxJumpHosts(raw: unknown): string | null {
|
||||||
|
const parsed = parseProxmoxJumpHosts(raw);
|
||||||
|
return parsed ? JSON.stringify(parsed) : null;
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ import { SSHHostKeyVerifier } from "../../hosts/host-key-verifier.js";
|
|||||||
import { resolveHostById } from "../../hosts/host-resolver.js";
|
import { resolveHostById } from "../../hosts/host-resolver.js";
|
||||||
import { createJumpHostChain } from "../../hosts/jump-host-chain.js";
|
import { createJumpHostChain } from "../../hosts/jump-host-chain.js";
|
||||||
import { resolveProxmoxImportAuth } from "./proxmox-import-auth.js";
|
import { resolveProxmoxImportAuth } from "./proxmox-import-auth.js";
|
||||||
|
import {
|
||||||
|
parseProxmoxJumpHosts,
|
||||||
|
serializeProxmoxJumpHosts,
|
||||||
|
} from "./proxmox-jump-hosts.js";
|
||||||
import { isSafeNodeName } from "../../hosts/proxmox-shared.js";
|
import { isSafeNodeName } from "../../hosts/proxmox-shared.js";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@@ -183,20 +187,6 @@ type ProxmoxSyncResult = {
|
|||||||
errors: string[];
|
errors: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseJumpHostsField(raw: unknown): unknown[] | null {
|
|
||||||
if (!raw) return null;
|
|
||||||
if (Array.isArray(raw)) return raw;
|
|
||||||
if (typeof raw === "string") {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(raw);
|
|
||||||
return Array.isArray(parsed) ? parsed : null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseJsonObject(value: unknown): Record<string, unknown> {
|
function parseJsonObject(value: unknown): Record<string, unknown> {
|
||||||
if (!value) return {};
|
if (!value) return {};
|
||||||
if (typeof value === "object") return value as Record<string, unknown>;
|
if (typeof value === "object") return value as Record<string, unknown>;
|
||||||
@@ -599,7 +589,7 @@ async function discoverProxmoxGuestsForHost(
|
|||||||
guests,
|
guests,
|
||||||
credentialId: hostCredentialId,
|
credentialId: hostCredentialId,
|
||||||
defaultCredentialId: config.defaultCredentialId,
|
defaultCredentialId: config.defaultCredentialId,
|
||||||
jumpHosts: parseJumpHostsField(
|
jumpHosts: parseProxmoxJumpHosts(
|
||||||
(host as unknown as { jumpHosts?: unknown }).jumpHosts,
|
(host as unknown as { jumpHosts?: unknown }).jumpHosts,
|
||||||
),
|
),
|
||||||
config,
|
config,
|
||||||
@@ -770,9 +760,7 @@ async function syncProxmoxHost(
|
|||||||
telnetPort: null,
|
telnetPort: null,
|
||||||
defaultPath: "/",
|
defaultPath: "/",
|
||||||
tunnelConnections: "[]",
|
tunnelConnections: "[]",
|
||||||
jumpHosts:
|
jumpHosts: serializeProxmoxJumpHosts(discovery.jumpHosts),
|
||||||
(discovery.host as unknown as { jumpHosts?: string | null })
|
|
||||||
.jumpHosts ?? null,
|
|
||||||
quickActions: null,
|
quickActions: null,
|
||||||
statsConfig: null,
|
statsConfig: null,
|
||||||
dockerConfig: null,
|
dockerConfig: null,
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user