Nodes
This commit is contained in:
+13
-1
@@ -13,9 +13,21 @@ export async function read<T extends object>(
|
|||||||
await fs.access(filePath);
|
await fs.access(filePath);
|
||||||
} catch {
|
} catch {
|
||||||
await fs.mkdir(dirPath, { recursive: true });
|
await fs.mkdir(dirPath, { recursive: true });
|
||||||
await fs.writeFile(filePath, JSON.stringify(template, null, 2), "utf-8");
|
await fs.writeFile(filePath, JSON.stringify(template(), null, 2), "utf-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = await fs.readFile(filePath, "utf-8");
|
const content = await fs.readFile(filePath, "utf-8");
|
||||||
return JSON.parse(content);
|
return JSON.parse(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function write<T extends object>(
|
||||||
|
val: T,
|
||||||
|
fp: string,
|
||||||
|
...filePaths: string[]
|
||||||
|
) {
|
||||||
|
const filePath = path.join(process.cwd(), fp, ...filePaths);
|
||||||
|
const dirPath = path.dirname(filePath);
|
||||||
|
|
||||||
|
await fs.mkdir(dirPath, { recursive: true });
|
||||||
|
await fs.writeFile(filePath, JSON.stringify(val, null, 2), "utf-8");
|
||||||
|
}
|
||||||
|
|||||||
+23
-36
@@ -16,6 +16,9 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Progress } from "@/components/ui/progress";
|
import { Progress } from "@/components/ui/progress";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { getLiveNodes, getNodes } from "@/core/client/node";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Node, NodeLiveData } from "@/lib/types";
|
||||||
|
|
||||||
const recentDeployments = [
|
const recentDeployments = [
|
||||||
{
|
{
|
||||||
@@ -86,34 +89,13 @@ const applications = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const nodes = [
|
|
||||||
{
|
|
||||||
name: "node-01",
|
|
||||||
ip: "10.0.1.10",
|
|
||||||
cpu: 72,
|
|
||||||
memory: 68,
|
|
||||||
containers: 8,
|
|
||||||
status: "running" as const,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "node-02",
|
|
||||||
ip: "10.0.1.11",
|
|
||||||
cpu: 45,
|
|
||||||
memory: 52,
|
|
||||||
containers: 6,
|
|
||||||
status: "running" as const,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "node-03",
|
|
||||||
ip: "10.0.1.12",
|
|
||||||
cpu: 89,
|
|
||||||
memory: 85,
|
|
||||||
containers: 12,
|
|
||||||
status: "running" as const,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function OverviewPage() {
|
export default function OverviewPage() {
|
||||||
|
const [nodes, setNodes] = useState<NodeLiveData[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getLiveNodes().then(setNodes);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout title="Overview" subtitle="System status and metrics">
|
<DashboardLayout title="Overview" subtitle="System status and metrics">
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid */}
|
||||||
@@ -246,7 +228,7 @@ export default function OverviewPage() {
|
|||||||
>
|
>
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-3 gap-2">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-3 gap-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<StatusIndicator status={node.status} />
|
<StatusIndicator status={node.liveData.status} />
|
||||||
<span className="font-mono text-sm">{node.name}</span>
|
<span className="font-mono text-sm">{node.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-muted-foreground font-mono">
|
<span className="text-xs text-muted-foreground font-mono">
|
||||||
@@ -256,20 +238,25 @@ export default function OverviewPage() {
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center justify-between text-xs">
|
<div className="flex items-center justify-between text-xs">
|
||||||
<span className="text-muted-foreground">CPU</span>
|
<span className="text-muted-foreground">CPU</span>
|
||||||
<span className="font-mono">{node.cpu}%</span>
|
<span className="font-mono">{node.liveData.cpu}%</span>
|
||||||
</div>
|
|
||||||
<Progress value={node.cpu} className="[&>div]:bg-chart-1" />
|
|
||||||
<div className="flex items-center justify-between text-xs">
|
|
||||||
<span className="text-muted-foreground">Memory</span>
|
|
||||||
<span className="font-mono">{node.memory}%</span>
|
|
||||||
</div>
|
</div>
|
||||||
<Progress
|
<Progress
|
||||||
value={node.memory}
|
value={node.liveData.cpu}
|
||||||
|
className="[&>div]:bg-chart-1"
|
||||||
|
/>
|
||||||
|
<div className="flex items-center justify-between text-xs">
|
||||||
|
<span className="text-muted-foreground">Memory</span>
|
||||||
|
<span className="font-mono">{node.liveData.memory}%</span>
|
||||||
|
</div>
|
||||||
|
<Progress
|
||||||
|
value={node.liveData.memory}
|
||||||
className="w-full [&>div]:bg-chart-3"
|
className="w-full [&>div]:bg-chart-3"
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center justify-between text-xs pt-2 border-t border-border mt-2">
|
<div className="flex items-center justify-between text-xs pt-2 border-t border-border mt-2">
|
||||||
<span className="text-muted-foreground">Containers</span>
|
<span className="text-muted-foreground">Containers</span>
|
||||||
<span className="font-mono">{node.containers}</span>
|
<span className="font-mono">
|
||||||
|
{node.liveData.containers}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
import { Node } from "@/lib/types";
|
||||||
|
|
||||||
|
export async function getDocker(node: Node): Promise<{ version: string }> {
|
||||||
|
return await (
|
||||||
|
await axios.get(`http://${node.ip}:3000/api/get-docker`, {
|
||||||
|
headers: { Authorization: `ApiKey ${node.key}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
"use server";
|
|
||||||
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export async function getDocker(
|
|
||||||
node_ip: string,
|
|
||||||
key: string
|
|
||||||
): Promise<{ version: string }> {
|
|
||||||
return await (
|
|
||||||
await axios.get(`http://${node_ip}:3000/api/get-docker`, {
|
|
||||||
headers: { Authorization: `ApiKey ${key}` },
|
|
||||||
})
|
|
||||||
).data;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { read, write } from "@/app/api/file";
|
||||||
|
import { Node, NodeLiveData } from "@/lib/types";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export async function getNodes(): Promise<Node[]> {
|
||||||
|
return await read(() => [], "data", "nodes.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setNodes(nodes: Node[]) {
|
||||||
|
await write(nodes, "data", "nodes.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getNode(node_id: string): Promise<Node | undefined> {
|
||||||
|
const nodes = await read<Node[]>(() => [], "data", "nodes.json");
|
||||||
|
return nodes.find((v) => v.node_id === node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getLiveNodes(): Promise<NodeLiveData[]> {
|
||||||
|
const nodes = await read(() => [], "data", "nodes.json");
|
||||||
|
return await Promise.all(nodes.map(getLiveNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getLiveNode(node: Node): Promise<NodeLiveData> {
|
||||||
|
const data = await (
|
||||||
|
await axios.get(`http://${node.ip}:3000/api/status`, {
|
||||||
|
headers: { Authorization: `ApiKey ${node.key}` },
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
return { ...node, liveData: data.liveData };
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export interface Node {
|
||||||
|
name: string;
|
||||||
|
node_id: string;
|
||||||
|
ip: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeLiveData {
|
||||||
|
name: string;
|
||||||
|
node_id: string;
|
||||||
|
ip: string;
|
||||||
|
key: string;
|
||||||
|
liveData: {
|
||||||
|
status: "running" | "pending" | "error";
|
||||||
|
cpu: number;
|
||||||
|
memory: number;
|
||||||
|
disk: number;
|
||||||
|
containers: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user