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

Commit8f02e63

Browse files
authored
feat: use wildcard Host entry in config-ssh (#16096)
Rather than create a separate `Host` entry for every workspace,configure a wildcard such as `coder.*` which can accomodate all of auser's workspaces.Depends on#16088.
1 parent1aa9e32 commit8f02e63

File tree

2 files changed

+192
-431
lines changed

2 files changed

+192
-431
lines changed

‎cli/configssh.go

Lines changed: 75 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cli
33
import (
44
"bufio"
55
"bytes"
6-
"context"
76
"errors"
87
"fmt"
98
"io"
@@ -12,7 +11,6 @@ import (
1211
"os"
1312
"path/filepath"
1413
"runtime"
15-
"sort"
1614
"strconv"
1715
"strings"
1816

@@ -22,11 +20,9 @@ import (
2220
"github.com/pkg/diff/write"
2321
"golang.org/x/exp/constraints"
2422
"golang.org/x/exp/slices"
25-
"golang.org/x/sync/errgroup"
2623
"golang.org/x/xerrors"
2724

2825
"github.com/coder/coder/v2/cli/cliui"
29-
"github.com/coder/coder/v2/coderd/util/slice"
3026
"github.com/coder/coder/v2/codersdk"
3127
"github.com/coder/serpent"
3228
)
@@ -139,74 +135,6 @@ func (o sshConfigOptions) asList() (list []string) {
139135
returnlist
140136
}
141137

142-
typesshWorkspaceConfigstruct {
143-
Namestring
144-
Hosts []string
145-
}
146-
147-
funcsshFetchWorkspaceConfigs(ctx context.Context,client*codersdk.Client) ([]sshWorkspaceConfig,error) {
148-
res,err:=client.Workspaces(ctx, codersdk.WorkspaceFilter{
149-
Owner:codersdk.Me,
150-
})
151-
iferr!=nil {
152-
returnnil,err
153-
}
154-
155-
varerrGroup errgroup.Group
156-
workspaceConfigs:=make([]sshWorkspaceConfig,len(res.Workspaces))
157-
fori,workspace:=rangeres.Workspaces {
158-
i:=i
159-
workspace:=workspace
160-
errGroup.Go(func()error {
161-
resources,err:=client.TemplateVersionResources(ctx,workspace.LatestBuild.TemplateVersionID)
162-
iferr!=nil {
163-
returnerr
164-
}
165-
166-
wc:=sshWorkspaceConfig{Name:workspace.Name}
167-
varagents []codersdk.WorkspaceAgent
168-
for_,resource:=rangeresources {
169-
ifresource.Transition!=codersdk.WorkspaceTransitionStart {
170-
continue
171-
}
172-
agents=append(agents,resource.Agents...)
173-
}
174-
175-
// handle both WORKSPACE and WORKSPACE.AGENT syntax
176-
iflen(agents)==1 {
177-
wc.Hosts=append(wc.Hosts,workspace.Name)
178-
}
179-
for_,agent:=rangeagents {
180-
hostname:=workspace.Name+"."+agent.Name
181-
wc.Hosts=append(wc.Hosts,hostname)
182-
}
183-
184-
workspaceConfigs[i]=wc
185-
186-
returnnil
187-
})
188-
}
189-
err=errGroup.Wait()
190-
iferr!=nil {
191-
returnnil,err
192-
}
193-
194-
returnworkspaceConfigs,nil
195-
}
196-
197-
funcsshPrepareWorkspaceConfigs(ctx context.Context,client*codersdk.Client) (receivefunc() ([]sshWorkspaceConfig,error)) {
198-
wcC:=make(chan []sshWorkspaceConfig,1)
199-
errC:=make(chanerror,1)
200-
gofunc() {
201-
wc,err:=sshFetchWorkspaceConfigs(ctx,client)
202-
wcC<-wc
203-
errC<-err
204-
}()
205-
returnfunc() ([]sshWorkspaceConfig,error) {
206-
return<-wcC,<-errC
207-
}
208-
}
209-
210138
func (r*RootCmd)configSSH()*serpent.Command {
211139
var (
212140
sshConfigFilestring
@@ -254,8 +182,6 @@ func (r *RootCmd) configSSH() *serpent.Command {
254182
// warning at any time.
255183
_,_=client.BuildInfo(ctx)
256184

257-
recvWorkspaceConfigs:=sshPrepareWorkspaceConfigs(ctx,client)
258-
259185
out:=inv.Stdout
260186
ifdryRun {
261187
// Print everything except diff to stderr so
@@ -371,11 +297,6 @@ func (r *RootCmd) configSSH() *serpent.Command {
371297
newline:=len(before)>0
372298
sshConfigWriteSectionHeader(buf,newline,sshConfigOpts)
373299

374-
workspaceConfigs,err:=recvWorkspaceConfigs()
375-
iferr!=nil {
376-
returnxerrors.Errorf("fetch workspace configs failed: %w",err)
377-
}
378-
379300
coderdConfig,err:=client.SSHConfiguration(ctx)
380301
iferr!=nil {
381302
// If the error is 404, this deployment does not support
@@ -394,91 +315,79 @@ func (r *RootCmd) configSSH() *serpent.Command {
394315
coderdConfig.HostnamePrefix=sshConfigOpts.userHostPrefix
395316
}
396317

397-
// Ensure stable sorting of output.
398-
slices.SortFunc(workspaceConfigs,func(a,bsshWorkspaceConfig)int {
399-
returnslice.Ascending(a.Name,b.Name)
400-
})
401-
for_,wc:=rangeworkspaceConfigs {
402-
sort.Strings(wc.Hosts)
403-
// Write agent configuration.
404-
for_,workspaceHostname:=rangewc.Hosts {
405-
sshHostname:=fmt.Sprintf("%s%s",coderdConfig.HostnamePrefix,workspaceHostname)
406-
defaultOptions:= []string{
407-
"HostName "+sshHostname,
408-
"ConnectTimeout=0",
409-
"StrictHostKeyChecking=no",
410-
// Without this, the "REMOTE HOST IDENTITY CHANGED"
411-
// message will appear.
412-
"UserKnownHostsFile=/dev/null",
413-
// This disables the "Warning: Permanently added 'hostname' (RSA) to the list of known hosts."
414-
// message from appearing on every SSH. This happens because we ignore the known hosts.
415-
"LogLevel ERROR",
416-
}
417-
418-
if!skipProxyCommand {
419-
rootFlags:=fmt.Sprintf("--global-config %s",escapedGlobalConfig)
420-
for_,h:=rangesshConfigOpts.header {
421-
rootFlags+=fmt.Sprintf(" --header %q",h)
422-
}
423-
ifsshConfigOpts.headerCommand!="" {
424-
rootFlags+=fmt.Sprintf(" --header-command %q",sshConfigOpts.headerCommand)
425-
}
426-
427-
flags:=""
428-
ifsshConfigOpts.waitEnum!="auto" {
429-
flags+=" --wait="+sshConfigOpts.waitEnum
430-
}
431-
ifsshConfigOpts.disableAutostart {
432-
flags+=" --disable-autostart=true"
433-
}
434-
defaultOptions=append(defaultOptions,fmt.Sprintf(
435-
"ProxyCommand %s %s ssh --stdio%s %s",
436-
escapedCoderBinary,rootFlags,flags,workspaceHostname,
437-
))
438-
}
318+
// Write agent configuration.
319+
defaultOptions:= []string{
320+
"ConnectTimeout=0",
321+
"StrictHostKeyChecking=no",
322+
// Without this, the "REMOTE HOST IDENTITY CHANGED"
323+
// message will appear.
324+
"UserKnownHostsFile=/dev/null",
325+
// This disables the "Warning: Permanently added 'hostname' (RSA) to the list of known hosts."
326+
// message from appearing on every SSH. This happens because we ignore the known hosts.
327+
"LogLevel ERROR",
328+
}
439329

440-
// Create a copy of the options so we can modify them.
441-
configOptions:=sshConfigOpts
442-
configOptions.sshOptions=nil
443-
444-
// User options first (SSH only uses the first
445-
// option unless it can be given multiple times)
446-
for_,opt:=rangesshConfigOpts.sshOptions {
447-
err:=configOptions.addOptions(opt)
448-
iferr!=nil {
449-
returnxerrors.Errorf("add flag config option %q: %w",opt,err)
450-
}
451-
}
330+
if!skipProxyCommand {
331+
rootFlags:=fmt.Sprintf("--global-config %s",escapedGlobalConfig)
332+
for_,h:=rangesshConfigOpts.header {
333+
rootFlags+=fmt.Sprintf(" --header %q",h)
334+
}
335+
ifsshConfigOpts.headerCommand!="" {
336+
rootFlags+=fmt.Sprintf(" --header-command %q",sshConfigOpts.headerCommand)
337+
}
452338

453-
// Deployment options second, allow them to
454-
// override standard options.
455-
fork,v:=rangecoderdConfig.SSHConfigOptions {
456-
opt:=fmt.Sprintf("%s %s",k,v)
457-
err:=configOptions.addOptions(opt)
458-
iferr!=nil {
459-
returnxerrors.Errorf("add coderd config option %q: %w",opt,err)
460-
}
461-
}
339+
flags:=""
340+
ifsshConfigOpts.waitEnum!="auto" {
341+
flags+=" --wait="+sshConfigOpts.waitEnum
342+
}
343+
ifsshConfigOpts.disableAutostart {
344+
flags+=" --disable-autostart=true"
345+
}
346+
defaultOptions=append(defaultOptions,fmt.Sprintf(
347+
"ProxyCommand %s %s ssh --stdio%s --ssh-host-prefix %s %%h",
348+
escapedCoderBinary,rootFlags,flags,coderdConfig.HostnamePrefix,
349+
))
350+
}
462351

463-
// Finally, add the standard options.
464-
err:=configOptions.addOptions(defaultOptions...)
465-
iferr!=nil {
466-
returnerr
467-
}
352+
// Create a copy of the options so we can modify them.
353+
configOptions:=sshConfigOpts
354+
configOptions.sshOptions=nil
468355

469-
hostBlock:= []string{
470-
"Host "+sshHostname,
471-
}
472-
// Prefix with '\t'
473-
for_,v:=rangeconfigOptions.sshOptions {
474-
hostBlock=append(hostBlock,"\t"+v)
475-
}
356+
// User options first (SSH only uses the first
357+
// option unless it can be given multiple times)
358+
for_,opt:=rangesshConfigOpts.sshOptions {
359+
err:=configOptions.addOptions(opt)
360+
iferr!=nil {
361+
returnxerrors.Errorf("add flag config option %q: %w",opt,err)
362+
}
363+
}
476364

477-
_,_=buf.WriteString(strings.Join(hostBlock,"\n"))
478-
_=buf.WriteByte('\n')
365+
// Deployment options second, allow them to
366+
// override standard options.
367+
fork,v:=rangecoderdConfig.SSHConfigOptions {
368+
opt:=fmt.Sprintf("%s %s",k,v)
369+
err:=configOptions.addOptions(opt)
370+
iferr!=nil {
371+
returnxerrors.Errorf("add coderd config option %q: %w",opt,err)
479372
}
480373
}
481374

375+
// Finally, add the standard options.
376+
iferr:=configOptions.addOptions(defaultOptions...);err!=nil {
377+
returnerr
378+
}
379+
380+
hostBlock:= []string{
381+
"Host "+coderdConfig.HostnamePrefix+"*",
382+
}
383+
// Prefix with '\t'
384+
for_,v:=rangeconfigOptions.sshOptions {
385+
hostBlock=append(hostBlock,"\t"+v)
386+
}
387+
388+
_,_=buf.WriteString(strings.Join(hostBlock,"\n"))
389+
_=buf.WriteByte('\n')
390+
482391
sshConfigWriteSectionEnd(buf)
483392

484393
// Write the remainder of the users config file to buf.
@@ -532,9 +441,17 @@ func (r *RootCmd) configSSH() *serpent.Command {
532441
_,_=fmt.Fprintf(out,"Updated %q\n",sshConfigFile)
533442
}
534443

535-
iflen(workspaceConfigs)>0 {
444+
res,err:=client.Workspaces(ctx, codersdk.WorkspaceFilter{
445+
Owner:codersdk.Me,
446+
Limit:1,
447+
})
448+
iferr!=nil {
449+
returnxerrors.Errorf("fetch workspaces failed: %w",err)
450+
}
451+
452+
iflen(res.Workspaces)>0 {
536453
_,_=fmt.Fprintln(out,"You should now be able to ssh into your workspace.")
537-
_,_=fmt.Fprintf(out,"For example, try running:\n\n\t$ ssh %s%s\n",coderdConfig.HostnamePrefix,workspaceConfigs[0].Name)
454+
_,_=fmt.Fprintf(out,"For example, try running:\n\n\t$ ssh %s%s\n",coderdConfig.HostnamePrefix,res.Workspaces[0].Name)
538455
}else {
539456
_,_=fmt.Fprint(out,"You don't have any workspaces yet, try creating one with:\n\n\t$ coder create <workspace>\n")
540457
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp