@@ -467,20 +467,27 @@ export class Remote {
467467 // "Host not found".
468468 try {
469469 this . storage . writeToCoderOutputChannel ( "Updating SSH config..." )
470- await this . updateSSHConfig ( workspaceRestClient , parts . label , parts . host , binaryPath , logDir )
470+ await this . updateSSHConfig ( workspaceRestClient , parts . label , parts . host , binaryPath , logDir , featureSet )
471471 } catch ( error ) {
472472 this . storage . writeToCoderOutputChannel ( `Failed to configure SSH: ${ error } ` )
473473 throw error
474474 }
475475
476476 // TODO: This needs to be reworked; it fails to pick up reconnects.
477- this . findSSHProcessID ( ) . then ( ( pid ) => {
477+ this . findSSHProcessID ( ) . then ( async ( pid ) => {
478478 if ( ! pid ) {
479479 // TODO: Show an error here!
480480 return
481481 }
482482 disposables . push ( this . showNetworkUpdates ( pid ) )
483- this . commands . workspaceLogPath = logDir ? path . join ( logDir , `${ pid } .log` ) : undefined
483+ if ( logDir ) {
484+ const logFiles = await fs . readdir ( logDir )
485+ this . commands . workspaceLogPath = logFiles
486+ . reverse ( )
487+ . find ( ( file ) => file === `${ pid } .log` || file . endsWith ( `-${ pid } .log` ) )
488+ } else {
489+ this . commands . workspaceLogPath = undefined
490+ }
484491 } )
485492
486493 // Register the label formatter again because SSH overrides it!
@@ -532,7 +539,14 @@ export class Remote {
532539
533540 // updateSSHConfig updates the SSH configuration with a wildcard that handles
534541 // all Coder entries.
535- private async updateSSHConfig ( restClient : Api , label : string , hostName : string , binaryPath : string , logDir : string ) {
542+ private async updateSSHConfig (
543+ restClient : Api ,
544+ label : string ,
545+ hostName : string ,
546+ binaryPath : string ,
547+ logDir : string ,
548+ featureSet : FeatureSet ,
549+ ) {
536550 let deploymentSSHConfig = { }
537551 try {
538552 const deploymentConfig = await restClient . getDeploymentSSHConfig ( )
@@ -610,13 +624,21 @@ export class Remote {
610624 headerArg = ` --header-command ${ escapeSubcommand ( headerCommand ) } `
611625 }
612626
627+ const hostPrefix = label ? `${ AuthorityPrefix } .${ label } --` : `${ AuthorityPrefix } --`
628+
629+ const proxyCommand = featureSet . wildcardSSH
630+ ? `${ escape ( binaryPath ) } ${ headerArg } --global-config ${ escape (
631+ path . dirname ( this . storage . getSessionTokenPath ( label ) ) ,
632+ ) } ssh --stdio --network-info-dir ${ escape ( this . storage . getNetworkInfoPath ( ) ) } ${ await this . formatLogArg ( logDir ) } --ssh-host-prefix ${ hostPrefix } %h`
633+ : `${ escape ( binaryPath ) } ${ headerArg } vscodessh --network-info-dir ${ escape (
634+ this . storage . getNetworkInfoPath ( ) ,
635+ ) } ${ await this . formatLogArg ( logDir ) } --session-token-file ${ escape ( this . storage . getSessionTokenPath ( label ) ) } --url-file ${ escape (
636+ this . storage . getUrlPath ( label ) ,
637+ ) } %h`
638+
613639 const sshValues : SSHValues = {
614- Host : label ? `${ AuthorityPrefix } .${ label } --*` : `${ AuthorityPrefix } --*` ,
615- ProxyCommand : `${ escape ( binaryPath ) } ${ headerArg } vscodessh --network-info-dir ${ escape (
616- this . storage . getNetworkInfoPath ( ) ,
617- ) } ${ await this . formatLogArg ( logDir ) } --session-token-file ${ escape ( this . storage . getSessionTokenPath ( label ) ) } --url-file ${ escape (
618- this . storage . getUrlPath ( label ) ,
619- ) } %h`,
640+ Host : hostPrefix + `*` ,
641+ ProxyCommand : proxyCommand ,
620642 ConnectTimeout : "0" ,
621643 StrictHostKeyChecking : "no" ,
622644 UserKnownHostsFile : "/dev/null" ,
0 commit comments