Skip to content

Commit 7cbd77f

Browse files
authored
feat: improve resources_monitoring for OOM & OOD monitoring (#16241)
As requested for [this issue](coder/internal#245) we need to have a new resource `resources_monitoring` in the agent. It needs to be parsed from the provisioner and inserted into a new db table.
1 parent 8c26501 commit 7cbd77f

File tree

76 files changed

+3170
-1041
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3170
-1041
lines changed

cli/testdata/coder_provisioner_list_--output_json.golden

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"last_seen_at": "====[timestamp]=====",
88
"name": "test",
99
"version": "v0.0.0-devel",
10-
"api_version": "1.2",
10+
"api_version": "1.3",
1111
"provisioners": [
1212
"echo"
1313
],

coderd/apidoc/docs.go

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/dbauthz.go

+32
Original file line numberDiff line numberDiff line change
@@ -1391,13 +1391,29 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error {
13911391
return update(q.log, q.auth, fetch, q.db.FavoriteWorkspace)(ctx, id)
13921392
}
13931393

1394+
func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) (database.WorkspaceAgentMemoryResourceMonitor, error) {
1395+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
1396+
return database.WorkspaceAgentMemoryResourceMonitor{}, err
1397+
}
1398+
1399+
return q.db.FetchMemoryResourceMonitorsByAgentID(ctx, agentID)
1400+
}
1401+
13941402
func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.FetchNewMessageMetadataParams) (database.FetchNewMessageMetadataRow, error) {
13951403
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceNotificationMessage); err != nil {
13961404
return database.FetchNewMessageMetadataRow{}, err
13971405
}
13981406
return q.db.FetchNewMessageMetadata(ctx, arg)
13991407
}
14001408

1409+
func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) ([]database.WorkspaceAgentVolumeResourceMonitor, error) {
1410+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
1411+
return nil, err
1412+
}
1413+
1414+
return q.db.FetchVolumesResourceMonitorsByAgentID(ctx, agentID)
1415+
}
1416+
14011417
func (q *querier) GetAPIKeyByID(ctx context.Context, id string) (database.APIKey, error) {
14021418
return fetch(q.log, q.auth, q.db.GetAPIKeyByID)(ctx, id)
14031419
}
@@ -3003,6 +3019,14 @@ func (q *querier) InsertLicense(ctx context.Context, arg database.InsertLicenseP
30033019
return q.db.InsertLicense(ctx, arg)
30043020
}
30053021

3022+
func (q *querier) InsertMemoryResourceMonitor(ctx context.Context, arg database.InsertMemoryResourceMonitorParams) (database.WorkspaceAgentMemoryResourceMonitor, error) {
3023+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
3024+
return database.WorkspaceAgentMemoryResourceMonitor{}, err
3025+
}
3026+
3027+
return q.db.InsertMemoryResourceMonitor(ctx, arg)
3028+
}
3029+
30063030
func (q *querier) InsertMissingGroups(ctx context.Context, arg database.InsertMissingGroupsParams) ([]database.Group, error) {
30073031
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
30083032
return nil, err
@@ -3195,6 +3219,14 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin
31953219
return q.db.InsertUserLink(ctx, arg)
31963220
}
31973221

3222+
func (q *querier) InsertVolumeResourceMonitor(ctx context.Context, arg database.InsertVolumeResourceMonitorParams) (database.WorkspaceAgentVolumeResourceMonitor, error) {
3223+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
3224+
return database.WorkspaceAgentVolumeResourceMonitor{}, err
3225+
}
3226+
3227+
return q.db.InsertVolumeResourceMonitor(ctx, arg)
3228+
}
3229+
31983230
func (q *querier) InsertWorkspace(ctx context.Context, arg database.InsertWorkspaceParams) (database.WorkspaceTable, error) {
31993231
obj := rbac.ResourceWorkspace.WithOwner(arg.OwnerID.String()).InOrg(arg.OrganizationID)
32003232
tpl, err := q.GetTemplateByID(ctx, arg.TemplateID)

coderd/database/dbauthz/dbauthz_test.go

+93
Original file line numberDiff line numberDiff line change
@@ -4562,3 +4562,96 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
45624562
}).Asserts(rbac.ResourceOauth2AppCodeToken.WithOwner(user.ID.String()), policy.ActionDelete)
45634563
}))
45644564
}
4565+
4566+
func (s *MethodTestSuite) TestResourcesMonitor() {
4567+
s.Run("InsertMemoryResourceMonitor", s.Subtest(func(db database.Store, check *expects) {
4568+
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
4569+
check.Args(database.InsertMemoryResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate)
4570+
}))
4571+
4572+
s.Run("InsertVolumeResourceMonitor", s.Subtest(func(db database.Store, check *expects) {
4573+
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
4574+
check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate)
4575+
}))
4576+
4577+
s.Run("FetchMemoryResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) {
4578+
u := dbgen.User(s.T(), db, database.User{})
4579+
o := dbgen.Organization(s.T(), db, database.Organization{})
4580+
tpl := dbgen.Template(s.T(), db, database.Template{
4581+
OrganizationID: o.ID,
4582+
CreatedBy: u.ID,
4583+
})
4584+
tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
4585+
TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true},
4586+
OrganizationID: o.ID,
4587+
CreatedBy: u.ID,
4588+
})
4589+
w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
4590+
TemplateID: tpl.ID,
4591+
OrganizationID: o.ID,
4592+
OwnerID: u.ID,
4593+
})
4594+
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
4595+
Type: database.ProvisionerJobTypeWorkspaceBuild,
4596+
})
4597+
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
4598+
JobID: j.ID,
4599+
WorkspaceID: w.ID,
4600+
TemplateVersionID: tv.ID,
4601+
})
4602+
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID})
4603+
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
4604+
dbgen.WorkspaceAgentMemoryResourceMonitor(s.T(), db, database.WorkspaceAgentMemoryResourceMonitor{
4605+
AgentID: agt.ID,
4606+
Enabled: true,
4607+
Threshold: 80,
4608+
CreatedAt: dbtime.Now(),
4609+
})
4610+
4611+
monitor, err := db.FetchMemoryResourceMonitorsByAgentID(context.Background(), agt.ID)
4612+
require.NoError(s.T(), err)
4613+
4614+
check.Args(agt.ID).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionRead).Returns(monitor)
4615+
}))
4616+
4617+
s.Run("FetchVolumesResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) {
4618+
u := dbgen.User(s.T(), db, database.User{})
4619+
o := dbgen.Organization(s.T(), db, database.Organization{})
4620+
tpl := dbgen.Template(s.T(), db, database.Template{
4621+
OrganizationID: o.ID,
4622+
CreatedBy: u.ID,
4623+
})
4624+
tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
4625+
TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true},
4626+
OrganizationID: o.ID,
4627+
CreatedBy: u.ID,
4628+
})
4629+
w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
4630+
TemplateID: tpl.ID,
4631+
OrganizationID: o.ID,
4632+
OwnerID: u.ID,
4633+
})
4634+
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
4635+
Type: database.ProvisionerJobTypeWorkspaceBuild,
4636+
})
4637+
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
4638+
JobID: j.ID,
4639+
WorkspaceID: w.ID,
4640+
TemplateVersionID: tv.ID,
4641+
})
4642+
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID})
4643+
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
4644+
dbgen.WorkspaceAgentVolumeResourceMonitor(s.T(), db, database.WorkspaceAgentVolumeResourceMonitor{
4645+
AgentID: agt.ID,
4646+
Path: "/var/lib",
4647+
Enabled: true,
4648+
Threshold: 80,
4649+
CreatedAt: dbtime.Now(),
4650+
})
4651+
4652+
monitors, err := db.FetchVolumesResourceMonitorsByAgentID(context.Background(), agt.ID)
4653+
require.NoError(s.T(), err)
4654+
4655+
check.Args(agt.ID).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionRead).Returns(monitors)
4656+
}))
4657+
}

coderd/database/dbgen/dbgen.go

+23
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,29 @@ func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth
10321032
return token
10331033
}
10341034

1035+
func WorkspaceAgentMemoryResourceMonitor(t testing.TB, db database.Store, seed database.WorkspaceAgentMemoryResourceMonitor) database.WorkspaceAgentMemoryResourceMonitor {
1036+
monitor, err := db.InsertMemoryResourceMonitor(genCtx, database.InsertMemoryResourceMonitorParams{
1037+
AgentID: takeFirst(seed.AgentID, uuid.New()),
1038+
Enabled: takeFirst(seed.Enabled, true),
1039+
Threshold: takeFirst(seed.Threshold, 100),
1040+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1041+
})
1042+
require.NoError(t, err, "insert workspace agent memory resource monitor")
1043+
return monitor
1044+
}
1045+
1046+
func WorkspaceAgentVolumeResourceMonitor(t testing.TB, db database.Store, seed database.WorkspaceAgentVolumeResourceMonitor) database.WorkspaceAgentVolumeResourceMonitor {
1047+
monitor, err := db.InsertVolumeResourceMonitor(genCtx, database.InsertVolumeResourceMonitorParams{
1048+
AgentID: takeFirst(seed.AgentID, uuid.New()),
1049+
Path: takeFirst(seed.Path, "/"),
1050+
Enabled: takeFirst(seed.Enabled, true),
1051+
Threshold: takeFirst(seed.Threshold, 100),
1052+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1053+
})
1054+
require.NoError(t, err, "insert workspace agent volume resource monitor")
1055+
return monitor
1056+
}
1057+
10351058
func CustomRole(t testing.TB, db database.Store, seed database.CustomRole) database.CustomRole {
10361059
role, err := db.InsertCustomRole(genCtx, database.InsertCustomRoleParams{
10371060
Name: takeFirst(seed.Name, strings.ToLower(testutil.GetRandomName(t))),

0 commit comments

Comments
 (0)