@@ -192,7 +192,7 @@ func TestAgent_Stats_Magic(t *testing.T) {
192
192
193
193
func TestAgent_SessionExec (t * testing.T ) {
194
194
t .Parallel ()
195
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
195
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
196
196
197
197
command := "echo test"
198
198
if runtime .GOOS == "windows" {
@@ -205,7 +205,7 @@ func TestAgent_SessionExec(t *testing.T) {
205
205
206
206
func TestAgent_GitSSH (t * testing.T ) {
207
207
t .Parallel ()
208
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
208
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
209
209
command := "sh -c 'echo $GIT_SSH_COMMAND'"
210
210
if runtime .GOOS == "windows" {
211
211
command = "cmd.exe /c echo %GIT_SSH_COMMAND%"
@@ -225,7 +225,7 @@ func TestAgent_SessionTTYShell(t *testing.T) {
225
225
// it seems like it could be either.
226
226
t .Skip ("ConPTY appears to be inconsistent on Windows." )
227
227
}
228
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
228
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
229
229
command := "sh"
230
230
if runtime .GOOS == "windows" {
231
231
command = "cmd.exe"
@@ -248,7 +248,7 @@ func TestAgent_SessionTTYShell(t *testing.T) {
248
248
249
249
func TestAgent_SessionTTYExitCode (t * testing.T ) {
250
250
t .Parallel ()
251
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
251
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
252
252
command := "areallynotrealcommand"
253
253
err := session .RequestPty ("xterm" , 128 , 128 , ssh.TerminalModes {})
254
254
require .NoError (t , err )
@@ -268,25 +268,22 @@ func TestAgent_SessionTTYExitCode(t *testing.T) {
268
268
}
269
269
}
270
270
271
- //nolint:paralleltest // This test sets an environment variable.
272
271
func TestAgent_Session_TTY_MOTD (t * testing.T ) {
272
+ t .Parallel ()
273
273
if runtime .GOOS == "windows" {
274
274
// This might be our implementation, or ConPTY itself.
275
275
// It's difficult to find extensive tests for it, so
276
276
// it seems like it could be either.
277
277
t .Skip ("ConPTY appears to be inconsistent on Windows." )
278
278
}
279
279
280
- wantMOTD := "Welcome to your Coder workspace!"
281
- wantServiceBanner := "Service banner text goes here"
280
+ u , err := user . Current ()
281
+ require . NoError ( t , err , "get current user" )
282
282
283
- tmpdir := t .TempDir ()
284
- name := filepath .Join (tmpdir , "motd" )
285
- err := os .WriteFile (name , []byte (wantMOTD ), 0o600 )
286
- require .NoError (t , err , "write motd file" )
283
+ name := filepath .Join (u .HomeDir , "motd" )
287
284
288
- // Set HOME so we can ensure no ~/.hushlogin is present.
289
- t . Setenv ( "HOME" , tmpdir )
285
+ wantMOTD := "Welcome to your Coder workspace!"
286
+ wantServiceBanner := "Service banner text goes here"
290
287
291
288
tests := []struct {
292
289
name string
@@ -362,14 +359,20 @@ func TestAgent_Session_TTY_MOTD(t *testing.T) {
362
359
for _ , test := range tests {
363
360
test := test
364
361
t .Run (test .name , func (t * testing.T ) {
365
- session := setupSSHSession (t , test .manifest , test .banner )
362
+ t .Parallel ()
363
+ session := setupSSHSession (t , test .manifest , test .banner , func (fs afero.Fs ) {
364
+ err := fs .MkdirAll (filepath .Dir (name ), 0o700 )
365
+ require .NoError (t , err )
366
+ err = afero .WriteFile (fs , name , []byte (wantMOTD ), 0o600 )
367
+ require .NoError (t , err )
368
+ })
366
369
testSessionOutput (t , session , test .expected , test .unexpected , test .expectedRe )
367
370
})
368
371
}
369
372
}
370
373
371
- //nolint:paralleltest // This test sets an environment variable.
372
374
func TestAgent_Session_TTY_MOTD_Update (t * testing.T ) {
375
+ t .Parallel ()
373
376
if runtime .GOOS == "windows" {
374
377
// This might be our implementation, or ConPTY itself.
375
378
// It's difficult to find extensive tests for it, so
@@ -380,11 +383,6 @@ func TestAgent_Session_TTY_MOTD_Update(t *testing.T) {
380
383
// Only the banner updates dynamically; the MOTD file does not.
381
384
wantServiceBanner := "Service banner text goes here"
382
385
383
- tmpdir := t .TempDir ()
384
-
385
- // Set HOME so we can ensure no ~/.hushlogin is present.
386
- t .Setenv ("HOME" , tmpdir )
387
-
388
386
tests := []struct {
389
387
banner codersdk.ServiceBannerConfig
390
388
expected []string
@@ -424,22 +422,25 @@ func TestAgent_Session_TTY_MOTD_Update(t *testing.T) {
424
422
},
425
423
}
426
424
427
- const updateInterval = 100 * time .Millisecond
428
-
429
425
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
430
426
defer cancel ()
431
427
//nolint:dogsled // Allow the blank identifiers.
432
428
conn , client , _ , _ , _ := setupAgent (t , & client {}, 0 )
433
429
for _ , test := range tests {
434
430
test := test
435
- // Set new banner func and wait for the agent to call it to update the
436
- // banner.
431
+
432
+ ready := make ( chan struct {}, 2 )
437
433
client .mu .Lock ()
438
434
client .getServiceBanner = func () (codersdk.ServiceBannerConfig , error ) {
435
+ select {
436
+ case ready <- struct {}{}:
437
+ default :
438
+ }
439
439
return test .banner , nil
440
440
}
441
441
client .mu .Unlock ()
442
- time .Sleep (updateInterval )
442
+ <- ready
443
+ <- ready // Wait for two updates to ensure the value has propagated.
443
444
444
445
sshClient , err := conn .SSHClient (ctx )
445
446
require .NoError (t , err )
@@ -466,50 +467,51 @@ func TestAgent_Session_TTY_QuietLogin(t *testing.T) {
466
467
}
467
468
468
469
wantNotMOTD := "Welcome to your Coder workspace!"
469
- wantServiceBanner := "Service banner text goes here"
470
+ wantMaybeServiceBanner := "Service banner text goes here"
470
471
471
- tmpdir := t .TempDir ()
472
- name := filepath .Join (tmpdir , "motd" )
473
- err := os .WriteFile (name , []byte (wantNotMOTD ), 0o600 )
474
- require .NoError (t , err , "write motd file" )
472
+ u , err := user .Current ()
473
+ require .NoError (t , err , "get current user" )
475
474
476
- // Set HOME so we can ensure ~/.hushlogin is present.
477
- t .Setenv ("HOME" , tmpdir )
475
+ name := filepath .Join (u .HomeDir , "motd" )
478
476
479
477
// Neither banner nor MOTD should show if not a login shell.
480
478
t .Run ("NotLogin" , func (t * testing.T ) {
481
- wantEcho := "foobar"
482
479
session := setupSSHSession (t , agentsdk.Manifest {
483
480
MOTDFile : name ,
484
481
}, codersdk.ServiceBannerConfig {
485
482
Enabled : true ,
486
- Message : wantServiceBanner ,
483
+ Message : wantMaybeServiceBanner ,
484
+ }, func (fs afero.Fs ) {
485
+ err := afero .WriteFile (fs , name , []byte (wantNotMOTD ), 0o600 )
486
+ require .NoError (t , err , "write motd file" )
487
487
})
488
488
err = session .RequestPty ("xterm" , 128 , 128 , ssh.TerminalModes {})
489
489
require .NoError (t , err )
490
490
491
+ wantEcho := "foobar"
491
492
command := "echo " + wantEcho
492
493
output , err := session .Output (command )
493
494
require .NoError (t , err )
494
495
495
496
require .Contains (t , string (output ), wantEcho , "should show echo" )
496
497
require .NotContains (t , string (output ), wantNotMOTD , "should not show motd" )
497
- require .NotContains (t , string (output ), wantServiceBanner , "should not show service banner" )
498
+ require .NotContains (t , string (output ), wantMaybeServiceBanner , "should not show service banner" )
498
499
})
499
500
500
- // Only the MOTD should be silenced.
501
+ // Only the MOTD should be silenced when hushlogin is present .
501
502
t .Run ("Hushlogin" , func (t * testing.T ) {
502
- // Create hushlogin to silence motd.
503
- f , err := os .Create (filepath .Join (tmpdir , ".hushlogin" ))
504
- require .NoError (t , err , "create .hushlogin file" )
505
- err = f .Close ()
506
- require .NoError (t , err , "close .hushlogin file" )
507
-
508
503
session := setupSSHSession (t , agentsdk.Manifest {
509
504
MOTDFile : name ,
510
505
}, codersdk.ServiceBannerConfig {
511
506
Enabled : true ,
512
- Message : wantServiceBanner ,
507
+ Message : wantMaybeServiceBanner ,
508
+ }, func (fs afero.Fs ) {
509
+ err := afero .WriteFile (fs , name , []byte (wantNotMOTD ), 0o600 )
510
+ require .NoError (t , err , "write motd file" )
511
+
512
+ // Create hushlogin to silence motd.
513
+ err = afero .WriteFile (fs , name , []byte {}, 0o600 )
514
+ require .NoError (t , err , "write hushlogin file" )
513
515
})
514
516
err = session .RequestPty ("xterm" , 128 , 128 , ssh.TerminalModes {})
515
517
require .NoError (t , err )
@@ -527,7 +529,7 @@ func TestAgent_Session_TTY_QuietLogin(t *testing.T) {
527
529
require .NoError (t , err )
528
530
529
531
require .NotContains (t , stdout .String (), wantNotMOTD , "should not show motd" )
530
- require .Contains (t , stdout .String (), wantServiceBanner , "should show service banner" )
532
+ require .Contains (t , stdout .String (), wantMaybeServiceBanner , "should show service banner" )
531
533
})
532
534
}
533
535
@@ -975,7 +977,7 @@ func TestAgent_EnvironmentVariables(t *testing.T) {
975
977
EnvironmentVariables : map [string ]string {
976
978
key : value ,
977
979
},
978
- }, codersdk.ServiceBannerConfig {})
980
+ }, codersdk.ServiceBannerConfig {}, nil )
979
981
command := "sh -c 'echo $" + key + "'"
980
982
if runtime .GOOS == "windows" {
981
983
command = "cmd.exe /c echo %" + key + "%"
@@ -992,7 +994,7 @@ func TestAgent_EnvironmentVariableExpansion(t *testing.T) {
992
994
EnvironmentVariables : map [string ]string {
993
995
key : "$SOMETHINGNOTSET" ,
994
996
},
995
- }, codersdk.ServiceBannerConfig {})
997
+ }, codersdk.ServiceBannerConfig {}, nil )
996
998
command := "sh -c 'echo $" + key + "'"
997
999
if runtime .GOOS == "windows" {
998
1000
command = "cmd.exe /c echo %" + key + "%"
@@ -1015,7 +1017,7 @@ func TestAgent_CoderEnvVars(t *testing.T) {
1015
1017
t .Run (key , func (t * testing.T ) {
1016
1018
t .Parallel ()
1017
1019
1018
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
1020
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
1019
1021
command := "sh -c 'echo $" + key + "'"
1020
1022
if runtime .GOOS == "windows" {
1021
1023
command = "cmd.exe /c echo %" + key + "%"
@@ -1038,7 +1040,7 @@ func TestAgent_SSHConnectionEnvVars(t *testing.T) {
1038
1040
t .Run (key , func (t * testing.T ) {
1039
1041
t .Parallel ()
1040
1042
1041
- session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {})
1043
+ session := setupSSHSession (t , agentsdk.Manifest {}, codersdk.ServiceBannerConfig {}, nil )
1042
1044
command := "sh -c 'echo $" + key + "'"
1043
1045
if runtime .GOOS == "windows" {
1044
1046
command = "cmd.exe /c echo %" + key + "%"
@@ -1876,16 +1878,20 @@ func setupSSHSession(
1876
1878
t * testing.T ,
1877
1879
options agentsdk.Manifest ,
1878
1880
serviceBanner codersdk.ServiceBannerConfig ,
1881
+ prepareFS func (fs afero.Fs ),
1879
1882
) * ssh.Session {
1880
1883
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
1881
1884
defer cancel ()
1882
1885
//nolint:dogsled
1883
- conn , _ , _ , _ , _ := setupAgent (t , & client {
1886
+ conn , _ , _ , fs , _ := setupAgent (t , & client {
1884
1887
manifest : options ,
1885
1888
getServiceBanner : func () (codersdk.ServiceBannerConfig , error ) {
1886
1889
return serviceBanner , nil
1887
1890
},
1888
1891
}, 0 )
1892
+ if prepareFS != nil {
1893
+ prepareFS (fs )
1894
+ }
1889
1895
sshClient , err := conn .SSHClient (ctx )
1890
1896
require .NoError (t , err )
1891
1897
t .Cleanup (func () {
0 commit comments