Files
dockhand/routes/api/host/+server.ts
Jarek Krochmalski 62e3c6439e Initial commit
2025-12-28 21:16:03 +01:00

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 });
}
};