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

Commit13a0cc9

Browse files
authored
Merge branch 'main' into jakehwll/routing-ai-governance
2 parents1b883f3 +2bcf084 commit13a0cc9

File tree

11 files changed

+259
-130
lines changed

11 files changed

+259
-130
lines changed

‎.github/workflows/ci.yaml‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,9 @@ jobs:
204204
205205
# Needed for helm chart linting
206206
-name:Install helm
207-
# uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
208-
# with:
209-
# version: v3.9.2
210-
# The below is taken from https://helm.sh/docs/intro/install/#from-apt-debianubuntu
211-
run:|
212-
set -euo pipefail
213-
sudo apt-get install curl gpg apt-transport-https --yes
214-
curl -fsSL https://packages.buildkite.com/helm-linux/helm-debian/gpgkey | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
215-
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://packages.buildkite.com/helm-linux/helm-debian/any/ any main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
216-
sudo apt-get update
217-
sudo apt-get install helm
207+
uses:azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4# v4.3.1
208+
with:
209+
version:v3.9.2
218210

219211
-name:make lint
220212
run:|

‎cli/exp_scaletest.go‎

Lines changed: 86 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,88 @@ func (s *scaletestPrometheusFlags) attach(opts *serpent.OptionSet) {
384384
)
385385
}
386386

387+
// workspaceTargetFlags holds common flags for targeting specific workspaces in scale tests.
388+
typeworkspaceTargetFlagsstruct {
389+
templatestring
390+
targetWorkspacesstring
391+
useHostLoginbool
392+
}
393+
394+
// attach adds the workspace target flags to the given options set.
395+
func (f*workspaceTargetFlags)attach(opts*serpent.OptionSet) {
396+
*opts=append(*opts,
397+
serpent.Option{
398+
Flag:"template",
399+
FlagShorthand:"t",
400+
Env:"CODER_SCALETEST_TEMPLATE",
401+
Description:"Name or ID of the template. Traffic generation will be limited to workspaces created from this template.",
402+
Value:serpent.StringOf(&f.template),
403+
},
404+
serpent.Option{
405+
Flag:"target-workspaces",
406+
Env:"CODER_SCALETEST_TARGET_WORKSPACES",
407+
Description:"Target a specific range of workspaces in the format [START]:[END] (exclusive). Example: 0:10 will target the 10 first alphabetically sorted workspaces (0-9).",
408+
Value:serpent.StringOf(&f.targetWorkspaces),
409+
},
410+
serpent.Option{
411+
Flag:"use-host-login",
412+
Env:"CODER_SCALETEST_USE_HOST_LOGIN",
413+
Default:"false",
414+
Description:"Connect as the currently logged in user.",
415+
Value:serpent.BoolOf(&f.useHostLogin),
416+
},
417+
)
418+
}
419+
420+
// getTargetedWorkspaces retrieves the workspaces based on the template filter and target range. warnWriter is where to
421+
// write a warning message if any workspaces were skipped due to ownership mismatch.
422+
func (f*workspaceTargetFlags)getTargetedWorkspaces(ctx context.Context,client*codersdk.Client,organizationIDs []uuid.UUID,warnWriter io.Writer) ([]codersdk.Workspace,error) {
423+
// Validate template if provided
424+
iff.template!="" {
425+
_,err:=parseTemplate(ctx,client,organizationIDs,f.template)
426+
iferr!=nil {
427+
returnnil,xerrors.Errorf("parse template: %w",err)
428+
}
429+
}
430+
431+
// Parse target range
432+
targetStart,targetEnd,err:=parseTargetRange("workspaces",f.targetWorkspaces)
433+
iferr!=nil {
434+
returnnil,xerrors.Errorf("parse target workspaces: %w",err)
435+
}
436+
437+
// Determine owner based on useHostLogin
438+
varownerstring
439+
iff.useHostLogin {
440+
owner=codersdk.Me
441+
}
442+
443+
// Get workspaces
444+
workspaces,numSkipped,err:=getScaletestWorkspaces(ctx,client,owner,f.template)
445+
iferr!=nil {
446+
returnnil,err
447+
}
448+
ifnumSkipped>0 {
449+
cliui.Warnf(warnWriter,"CODER_DISABLE_OWNER_WORKSPACE_ACCESS is set on the deployment.\n\t%d workspace(s) were skipped due to ownership mismatch.\n\tSet --use-host-login to only target workspaces you own.",numSkipped)
450+
}
451+
452+
// Adjust targetEnd if not specified
453+
iftargetEnd==0 {
454+
targetEnd=len(workspaces)
455+
}
456+
457+
// Validate range
458+
iflen(workspaces)==0 {
459+
returnnil,xerrors.Errorf("no scaletest workspaces exist")
460+
}
461+
iftargetEnd>len(workspaces) {
462+
returnnil,xerrors.Errorf("target workspace end %d is greater than the number of workspaces %d",targetEnd,len(workspaces))
463+
}
464+
465+
// Return the sliced workspaces
466+
returnworkspaces[targetStart:targetEnd],nil
467+
}
468+
387469
funcrequireAdmin(ctx context.Context,client*codersdk.Client) (codersdk.User,error) {
388470
me,err:=client.User(ctx,codersdk.Me)
389471
iferr!=nil {
@@ -1193,12 +1275,10 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
11931275
bytesPerTickint64
11941276
sshbool
11951277
disableDirectbool
1196-
useHostLoginbool
11971278
appstring
1198-
templatestring
1199-
targetWorkspacesstring
12001279
workspaceProxyURLstring
12011280

1281+
targetFlags=&workspaceTargetFlags{}
12021282
tracingFlags=&scaletestTracingFlags{}
12031283
strategy=&scaletestStrategyFlags{}
12041284
cleanupStrategy=newScaletestCleanupStrategy()
@@ -1243,46 +1323,16 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
12431323
},
12441324
}
12451325

1246-
iftemplate!="" {
1247-
_,err:=parseTemplate(ctx,client,me.OrganizationIDs,template)
1248-
iferr!=nil {
1249-
returnxerrors.Errorf("parse template: %w",err)
1250-
}
1251-
}
1252-
targetWorkspaceStart,targetWorkspaceEnd,err:=parseTargetRange("workspaces",targetWorkspaces)
1326+
workspaces,err:=targetFlags.getTargetedWorkspaces(ctx,client,me.OrganizationIDs,inv.Stdout)
12531327
iferr!=nil {
1254-
returnxerrors.Errorf("parse target workspaces: %w",err)
1328+
returnerr
12551329
}
12561330

12571331
appHost,err:=client.AppHost(ctx)
12581332
iferr!=nil {
12591333
returnxerrors.Errorf("get app host: %w",err)
12601334
}
12611335

1262-
varownerstring
1263-
ifuseHostLogin {
1264-
owner=codersdk.Me
1265-
}
1266-
1267-
workspaces,numSkipped,err:=getScaletestWorkspaces(inv.Context(),client,owner,template)
1268-
iferr!=nil {
1269-
returnerr
1270-
}
1271-
ifnumSkipped>0 {
1272-
cliui.Warnf(inv.Stdout,"CODER_DISABLE_OWNER_WORKSPACE_ACCESS is set on the deployment.\n\t%d workspace(s) were skipped due to ownership mismatch.\n\tSet --use-host-login to only target workspaces you own.",numSkipped)
1273-
}
1274-
1275-
iftargetWorkspaceEnd==0 {
1276-
targetWorkspaceEnd=len(workspaces)
1277-
}
1278-
1279-
iflen(workspaces)==0 {
1280-
returnxerrors.Errorf("no scaletest workspaces exist")
1281-
}
1282-
iftargetWorkspaceEnd>len(workspaces) {
1283-
returnxerrors.Errorf("target workspace end %d is greater than the number of workspaces %d",targetWorkspaceEnd,len(workspaces))
1284-
}
1285-
12861336
tracerProvider,closeTracing,tracingEnabled,err:=tracingFlags.provider(ctx)
12871337
iferr!=nil {
12881338
returnxerrors.Errorf("create tracer provider: %w",err)
@@ -1307,10 +1357,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
13071357

13081358
th:=harness.NewTestHarness(strategy.toStrategy(),cleanupStrategy.toStrategy())
13091359
foridx,ws:=rangeworkspaces {
1310-
ifidx<targetWorkspaceStart||idx>=targetWorkspaceEnd {
1311-
continue
1312-
}
1313-
13141360
var (
13151361
agent codersdk.WorkspaceAgent
13161362
name="workspace-traffic"
@@ -1415,19 +1461,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
14151461
}
14161462

14171463
cmd.Options= []serpent.Option{
1418-
{
1419-
Flag:"template",
1420-
FlagShorthand:"t",
1421-
Env:"CODER_SCALETEST_TEMPLATE",
1422-
Description:"Name or ID of the template. Traffic generation will be limited to workspaces created from this template.",
1423-
Value:serpent.StringOf(&template),
1424-
},
1425-
{
1426-
Flag:"target-workspaces",
1427-
Env:"CODER_SCALETEST_TARGET_WORKSPACES",
1428-
Description:"Target a specific range of workspaces in the format [START]:[END] (exclusive). Example: 0:10 will target the 10 first alphabetically sorted workspaces (0-9).",
1429-
Value:serpent.StringOf(&targetWorkspaces),
1430-
},
14311464
{
14321465
Flag:"bytes-per-tick",
14331466
Env:"CODER_SCALETEST_WORKSPACE_TRAFFIC_BYTES_PER_TICK",
@@ -1463,13 +1496,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
14631496
Description:"Send WebSocket traffic to a workspace app (proxied via coderd), cannot be used with --ssh.",
14641497
Value:serpent.StringOf(&app),
14651498
},
1466-
{
1467-
Flag:"use-host-login",
1468-
Env:"CODER_SCALETEST_USE_HOST_LOGIN",
1469-
Default:"false",
1470-
Description:"Connect as the currently logged in user.",
1471-
Value:serpent.BoolOf(&useHostLogin),
1472-
},
14731499
{
14741500
Flag:"workspace-proxy-url",
14751501
Env:"CODER_SCALETEST_WORKSPACE_PROXY_URL",
@@ -1479,6 +1505,7 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
14791505
},
14801506
}
14811507

1508+
targetFlags.attach(&cmd.Options)
14821509
tracingFlags.attach(&cmd.Options)
14831510
strategy.attach(&cmd.Options)
14841511
cleanupStrategy.attach(&cmd.Options)

‎coderd/aitasks_test.go‎

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,10 @@ func TestTasks(t *testing.T) {
355355
}
356356
})
357357

358-
t.Run("NoWorkspace",func(t*testing.T) {
358+
t.Run("DeletedWorkspace",func(t*testing.T) {
359359
t.Parallel()
360360

361-
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
361+
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
362362
user:=coderdtest.CreateFirstUser(t,client)
363363
template:=createAITemplate(t,client,user)
364364
ctx:=testutil.Context(t,testutil.WaitLong)
@@ -372,14 +372,54 @@ func TestTasks(t *testing.T) {
372372
ws,err:=client.Workspace(ctx,task.WorkspaceID.UUID)
373373
require.NoError(t,err)
374374
coderdtest.AwaitWorkspaceBuildJobCompleted(t,client,ws.LatestBuild.ID)
375-
// Delete the task workspace
376-
coderdtest.MustTransitionWorkspace(t,client,ws.ID,codersdk.WorkspaceTransitionStart,codersdk.WorkspaceTransitionDelete)
377-
// We should still be able to fetch the task after deleting its workspace
375+
376+
// Mark the workspace as deleted directly in the database, bypassing provisionerd.
377+
require.NoError(t,db.UpdateWorkspaceDeletedByID(dbauthz.AsProvisionerd(ctx), database.UpdateWorkspaceDeletedByIDParams{
378+
ID:ws.ID,
379+
Deleted:true,
380+
}))
381+
// We should still be able to fetch the task if its workspace was deleted.
382+
// Provisionerdserver will attempt delete the related task when deleting a workspace.
383+
// This test ensures that we can still handle the case where, for some reason, the
384+
// task has not been marked as deleted, but the workspace has.
378385
task,err=exp.TaskByID(ctx,task.ID)
379-
require.NoError(t,err,"fetching a task should still workafter deletingits related workspace")
386+
require.NoError(t,err,"fetching a task should still workifits related workspace is deleted")
380387
err=exp.DeleteTask(ctx,task.OwnerID.String(),task.ID)
381388
require.NoError(t,err,"should be possible to delete a task with no workspace")
382389
})
390+
391+
t.Run("DeletingTaskWorkspaceDeletesTask",func(t*testing.T) {
392+
t.Parallel()
393+
394+
client:=coderdtest.New(t,&coderdtest.Options{IncludeProvisionerDaemon:true})
395+
user:=coderdtest.CreateFirstUser(t,client)
396+
template:=createAITemplate(t,client,user)
397+
398+
ctx:=testutil.Context(t,testutil.WaitLong)
399+
400+
exp:=codersdk.NewExperimentalClient(client)
401+
task,err:=exp.CreateTask(ctx,"me", codersdk.CreateTaskRequest{
402+
TemplateVersionID:template.ActiveVersionID,
403+
Input:"delete me",
404+
})
405+
require.NoError(t,err)
406+
require.True(t,task.WorkspaceID.Valid,"task should have a workspace ID")
407+
ws,err:=client.Workspace(ctx,task.WorkspaceID.UUID)
408+
require.NoError(t,err)
409+
ifassert.True(t,ws.TaskID.Valid,"task id should be set on workspace") {
410+
assert.Equal(t,task.ID,ws.TaskID.UUID,"workspace task id should match")
411+
}
412+
coderdtest.AwaitWorkspaceBuildJobCompleted(t,client,ws.LatestBuild.ID)
413+
414+
// When; the task workspace is deleted
415+
coderdtest.MustTransitionWorkspace(t,client,ws.ID,codersdk.WorkspaceTransitionStart,codersdk.WorkspaceTransitionDelete)
416+
// Then: the task associated with the workspace is also deleted
417+
_,err=exp.TaskByID(ctx,task.ID)
418+
require.Error(t,err,"expected an error fetching the task")
419+
varsdkErr*codersdk.Error
420+
require.ErrorAs(t,err,&sdkErr,"expected a codersdk.Error")
421+
require.Equal(t,http.StatusNotFound,sdkErr.StatusCode())
422+
})
383423
})
384424

385425
t.Run("Send",func(t*testing.T) {

‎coderd/database/dbauthz/dbauthz.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ var (
219219
rbac.ResourceUser.Type: {policy.ActionRead,policy.ActionReadPersonal,policy.ActionUpdatePersonal},
220220
rbac.ResourceWorkspaceDormant.Type: {policy.ActionDelete,policy.ActionRead,policy.ActionUpdate,policy.ActionWorkspaceStop},
221221
rbac.ResourceWorkspace.Type: {policy.ActionDelete,policy.ActionRead,policy.ActionUpdate,policy.ActionWorkspaceStart,policy.ActionWorkspaceStop,policy.ActionCreateAgent},
222-
// Provisionerd needs to readandupdate tasks associated with workspaces.
223-
rbac.ResourceTask.Type: {policy.ActionRead,policy.ActionUpdate},
222+
// Provisionerd needs to read, update,anddelete tasks associated with workspaces.
223+
rbac.ResourceTask.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionDelete},
224224
rbac.ResourceApiKey.Type: {policy.WildcardSymbol},
225225
// When org scoped provisioner credentials are implemented,
226226
// this can be reduced to read a specific org.

‎coderd/provisionerdserver/provisionerdserver.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,14 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
22782278
iferr!=nil {
22792279
returnxerrors.Errorf("update workspace deleted: %w",err)
22802280
}
2281+
ifworkspace.TaskID.Valid {
2282+
if_,err:=db.DeleteTask(ctx, database.DeleteTaskParams{
2283+
ID:workspace.TaskID.UUID,
2284+
DeletedAt:dbtime.Now(),
2285+
});err!=nil&&!errors.Is(err,sql.ErrNoRows) {
2286+
returnxerrors.Errorf("delete task related to workspace: %w",err)
2287+
}
2288+
}
22812289

22822290
returnnil
22832291
},nil)

‎docs/admin/templates/managing-templates/external-workspaces.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ External workspaces offer flexibility and control in complex environments:
2020

2121
-**Incremental adoption of Coder**
2222

23-
Integrate with existing infrastructure gradually without needing to migrate everything at once. This is particularly useful when gradually migratingworklods to Coder without refactoring current infrastructure.
23+
Integrate with existing infrastructure gradually without needing to migrate everything at once. This is particularly useful when gradually migratingworkloads to Coder without refactoring current infrastructure.
2424

2525
-**Flexibility**
2626

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp