Initial commit: Docker Dashboard with Next.js and Netbox integration
This commit is contained in:
152
frontend/src/lib/netbox.ts
Normal file
152
frontend/src/lib/netbox.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
export interface NetboxIP {
|
||||
id: number;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface NetboxCluster {
|
||||
id: number;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface NetboxDevice {
|
||||
id: number;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface NetboxCustomFields {
|
||||
docker_run_command?: string;
|
||||
docker_volumes?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface NetboxVM {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string; // Kurze Beschreibung
|
||||
comments?: string; // Markdown Kommentare
|
||||
status: { value: string; label: string };
|
||||
primary_ip?: NetboxIP;
|
||||
primary_ip4?: NetboxIP;
|
||||
cluster?: NetboxCluster;
|
||||
device?: NetboxDevice; // Das Host-Gerät
|
||||
custom_fields?: NetboxCustomFields;
|
||||
netboxUrl?: string; // Computed URL to NetBox UI
|
||||
}
|
||||
|
||||
export interface NetboxResponse<T> {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
// Helper to group containers by host (device)
|
||||
export type GroupedContainers = Record<string, NetboxVM[]>;
|
||||
|
||||
const MOCK_DATA: NetboxVM[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "nginx-proxy",
|
||||
description: "Reverse Proxy",
|
||||
comments: "Dies ist ein **wichtiger** Container.\nBitte nicht stoppen!",
|
||||
status: { value: "active", label: "Active" },
|
||||
primary_ip4: { id: 10, address: "192.168.1.50/24" },
|
||||
device: { id: 1, name: "docker-host-01", url: "" },
|
||||
cluster: { id: 99, name: "Docker-Hosts", url: "" },
|
||||
custom_fields: {
|
||||
docker_run_command: "docker run -d -p 80:80 --name nginx-proxy nginx:latest",
|
||||
docker_volumes: "-v /etc/nginx:/etc/nginx\n-v /var/log/nginx:/var/log/nginx"
|
||||
},
|
||||
netboxUrl: "#",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "postgres-db",
|
||||
description: "DB Main",
|
||||
status: { value: "active", label: "Active" },
|
||||
primary_ip4: { id: 11, address: "192.168.1.51/24" },
|
||||
device: { id: 1, name: "docker-host-01", url: "" },
|
||||
cluster: { id: 99, name: "Docker-Hosts", url: "" },
|
||||
custom_fields: {
|
||||
docker_run_command: "docker run -d postgres:14",
|
||||
},
|
||||
netboxUrl: "#",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "grafana",
|
||||
description: "Monitoring",
|
||||
status: { value: "staged", label: "Staged" },
|
||||
device: { id: 2, name: "docker-host-02", url: "" },
|
||||
cluster: { id: 99, name: "Docker-Hosts", url: "" },
|
||||
custom_fields: {
|
||||
docker_run_command: "docker run -d grafana/grafana"
|
||||
},
|
||||
netboxUrl: "#",
|
||||
},
|
||||
];
|
||||
|
||||
export async function getDockerContainers(): Promise<GroupedContainers> {
|
||||
const apiUrl = process.env.NETBOX_API_URL;
|
||||
const apiToken = process.env.NETBOX_API_TOKEN;
|
||||
|
||||
if (!apiUrl || !apiToken) {
|
||||
console.warn("NETBOX_API_URL or NETBOX_API_TOKEN not set. Using mock data.");
|
||||
return groupContainers(MOCK_DATA);
|
||||
}
|
||||
|
||||
try {
|
||||
// Fetch VMs with role 'docker-container'.
|
||||
const res = await fetch(
|
||||
`${apiUrl}/api/virtualization/virtual-machines/?role=docker-container&limit=1000`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Token ${apiToken}`,
|
||||
Accept: "application/json",
|
||||
},
|
||||
next: { revalidate: 10 }, // Short cache for testing
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
console.error("Failed to fetch from Netbox:", res.status, res.statusText);
|
||||
return groupContainers(MOCK_DATA);
|
||||
}
|
||||
|
||||
const data: NetboxResponse<NetboxVM> = await res.json();
|
||||
|
||||
// Compute NetBox UI URL
|
||||
// Assumes apiUrl is something like "https://netbox.local/api" or "https://netbox.local/"
|
||||
// We want "https://netbox.local/virtualization/virtual-machines/{id}/"
|
||||
const baseUrl = apiUrl.replace(new RegExp("/api/?$"), "").replace(new RegExp("$"), "");
|
||||
|
||||
const enrichedResults = data.results.map(vm => ({
|
||||
...vm,
|
||||
netboxUrl: `${baseUrl}/virtualization/virtual-machines/${vm.id}/`
|
||||
}));
|
||||
|
||||
return groupContainers(enrichedResults);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching netbox data:", error);
|
||||
return groupContainers(MOCK_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
function groupContainers(vms: NetboxVM[]): GroupedContainers {
|
||||
const grouped: GroupedContainers = {};
|
||||
|
||||
vms.forEach((vm) => {
|
||||
// Prioritize 'device' name, fallback to 'cluster' name, then "Unassigned"
|
||||
const hostName = vm.device?.name || vm.cluster?.name || "Unassigned";
|
||||
|
||||
if (!grouped[hostName]) {
|
||||
grouped[hostName] = [];
|
||||
}
|
||||
grouped[hostName].push(vm);
|
||||
});
|
||||
|
||||
return grouped;
|
||||
}
|
||||
Reference in New Issue
Block a user