import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; import * as vscode from 'vscode'; import * as rd from 'readline' const { NodeSSH } = require('node-ssh') import * as utils from './utils'; import User from './user'; export default class RemoteContainer { private user: User; constructor(user: User) { this.user = user } async firstConnect(host: string, username: string, port: number): Promise; // connect with key // deprecated async firstConnect(host: string, username: string, port: number, password: string): Promise; async firstConnect(host: string, username: string, port: number, password?: string): Promise { return new Promise(async (resolve) => { const ssh = new NodeSSH(); vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: "正在容器中安装vscode-server及devstar插件", cancellable: false }, async (progress) => { try { if (password === undefined) { // connect with key await ssh.connect({ host: host, username: username, port: port, privateKeyPath: this.user.getUserPrivateKeyPath() }); progress.report({ message: "连接成功,开始安装" }); // install vscode-server and devstar extension const vscodeCommitId = await utils.getVsCodeCommitId() if ("" != vscodeCommitId) { const vscodeServerUrl = `https://vscode.download.prss.microsoft.com/dbazure/download/stable/${vscodeCommitId}/vscode-server-linux-x64.tar.gz` const installVscodeServerScript = ` mkdir -p ~/.vscode-server/bin/${vscodeCommitId} && \\ if [ "$(ls -A ~/.vscode-server/bin/${vscodeCommitId})" ]; then ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar else wget ${vscodeServerUrl} -O vscode-server-linux-x64.tar.gz && \\ mv vscode-server-linux-x64.tar.gz ~/.vscode-server/bin/${vscodeCommitId} && \\ cd ~/.vscode-server/bin/${vscodeCommitId} && \\ tar -xvzf vscode-server-linux-x64.tar.gz --strip-components 1 && \\ rm vscode-server-linux-x64.tar.gz && \\ ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar fi `; await ssh.execCommand(installVscodeServerScript); console.log("vscode-server and extension installed"); vscode.window.showInformationMessage('安装完成!'); } await ssh.dispose(); } else { // connect with password (deprecate in future) await ssh.connect({ host: host, username: username, password: password, port: port }); progress.report({ message: "连接成功,开始安装" }); // install vscode-server and devstar extension const vscodeCommitId = await utils.getVsCodeCommitId() if ("" != vscodeCommitId) { const vscodeServerUrl = `https://vscode.download.prss.microsoft.com/dbazure/download/stable/${vscodeCommitId}/vscode-server-linux-x64.tar.gz` const installVscodeServerScript = ` mkdir -p ~/.vscode-server/bin/${vscodeCommitId} && \\ if [ "$(ls -A ~/.vscode-server/bin/${vscodeCommitId})" ]; then ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar else wget ${vscodeServerUrl} -O vscode-server-linux-x64.tar.gz && \\ mv vscode-server-linux-x64.tar.gz ~/.vscode-server/bin/${vscodeCommitId} && \\ cd ~/.vscode-server/bin/${vscodeCommitId} && \\ tar -xvzf vscode-server-linux-x64.tar.gz --strip-components 1 && \\ rm vscode-server-linux-x64.tar.gz && \\ ~/.vscode-server/bin/${vscodeCommitId}/bin/code-server --install-extension mengning.devstar fi `; await ssh.execCommand(installVscodeServerScript); console.log("vscode-server and extension installed"); vscode.window.showInformationMessage('安装完成!'); } await ssh.dispose(); } // only connect successfully then save the host info await this.storeHostInfo(host, port, username) resolve('success') } catch (error) { console.error('Failed to install vscode-server and extension: ', error); await ssh.dispose(); } }); }); } async storeHostInfo(host:string, port:number, username:string): Promise { const sshConfigPath = path.join(os.homedir(), '.ssh', 'config'); // check if the host and related info exist in local ssh config file before saving var canAppendSSHConfig = true if (fs.existsSync(sshConfigPath)) { var reader = rd.createInterface(fs.createReadStream(sshConfigPath)) for await (const line of reader) { // host format: hostname:port if (line.includes(`Host ${host}-${port}`)) { // the container ssh info exists canAppendSSHConfig = false break; } } } if (canAppendSSHConfig) { // save the host to the local ssh config file const hostInConfig = `${host}-${port}` // host format: hostname-port const privateKeyPath = this.user.getUserPrivateKeyPath(); const newSShConfigContent = `\nHost ${hostInConfig}\n HostName ${host}\n Port ${port}\n User ${username}\n PreferredAuthentications publickey\n IdentityFile ${privateKeyPath}\n `; fs.writeFileSync(sshConfigPath, newSShConfigContent, { encoding: 'utf8', flag: 'a' }); console.log('Host registered in local ssh config'); } } openRemoteFolder(host: string, port: number, username: string, path: string): void { // var host = `${host}-${port}` const command = `code --remote ssh-remote+${username}@${host}:${port} ${path} --reuse-window` let terminal = vscode.window.activeTerminal || vscode.window.createTerminal(`Ext Terminal`); terminal.show(true); terminal.sendText(command); } } export async function openProjectWithoutLogging(host: string, port: number, username: string, path: string): Promise { const command = `code --remote ssh-remote+${username}@${host}:${port} ${path} --reuse-window` let terminal = vscode.window.activeTerminal || vscode.window.createTerminal(`Ext Terminal`); terminal.show(true); terminal.sendText(command); }