feat: add IPAM discovery from Proxmox with IP enrichment, improve workload insights, and enhance DataTable interactivity
CI / backend (push) Failing after 3s
CI / frontend (push) Failing after 29s

Add /ipam/discover endpoint to automatically import IP addresses from Proxmox clusters with error tracking and audit logging, implement ensure_discovered_network helper to create "discovered-ipam" network for auto-discovered IPs, add import_discovered_ips function to parse IP interfaces and create subnet/address records with assignment tracking, enhance ProxmoxProvider.enrich_work
This commit is contained in:
2026-07-09 13:14:01 +02:00
parent 4554b00b73
commit 150a69b60b
8 changed files with 368 additions and 70 deletions
+6 -13
View File
@@ -1,10 +1,9 @@
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Activity, Server } from "lucide-react";
import { Activity } from "lucide-react";
import { api, Workload, WorkloadInsight } from "../api/client";
import { DataTable } from "../components/DataTable";
import { secondaryButtonClass } from "../components/FormControls";
import { PageHeader } from "../components/PageHeader";
export function Workloads() {
@@ -25,15 +24,9 @@ export function Workloads() {
<DataTable
rows={(workloads.data ?? []) as unknown as Record<string, unknown>[]}
columns={[{ key: "name", label: "Name" }, { key: "kind", label: "Kind" }, { key: "status", label: "Status" }, { key: "external_id", label: "VMID" }]}
selectedId={selected}
onRowClick={(row) => setSelectedId(String(row.id))}
/>
<div className="flex flex-wrap gap-2">
{(workloads.data ?? []).map((workload) => (
<button key={workload.id} className={secondaryButtonClass} onClick={() => setSelectedId(workload.id)}>
<Server size={16} />
{workload.name}
</button>
))}
</div>
</section>
<aside className="rounded-md border border-border bg-panel p-4">
<div className="mb-4 flex items-center gap-2 font-medium"><Activity size={18} /> Workload Detail</div>
@@ -46,12 +39,13 @@ export function Workloads() {
<section>
<div className="mb-2 font-medium">Traffic</div>
<div className="space-y-2">
{insight.data.traffic.map((flow, index) => (
{insight.data.traffic.length ? insight.data.traffic.map((flow, index) => (
<div key={index} className="rounded-md border border-border p-3">
<div>{String(flow.source)} {String(flow.destination)}</div>
<div className="text-xs text-slate-500">{String(flow.protocol)}:{String(flow.port)} · {String(flow.bytes)} bytes · {String(flow.decision)}</div>
{Array.isArray(flow.ip_addresses) ? <div className="mt-1 text-xs text-slate-500">IPs: {flow.ip_addresses.join(", ")}</div> : null}
</div>
))}
)) : <div className="rounded-md border border-border p-3 text-xs text-slate-500">No real traffic telemetry has been collected yet. Install the node agent or enable a flow source to populate this section.</div>}
</div>
</section>
<section>
@@ -80,4 +74,3 @@ export function Workloads() {
</>
);
}