Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit29cc88e

Browse files
committed
test: add cancel pending prebuilds to template version active version
1 parented0e3ab commit29cc88e

File tree

2 files changed

+256
-9
lines changed

2 files changed

+256
-9
lines changed

‎coderd/database/dbfake/dbfake.go‎

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,10 @@ type WorkspaceBuildBuilder struct {
5555
resources []*sdkproto.Resource
5656
params []database.WorkspaceBuildParameter
5757
agentTokenstring
58-
dispoworkspaceBuildDisposition
58+
jobStatus database.ProvisionerJobStatus
5959
taskAppID uuid.UUID
6060
}
6161

62-
typeworkspaceBuildDispositionstruct {
63-
startingbool
64-
}
65-
6662
// WorkspaceBuild generates a workspace build for the provided workspace.
6763
// Pass a database.Workspace{} with a nil ID to also generate a new workspace.
6864
// Omitting the template ID on a workspace will also generate a new template
@@ -141,8 +137,17 @@ func (b WorkspaceBuildBuilder) WithTask(seed *sdkproto.App) WorkspaceBuildBuilde
141137
}
142138

143139
func (bWorkspaceBuildBuilder)Starting()WorkspaceBuildBuilder {
144-
//nolint: revive // returns modified struct
145-
b.dispo.starting=true
140+
b.jobStatus=database.ProvisionerJobStatusRunning
141+
returnb
142+
}
143+
144+
func (bWorkspaceBuildBuilder)Pending()WorkspaceBuildBuilder {
145+
b.jobStatus=database.ProvisionerJobStatusPending
146+
returnb
147+
}
148+
149+
func (bWorkspaceBuildBuilder)Canceled()WorkspaceBuildBuilder {
150+
b.jobStatus=database.ProvisionerJobStatusCanceled
146151
returnb
147152
}
148153

@@ -227,7 +232,11 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
227232
require.NoError(b.t,err,"insert job")
228233
b.logger.Debug(context.Background(),"inserted provisioner job",slog.F("job_id",job.ID))
229234

230-
ifb.dispo.starting {
235+
switchb.jobStatus {
236+
casedatabase.ProvisionerJobStatusPending:
237+
// Created provisioner jobs are created in pending status
238+
b.logger.Debug(context.Background(),"pending the provisioner job")
239+
casedatabase.ProvisionerJobStatusRunning:
231240
// might need to do this multiple times if we got a template version
232241
// import job as well
233242
b.logger.Debug(context.Background(),"looping to acquire provisioner job")
@@ -251,7 +260,22 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
251260
break
252261
}
253262
}
254-
}else {
263+
casedatabase.ProvisionerJobStatusCanceled:
264+
b.logger.Debug(context.Background(),"canceling the provisioner job")
265+
err=b.db.UpdateProvisionerJobWithCancelByID(ownerCtx, database.UpdateProvisionerJobWithCancelByIDParams{
266+
ID:jobID,
267+
CanceledAt: sql.NullTime{
268+
Time:dbtime.Now(),
269+
Valid:true,
270+
},
271+
CompletedAt: sql.NullTime{
272+
Time:dbtime.Now(),
273+
Valid:true,
274+
},
275+
})
276+
require.NoError(b.t,err,"cancel job")
277+
default:
278+
// By default, consider jobs in 'succeeded' status
255279
b.logger.Debug(context.Background(),"completing the provisioner job")
256280
err=b.db.UpdateProvisionerJobWithCompleteByID(ownerCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
257281
ID:job.ID,
@@ -543,6 +567,12 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
543567
t.params[i]=dbgen.TemplateVersionParameter(t.t,t.db,param)
544568
}
545569

570+
// Update response with template and version
571+
ifresp.Template.ID==uuid.Nil&&version.TemplateID.Valid {
572+
template,err:=t.db.GetTemplateByID(ownerCtx,version.TemplateID.UUID)
573+
require.NoError(t.t,err)
574+
resp.Template=template
575+
}
546576
resp.TemplateVersion=version
547577
returnresp
548578
}

‎coderd/templateversions_test.go‎

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"regexp"
88
"strings"
99
"testing"
10+
"time"
1011

1112
"github.com/google/uuid"
1213
"github.com/stretchr/testify/assert"
@@ -17,6 +18,7 @@ import (
1718
"github.com/coder/coder/v2/coderd/coderdtest"
1819
"github.com/coder/coder/v2/coderd/database"
1920
"github.com/coder/coder/v2/coderd/database/dbauthz"
21+
"github.com/coder/coder/v2/coderd/database/dbfake"
2022
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2123
"github.com/coder/coder/v2/coderd/externalauth"
2224
"github.com/coder/coder/v2/coderd/rbac"
@@ -27,6 +29,7 @@ import (
2729
"github.com/coder/coder/v2/provisionersdk"
2830
"github.com/coder/coder/v2/provisionersdk/proto"
2931
"github.com/coder/coder/v2/testutil"
32+
"github.com/coder/quartz"
3033
)
3134

3235
funcTestTemplateVersion(t*testing.T) {
@@ -1194,6 +1197,220 @@ func TestPatchActiveTemplateVersion(t *testing.T) {
11941197
require.Len(t,auditor.AuditLogs(),6)
11951198
assert.Equal(t,database.AuditActionWrite,auditor.AuditLogs()[5].Action)
11961199
})
1200+
1201+
t.Run("CancelPendingPrebuilds",func(t*testing.T) {
1202+
t.Parallel()
1203+
1204+
for_,tt:=range []struct {
1205+
namestring
1206+
setupBuildfunc(
1207+
t*testing.T,
1208+
db database.Store,
1209+
client*codersdk.Client,
1210+
orgID uuid.UUID,
1211+
templateID uuid.UUID,
1212+
) dbfake.WorkspaceResponse
1213+
previouslyCanceledbool
1214+
previouslyCompletedbool
1215+
shouldCancelbool
1216+
}{
1217+
// Should cancel pending prebuild-related jobs from the previous template version
1218+
{
1219+
name:"CancelsPendingPrebuildJobFromPreviousVersion",
1220+
// Given: a pending prebuild job
1221+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1222+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1223+
OwnerID:database.PrebuildsSystemUserID,
1224+
OrganizationID:orgID,
1225+
TemplateID:templateID,
1226+
}).Pending().Seed(database.WorkspaceBuild{
1227+
InitiatorID:database.PrebuildsSystemUserID,
1228+
}).Do()
1229+
},
1230+
previouslyCanceled:false,
1231+
previouslyCompleted:false,
1232+
shouldCancel:true,
1233+
},
1234+
// Should not cancel pending prebuild-related jobs of a different template
1235+
{
1236+
name:"DoesNotCancelPrebuildJobDifferentTemplate",
1237+
// Given: a pending prebuild job belonging to a different template
1238+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1239+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1240+
OwnerID:database.PrebuildsSystemUserID,
1241+
OrganizationID:orgID,
1242+
TemplateID:uuid.Nil,
1243+
}).Pending().Seed(database.WorkspaceBuild{
1244+
InitiatorID:database.PrebuildsSystemUserID,
1245+
}).Do()
1246+
},
1247+
previouslyCanceled:false,
1248+
previouslyCompleted:false,
1249+
shouldCancel:false,
1250+
},
1251+
// Should not cancel pending user workspace build jobs
1252+
{
1253+
name:"DoesNotCancelUserWorkspaceJob",
1254+
// Given: a pending user workspace build job
1255+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1256+
_,member:=coderdtest.CreateAnotherUser(t,client,orgID,rbac.RoleMember())
1257+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1258+
OwnerID:member.ID,
1259+
OrganizationID:orgID,
1260+
TemplateID:uuid.Nil,
1261+
}).Pending().Seed(database.WorkspaceBuild{
1262+
InitiatorID:member.ID,
1263+
}).Do()
1264+
},
1265+
previouslyCanceled:false,
1266+
previouslyCompleted:false,
1267+
shouldCancel:false,
1268+
},
1269+
// Should not cancel pending prebuild-related jobs with a delete transition
1270+
{
1271+
name:"DoesNotCancelPrebuildJobDeleteTransition",
1272+
// Given: a pending prebuild job with a delete transition
1273+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1274+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1275+
OwnerID:database.PrebuildsSystemUserID,
1276+
OrganizationID:orgID,
1277+
TemplateID:templateID,
1278+
}).Pending().Seed(database.WorkspaceBuild{
1279+
InitiatorID:database.PrebuildsSystemUserID,
1280+
Transition:database.WorkspaceTransitionDelete,
1281+
}).Do()
1282+
},
1283+
previouslyCanceled:false,
1284+
previouslyCompleted:false,
1285+
shouldCancel:false,
1286+
},
1287+
// Should not cancel prebuild-related jobs already being processed by a provisioner
1288+
{
1289+
name:"DoesNotCancelRunningPrebuildJob",
1290+
// Given: a running prebuild job
1291+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1292+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1293+
OwnerID:database.PrebuildsSystemUserID,
1294+
OrganizationID:orgID,
1295+
TemplateID:templateID,
1296+
}).Starting().Seed(database.WorkspaceBuild{
1297+
InitiatorID:database.PrebuildsSystemUserID,
1298+
}).Do()
1299+
},
1300+
previouslyCanceled:false,
1301+
previouslyCompleted:false,
1302+
shouldCancel:false,
1303+
},
1304+
// Should not cancel canceled prebuild-related jobs
1305+
{
1306+
name:"DoesNotCancelCanceledPrebuildJob",
1307+
// Given: a canceled prebuild job
1308+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1309+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1310+
OwnerID:database.PrebuildsSystemUserID,
1311+
OrganizationID:orgID,
1312+
TemplateID:templateID,
1313+
}).Canceled().Seed(database.WorkspaceBuild{
1314+
InitiatorID:database.PrebuildsSystemUserID,
1315+
}).Do()
1316+
},
1317+
shouldCancel:false,
1318+
previouslyCanceled:true,
1319+
previouslyCompleted:true,
1320+
},
1321+
// Should not cancel completed prebuild-related jobs
1322+
{
1323+
name:"DoesNotCancelCompletedPrebuildJob",
1324+
// Given: a completed prebuild job
1325+
setupBuild:func(t*testing.T,db database.Store,client*codersdk.Client,orgID uuid.UUID,templateID uuid.UUID) dbfake.WorkspaceResponse {
1326+
returndbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
1327+
OwnerID:database.PrebuildsSystemUserID,
1328+
OrganizationID:orgID,
1329+
TemplateID:templateID,
1330+
}).Seed(database.WorkspaceBuild{
1331+
InitiatorID:database.PrebuildsSystemUserID,
1332+
}).Do()
1333+
},
1334+
shouldCancel:false,
1335+
previouslyCanceled:false,
1336+
previouslyCompleted:true,
1337+
},
1338+
} {
1339+
t.Run(tt.name,func(t*testing.T) {
1340+
t.Parallel()
1341+
1342+
// Set the clock to Monday, January 1st, 2024 at 8:00 AM UTC to keep the test deterministic
1343+
clock:=quartz.NewMock(t)
1344+
clock.Set(time.Date(2024,1,1,8,0,0,0,time.UTC))
1345+
1346+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
1347+
defercancel()
1348+
1349+
// Setup
1350+
db,ps:=dbtestutil.NewDB(t)
1351+
client,_,_:=coderdtest.NewWithAPI(t,&coderdtest.Options{
1352+
// Explicitly not including provisioner daemons, as we don't want the jobs to be processed
1353+
// Jobs operations will be simulated via the database model
1354+
IncludeProvisionerDaemon:false,
1355+
Database:db,
1356+
Pubsub:ps,
1357+
Clock:clock,
1358+
})
1359+
owner:=coderdtest.CreateFirstUser(t,client)
1360+
1361+
// Given: a template with an initial version
1362+
templateVersion:=dbfake.TemplateVersion(t,db).Seed(database.TemplateVersion{
1363+
OrganizationID:owner.OrganizationID,
1364+
CreatedBy:owner.UserID,
1365+
}).Do()
1366+
templateID:=templateVersion.Template.ID
1367+
1368+
// Given: a workspace, workspace build and respective provisioner job
1369+
workspace:=tt.setupBuild(t,db,client,owner.OrganizationID,templateID)
1370+
1371+
// Given: a new template version
1372+
newTemplateVersion:=dbfake.TemplateVersion(t,db).Seed(database.TemplateVersion{
1373+
OrganizationID:owner.OrganizationID,
1374+
CreatedBy:owner.UserID,
1375+
TemplateID: uuid.NullUUID{
1376+
UUID:templateID,
1377+
Valid:true,
1378+
},
1379+
}).SkipCreateTemplate().Do()
1380+
1381+
// When: a new active version is promoted
1382+
err:=client.UpdateActiveTemplateVersion(ctx,templateID, codersdk.UpdateActiveTemplateVersion{
1383+
ID:newTemplateVersion.TemplateVersion.ID,
1384+
})
1385+
require.NoError(t,err)
1386+
1387+
// Then: the template's active version should be updated
1388+
updatedTemplate,err:=db.GetTemplateByID(ctx,templateID)
1389+
require.NoError(t,err)
1390+
require.Equal(t,newTemplateVersion.TemplateVersion.ID,updatedTemplate.ActiveVersionID)
1391+
1392+
iftt.shouldCancel {
1393+
// Then: the prebuild related jobs from the previous version should be canceled
1394+
cancelledJob,err:=db.GetProvisionerJobByID(ctx,workspace.Build.JobID)
1395+
require.NoError(t,err)
1396+
require.Equal(t,clock.Now().UTC(),cancelledJob.CanceledAt.Time.UTC())
1397+
require.Equal(t,clock.Now().UTC(),cancelledJob.CompletedAt.Time.UTC())
1398+
require.Equal(t,database.ProvisionerJobStatusCanceled,cancelledJob.JobStatus)
1399+
}else {
1400+
// Then: the provisioner job should not be canceled
1401+
job,err:=db.GetProvisionerJobByID(ctx,workspace.Build.JobID)
1402+
require.NoError(t,err)
1403+
if!tt.previouslyCanceled {
1404+
require.Zero(t,job.CanceledAt.Time.UTC())
1405+
require.NotEqual(t,database.ProvisionerJobStatusCanceled,job.JobStatus)
1406+
}
1407+
if!tt.previouslyCompleted {
1408+
require.Zero(t,job.CompletedAt.Time.UTC())
1409+
}
1410+
}
1411+
})
1412+
}
1413+
})
11971414
}
11981415

11991416
funcTestTemplateVersionDryRun(t*testing.T) {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp