@@ -14,6 +14,7 @@ import * as vscode from 'vscode';
14
14
import Log from './common/logger' ;
15
15
import { Disposable } from './common/dispose' ;
16
16
import { withServerApi } from './internalApi' ;
17
+ import TelemetryReporter from './telemetryReporter' ;
17
18
18
19
interface SSHConnectionParams {
19
20
workspaceId : string ;
@@ -84,7 +85,7 @@ export default class RemoteConnector extends Disposable {
84
85
public static AUTH_COMPLETE_PATH = '/auth-complete' ;
85
86
private static LOCK_COUNT = 0 ;
86
87
87
- constructor ( private readonly context : vscode . ExtensionContext , private readonly logger : Log ) {
88
+ constructor ( private readonly context : vscode . ExtensionContext , private readonly logger : Log , private readonly telemetry : TelemetryReporter ) {
88
89
super ( ) ;
89
90
90
91
this . releaseStaleLocks ( ) ;
@@ -451,7 +452,9 @@ export default class RemoteConnector extends Disposable {
451
452
}
452
453
} ,
453
454
hostVerifier ( hashedKey ) {
454
- return ( hashedKey as any as Buffer ) . toString ( 'base64' ) === sshHostKeys [ 0 ] . host_key ;
455
+ // We didn't specify `hostHash` so `hashedKey` is a Buffer object
456
+ const encodedKey = ( hashedKey as any as Buffer ) . toString ( 'base64' ) ;
457
+ return sshHostKeys . some ( keyData => keyData . host_key === encodedKey ) ;
455
458
}
456
459
} ) ;
457
460
} ) ;
@@ -548,8 +551,10 @@ export default class RemoteConnector extends Disposable {
548
551
return ;
549
552
}
550
553
551
- const params : SSHConnectionParams = JSON . parse ( uri . query ) ;
552
554
const gitpodHost = vscode . workspace . getConfiguration ( 'gitpod' ) . get < string > ( 'host' ) ! ;
555
+ const forceUseLocalApp = vscode . workspace . getConfiguration ( 'gitpod' ) . get < boolean > ( 'remote.useLocalApp' ) ! ;
556
+
557
+ const params : SSHConnectionParams = JSON . parse ( uri . query ) ;
553
558
if ( new URL ( params . gitpodHost ) . host !== new URL ( gitpodHost ) . host ) {
554
559
const yes = 'Yes' ;
555
560
const cancel = 'Cancel' ;
@@ -565,41 +570,56 @@ export default class RemoteConnector extends Disposable {
565
570
this . logger . info ( 'Opening remote workspace' , uri . toString ( ) ) ;
566
571
567
572
let sshDestination : string | undefined ;
568
- try {
569
- sshDestination = await this . getWorkspaceSSHDestination ( params . workspaceId , params . gitpodHost ) ;
570
- } catch ( e ) {
571
- if ( e instanceof SSHError ) {
572
- this . logger . error ( 'SSH test connection error' , e . cause ) ;
573
- vscode . window . showWarningMessage ( `There was an error connecting to ${ params . workspaceId } through SSH, connecting via the deprecated SSH tunnel over WebSocket.` ) ;
574
- // Do nothing and continue execution
575
- } else if ( e instanceof Error && e . message === 'no_ssh_gateway' ) {
576
- this . logger . error ( `SSH gateway not configured for this Gitpod Host ${ params . gitpodHost } ` ) ;
577
- vscode . window . showWarningMessage ( `${ params . gitpodHost } does not support [direct SSH access](https://github.com/gitpod-io/gitpod/blob/main/install/installer/docs/workspace-ssh-access.md), connecting via the deprecated SSH tunnel over WebSocket.` ) ;
578
- // Do nothing and continue execution
579
- } else if ( e instanceof Error && e . message === 'no_running_instance' ) {
580
- this . logger . error ( `No running instance for this workspaceId ${ params . workspaceId } ` ) ;
581
- vscode . window . showErrorMessage ( `Failed to connect to remote workspace: No running instance for '${ params . workspaceId } '` ) ;
582
- return ;
583
- } else {
584
- this . logger . error ( `Failed to connect to remote workspace ${ params . workspaceId } ` , e ) ;
585
- const seeLogs = 'See Logs' ;
586
- const action = await vscode . window . showErrorMessage ( `Failed to connect to remote workspace ${ params . workspaceId } ` , seeLogs ) ;
587
- if ( action === seeLogs ) {
588
- this . logger . show ( ) ;
573
+ if ( ! forceUseLocalApp ) {
574
+ try {
575
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'connecting' } ) ;
576
+
577
+ sshDestination = await this . getWorkspaceSSHDestination ( params . workspaceId , params . gitpodHost ) ;
578
+
579
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'connected' } ) ;
580
+ } catch ( e ) {
581
+ if ( e instanceof Error && e . message === 'no_ssh_gateway' ) {
582
+ this . logger . error ( `SSH gateway not configured for this Gitpod Host ${ params . gitpodHost } ` ) ;
583
+ vscode . window . showWarningMessage ( `${ params . gitpodHost } does not support [direct SSH access](https://github.com/gitpod-io/gitpod/blob/main/install/installer/docs/workspace-ssh-access.md), connecting via the deprecated SSH tunnel over WebSocket.` ) ;
584
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'failed' , reason : 'no-ssh-gateway' } ) ;
585
+ // Do nothing and continue execution
586
+ } else if ( e instanceof Error && e . message === 'no_running_instance' ) {
587
+ this . logger . error ( `No running instance for this workspaceId ${ params . workspaceId } ` ) ;
588
+ vscode . window . showErrorMessage ( `Failed to connect to remote workspace: No running instance for '${ params . workspaceId } '` ) ;
589
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'failed' , reason : 'ws-not-running' } ) ;
590
+ return ;
591
+ } else {
592
+ if ( e instanceof SSHError ) {
593
+ this . logger . error ( 'SSH test connection error' , e . cause ) ;
594
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'failed' , reason : 'ssh-blocked' } ) ;
595
+ } else {
596
+ this . logger . error ( `Failed to connect to remote workspace ${ params . workspaceId } ` , e ) ;
597
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'gateway' , status : 'failed' , reason : 'other-error' } ) ;
598
+ }
599
+ const seeLogs = 'See Logs' ;
600
+ const action = await vscode . window . showErrorMessage ( `Failed to connect to remote workspace ${ params . workspaceId } ` , seeLogs ) ;
601
+ if ( action === seeLogs ) {
602
+ this . logger . show ( ) ;
603
+ }
604
+ return ;
589
605
}
590
- return ;
591
606
}
592
607
}
593
608
594
609
const usingSSHGateway = ! ! sshDestination ;
595
610
let localAppSSHConfigPath : string | undefined ;
596
611
if ( ! usingSSHGateway ) {
597
612
try {
613
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'local-app' , status : 'connecting' } ) ;
614
+
598
615
const localAppDestData = await this . getWorkspaceLocalAppSSHDestination ( params ) ;
599
616
sshDestination = localAppDestData . localAppSSHDest ;
600
617
localAppSSHConfigPath = localAppDestData . localAppSSHConfigPath ;
618
+
619
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'local-app' , status : 'connected' } ) ;
601
620
} catch ( e ) {
602
621
this . logger . error ( `Failed to connect to remote workspace ${ params . workspaceId } ` , e ) ;
622
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'local-app' , status : 'failed' , reason : 'other-error' } ) ;
603
623
if ( e instanceof LocalAppError ) {
604
624
const seeLogs = 'See Logs' ;
605
625
const action = await vscode . window . showErrorMessage ( `Failed to connect to remote workspace ${ params . workspaceId } ` , seeLogs ) ;
@@ -612,6 +632,7 @@ export default class RemoteConnector extends Disposable {
612
632
}
613
633
} else {
614
634
// Do nothing, user cancelled the operation
635
+ this . telemetry . sendTelemetryEvent ( 'gitpod_desktop_ssh' , { kind : 'local-app' , status : 'failed' , reason : 'cancelled' } ) ;
615
636
}
616
637
return ;
617
638
}
0 commit comments