@@ -3,7 +3,6 @@ package cli
3
3
import (
4
4
"bufio"
5
5
"bytes"
6
- "context"
7
6
"errors"
8
7
"fmt"
9
8
"io"
@@ -12,7 +11,6 @@ import (
12
11
"os"
13
12
"path/filepath"
14
13
"runtime"
15
- "sort"
16
14
"strconv"
17
15
"strings"
18
16
@@ -22,11 +20,9 @@ import (
22
20
"github.com/pkg/diff/write"
23
21
"golang.org/x/exp/constraints"
24
22
"golang.org/x/exp/slices"
25
- "golang.org/x/sync/errgroup"
26
23
"golang.org/x/xerrors"
27
24
28
25
"github.com/coder/coder/v2/cli/cliui"
29
- "github.com/coder/coder/v2/coderd/util/slice"
30
26
"github.com/coder/coder/v2/codersdk"
31
27
"github.com/coder/serpent"
32
28
)
@@ -139,74 +135,6 @@ func (o sshConfigOptions) asList() (list []string) {
139
135
return list
140
136
}
141
137
142
- type sshWorkspaceConfig struct {
143
- Name string
144
- Hosts []string
145
- }
146
-
147
- func sshFetchWorkspaceConfigs (ctx context.Context , client * codersdk.Client ) ([]sshWorkspaceConfig , error ) {
148
- res , err := client .Workspaces (ctx , codersdk.WorkspaceFilter {
149
- Owner : codersdk .Me ,
150
- })
151
- if err != nil {
152
- return nil , err
153
- }
154
-
155
- var errGroup errgroup.Group
156
- workspaceConfigs := make ([]sshWorkspaceConfig , len (res .Workspaces ))
157
- for i , workspace := range res .Workspaces {
158
- i := i
159
- workspace := workspace
160
- errGroup .Go (func () error {
161
- resources , err := client .TemplateVersionResources (ctx , workspace .LatestBuild .TemplateVersionID )
162
- if err != nil {
163
- return err
164
- }
165
-
166
- wc := sshWorkspaceConfig {Name : workspace .Name }
167
- var agents []codersdk.WorkspaceAgent
168
- for _ , resource := range resources {
169
- if resource .Transition != codersdk .WorkspaceTransitionStart {
170
- continue
171
- }
172
- agents = append (agents , resource .Agents ... )
173
- }
174
-
175
- // handle both WORKSPACE and WORKSPACE.AGENT syntax
176
- if len (agents ) == 1 {
177
- wc .Hosts = append (wc .Hosts , workspace .Name )
178
- }
179
- for _ , agent := range agents {
180
- hostname := workspace .Name + "." + agent .Name
181
- wc .Hosts = append (wc .Hosts , hostname )
182
- }
183
-
184
- workspaceConfigs [i ] = wc
185
-
186
- return nil
187
- })
188
- }
189
- err = errGroup .Wait ()
190
- if err != nil {
191
- return nil , err
192
- }
193
-
194
- return workspaceConfigs , nil
195
- }
196
-
197
- func sshPrepareWorkspaceConfigs (ctx context.Context , client * codersdk.Client ) (receive func () ([]sshWorkspaceConfig , error )) {
198
- wcC := make (chan []sshWorkspaceConfig , 1 )
199
- errC := make (chan error , 1 )
200
- go func () {
201
- wc , err := sshFetchWorkspaceConfigs (ctx , client )
202
- wcC <- wc
203
- errC <- err
204
- }()
205
- return func () ([]sshWorkspaceConfig , error ) {
206
- return <- wcC , <- errC
207
- }
208
- }
209
-
210
138
func (r * RootCmd ) configSSH () * serpent.Command {
211
139
var (
212
140
sshConfigFile string
@@ -254,8 +182,6 @@ func (r *RootCmd) configSSH() *serpent.Command {
254
182
// warning at any time.
255
183
_ , _ = client .BuildInfo (ctx )
256
184
257
- recvWorkspaceConfigs := sshPrepareWorkspaceConfigs (ctx , client )
258
-
259
185
out := inv .Stdout
260
186
if dryRun {
261
187
// Print everything except diff to stderr so
@@ -371,11 +297,6 @@ func (r *RootCmd) configSSH() *serpent.Command {
371
297
newline := len (before ) > 0
372
298
sshConfigWriteSectionHeader (buf , newline , sshConfigOpts )
373
299
374
- workspaceConfigs , err := recvWorkspaceConfigs ()
375
- if err != nil {
376
- return xerrors .Errorf ("fetch workspace configs failed: %w" , err )
377
- }
378
-
379
300
coderdConfig , err := client .SSHConfiguration (ctx )
380
301
if err != nil {
381
302
// If the error is 404, this deployment does not support
@@ -394,91 +315,79 @@ func (r *RootCmd) configSSH() *serpent.Command {
394
315
coderdConfig .HostnamePrefix = sshConfigOpts .userHostPrefix
395
316
}
396
317
397
- // Ensure stable sorting of output.
398
- slices .SortFunc (workspaceConfigs , func (a , b sshWorkspaceConfig ) int {
399
- return slice .Ascending (a .Name , b .Name )
400
- })
401
- for _ , wc := range workspaceConfigs {
402
- sort .Strings (wc .Hosts )
403
- // Write agent configuration.
404
- for _ , workspaceHostname := range wc .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 := range sshConfigOpts .header {
421
- rootFlags += fmt .Sprintf (" --header %q" , h )
422
- }
423
- if sshConfigOpts .headerCommand != "" {
424
- rootFlags += fmt .Sprintf (" --header-command %q" , sshConfigOpts .headerCommand )
425
- }
426
-
427
- flags := ""
428
- if sshConfigOpts .waitEnum != "auto" {
429
- flags += " --wait=" + sshConfigOpts .waitEnum
430
- }
431
- if sshConfigOpts .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
+ }
439
329
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 := range sshConfigOpts .sshOptions {
447
- err := configOptions .addOptions (opt )
448
- if err != nil {
449
- return xerrors .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 := range sshConfigOpts .header {
333
+ rootFlags += fmt .Sprintf (" --header %q" , h )
334
+ }
335
+ if sshConfigOpts .headerCommand != "" {
336
+ rootFlags += fmt .Sprintf (" --header-command %q" , sshConfigOpts .headerCommand )
337
+ }
452
338
453
- // Deployment options second, allow them to
454
- // override standard options.
455
- for k , v := range coderdConfig .SSHConfigOptions {
456
- opt := fmt .Sprintf ("%s %s" , k , v )
457
- err := configOptions .addOptions (opt )
458
- if err != nil {
459
- return xerrors .Errorf ("add coderd config option %q: %w" , opt , err )
460
- }
461
- }
339
+ flags := ""
340
+ if sshConfigOpts .waitEnum != "auto" {
341
+ flags += " --wait=" + sshConfigOpts .waitEnum
342
+ }
343
+ if sshConfigOpts .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
+ }
462
351
463
- // Finally, add the standard options.
464
- err := configOptions .addOptions (defaultOptions ... )
465
- if err != nil {
466
- return err
467
- }
352
+ // Create a copy of the options so we can modify them.
353
+ configOptions := sshConfigOpts
354
+ configOptions .sshOptions = nil
468
355
469
- hostBlock := []string {
470
- "Host " + sshHostname ,
471
- }
472
- // Prefix with '\t'
473
- for _ , v := range configOptions .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 := range sshConfigOpts .sshOptions {
359
+ err := configOptions .addOptions (opt )
360
+ if err != nil {
361
+ return xerrors .Errorf ("add flag config option %q: %w" , opt , err )
362
+ }
363
+ }
476
364
477
- _ , _ = buf .WriteString (strings .Join (hostBlock , "\n " ))
478
- _ = buf .WriteByte ('\n' )
365
+ // Deployment options second, allow them to
366
+ // override standard options.
367
+ for k , v := range coderdConfig .SSHConfigOptions {
368
+ opt := fmt .Sprintf ("%s %s" , k , v )
369
+ err := configOptions .addOptions (opt )
370
+ if err != nil {
371
+ return xerrors .Errorf ("add coderd config option %q: %w" , opt , err )
479
372
}
480
373
}
481
374
375
+ // Finally, add the standard options.
376
+ if err := configOptions .addOptions (defaultOptions ... ); err != nil {
377
+ return err
378
+ }
379
+
380
+ hostBlock := []string {
381
+ "Host " + coderdConfig .HostnamePrefix + "*" ,
382
+ }
383
+ // Prefix with '\t'
384
+ for _ , v := range configOptions .sshOptions {
385
+ hostBlock = append (hostBlock , "\t " + v )
386
+ }
387
+
388
+ _ , _ = buf .WriteString (strings .Join (hostBlock , "\n " ))
389
+ _ = buf .WriteByte ('\n' )
390
+
482
391
sshConfigWriteSectionEnd (buf )
483
392
484
393
// Write the remainder of the users config file to buf.
@@ -532,9 +441,17 @@ func (r *RootCmd) configSSH() *serpent.Command {
532
441
_ , _ = fmt .Fprintf (out , "Updated %q\n " , sshConfigFile )
533
442
}
534
443
535
- if len (workspaceConfigs ) > 0 {
444
+ res , err := client .Workspaces (ctx , codersdk.WorkspaceFilter {
445
+ Owner : codersdk .Me ,
446
+ Limit : 1 ,
447
+ })
448
+ if err != nil {
449
+ return xerrors .Errorf ("fetch workspaces failed: %w" , err )
450
+ }
451
+
452
+ if len (res .Workspaces ) > 0 {
536
453
_ , _ = 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 )
538
455
} else {
539
456
_ , _ = fmt .Fprint (out , "You don't have any workspaces yet, try creating one with:\n \n \t $ coder create <workspace>\n " )
540
457
}
0 commit comments