From 9a22590fd02f66c2ce128591ceca644887417c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Tue, 29 Oct 2024 09:33:34 +0100 Subject: [PATCH] Dev Container heartbeats (#113) Co-authored-by: jeanp413 --- src/commands/workspaces.ts | 2 +- src/remote.ts | 31 ++++++++++++++++---- src/remoteConnector.ts | 4 +-- src/services/remoteService.ts | 53 +++++++++++++++++++++++++---------- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/commands/workspaces.ts b/src/commands/workspaces.ts index af21373..c95226d 100644 --- a/src/commands/workspaces.ts +++ b/src/commands/workspaces.ts @@ -361,7 +361,7 @@ export class ConnectInCurrentWindowCommand implements Command { private async initializeLocalSSH(workspaceId: string) { try { - await this.remoteService.updateRemoteSSHConfig(); + await this.remoteService.updateRemoteConfig(); await Promise.all([ this.remoteService.setupSSHProxy(), this.remoteService.startLocalSSHServiceServer() diff --git a/src/remote.ts b/src/remote.ts index 7a54efc..35506a8 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -59,6 +59,25 @@ export function getGitpodRemoteWindowConnectionInfo(context: vscode.ExtensionCon const remoteUri = vscode.workspace.workspaceFile?.scheme !== 'untitled' ? vscode.workspace.workspaceFile || vscode.workspace.workspaceFolders?.[0].uri : vscode.workspace.workspaceFolders?.[0].uri; + if (vscode.env.remoteName === 'dev-container' && context.extension.extensionKind === vscode.ExtensionKind.UI && remoteUri) { + const authorities = remoteUri.authority.split('@'); + const sshAuthority = authorities.find((str) => str.includes('ssh-remote')); + const containerAuthority = authorities.find((str) => str.includes('dev-container')); + if (!sshAuthority || !containerAuthority) { + return undefined; + } + const [, sshEncoded] = sshAuthority.split('+'); + if (!sshEncoded) { + return undefined; + } + + const sshDest = SSHDestination.fromRemoteSSHString(sshEncoded); + + const connectionInfo = context.globalState.get(`${SSH_DEST_KEY}${sshDest.toRemoteSSHString()}`); + if (connectionInfo) { + return { connectionInfo, remoteUri, sshDestStr: sshDest.toRemoteSSHString() }; + } + } if (vscode.env.remoteName === 'ssh-remote' && context.extension.extensionKind === vscode.ExtensionKind.UI && remoteUri) { const [, sshDestStr] = remoteUri.authority.split('+'); const connectionInfo = context.globalState.get(`${SSH_DEST_KEY}${sshDestStr}`); @@ -97,14 +116,14 @@ export function isGitpodFlexRemoteWindow() { return /gitpod\.(local|remote)$/.test(sshDest.hostname); } if (vscode.env.remoteName === 'ssh-remote') { - const [, sshEncoded] = remoteUri.authority.split('+'); - if (!sshEncoded) { - return; - } - const sshDest = SSHDestination.fromRemoteSSHString(sshEncoded); + const [, sshEncoded] = remoteUri.authority.split('+'); + if (!sshEncoded) { + return; + } + const sshDest = SSHDestination.fromRemoteSSHString(sshEncoded); return /gitpod\.(local|remote)$/.test(sshDest.hostname); - } + } return false; } diff --git a/src/remoteConnector.ts b/src/remoteConnector.ts index 889508a..3708201 100644 --- a/src/remoteConnector.ts +++ b/src/remoteConnector.ts @@ -265,7 +265,7 @@ export class RemoteConnector extends Disposable { try { this.telemetryService.sendUserFlowStatus('connecting', localSSHFlow); // If needed, revert local-app changes first - await this.remoteService.updateRemoteSSHConfig(); + await this.remoteService.updateRemoteConfig(); this.remoteService.flow = sshFlow; await Promise.all([ @@ -344,7 +344,7 @@ export class RemoteConnector extends Disposable { } } - await this.remoteService.updateRemoteSSHConfig(); + await this.remoteService.updateRemoteConfig(); await this.context.globalState.update(`${SSH_DEST_KEY}${sshDestination!.toRemoteSSHString()}`, { ...params } as SSHConnectionParams); diff --git a/src/services/remoteService.ts b/src/services/remoteService.ts index 2c8ef06..14e3386 100644 --- a/src/services/remoteService.ts +++ b/src/services/remoteService.ts @@ -43,7 +43,7 @@ export interface IRemoteService { getWorkspaceSSHDestination(wsData: WorkspaceData): Promise<{ destination: SSHDestination; password?: string }>; showSSHPasswordModal(wsData: WorkspaceData, password: string): Promise; - updateRemoteSSHConfig(): Promise; + updateRemoteConfig(): Promise; initializeRemoteExtensions(): Promise; } @@ -329,19 +329,41 @@ export class RemoteService extends Disposable implements IRemoteService { throw new Error('SSH password modal dialog, Canceled'); } - async updateRemoteSSHConfig() { - const remoteSSHconfig = vscode.workspace.getConfiguration('remote.SSH'); - const defaultExtConfigInfo = remoteSSHconfig.inspect('defaultExtensions'); - const defaultExtensions = defaultExtConfigInfo?.globalValue ?? []; - if (!defaultExtensions.includes('gitpod.gitpod-remote-ssh')) { - defaultExtensions.unshift('gitpod.gitpod-remote-ssh'); - await remoteSSHconfig.update('defaultExtensions', defaultExtensions, vscode.ConfigurationTarget.Global); - } - - const currentConfigFile = remoteSSHconfig.get('configFile'); - if (currentConfigFile?.includes('gitpod_ssh_config')) { - await remoteSSHconfig.update('configFile', undefined, vscode.ConfigurationTarget.Global); - } + async updateRemoteConfig() { + const remoteSSHconfig = vscode.workspace.getConfiguration('remote.SSH'); + const defaultSSHExtConfigInfo = + remoteSSHconfig.inspect('defaultExtensions'); + const defaultSSHExtensions = defaultSSHExtConfigInfo?.globalValue ?? []; + if (!defaultSSHExtensions.includes('gitpod.gitpod-remote-ssh')) { + defaultSSHExtensions.unshift('gitpod.gitpod-remote-ssh'); + await remoteSSHconfig.update( + 'defaultExtensions', + defaultSSHExtensions, + vscode.ConfigurationTarget.Global, + ); + } + + const remoteDevContainerConfig = + vscode.workspace.getConfiguration('dev.containers'); + const defaultDevContainerExtConfigInfo = remoteDevContainerConfig.inspect('defaultExtensions'); + const defaultDevContainerExtensions = defaultDevContainerExtConfigInfo?.globalValue ?? []; + if (!defaultDevContainerExtensions.includes('gitpod.gitpod-remote-ssh')) { + defaultDevContainerExtensions.unshift('gitpod.gitpod-remote-ssh'); + await remoteDevContainerConfig.update( + 'defaultExtensions', + defaultDevContainerExtensions, + vscode.ConfigurationTarget.Global, + ); + } + + const currentConfigFile = remoteSSHconfig.get('configFile'); + if (currentConfigFile?.includes('gitpod_ssh_config')) { + await remoteSSHconfig.update( + 'configFile', + undefined, + vscode.ConfigurationTarget.Global, + ); + } } async initializeRemoteExtensions() { @@ -379,9 +401,10 @@ export class RemoteService extends Disposable implements IRemoteService { throw e; } this.telemetryService.sendUserFlowStatus('synced', flowData); - } catch { + } catch (error) { const msg = `Error while installing local extensions on remote.`; this.logService.error(msg); + this.logService.trace(error); const status = 'failed'; const seeLogs = 'See Logs';