@@ -766,6 +766,94 @@ func TestPostWorkspacesByOrganization(t *testing.T) {
766
766
require .NoError (t ,err )
767
767
require .EqualValues (t ,exp ,* ws .TTLMillis )
768
768
})
769
+
770
+ t .Run ("NoProvisionersAvailable" ,func (t * testing.T ) {
771
+ t .Parallel ()
772
+ if ! dbtestutil .WillUsePostgres () {
773
+ t .Skip ("this test requires postgres" )
774
+ }
775
+ // Given: a coderd instance with a provisioner daemon
776
+ store ,ps ,db := dbtestutil .NewDBWithSQLDB (t )
777
+ client ,closeDaemon := coderdtest .NewWithProvisionerCloser (t ,& coderdtest.Options {
778
+ Database :store ,
779
+ Pubsub :ps ,
780
+ IncludeProvisionerDaemon :true ,
781
+ })
782
+ defer closeDaemon .Close ()
783
+
784
+ // Given: a user, template, and workspace
785
+ user := coderdtest .CreateFirstUser (t ,client )
786
+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
787
+ coderdtest .AwaitTemplateVersionJobCompleted (t ,client ,version .ID )
788
+ template := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID )
789
+
790
+ // Given: all the provisioner daemons disappear
791
+ ctx := testutil .Context (t ,testutil .WaitLong )
792
+ _ ,err := db .ExecContext (ctx ,`DELETE FROM provisioner_daemons;` )
793
+ require .NoError (t ,err )
794
+
795
+ // When: a new workspace is created
796
+ ws ,err := client .CreateUserWorkspace (ctx ,codersdk .Me , codersdk.CreateWorkspaceRequest {
797
+ TemplateID :template .ID ,
798
+ Name :"testing" ,
799
+ })
800
+ // Then: the request succeeds
801
+ require .NoError (t ,err )
802
+ // Then: the workspace build is pending
803
+ require .Equal (t ,codersdk .ProvisionerJobPending ,ws .LatestBuild .Job .Status )
804
+ // Then: the workspace build has no matched provisioners
805
+ if assert .NotNil (t ,ws .LatestBuild .MatchedProvisioners ) {
806
+ assert .Zero (t ,ws .LatestBuild .MatchedProvisioners .Count )
807
+ assert .Zero (t ,ws .LatestBuild .MatchedProvisioners .Available )
808
+ assert .Zero (t ,ws .LatestBuild .MatchedProvisioners .MostRecentlySeen .Time )
809
+ assert .False (t ,ws .LatestBuild .MatchedProvisioners .MostRecentlySeen .Valid )
810
+ }
811
+ })
812
+
813
+ t .Run ("AllProvisionersStale" ,func (t * testing.T ) {
814
+ t .Parallel ()
815
+ if ! dbtestutil .WillUsePostgres () {
816
+ t .Skip ("this test requires postgres" )
817
+ }
818
+
819
+ // Given: a coderd instance with a provisioner daemon
820
+ store ,ps ,db := dbtestutil .NewDBWithSQLDB (t )
821
+ client ,closeDaemon := coderdtest .NewWithProvisionerCloser (t ,& coderdtest.Options {
822
+ Database :store ,
823
+ Pubsub :ps ,
824
+ IncludeProvisionerDaemon :true ,
825
+ })
826
+ defer closeDaemon .Close ()
827
+
828
+ // Given: a user, template, and workspace
829
+ user := coderdtest .CreateFirstUser (t ,client )
830
+ version := coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,nil )
831
+ coderdtest .AwaitTemplateVersionJobCompleted (t ,client ,version .ID )
832
+ template := coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID )
833
+
834
+ // Given: all the provisioner daemons have not been seen for a while
835
+ ctx := testutil .Context (t ,testutil .WaitLong )
836
+ newLastSeenAt := dbtime .Now ().Add (- time .Hour )
837
+ _ ,err := db .ExecContext (ctx ,`UPDATE provisioner_daemons SET last_seen_at = $1;` ,newLastSeenAt )
838
+ require .NoError (t ,err )
839
+
840
+ // When: a new workspace is created
841
+ ws ,err := client .CreateUserWorkspace (ctx ,codersdk .Me , codersdk.CreateWorkspaceRequest {
842
+ TemplateID :template .ID ,
843
+ Name :"testing" ,
844
+ })
845
+ // Then: the request succeeds
846
+ require .NoError (t ,err )
847
+ // Then: the workspace build is pending
848
+ require .Equal (t ,codersdk .ProvisionerJobPending ,ws .LatestBuild .Job .Status )
849
+ // Then: we can see that there are some provisioners that are stale
850
+ if assert .NotNil (t ,ws .LatestBuild .MatchedProvisioners ) {
851
+ assert .Equal (t ,1 ,ws .LatestBuild .MatchedProvisioners .Count )
852
+ assert .Zero (t ,ws .LatestBuild .MatchedProvisioners .Available )
853
+ assert .Equal (t ,newLastSeenAt .UTC (),ws .LatestBuild .MatchedProvisioners .MostRecentlySeen .Time .UTC ())
854
+ assert .True (t ,ws .LatestBuild .MatchedProvisioners .MostRecentlySeen .Valid )
855
+ }
856
+ })
769
857
}
770
858
771
859
func TestWorkspaceByOwnerAndName (t * testing.T ) {