Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit195151a

Browse files
committed
switch to coder connect dynamically
1 parent9252fff commit195151a

File tree

4 files changed

+96
-76
lines changed

4 files changed

+96
-76
lines changed

‎src/api.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import{AxiosInstance}from"axios"
1+
import{AxiosInstance,isAxiosError}from"axios"
22
import{spawn}from"child_process"
33
import{Api}from"coder/site/src/api/api"
4-
import{ProvisionerJobLog,Workspace}from"coder/site/src/api/typesGenerated"
4+
import{ProvisionerJobLog,SSHConfigResponse,Workspace}from"coder/site/src/api/typesGenerated"
55
import{FetchLikeInit}from"eventsource"
66
importfsfrom"fs/promises"
77
import{ProxyAgent}from"proxy-agent"
@@ -280,3 +280,34 @@ export async function waitForBuild(
280280
writeEmitter.fire(`Workspace is now${updatedWorkspace.latest_build.status}\r\n`)
281281
returnupdatedWorkspace
282282
}
283+
284+
exportasyncfunctionfetchSSHConfig(restClient:Api,vsc:typeofvscode):Promise<SSHConfigResponse>{
285+
try{
286+
constsshConfig=awaitrestClient.getDeploymentSSHConfig()
287+
return{
288+
hostname_prefix:sshConfig.hostname_prefix,
289+
hostname_suffix:sshConfig.hostname_suffix??"coder",
290+
ssh_config_options:sshConfig.ssh_config_options,
291+
}
292+
}catch(error){
293+
if(!isAxiosError(error)){
294+
throwerror
295+
}
296+
switch(error.response?.status){
297+
case404:{
298+
// Very old deployment that doesn't support SSH config
299+
return{
300+
hostname_prefix:"coder",
301+
hostname_suffix:"coder",
302+
ssh_config_options:{},
303+
}
304+
}
305+
case401:{
306+
vsc.window.showErrorMessage("Your session expired...")
307+
throwerror
308+
}
309+
default:
310+
throwerror
311+
}
312+
}
313+
}

‎src/commands.ts

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
import{isAxiosError}from"axios"
21
import{Api}from"coder/site/src/api/api"
32
import{getErrorMessage}from"coder/site/src/api/errors"
43
import{User,Workspace,WorkspaceAgent}from"coder/site/src/api/typesGenerated"
5-
import{lookup}from"dns"
6-
importipRangeCheckfrom"ip-range-check"
7-
import{promisify}from"util"
84
import*asvscodefrom"vscode"
9-
import{makeCoderSdk,needToken}from"./api"
5+
import{fetchSSHConfig,makeCoderSdk,needToken}from"./api"
106
import{extractAgents}from"./api-helper"
117
import{CertificateError}from"./error"
128
import{Storage}from"./storage"
13-
import{toRemoteAuthority,toSafeHost}from"./util"
9+
import{maybeCoderConnectAddr,toRemoteAuthority,toSafeHost}from"./util"
1410
import{OpenableTreeItem}from"./workspacesProvider"
1511

1612
exportclassCommands{
@@ -573,10 +569,10 @@ export class Commands {
573569
// if the workspace is stopped, in which case we can't use Coder Connect
574570
// When called from `open`, the workspaceAgent will always be set.
575571
if(workspaceAgent){
576-
lethostnameSuffix="coder"
572+
letsshConfig
577573
try{
578-
//If the field was undefined, it's an older server, and always 'coder'
579-
hostnameSuffix=(awaitthis.fetchHostnameSuffix())??hostnameSuffix
574+
//Fetch (or get defaults) for the SSH config.
575+
sshConfig=awaitfetchSSHConfig(this.restClient,this.vscodeProposed)
580576
}catch(error){
581577
constmessage=getErrorMessage(error,"no response from the server")
582578
this.storage.writeToCoderOutputChannel(`Failed to open workspace:${message}`)
@@ -592,7 +588,7 @@ export class Commands {
592588
workspaceAgent,
593589
workspaceName,
594590
workspaceOwner,
595-
hostnameSuffix,
591+
sshConfig.hostname_suffix,
596592
)
597593
if(coderConnectAddr){
598594
remoteAuthority=`ssh-remote+${coderConnectAddr}`
@@ -656,42 +652,6 @@ export class Commands {
656652
reuseWindow:!newWindow,
657653
})
658654
}
659-
660-
privateasyncfetchHostnameSuffix():Promise<string|undefined>{
661-
try{
662-
constsshConfig=awaitthis.restClient.getDeploymentSSHConfig()
663-
returnsshConfig.hostname_suffix
664-
}catch(error){
665-
if(!isAxiosError(error)){
666-
throwerror
667-
}
668-
switch(error.response?.status){
669-
case404:{
670-
// Likely a very old deployment, just use the default.
671-
break
672-
}
673-
default:
674-
throwerror
675-
}
676-
}
677-
}
678-
}
679-
680-
asyncfunctionmaybeCoderConnectAddr(
681-
agent:string,
682-
workspace:string,
683-
owner:string,
684-
hostnameSuffix:string,
685-
):Promise<string|undefined>{
686-
constcoderConnectHostname=`${agent}.${workspace}.${owner}.${hostnameSuffix}`
687-
try{
688-
constres=awaitpromisify(lookup)(coderConnectHostname)
689-
// Captive DNS portals may return an unrelated address, so we check it's
690-
// within the Coder Service Prefix.
691-
returnres.family===6&&ipRangeCheck(res.address,"fd60:627a:a42b::/48") ?coderConnectHostname :undefined
692-
}catch{
693-
returnundefined
694-
}
695655
}
696656

697657
asyncfunctionopenDevContainer(

‎src/remote.ts

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import{isAxiosError}from"axios"
22
import{Api}from"coder/site/src/api/api"
3-
import{Workspace}from"coder/site/src/api/typesGenerated"
3+
import{SSHConfigResponse,Workspace}from"coder/site/src/api/typesGenerated"
44
importfindfrom"find-process"
55
import*asfsfrom"fs/promises"
66
import*asjsoncfrom"jsonc-parser"
@@ -9,7 +9,14 @@ import * as path from "path"
99
importprettyBytesfrom"pretty-bytes"
1010
import*assemverfrom"semver"
1111
import*asvscodefrom"vscode"
12-
import{createHttpAgent,makeCoderSdk,needToken,startWorkspaceIfStoppedOrFailed,waitForBuild}from"./api"
12+
import{
13+
createHttpAgent,
14+
fetchSSHConfig,
15+
makeCoderSdk,
16+
needToken,
17+
startWorkspaceIfStoppedOrFailed,
18+
waitForBuild,
19+
}from"./api"
1320
import{extractAgents}from"./api-helper"
1421
import*asclifrom"./cliManager"
1522
import{Commands}from"./commands"
@@ -19,7 +26,7 @@ import { Inbox } from "./inbox"
1926
import{SSHConfig,SSHValues,mergeSSHConfigValues}from"./sshConfig"
2027
import{computeSSHProperties,sshSupportsSetEnv}from"./sshSupport"
2128
import{Storage}from"./storage"
22-
import{AuthorityPrefix,expandPath,parseRemoteAuthority}from"./util"
29+
import{AuthorityPrefix,expandPath,maybeCoderConnectAddr,parseRemoteAuthority}from"./util"
2330
import{WorkspaceMonitor}from"./workspaceMonitor"
2431

2532
exportinterfaceRemoteDetailsextendsvscode.Disposable{
@@ -469,9 +476,19 @@ export class Remote {
469476
//
470477
// If we didn't write to the SSH config file, connecting would fail with
471478
// "Host not found".
479+
letsshConfigResponse:SSHConfigResponse
472480
try{
473481
this.storage.writeToCoderOutputChannel("Updating SSH config...")
474-
awaitthis.updateSSHConfig(workspaceRestClient,parts.label,parts.host,binaryPath,logDir,featureSet)
482+
sshConfigResponse=awaitfetchSSHConfig(workspaceRestClient,this.vscodeProposed)
483+
awaitthis.updateSSHConfig(
484+
workspaceRestClient,
485+
parts.label,
486+
parts.host,
487+
binaryPath,
488+
logDir,
489+
featureSet,
490+
sshConfigResponse,
491+
)
475492
}catch(error){
476493
this.storage.writeToCoderOutputChannel(`Failed to configure SSH:${error}`)
477494
throwerror
@@ -503,6 +520,20 @@ export class Remote {
503520

504521
this.storage.writeToCoderOutputChannel("Remote setup complete")
505522

523+
// If Coder Connect is available for this workspace, switch to that
524+
constcoderConnectAddr=awaitmaybeCoderConnectAddr(
525+
agent.name,
526+
parts.workspace,
527+
parts.username,
528+
sshConfigResponse.hostname_suffix,
529+
)
530+
if(coderConnectAddr){
531+
awaitvscode.commands.executeCommand("vscode.newWindow",{
532+
remoteAuthority:`ssh-remote+${coderConnectAddr}`,
533+
reuseWindow:true,
534+
})
535+
}
536+
506537
// Returning the URL and token allows the plugin to authenticate its own
507538
// client, for example to display the list of workspaces belonging to this
508539
// deployment in the sidebar. We use our own client in here for reasons
@@ -550,30 +581,8 @@ export class Remote {
550581
binaryPath:string,
551582
logDir:string,
552583
featureSet:FeatureSet,
584+
sshConfigResponse:SSHConfigResponse,
553585
){
554-
letdeploymentSSHConfig={}
555-
try{
556-
constdeploymentConfig=awaitrestClient.getDeploymentSSHConfig()
557-
deploymentSSHConfig=deploymentConfig.ssh_config_options
558-
}catch(error){
559-
if(!isAxiosError(error)){
560-
throwerror
561-
}
562-
switch(error.response?.status){
563-
case404:{
564-
// Deployment does not support overriding ssh config yet. Likely an
565-
// older version, just use the default.
566-
break
567-
}
568-
case401:{
569-
awaitthis.vscodeProposed.window.showErrorMessage("Your session expired...")
570-
throwerror
571-
}
572-
default:
573-
throwerror
574-
}
575-
}
576-
577586
// deploymentConfig is now set from the remote coderd deployment.
578587
// Now override with the user's config.
579588
constuserConfigSSH=vscode.workspace.getConfiguration("coder").get<string[]>("sshConfig")||[]
@@ -596,7 +605,7 @@ export class Remote {
596605
},
597606
{}asRecord<string,string>,
598607
)
599-
constsshConfigOverrides=mergeSSHConfigValues(deploymentSSHConfig,userConfig)
608+
constsshConfigOverrides=mergeSSHConfigValues(sshConfigResponse.ssh_config_options,userConfig)
600609

601610
letsshConfigFile=vscode.workspace.getConfiguration().get<string>("remote.SSH.configFile")
602611
if(!sshConfigFile){

‎src/util.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import{lookup}from"dns"
2+
importipRangeCheckfrom"ip-range-check"
13
import*asosfrom"os"
24
importurlfrom"url"
5+
import{promisify}from"util"
36

47
exportinterfaceAuthorityParts{
58
agent:string|undefined
@@ -61,6 +64,23 @@ export function parseRemoteAuthority(authority: string): AuthorityParts | null {
6164
}
6265
}
6366

67+
exportasyncfunctionmaybeCoderConnectAddr(
68+
agent:string,
69+
workspace:string,
70+
owner:string,
71+
hostnameSuffix:string,
72+
):Promise<string|undefined>{
73+
constcoderConnectHostname=`${agent}.${workspace}.${owner}.${hostnameSuffix}`
74+
try{
75+
constres=awaitpromisify(lookup)(coderConnectHostname)
76+
// Captive DNS portals may return an unrelated address, so we check it's
77+
// within the Coder Service Prefix.
78+
returnres.family===6&&ipRangeCheck(res.address,"fd60:627a:a42b::/48") ?coderConnectHostname :undefined
79+
}catch{
80+
returnundefined
81+
}
82+
}
83+
6484
exportfunctiontoRemoteAuthority(
6585
baseUrl:string,
6686
workspaceOwner:string,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp