mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-03 13:18:56 +00:00
159 lines
5.1 KiB
TypeScript
159 lines
5.1 KiB
TypeScript
import { json } from '@sveltejs/kit';
|
|
import type { RequestHandler } from './$types';
|
|
import { getDockerInfo, getHawserInfo } from '$lib/server/docker';
|
|
import { getEnvironment } from '$lib/server/db';
|
|
import { authorize } from '$lib/server/authorize';
|
|
import { getEdgeConnectionInfo } from '$lib/server/hawser';
|
|
import os from 'node:os';
|
|
|
|
export interface HostInfo {
|
|
hostname: string;
|
|
ipAddress: string;
|
|
platform: string;
|
|
arch: string;
|
|
cpus: number;
|
|
totalMemory: number;
|
|
freeMemory: number;
|
|
uptime: number;
|
|
dockerVersion: string;
|
|
dockerContainers: number;
|
|
dockerContainersRunning: number;
|
|
dockerImages: number;
|
|
environment: {
|
|
id: number;
|
|
name: string;
|
|
icon?: string;
|
|
socketPath?: string;
|
|
connectionType?: string;
|
|
hawserVersion?: string;
|
|
highlightChanges?: boolean;
|
|
};
|
|
}
|
|
|
|
function getLocalIpAddress(): string {
|
|
const interfaces = os.networkInterfaces();
|
|
for (const name of Object.keys(interfaces)) {
|
|
const netInterface = interfaces[name];
|
|
if (!netInterface) continue;
|
|
for (const net of netInterface) {
|
|
// Skip internal and non-IPv4 addresses
|
|
if (!net.internal && net.family === 'IPv4') {
|
|
return net.address;
|
|
}
|
|
}
|
|
}
|
|
return '127.0.0.1';
|
|
}
|
|
|
|
export const GET: RequestHandler = async ({ url, cookies }) => {
|
|
const auth = await authorize(cookies);
|
|
|
|
// Check basic environment view permission
|
|
if (auth.authEnabled && !await auth.can('environments', 'view')) {
|
|
return json({ error: 'Permission denied' }, { status: 403 });
|
|
}
|
|
|
|
try {
|
|
// Get environment ID from query param, or use default
|
|
const envIdParam = url.searchParams.get('env');
|
|
let env;
|
|
|
|
if (envIdParam) {
|
|
const envId = parseInt(envIdParam);
|
|
// Check if user can access this specific environment
|
|
if (auth.authEnabled && auth.isEnterprise && !await auth.canAccessEnvironment(envId)) {
|
|
return json({ error: 'Access denied to this environment' }, { status: 403 });
|
|
}
|
|
env = await getEnvironment(envId);
|
|
}
|
|
|
|
if (!env) {
|
|
// No environment specified - return basic local info
|
|
return json({
|
|
hostname: os.hostname(),
|
|
ipAddress: getLocalIpAddress(),
|
|
platform: os.platform(),
|
|
arch: os.arch(),
|
|
cpus: os.cpus().length,
|
|
totalMemory: os.totalmem(),
|
|
freeMemory: os.freemem(),
|
|
uptime: os.uptime(),
|
|
dockerVersion: null,
|
|
dockerContainers: 0,
|
|
dockerContainersRunning: 0,
|
|
dockerImages: 0,
|
|
environment: null
|
|
});
|
|
}
|
|
|
|
// Determine if this is a truly local connection (socket without remote host)
|
|
const isSocketType = env.connectionType === 'socket' || !env.connectionType;
|
|
const isLocalConnection = isSocketType && (!env.host || env.host === 'localhost' || env.host === '127.0.0.1');
|
|
|
|
// Fetch Docker info and Hawser info in parallel for hawser-standard mode
|
|
let dockerInfo: any;
|
|
let uptime = 0;
|
|
let hawserVersion: string | undefined;
|
|
|
|
if (env.connectionType === 'hawser-standard') {
|
|
// Parallel fetch for hawser-standard
|
|
const [dockerResult, hawserInfo] = await Promise.all([
|
|
getDockerInfo(env.id),
|
|
getHawserInfo(env.id)
|
|
]);
|
|
dockerInfo = dockerResult;
|
|
if (hawserInfo?.uptime) {
|
|
uptime = hawserInfo.uptime;
|
|
}
|
|
if (hawserInfo?.hawserVersion) {
|
|
hawserVersion = hawserInfo.hawserVersion;
|
|
}
|
|
} else {
|
|
// Sequential for other connection types
|
|
dockerInfo = await getDockerInfo(env.id);
|
|
|
|
if (isLocalConnection) {
|
|
uptime = os.uptime();
|
|
} else if (env.connectionType === 'hawser-edge') {
|
|
// For Hawser edge mode, get from edge connection metrics (sync lookup)
|
|
const edgeConn = getEdgeConnectionInfo(env.id);
|
|
if (edgeConn?.lastMetrics?.uptime) {
|
|
uptime = edgeConn.lastMetrics.uptime;
|
|
}
|
|
}
|
|
// For 'direct' connections without Hawser, uptime remains 0 (not available)
|
|
}
|
|
|
|
const hostInfo: HostInfo = {
|
|
// For local connections, show local system info; for remote, show Docker host info
|
|
hostname: isLocalConnection ? os.hostname() : (dockerInfo.Name || env.host || 'unknown'),
|
|
ipAddress: isLocalConnection ? getLocalIpAddress() : (env.host || 'unknown'),
|
|
platform: isLocalConnection ? os.platform() : (dockerInfo.OperatingSystem || 'unknown'),
|
|
arch: isLocalConnection ? os.arch() : (dockerInfo.Architecture || 'unknown'),
|
|
cpus: isLocalConnection ? os.cpus().length : (dockerInfo.NCPU || 0),
|
|
totalMemory: isLocalConnection ? os.totalmem() : (dockerInfo.MemTotal || 0),
|
|
freeMemory: isLocalConnection ? os.freemem() : 0, // Not available from Docker API
|
|
uptime,
|
|
dockerVersion: dockerInfo.ServerVersion || 'unknown',
|
|
dockerContainers: dockerInfo.Containers || 0,
|
|
dockerContainersRunning: dockerInfo.ContainersRunning || 0,
|
|
dockerImages: dockerInfo.Images || 0,
|
|
environment: {
|
|
id: env.id,
|
|
name: env.name,
|
|
icon: env.icon,
|
|
socketPath: env.socketPath,
|
|
connectionType: env.connectionType || 'socket',
|
|
// For standard mode, use live-fetched version; for edge mode, use stored version
|
|
hawserVersion: hawserVersion || env.hawserVersion,
|
|
highlightChanges: env.highlightChanges
|
|
}
|
|
};
|
|
|
|
return json(hostInfo);
|
|
} catch (error) {
|
|
console.error('Failed to get host info:', error);
|
|
return json({ error: 'Failed to get host info' }, { status: 500 });
|
|
}
|
|
};
|