Cloudshell: Few Enhancement (#2128)

* few enhancement

* fix time
This commit is contained in:
Sourabh Jain 2025-05-05 21:17:36 +05:30 committed by GitHub
parent f9b0abdd14
commit ea6f3d1579
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 66 deletions

View File

@ -55,20 +55,16 @@ export const startCloudShellTerminal = async (terminal: Terminal, shellType: Ter
TelemetryProcessor.trace( TelemetryProcessor.trace(
Action.CloudShellUserConsent, Action.CloudShellUserConsent,
consentGranted ? ActionModifiers.Success : ActionModifiers.Cancel, consentGranted ? ActionModifiers.Success : ActionModifiers.Cancel,
{ dataExplorerArea: Areas.CloudShell }, {
dataExplorerArea: Areas.CloudShell,
shellType: TerminalKind[shellType],
isConsent: consentGranted,
region: resolvedRegion,
},
startKey,
); );
if (!consentGranted) { if (!consentGranted) {
TelemetryProcessor.traceCancel(
Action.CloudShellTerminalSession,
{
shellType: TerminalKind[shellType],
dataExplorerArea: Areas.CloudShell,
region: resolvedRegion,
isConsent: false,
},
startKey,
);
terminal.writeln( terminal.writeln(
formatErrorMessage("Session ended. Please close this tab and initiate a new shell session if needed."), formatErrorMessage("Session ended. Please close this tab and initiate a new shell session if needed."),
); );
@ -262,28 +258,27 @@ export const configureSocketConnection = async (
}; };
export const sendTerminalStartupCommands = (socket: WebSocket, initCommands: string): void => { export const sendTerminalStartupCommands = (socket: WebSocket, initCommands: string): void => {
// ensures connections don't remain open indefinitely by implementing an automatic timeout after 120 minutes.
const keepSocketAlive = (socket: WebSocket) => {
if (socket.readyState === WebSocket.OPEN) {
if (pingCount >= MAX_PING_COUNT) {
socket.close();
} else {
pingCount++;
// The code uses a recursive setTimeout pattern rather than setInterval,
// which ensures each new ping only happens after the previous one completes
// and naturally stops if the socket closes.
keepAliveID = setTimeout(() => keepSocketAlive(socket), 1000);
}
}
};
if (socket && socket.readyState === WebSocket.OPEN) { if (socket && socket.readyState === WebSocket.OPEN) {
socket.send(initCommands); socket.send(initCommands);
keepSocketAlive(socket);
} else { } else {
socket.onopen = () => { socket.onopen = () => {
socket.send(initCommands); socket.send(initCommands);
// ensures connections don't remain open indefinitely by implementing an automatic timeout after 20 minutes.
const keepSocketAlive = (socket: WebSocket) => {
if (socket.readyState === WebSocket.OPEN) {
if (pingCount >= MAX_PING_COUNT) {
socket.close();
} else {
socket.send("");
pingCount++;
// The code uses a recursive setTimeout pattern rather than setInterval,
// which ensures each new ping only happens after the previous one completes
// and naturally stops if the socket closes.
keepAliveID = setTimeout(() => keepSocketAlive(socket), 1000);
}
}
};
keepSocketAlive(socket); keepSocketAlive(socket);
}; };
} }

View File

@ -56,4 +56,30 @@ export abstract class AbstractShellHandler {
return allCommands.join("\n").concat("\n"); return allCommands.join("\n").concat("\n");
} }
/**
* Setup commands for MongoDB shell:
*
* 1. Check if mongosh is already installed
* 2. Download mongosh package if not installed
* 3. Extract the package to access mongosh binaries
* 4. Move extracted files to ~/mongosh directory
* 5. Add mongosh binary path to system PATH
* 6. Apply PATH changes by sourcing .bashrc
*
* Each command runs conditionally only if mongosh
* is not already present in the environment.
*/
protected mongoShellSetupCommands(): string[] {
const PACKAGE_VERSION: string = "2.5.0";
return [
"if ! command -v mongosh &> /dev/null; then echo '⚠️ mongosh not found. Installing...'; fi",
`if ! command -v mongosh &> /dev/null; then curl -LO https://downloads.mongodb.com/compass/mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then tar -xvzf mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then mkdir -p ~/mongosh/bin && mv mongosh-${PACKAGE_VERSION}-linux-x64/bin/mongosh ~/mongosh/bin/ && chmod +x ~/mongosh/bin/mongosh; fi`,
`if ! command -v mongosh &> /dev/null; then rm -rf mongosh-${PACKAGE_VERSION}-linux-x64 mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
"if ! command -v mongosh &> /dev/null; then echo 'export PATH=$HOME/mongosh/bin:$PATH' >> ~/.bashrc; fi",
"source ~/.bashrc",
];
}
} }

View File

@ -68,7 +68,7 @@ describe("MongoShellHandler", () => {
const commands = mongoShellHandler.getSetUpCommands(); const commands = mongoShellHandler.getSetUpCommands();
expect(Array.isArray(commands)).toBe(true); expect(Array.isArray(commands)).toBe(true);
expect(commands.length).toBe(6); expect(commands.length).toBe(7);
expect(commands[1]).toContain("mongosh-2.5.0-linux-x64.tgz"); expect(commands[1]).toContain("mongosh-2.5.0-linux-x64.tgz");
}); });
}); });

View File

@ -2,8 +2,6 @@ import { userContext } from "../../../../UserContext";
import { getHostFromUrl } from "../Utils/CommonUtils"; import { getHostFromUrl } from "../Utils/CommonUtils";
import { AbstractShellHandler } from "./AbstractShellHandler"; import { AbstractShellHandler } from "./AbstractShellHandler";
const PACKAGE_VERSION: string = "2.5.0";
export class MongoShellHandler extends AbstractShellHandler { export class MongoShellHandler extends AbstractShellHandler {
private _key: string; private _key: string;
private _endpoint: string | undefined; private _endpoint: string | undefined;
@ -18,14 +16,7 @@ export class MongoShellHandler extends AbstractShellHandler {
} }
public getSetUpCommands(): string[] { public getSetUpCommands(): string[] {
return [ return this.mongoShellSetupCommands();
"if ! command -v mongosh &> /dev/null; then echo '⚠️ mongosh not found. Installing...'; fi",
`if ! command -v mongosh &> /dev/null; then curl -LO https://downloads.mongodb.com/compass/mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then tar -xvzf mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then mkdir -p ~/mongosh && mv mongosh-${PACKAGE_VERSION}-linux-x64/* ~/mongosh/; fi`,
"if ! command -v mongosh &> /dev/null; then echo 'export PATH=$HOME/mongosh/bin:$PATH' >> ~/.bashrc; fi",
"source ~/.bashrc",
];
} }
public getConnectionCommand(): string { public getConnectionCommand(): string {

View File

@ -44,7 +44,7 @@ describe("VCoreMongoShellHandler", () => {
const commands = vcoreMongoShellHandler.getSetUpCommands(); const commands = vcoreMongoShellHandler.getSetUpCommands();
expect(Array.isArray(commands)).toBe(true); expect(Array.isArray(commands)).toBe(true);
expect(commands.length).toBe(6); expect(commands.length).toBe(7);
expect(commands[1]).toContain("mongosh-2.5.0-linux-x64.tgz"); expect(commands[1]).toContain("mongosh-2.5.0-linux-x64.tgz");
expect(commands[0]).toContain("mongosh not found"); expect(commands[0]).toContain("mongosh not found");
}); });

View File

@ -1,8 +1,6 @@
import { userContext } from "../../../../UserContext"; import { userContext } from "../../../../UserContext";
import { AbstractShellHandler } from "./AbstractShellHandler"; import { AbstractShellHandler } from "./AbstractShellHandler";
const PACKAGE_VERSION: string = "2.5.0";
export class VCoreMongoShellHandler extends AbstractShellHandler { export class VCoreMongoShellHandler extends AbstractShellHandler {
private _endpoint: string | undefined; private _endpoint: string | undefined;
@ -15,28 +13,8 @@ export class VCoreMongoShellHandler extends AbstractShellHandler {
return "MongoDB VCore"; return "MongoDB VCore";
} }
/**
* Setup commands for MongoDB VCore shell:
*
* 1. Check if mongosh is already installed
* 2. Download mongosh package if not installed
* 3. Extract the package to access mongosh binaries
* 4. Move extracted files to ~/mongosh directory
* 5. Add mongosh binary path to system PATH
* 6. Apply PATH changes by sourcing .bashrc
*
* Each command runs conditionally only if mongosh
* is not already present in the environment.
*/
public getSetUpCommands(): string[] { public getSetUpCommands(): string[] {
return [ return this.mongoShellSetupCommands();
"if ! command -v mongosh &> /dev/null; then echo '⚠️ mongosh not found. Installing...'; fi",
`if ! command -v mongosh &> /dev/null; then curl -LO https://downloads.mongodb.com/compass/mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then tar -xvzf mongosh-${PACKAGE_VERSION}-linux-x64.tgz; fi`,
`if ! command -v mongosh &> /dev/null; then mkdir -p ~/mongosh && mv mongosh-${PACKAGE_VERSION}-linux-x64/* ~/mongosh/; fi`,
"if ! command -v mongosh &> /dev/null; then echo 'export PATH=$HOME/mongosh/bin:$PATH' >> ~/.bashrc; fi",
"source ~/.bashrc",
];
} }
public getConnectionCommand(): string { public getConnectionCommand(): string {

View File

@ -1,5 +1,6 @@
import { AbstractShellHandler } from "Explorer/Tabs/CloudShellTab/ShellTypes/AbstractShellHandler";
import { IDisposable, ITerminalAddon, Terminal } from "@xterm/xterm"; import { IDisposable, ITerminalAddon, Terminal } from "@xterm/xterm";
import { AbstractShellHandler } from "../ShellTypes/AbstractShellHandler";
import { formatErrorMessage } from "./TerminalLogFormats";
interface IAttachOptions { interface IAttachOptions {
bidirectional?: boolean; bidirectional?: boolean;
@ -56,8 +57,27 @@ export class AttachAddon implements ITerminalAddon {
this._disposables.push(terminal.onBinary((data) => this._sendBinary(data))); this._disposables.push(terminal.onBinary((data) => this._sendBinary(data)));
} }
this._disposables.push(addSocketListener(this._socket, "close", () => this.dispose())); this._disposables.push(addSocketListener(this._socket, "close", () => this._handleSocketClose(terminal)));
this._disposables.push(addSocketListener(this._socket, "error", () => this.dispose())); this._disposables.push(addSocketListener(this._socket, "error", () => this._handleSocketClose(terminal)));
}
/**
* Handles socket close events by terminating processes and showing a message
*/
private _handleSocketClose(terminal: Terminal): void {
if (terminal) {
terminal.writeln(
formatErrorMessage("Session ended. Please close this tab and initiate a new shell session if needed."),
);
// Send exit command to terminal
if (this._bidirectional) {
terminal.write(formatErrorMessage("exit\r\n"));
}
}
// Clean up resources
this.dispose();
} }
/** /**