diff --git a/backend/src/integrations/proxmox.ts b/backend/src/integrations/proxmox.ts new file mode 100644 index 0000000..e67b3b3 --- /dev/null +++ b/backend/src/integrations/proxmox.ts @@ -0,0 +1,43 @@ +import type { IntegrationAdapter, Resource } from './types.js' + +interface ProxmoxResourceEntry { + type: string + name?: string + status?: string + vmid?: number + node?: string +} + +function authHeader(apiKey: string): Record { + return { Authorization: `PVEAPIToken=${apiKey}` } +} + +export const proxmox: IntegrationAdapter = { + async testConnection(config, secrets) { + const baseUrl = config.baseUrl?.replace(/\/$/, '') + const apiKey = secrets.apiKey + if (!baseUrl) return { ok: false, message: 'Missing baseUrl' } + if (!apiKey) return { ok: false, message: 'Missing API token' } + try { + const res = await fetch(`${baseUrl}/api2/json/version`, { headers: authHeader(apiKey) }) + if (!res.ok) return { ok: false, message: `HTTP ${res.status}` } + return { ok: true, message: 'Connected' } + } catch (err) { + return { ok: false, message: err instanceof Error ? err.message : 'Connection failed' } + } + }, + + async listResources(config, secrets): Promise { + const baseUrl = config.baseUrl?.replace(/\/$/, '') + const apiKey = secrets.apiKey + if (!baseUrl || !apiKey) return [] + const res = await fetch(`${baseUrl}/api2/json/cluster/resources?type=vm`, { headers: authHeader(apiKey) }) + if (!res.ok) return [] + const body = (await res.json()) as { data: ProxmoxResourceEntry[] } + return body.data.map((entry) => ({ + name: entry.name ?? `vm-${entry.vmid}`, + status: entry.status === 'running' ? 'healthy' : entry.status === 'stopped' ? 'unknown' : 'warning', + detail: `${entry.type} on ${entry.node} — ${entry.status}`, + })) + }, +} diff --git a/backend/src/integrations/registry.ts b/backend/src/integrations/registry.ts index cf1e0d0..82af46d 100644 --- a/backend/src/integrations/registry.ts +++ b/backend/src/integrations/registry.ts @@ -1,6 +1,7 @@ import type { IntegrationAdapter, IntegrationType } from './types.js' import { uptimeKuma } from './uptimeKuma.js' import { docker } from './docker.js' +import { proxmox } from './proxmox.js' const notImplemented: IntegrationAdapter = { async testConnection() { @@ -11,7 +12,7 @@ const notImplemented: IntegrationAdapter = { export const adapterRegistry: Record = { uptime_kuma: uptimeKuma, docker, - proxmox: notImplemented, + proxmox, netbird: notImplemented, cloudflare: notImplemented, aws: notImplemented,