@@ -57,7 +57,7 @@ func TestAgent_Stats_SSH(t *testing.T) {
57
57
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
58
58
defer cancel ()
59
59
60
- conn , stats , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
60
+ conn , _ , stats , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
61
61
62
62
sshClient , err := conn .SSHClient (ctx )
63
63
require .NoError (t , err )
@@ -83,7 +83,7 @@ func TestAgent_Stats_ReconnectingPTY(t *testing.T) {
83
83
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
84
84
defer cancel ()
85
85
86
- conn , stats , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
86
+ conn , _ , stats , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
87
87
88
88
ptyConn , err := conn .ReconnectingPTY (ctx , uuid .New (), 128 , 128 , "/bin/bash" )
89
89
require .NoError (t , err )
@@ -531,7 +531,7 @@ func TestAgent_SFTP(t *testing.T) {
531
531
if runtime .GOOS == "windows" {
532
532
home = "/" + strings .ReplaceAll (home , "\\ " , "/" )
533
533
}
534
- conn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
534
+ conn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
535
535
sshClient , err := conn .SSHClient (ctx )
536
536
require .NoError (t , err )
537
537
defer sshClient .Close ()
@@ -562,7 +562,7 @@ func TestAgent_SCP(t *testing.T) {
562
562
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
563
563
defer cancel ()
564
564
565
- conn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
565
+ conn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
566
566
sshClient , err := conn .SSHClient (ctx )
567
567
require .NoError (t , err )
568
568
defer sshClient .Close ()
@@ -666,7 +666,7 @@ func TestAgent_StartupScript(t *testing.T) {
666
666
t .Skip ("This test doesn't work on Windows for some reason..." )
667
667
}
668
668
content := "output"
669
- _ , _ , fs := setupAgent (t , codersdk.WorkspaceAgentMetadata {
669
+ _ , _ , _ , fs := setupAgent (t , codersdk.WorkspaceAgentMetadata {
670
670
StartupScript : "echo " + content ,
671
671
}, 0 )
672
672
var gotContent string
@@ -694,6 +694,97 @@ func TestAgent_StartupScript(t *testing.T) {
694
694
require .Equal (t , content , strings .TrimSpace (gotContent ))
695
695
}
696
696
697
+ func TestAgent_Lifecycle (t * testing.T ) {
698
+ t .Parallel ()
699
+
700
+ t .Run ("Timeout" , func (t * testing.T ) {
701
+ t .Parallel ()
702
+
703
+ _ , client , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {
704
+ StartupScript : "sleep 10" ,
705
+ StartupScriptTimeout : time .Nanosecond ,
706
+ }, 0 )
707
+
708
+ want := []codersdk.WorkspaceAgentLifecycle {
709
+ codersdk .WorkspaceAgentLifecycleStarting ,
710
+ codersdk .WorkspaceAgentLifecycleStartTimeout ,
711
+ }
712
+
713
+ var got []codersdk.WorkspaceAgentLifecycle
714
+ assert .Eventually (t , func () bool {
715
+ got = client .getLifecycleStates ()
716
+ return len (got ) > 0 && got [len (got )- 1 ] == want [len (want )- 1 ]
717
+ }, testutil .WaitShort , testutil .IntervalMedium )
718
+ switch len (got ) {
719
+ case 1 :
720
+ // This can happen if lifecycle states are too
721
+ // fast, only the latest on is reported.
722
+ require .Equal (t , want [1 :], got )
723
+ default :
724
+ // This is the expected case.
725
+ require .Equal (t , want , got )
726
+ }
727
+ })
728
+
729
+ t .Run ("Error" , func (t * testing.T ) {
730
+ t .Parallel ()
731
+
732
+ _ , client , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {
733
+ StartupScript : "false" ,
734
+ StartupScriptTimeout : 30 * time .Second ,
735
+ }, 0 )
736
+
737
+ want := []codersdk.WorkspaceAgentLifecycle {
738
+ codersdk .WorkspaceAgentLifecycleStarting ,
739
+ codersdk .WorkspaceAgentLifecycleStartError ,
740
+ }
741
+
742
+ var got []codersdk.WorkspaceAgentLifecycle
743
+ assert .Eventually (t , func () bool {
744
+ got = client .getLifecycleStates ()
745
+ return len (got ) > 0 && got [len (got )- 1 ] == want [len (want )- 1 ]
746
+ }, testutil .WaitShort , testutil .IntervalMedium )
747
+ switch len (got ) {
748
+ case 1 :
749
+ // This can happen if lifecycle states are too
750
+ // fast, only the latest on is reported.
751
+ require .Equal (t , want [1 :], got )
752
+ default :
753
+ // This is the expected case.
754
+ require .Equal (t , want , got )
755
+ }
756
+ })
757
+
758
+ t .Run ("Ready" , func (t * testing.T ) {
759
+ t .Parallel ()
760
+
761
+ _ , client , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {
762
+ StartupScript : "true" ,
763
+ StartupScriptTimeout : 30 * time .Second ,
764
+ }, 0 )
765
+
766
+ want := []codersdk.WorkspaceAgentLifecycle {
767
+ codersdk .WorkspaceAgentLifecycleStarting ,
768
+ codersdk .WorkspaceAgentLifecycleReady ,
769
+ }
770
+
771
+ var got []codersdk.WorkspaceAgentLifecycle
772
+ assert .Eventually (t , func () bool {
773
+ got = client .getLifecycleStates ()
774
+ return len (got ) > 0 && got [len (got )- 1 ] == want [len (want )- 1 ]
775
+ }, testutil .WaitShort , testutil .IntervalMedium )
776
+ switch len (got ) {
777
+ case 1 :
778
+ // This can happen if lifecycle states are too
779
+ // fast, only the latest on is reported.
780
+ require .Equal (t , want [1 :], got )
781
+ default :
782
+ // This is the expected case.
783
+ require .Equal (t , want , got )
784
+ }
785
+ })
786
+ }
787
+
697
788
func TestAgent_ReconnectingPTY (t * testing.T ) {
698
789
t .Parallel ()
699
790
if runtime .GOOS == "windows" {
@@ -706,7 +797,7 @@ func TestAgent_ReconnectingPTY(t *testing.T) {
706
797
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
707
798
defer cancel ()
708
799
709
- conn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
800
+ conn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
710
801
id := uuid .New ()
711
802
netConn , err := conn .ReconnectingPTY (ctx , id , 100 , 100 , "/bin/bash" )
712
803
require .NoError (t , err )
@@ -807,7 +898,7 @@ func TestAgent_Dial(t *testing.T) {
807
898
}
808
899
}()
809
900
810
- conn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
901
+ conn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
811
902
require .True (t , conn .AwaitReachable (context .Background ()))
812
903
conn1 , err := conn .DialContext (context .Background (), l .Addr ().Network (), l .Addr ().String ())
813
904
require .NoError (t , err )
@@ -828,7 +919,7 @@ func TestAgent_Speedtest(t *testing.T) {
828
919
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
829
920
defer cancel ()
830
921
derpMap := tailnettest .RunDERPAndSTUN (t )
831
- conn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {
922
+ conn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {
832
923
DERPMap : derpMap ,
833
924
}, 0 )
834
925
defer conn .Close ()
@@ -913,7 +1004,7 @@ func TestAgent_WriteVSCodeConfigs(t *testing.T) {
913
1004
}
914
1005
915
1006
func setupSSHCommand (t * testing.T , beforeArgs []string , afterArgs []string ) * exec.Cmd {
916
- agentConn , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
1007
+ agentConn , _ , _ , _ := setupAgent (t , codersdk.WorkspaceAgentMetadata {}, 0 )
917
1008
listener , err := net .Listen ("tcp" , "127.0.0.1:0" )
918
1009
require .NoError (t , err )
919
1010
waitGroup := sync.WaitGroup {}
@@ -959,7 +1050,7 @@ func setupSSHCommand(t *testing.T, beforeArgs []string, afterArgs []string) *exe
959
1050
func setupSSHSession (t * testing.T , options codersdk.WorkspaceAgentMetadata ) * ssh.Session {
960
1051
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
961
1052
defer cancel ()
962
- conn , _ , _ := setupAgent (t , options , 0 )
1053
+ conn , _ , _ , _ := setupAgent (t , options , 0 )
963
1054
sshClient , err := conn .SSHClient (ctx )
964
1055
require .NoError (t , err )
965
1056
t .Cleanup (func () {
@@ -981,6 +1072,7 @@ func (c closeFunc) Close() error {
981
1072
982
1073
func setupAgent (t * testing.T , metadata codersdk.WorkspaceAgentMetadata , ptyTimeout time.Duration ) (
983
1074
* codersdk.AgentConn ,
1075
+ * client ,
984
1076
<- chan * codersdk.AgentStats ,
985
1077
afero.Fs ,
986
1078
) {
@@ -994,14 +1086,15 @@ func setupAgent(t *testing.T, metadata codersdk.WorkspaceAgentMetadata, ptyTimeo
994
1086
agentID := uuid .New ()
995
1087
statsCh := make (chan * codersdk.AgentStats , 50 )
996
1088
fs := afero .NewMemMapFs ()
1089
+ c := & client {
1090
+ t : t ,
1091
+ agentID : agentID ,
1092
+ metadata : metadata ,
1093
+ statsChan : statsCh ,
1094
+ coordinator : coordinator ,
1095
+ }
997
1096
closer := agent .New (agent.Options {
998
- Client : & client {
999
- t : t ,
1000
- agentID : agentID ,
1001
- metadata : metadata ,
1002
- statsChan : statsCh ,
1003
- coordinator : coordinator ,
1004
- },
1097
+ Client : c ,
1005
1098
Filesystem : fs ,
1006
1099
Logger : slogtest .Make (t , nil ).Leveled (slog .LevelDebug ),
1007
1100
ReconnectingPTYTimeout : ptyTimeout ,
@@ -1034,7 +1127,7 @@ func setupAgent(t *testing.T, metadata codersdk.WorkspaceAgentMetadata, ptyTimeo
1034
1127
conn .SetNodeCallback (sendNode )
1035
1128
return & codersdk.AgentConn {
1036
1129
Conn : conn ,
1037
- }, statsCh , fs
1130
+ }, c , statsCh , fs
1038
1131
}
1039
1132
1040
1133
var dialTestPayload = []byte ("dean-was-here123" )
@@ -1075,6 +1168,9 @@ type client struct {
1075
1168
statsChan chan * codersdk.AgentStats
1076
1169
coordinator tailnet.Coordinator
1077
1170
lastWorkspaceAgent func ()
1171
+
1172
+ mu sync.Mutex // Protects following.
1173
+ lifecycleStates []codersdk.WorkspaceAgentLifecycle
1078
1174
}
1079
1175
1080
1176
func (c * client ) WorkspaceAgentMetadata (_ context.Context ) (codersdk.WorkspaceAgentMetadata , error ) {
@@ -1130,7 +1226,16 @@ func (c *client) AgentReportStats(ctx context.Context, _ slog.Logger, stats func
1130
1226
}), nil
1131
1227
}
1132
1228
1133
- func (* client ) PostWorkspaceAgentLifecycle (_ context.Context , _ codersdk.PostWorkspaceAgentLifecycleRequest ) error {
1229
+ func (c * client ) getLifecycleStates () []codersdk.WorkspaceAgentLifecycle {
1230
+ c .mu .Lock ()
1231
+ defer c .mu .Unlock ()
1232
+ return c .lifecycleStates
1233
+ }
1234
+
1235
+ func (c * client ) PostWorkspaceAgentLifecycle (_ context.Context , req codersdk.PostWorkspaceAgentLifecycleRequest ) error {
1236
+ c .mu .Lock ()
1237
+ defer c .mu .Unlock ()
1238
+ c .lifecycleStates = append (c .lifecycleStates , req .State )
1134
1239
return nil
1135
1240
}
1136
1241
0 commit comments