fixed terminal stuff

This commit is contained in:
biersoeckli
2024-11-28 10:27:17 +00:00
parent c599941485
commit 87f6f062ff
5 changed files with 44 additions and 77 deletions

View File

@@ -7,7 +7,7 @@ RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY bun.lockb package.json ./
COPY yarn.lock package.json ./
RUN yarn install

View File

@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev",
"dev-live": "tsc src/server.ts",
"dev-live": "tsc --project tsconfig.server.json && node dist/server.js",
"build": "next build && tsc --project tsconfig.server.json",
"start": "next start",
"start-prod": "cross-env NODE_ENV=production node dist/server.js",

View File

@@ -9,7 +9,7 @@ import FullLoadingSpinner from "@/components/ui/full-loading-spinnter";
import { toast } from "sonner";
import { LogsDialog } from "@/components/custom/logs-overlay";
import { Button } from "@/components/ui/button";
import { Expand, SquareArrowUp, SquareArrowUpRight } from "lucide-react";
import { Expand, SquareArrowUp, SquareArrowUpRight, Terminal } from "lucide-react";
import { TerminalDialog } from "./terminal-overlay";
export default function Logs({
@@ -81,7 +81,7 @@ export default function Logs({
namespace: app.projectId
}} >
<Button variant="secondary">
Terminal
<Terminal /> Terminal
</Button>
</TerminalDialog>
</div>

View File

@@ -46,34 +46,31 @@ export default function TerminalStreamed({
});
podTerminalSocket.on(terminalOutputKey, (data: string) => {
console.log('Received data:', data);
term.write(data);
});
podTerminalSocket.emit('openTerminal', termInfo);
term.write('Terminal is ready');
setTerminal(term);
setSessionTerminalInfo(termInfo);
};
useEffect(() => {
return () => {
console.log('Disconnecting from terminal...');
//terminal?.dispose();
//if (sessionTerminalInfo) podTerminalSocket.emit('closeTerminal', sessionTerminalInfo);
};
});
const disconnectTerminalSession = () => {
terminal?.dispose();
if (sessionTerminalInfo) {
podTerminalSocket.emit('closeTerminal', sessionTerminalInfo);
setSessionTerminalInfo(undefined);
}
}
return <>
<div className="space-y-4">
{!sessionTerminalInfo && <>
{!sessionTerminalInfo ? <>
<div className="flex gap-4">
<Button variant="secondary" onClick={() => startTerminalSession('sh')}>Start sh</Button>
<Button variant="secondary" onClick={() => startTerminalSession('bash')}>Start bash</Button>
</div>
</>}
<div ref={terminalWindow} ></div>
</> : <Button variant="secondary" onClick={() => disconnectTerminalSession()}>Disconnect Session</Button>}
<div ref={terminalWindow}></div>
</div>
</>;

View File

@@ -5,6 +5,7 @@ import * as k8s from '@kubernetes/client-node';
import stream from 'stream';
import { StreamUtils } from "../../shared/utils/stream.utils";
import WebSocket from "ws";
import setupPodService from "./setup-services/setup-pod.service";
interface TerminalStrean {
stdoutStream: stream.PassThrough;
@@ -33,68 +34,60 @@ export class TerminalService {
const streamInputKey = StreamUtils.getInputStreamName(terminalInfo);
const streamOutputKey = StreamUtils.getOutputStreamName(terminalInfo);
/*const podReachable = await setupPodService.waitUntilPodIsRunningFailedOrSucceded(terminalInfo.namespace, terminalInfo.podName);
const podReachable = await setupPodService.waitUntilPodIsRunningFailedOrSucceded(terminalInfo.namespace, terminalInfo.podName);
if (!podReachable) {
socket.emit(streamOutputKey, 'Pod is not reachable.');
return;
}*/
}
const exec = new k8s.Exec(k3s.getKubeConfig());
const stdoutStream = new stream.PassThrough();
const stderrStream = new stream.PassThrough();
const stdinStream = new stream.PassThrough();
console.log('starting exec')
await exec.exec(
const socketStreamInfo = {
stdoutStream,
stderrStream,
stdinStream,
terminalSessionKey: terminalInfo.terminalSessionKey ?? '',
} as TerminalStrean;
streamsOfSocket.push(socketStreamInfo);
const websocket = await exec.exec(
terminalInfo.namespace,
terminalInfo.podName,
terminalInfo.containerName,
[terminalInfo.terminalType === 'sh' ? '/bin/sh' : '/bin/bash'],
/* process.stdout,
process.stderr,
process.stdin,*/
stdoutStream,
stderrStream,
stdinStream,
false /* tty */,
true /* tty */,
(status: k8s.V1Status) => {
console.log('[EXIT] Exited with status:');
console.log(JSON.stringify(status, null, 2));
stderrStream!.end();
stdoutStream!.end();
stdinStream!.end();
if (status.status === 'Failure') {
socket.emit(streamOutputKey, `\n[ERROR] Error while opening Terminal session\n`);
socket.emit(streamOutputKey, `\n${status.message}\n`);
} else {
socket.emit(streamOutputKey, `\n[INFO] Terminal session closed\n`);
}
this.cleanupLogStream(socketStreamInfo);
},
);
socketStreamInfo.websocket = websocket;
stdoutStream.on('data', (chunk) => {
console.log(chunk)
socket.emit(streamOutputKey, chunk.toString());
});
stdoutStream.on('error', (error) => {
console.error("Error in terminal stream:", error);
});
stdoutStream.on('end', () => {
//console.log(`[END] Log stream ended for ${streamKey} by ${streamEndedByClient ? 'client' : 'server'}`);
});
stderrStream.on('data', (chunk) => {
console.log(chunk)
socket.emit(streamOutputKey, chunk.toString());
});
socket.on(streamInputKey, (data) => {
console.log('Received data:', data);
stdinStream!.write(data);
});
streamsOfSocket.push({
stdoutStream,
stderrStream,
stdinStream,
terminalSessionKey: terminalInfo.terminalSessionKey ?? '',
//websocket
});
console.log(`Client ${socket.id} joined terminal stream for:`);
console.log(`Input: ${streamInputKey}`);
console.log(`Output: ${streamOutputKey}`);
@@ -109,49 +102,26 @@ export class TerminalService {
const streams = streamsOfSocket.find(stream => stream.terminalSessionKey === terminalInfo.terminalSessionKey);
if (streams) {
this.deleteLogStream(streams);
this.cleanupLogStream(streams);
}
});
socket.on('disconnecting', () => {
// Stop all log streams for this client
for (const stream of streamsOfSocket) {
this.deleteLogStream(stream);
this.cleanupLogStream(stream);
}
});
}
private deleteLogStream(streams: TerminalStrean) {
/* streams.stderrStream.end();
streams.stdoutStream.end();
streams.stdinStream.end();
streams.websocket.close();*/
console.log(`Stopped log stream for ${streams.terminalSessionKey}.`);
private cleanupLogStream(stream: TerminalStrean) {
stream.stderrStream.end();
stream.stdoutStream.end();
stream.stdinStream.end();
stream.websocket?.close();
console.log(`Stopped terminal stream for ${stream.terminalSessionKey}.`);
}
/*
private async createLogStreamForPod(socket: Socket<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>,
streamKey: string, inputInfo: TerminalSetupInfoModel) {
logStream.on('data', (chunk) => {
socket.emit(streamKey, chunk.toString());
});
logStream.on('data', (chunk) => {
socket.to(streamKey).emit(`${streamKey}`, chunk.toString());
});
let k3sStreamRequest = await k3s.log.log(app.projectId, pod.podName, pod.containerName, logStream, {
follow: true,
pretty: false,
tailLines: 100,
});
const retVal = { logStream, clients: 0, k3sStreamRequest };
return retVal;
}*/
}
const terminalService = new TerminalService();