@@ -42,6 +42,7 @@ import (
42
42
agplschedule "github.com/coder/coder/v2/coderd/schedule"
43
43
"github.com/coder/coder/v2/coderd/schedule/cron"
44
44
"github.com/coder/coder/v2/coderd/util/ptr"
45
+ "github.com/coder/coder/v2/coderd/workspacestats"
45
46
"github.com/coder/coder/v2/codersdk"
46
47
entaudit "github.com/coder/coder/v2/enterprise/audit"
47
48
"github.com/coder/coder/v2/enterprise/audit/backends"
@@ -2767,6 +2768,114 @@ func TestPrebuildUpdateLifecycleParams(t *testing.T) {
2767
2768
}
2768
2769
}
2769
2770
2771
+ func TestPrebuildActivityBump (t * testing.T ) {
2772
+ t .Parallel ()
2773
+
2774
+ clock := quartz .NewMock (t )
2775
+ clock .Set (dbtime .Now ())
2776
+
2777
+ // Setup
2778
+ log := testutil .Logger (t )
2779
+ client , db , owner := coderdenttest .NewWithDatabase (t , & coderdenttest.Options {
2780
+ Options : & coderdtest.Options {
2781
+ IncludeProvisionerDaemon : true ,
2782
+ Clock : clock ,
2783
+ },
2784
+ LicenseOptions : & coderdenttest.LicenseOptions {
2785
+ Features : license.Features {
2786
+ codersdk .FeatureWorkspacePrebuilds : 1 ,
2787
+ },
2788
+ },
2789
+ })
2790
+
2791
+ // Given: a template and a template version with preset and a prebuilt workspace
2792
+ presetID := uuid .New ()
2793
+ version := coderdtest .CreateTemplateVersion (t , client , owner .OrganizationID , nil )
2794
+ _ = coderdtest .AwaitTemplateVersionJobCompleted (t , client , version .ID )
2795
+ // Configure activity bump on the template
2796
+ activityBump := time .Hour
2797
+ template := coderdtest .CreateTemplate (t , client , owner .OrganizationID , version .ID , func (ctr * codersdk.CreateTemplateRequest ) {
2798
+ ctr .ActivityBumpMillis = ptr.Ref [int64 ](activityBump .Milliseconds ())
2799
+ })
2800
+ dbgen .Preset (t , db , database.InsertPresetParams {
2801
+ ID : presetID ,
2802
+ TemplateVersionID : version .ID ,
2803
+ DesiredInstances : sql.NullInt32 {Int32 : 1 , Valid : true },
2804
+ })
2805
+ // Given: a prebuild with an expired Deadline
2806
+ deadline := clock .Now ().Add (- 30 * time .Minute )
2807
+ wb := dbfake .WorkspaceBuild (t , db , database.WorkspaceTable {
2808
+ OwnerID : database .PrebuildsSystemUserID ,
2809
+ TemplateID : template .ID ,
2810
+ }).Seed (database.WorkspaceBuild {
2811
+ TemplateVersionID : version .ID ,
2812
+ TemplateVersionPresetID : uuid.NullUUID {
2813
+ UUID : presetID ,
2814
+ Valid : true ,
2815
+ },
2816
+ Deadline : deadline ,
2817
+ }).WithAgent (func (agent []* proto.Agent ) []* proto.Agent {
2818
+ return agent
2819
+ }).Do ()
2820
+
2821
+ // Mark the prebuilt workspace's agent as ready so the prebuild can be claimed
2822
+ // nolint:gocritic
2823
+ ctx := dbauthz .AsSystemRestricted (testutil .Context (t , testutil .WaitLong ))
2824
+ agent , err := db .GetWorkspaceAgentAndLatestBuildByAuthToken (ctx , uuid .MustParse (wb .AgentToken ))
2825
+ require .NoError (t , err )
2826
+ err = db .UpdateWorkspaceAgentLifecycleStateByID (ctx , database.UpdateWorkspaceAgentLifecycleStateByIDParams {
2827
+ ID : agent .WorkspaceAgent .ID ,
2828
+ LifecycleState : database .WorkspaceAgentLifecycleStateReady ,
2829
+ })
2830
+ require .NoError (t , err )
2831
+
2832
+ // Given: a prebuilt workspace with a Deadline and an empty MaxDeadline
2833
+ prebuild := coderdtest .MustWorkspace (t , client , wb .Workspace .ID )
2834
+ require .Equal (t , deadline .UTC (), prebuild .LatestBuild .Deadline .Time .UTC ())
2835
+ require .Zero (t , prebuild .LatestBuild .MaxDeadline )
2836
+
2837
+ // When: activity bump is applied to an unclaimed prebuild
2838
+ workspacestats .ActivityBumpWorkspace (ctx , log , db , prebuild .ID , clock .Now ().Add (10 * time .Hour ))
2839
+
2840
+ // Then: prebuild Deadline/MaxDeadline remain unchanged
2841
+ prebuild = coderdtest .MustWorkspace (t , client , wb .Workspace .ID )
2842
+ require .Equal (t , deadline .UTC (), prebuild .LatestBuild .Deadline .Time .UTC ())
2843
+ require .Zero (t , prebuild .LatestBuild .MaxDeadline )
2844
+
2845
+ // Given: the prebuilt workspace is claimed by a user
2846
+ user , err := client .User (ctx , "testUser" )
2847
+ require .NoError (t , err )
2848
+ claimedWorkspace , err := client .CreateUserWorkspace (ctx , user .ID .String (), codersdk.CreateWorkspaceRequest {
2849
+ TemplateVersionID : version .ID ,
2850
+ TemplateVersionPresetID : presetID ,
2851
+ Name : coderdtest .RandomUsername (t ),
2852
+ })
2853
+ require .NoError (t , err )
2854
+ coderdtest .AwaitWorkspaceBuildJobCompleted (t , client , claimedWorkspace .LatestBuild .ID )
2855
+ workspace := coderdtest .MustWorkspace (t , client , claimedWorkspace .ID )
2856
+ require .Equal (t , prebuild .ID , workspace .ID )
2857
+ // Claimed workspaces have an empty Deadline and MaxDeadline
2858
+ require .Zero (t , workspace .LatestBuild .Deadline )
2859
+ require .Zero (t , workspace .LatestBuild .MaxDeadline )
2860
+
2861
+ // Given: the claimed workspace has an expired Deadline
2862
+ err = db .UpdateWorkspaceBuildDeadlineByID (ctx , database.UpdateWorkspaceBuildDeadlineByIDParams {
2863
+ ID : workspace .LatestBuild .ID ,
2864
+ Deadline : deadline ,
2865
+ UpdatedAt : clock .Now (),
2866
+ })
2867
+ require .NoError (t , err )
2868
+ workspace = coderdtest .MustWorkspace (t , client , claimedWorkspace .ID )
2869
+
2870
+ // When: activity bump is applied to a claimed prebuild
2871
+ workspacestats .ActivityBumpWorkspace (ctx , log , db , workspace .ID , clock .Now ().Add (10 * time .Hour ))
2872
+
2873
+ // Then: Deadline is extended by the activity bump, MaxDeadline remains unset
2874
+ workspace = coderdtest .MustWorkspace (t , client , claimedWorkspace .ID )
2875
+ require .WithinDuration (t , clock .Now ().Add (activityBump ).UTC (), workspace .LatestBuild .Deadline .Time .UTC (), testutil .WaitMedium )
2876
+ require .Zero (t , workspace .LatestBuild .MaxDeadline )
2877
+ }
2878
+
2770
2879
// TestWorkspaceTemplateParamsChange tests a workspace with a parameter that
2771
2880
// validation changes on apply. The params used in create workspace are invalid
2772
2881
// according to the static params on import.
0 commit comments