Skip to content

Commit 8342301

Browse files
committed
chore: add OAuth2 device flow test scripts
Change-Id: Ic232851727e683ab3d8b7ce970c505588da2f827 Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent 3795d4f commit 8342301

33 files changed

+1197
-712
lines changed

.claude/scripts/format.sh

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,30 +101,36 @@ fi
101101
# Get the file extension to determine the appropriate formatter
102102
file_ext="${file_path##*.}"
103103

104+
# Helper function to run formatter and handle errors
105+
run_formatter() {
106+
local target="$1"
107+
local file_type="$2"
108+
109+
if ! make FILE="$file_path" "$target"; then
110+
echo "Error: Failed to format $file_type file: $file_path" >&2
111+
exit 2
112+
fi
113+
echo "✓ Formatted $file_type file: $file_path"
114+
}
104115
# Change to the project root directory (where the Makefile is located)
105116
cd "$(dirname "$0")/../.."
106117

107118
# Call the appropriate Makefile target based on file extension
108119
case "$file_ext" in
109120
go)
110-
make fmt/go FILE="$file_path"
111-
echo "✓ Formatted Go file: $file_path"
121+
run_formatter "fmt/go" "Go"
112122
;;
113123
js | jsx | ts | tsx)
114-
make fmt/ts FILE="$file_path"
115-
echo "✓ Formatted TypeScript/JavaScript file: $file_path"
124+
run_formatter "fmt/ts" "TypeScript/JavaScript"
116125
;;
117126
tf | tfvars)
118-
make fmt/terraform FILE="$file_path"
119-
echo "✓ Formatted Terraform file: $file_path"
127+
run_formatter "fmt/terraform" "Terraform"
120128
;;
121129
sh)
122-
make fmt/shfmt FILE="$file_path"
123-
echo "✓ Formatted shell script: $file_path"
130+
run_formatter "fmt/shfmt" "shell script"
124131
;;
125132
md)
126-
make fmt/markdown FILE="$file_path"
127-
echo "✓ Formatted Markdown file: $file_path"
133+
run_formatter "fmt/markdown" "Markdown"
128134
;;
129135
*)
130136
echo "No formatter available for file extension: $file_ext"

coderd/coderd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ func New(options *Options) *API {
984984
r.Route("/device", func(r chi.Router) {
985985
r.Post("/", api.postOAuth2DeviceAuthorization()) // RFC 8628 compliant endpoint
986986
r.Route("/verify", func(r chi.Router) {
987-
r.Use(apiKeyMiddleware)
987+
r.Use(apiKeyMiddlewareRedirect)
988988
r.Get("/", api.getOAuth2DeviceVerification())
989989
r.Post("/", api.postOAuth2DeviceVerification())
990990
})

coderd/database/dbauthz/dbauthz.go

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ var (
417417
rbac.ResourceProvisionerJobs.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionCreate},
418418
rbac.ResourceOauth2App.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
419419
rbac.ResourceOauth2AppSecret.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
420+
rbac.ResourceOauth2AppCodeToken.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
420421
}),
421422
Org: map[string][]rbac.Permission{},
422423
User: []rbac.Permission{},
@@ -1346,6 +1347,14 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
13461347
return q.db.CleanTailnetTunnels(ctx)
13471348
}
13481349

1350+
func (q *querier) ConsumeOAuth2ProviderAppCodeByPrefix(ctx context.Context, secretPrefix []byte) (database.OAuth2ProviderAppCode, error) {
1351+
return updateWithReturn(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByPrefix, q.db.ConsumeOAuth2ProviderAppCodeByPrefix)(ctx, secretPrefix)
1352+
}
1353+
1354+
func (q *querier) ConsumeOAuth2ProviderDeviceCodeByPrefix(ctx context.Context, deviceCodePrefix string) (database.OAuth2ProviderDeviceCode, error) {
1355+
return updateWithReturn(q.log, q.auth, q.db.GetOAuth2ProviderDeviceCodeByPrefix, q.db.ConsumeOAuth2ProviderDeviceCodeByPrefix)(ctx, deviceCodePrefix)
1356+
}
1357+
13491358
func (q *querier) CountAuditLogs(ctx context.Context, arg database.CountAuditLogsParams) (int64, error) {
13501359
// Shortcut if the user is an owner. The SQL filter is noticeable,
13511360
// and this is an easy win for owners. Which is the common case.
@@ -1560,27 +1569,30 @@ func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Contex
15601569
return q.db.DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx, arg)
15611570
}
15621571

1563-
func (q *querier) DeleteOldAuditLogConnectionEvents(ctx context.Context, threshold database.DeleteOldAuditLogConnectionEventsParams) error {
1564-
// `ResourceSystem` is deprecated, but it doesn't make sense to add
1565-
// `policy.ActionDelete` to `ResourceAuditLog`, since this is the one and
1566-
// only time we'll be deleting from the audit log.
1567-
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
1568-
return err
1569-
}
1570-
return q.db.DeleteOldAuditLogConnectionEvents(ctx, threshold)
1571-
}
1572-
15731572
func (q *querier) DeleteOAuth2ProviderDeviceCodeByID(ctx context.Context, id uuid.UUID) error {
15741573
// Fetch the device code first to check authorization
15751574
deviceCode, err := q.db.GetOAuth2ProviderDeviceCodeByID(ctx, id)
15761575
if err != nil {
1577-
return err
1576+
return xerrors.Errorf("get oauth2 provider device code: %w", err)
15781577
}
15791578
if err := q.authorizeContext(ctx, policy.ActionDelete, deviceCode); err != nil {
1580-
return err
1579+
return xerrors.Errorf("authorize oauth2 provider device code deletion: %w", err)
15811580
}
15821581

1583-
return q.db.DeleteOAuth2ProviderDeviceCodeByID(ctx, id)
1582+
if err := q.db.DeleteOAuth2ProviderDeviceCodeByID(ctx, id); err != nil {
1583+
return xerrors.Errorf("delete oauth2 provider device code: %w", err)
1584+
}
1585+
return nil
1586+
}
1587+
1588+
func (q *querier) DeleteOldAuditLogConnectionEvents(ctx context.Context, threshold database.DeleteOldAuditLogConnectionEventsParams) error {
1589+
// `ResourceSystem` is deprecated, but it doesn't make sense to add
1590+
// `policy.ActionDelete` to `ResourceAuditLog`, since this is the one and
1591+
// only time we'll be deleting from the audit log.
1592+
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil {
1593+
return err
1594+
}
1595+
return q.db.DeleteOldAuditLogConnectionEvents(ctx, threshold)
15841596
}
15851597

15861598
func (q *querier) DeleteOldNotificationMessages(ctx context.Context) error {
@@ -2359,8 +2371,8 @@ func (q *querier) GetOAuth2ProviderDeviceCodeByUserCode(ctx context.Context, use
23592371
}
23602372

23612373
func (q *querier) GetOAuth2ProviderDeviceCodesByClientID(ctx context.Context, clientID uuid.UUID) ([]database.OAuth2ProviderDeviceCode, error) {
2362-
// This requires access to read the OAuth2 app
2363-
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOauth2App); err != nil {
2374+
// This requires access to read OAuth2 app code tokens
2375+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOauth2AppCodeToken); err != nil {
23642376
return []database.OAuth2ProviderDeviceCode{}, err
23652377
}
23662378
return q.db.GetOAuth2ProviderDeviceCodesByClientID(ctx, clientID)
@@ -3802,8 +3814,8 @@ func (q *querier) InsertOAuth2ProviderAppToken(ctx context.Context, arg database
38023814
}
38033815

38043816
func (q *querier) InsertOAuth2ProviderDeviceCode(ctx context.Context, arg database.InsertOAuth2ProviderDeviceCodeParams) (database.OAuth2ProviderDeviceCode, error) {
3805-
// Creating device codes requires OAuth2 app access
3806-
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOauth2App); err != nil {
3817+
// Creating device codes requires OAuth2 app code token creation access
3818+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOauth2AppCodeToken); err != nil {
38073819
return database.OAuth2ProviderDeviceCode{}, err
38083820
}
38093821
return q.db.InsertOAuth2ProviderDeviceCode(ctx, arg)
@@ -4482,13 +4494,10 @@ func (q *querier) UpdateOAuth2ProviderAppSecretByID(ctx context.Context, arg dat
44824494
}
44834495

44844496
func (q *querier) UpdateOAuth2ProviderDeviceCodeAuthorization(ctx context.Context, arg database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams) (database.OAuth2ProviderDeviceCode, error) {
4485-
// Verify the user is authenticated for device code authorization
4486-
_, ok := ActorFromContext(ctx)
4487-
if !ok {
4488-
return database.OAuth2ProviderDeviceCode{}, ErrNoActor
4497+
fetch := func(ctx context.Context, arg database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams) (database.OAuth2ProviderDeviceCode, error) {
4498+
return q.db.GetOAuth2ProviderDeviceCodeByID(ctx, arg.ID)
44894499
}
4490-
4491-
return q.db.UpdateOAuth2ProviderDeviceCodeAuthorization(ctx, arg)
4500+
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateOAuth2ProviderDeviceCodeAuthorization)(ctx, arg)
44924501
}
44934502

44944503
func (q *querier) UpdateOrganization(ctx context.Context, arg database.UpdateOrganizationParams) (database.Organization, error) {

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5531,6 +5531,19 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() {
55315531
UserID: user.ID,
55325532
}).Asserts(rbac.ResourceOauth2AppCodeToken.WithOwner(user.ID.String()), policy.ActionDelete)
55335533
}))
5534+
s.Run("ConsumeOAuth2ProviderAppCodeByPrefix", s.Subtest(func(db database.Store, check *expects) {
5535+
user := dbgen.User(s.T(), db, database.User{})
5536+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5537+
// Use unique prefix to avoid test isolation issues
5538+
uniquePrefix := fmt.Sprintf("prefix-%s-%d", s.T().Name(), time.Now().UnixNano())
5539+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
5540+
SecretPrefix: []byte(uniquePrefix),
5541+
UserID: user.ID,
5542+
AppID: app.ID,
5543+
ExpiresAt: time.Now().Add(24 * time.Hour), // Extended expiry for test stability
5544+
})
5545+
check.Args(code.SecretPrefix).Asserts(code, policy.ActionUpdate).Returns(code)
5546+
}))
55345547
}
55355548

55365549
func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
@@ -5606,6 +5619,115 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
56065619
}))
56075620
}
56085621

5622+
func (s *MethodTestSuite) TestOAuth2ProviderDeviceCodes() {
5623+
s.Run("InsertOAuth2ProviderDeviceCode", s.Subtest(func(db database.Store, check *expects) {
5624+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5625+
check.Args(database.InsertOAuth2ProviderDeviceCodeParams{
5626+
ClientID: app.ID,
5627+
DeviceCodePrefix: "testpref",
5628+
DeviceCodeHash: []byte("hash"),
5629+
UserCode: "TEST1234",
5630+
VerificationUri: "http://example.com/device",
5631+
}).Asserts(rbac.ResourceOauth2AppCodeToken, policy.ActionCreate)
5632+
}))
5633+
s.Run("GetOAuth2ProviderDeviceCodeByID", s.Subtest(func(db database.Store, check *expects) {
5634+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5635+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(context.Background(), database.InsertOAuth2ProviderDeviceCodeParams{
5636+
ClientID: app.ID,
5637+
DeviceCodePrefix: "testpref",
5638+
UserCode: "TEST1234",
5639+
VerificationUri: "http://example.com/device",
5640+
})
5641+
require.NoError(s.T(), err)
5642+
check.Args(deviceCode.ID).Asserts(deviceCode, policy.ActionRead).Returns(deviceCode)
5643+
}))
5644+
s.Run("GetOAuth2ProviderDeviceCodeByPrefix", s.Subtest(func(db database.Store, check *expects) {
5645+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5646+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(context.Background(), database.InsertOAuth2ProviderDeviceCodeParams{
5647+
ClientID: app.ID,
5648+
DeviceCodePrefix: "testpref",
5649+
UserCode: "TEST1234",
5650+
VerificationUri: "http://example.com/device",
5651+
})
5652+
require.NoError(s.T(), err)
5653+
check.Args(deviceCode.DeviceCodePrefix).Asserts(deviceCode, policy.ActionRead).Returns(deviceCode)
5654+
}))
5655+
s.Run("GetOAuth2ProviderDeviceCodeByUserCode", s.Subtest(func(db database.Store, check *expects) {
5656+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5657+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(context.Background(), database.InsertOAuth2ProviderDeviceCodeParams{
5658+
ClientID: app.ID,
5659+
DeviceCodePrefix: "testpref",
5660+
UserCode: "TEST1234",
5661+
VerificationUri: "http://example.com/device",
5662+
})
5663+
require.NoError(s.T(), err)
5664+
check.Args(deviceCode.UserCode).Asserts(deviceCode, policy.ActionRead).Returns(deviceCode)
5665+
}))
5666+
s.Run("GetOAuth2ProviderDeviceCodesByClientID", s.Subtest(func(db database.Store, check *expects) {
5667+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5668+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(context.Background(), database.InsertOAuth2ProviderDeviceCodeParams{
5669+
ClientID: app.ID,
5670+
DeviceCodePrefix: "testpref",
5671+
UserCode: "TEST1234",
5672+
VerificationUri: "http://example.com/device",
5673+
})
5674+
require.NoError(s.T(), err)
5675+
check.Args(app.ID).Asserts(rbac.ResourceOauth2AppCodeToken, policy.ActionRead).Returns([]database.OAuth2ProviderDeviceCode{deviceCode})
5676+
}))
5677+
s.Run("ConsumeOAuth2ProviderDeviceCodeByPrefix", s.Subtest(func(db database.Store, check *expects) {
5678+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5679+
user := dbgen.User(s.T(), db, database.User{})
5680+
// Use unique identifiers to avoid test isolation issues
5681+
// Device code prefix must be exactly 8 characters
5682+
uniquePrefix := fmt.Sprintf("t%07d", time.Now().UnixNano()%10000000)
5683+
uniqueUserCode := fmt.Sprintf("USER%04d", time.Now().UnixNano()%10000)
5684+
// Create device code using dbgen (now available!)
5685+
deviceCode := dbgen.OAuth2ProviderDeviceCode(s.T(), db, database.OAuth2ProviderDeviceCode{
5686+
DeviceCodePrefix: uniquePrefix,
5687+
UserCode: uniqueUserCode,
5688+
ClientID: app.ID,
5689+
ExpiresAt: time.Now().Add(24 * time.Hour), // Extended expiry for test stability
5690+
})
5691+
// Authorize the device code so it can be consumed
5692+
deviceCode, err := db.UpdateOAuth2ProviderDeviceCodeAuthorization(s.T().Context(), database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams{
5693+
ID: deviceCode.ID,
5694+
UserID: uuid.NullUUID{UUID: user.ID, Valid: true},
5695+
Status: database.OAuth2DeviceStatusAuthorized,
5696+
})
5697+
require.NoError(s.T(), err)
5698+
require.Equal(s.T(), database.OAuth2DeviceStatusAuthorized, deviceCode.Status)
5699+
check.Args(uniquePrefix).Asserts(deviceCode, policy.ActionUpdate).Returns(deviceCode)
5700+
}))
5701+
s.Run("UpdateOAuth2ProviderDeviceCodeAuthorization", s.Subtest(func(db database.Store, check *expects) {
5702+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5703+
user := dbgen.User(s.T(), db, database.User{})
5704+
// Create device code using dbgen
5705+
deviceCode := dbgen.OAuth2ProviderDeviceCode(s.T(), db, database.OAuth2ProviderDeviceCode{
5706+
ClientID: app.ID,
5707+
})
5708+
require.Equal(s.T(), database.OAuth2DeviceStatusPending, deviceCode.Status)
5709+
check.Args(database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams{
5710+
ID: deviceCode.ID,
5711+
UserID: uuid.NullUUID{UUID: user.ID, Valid: true},
5712+
Status: database.OAuth2DeviceStatusAuthorized,
5713+
}).Asserts(deviceCode, policy.ActionUpdate)
5714+
}))
5715+
s.Run("DeleteOAuth2ProviderDeviceCodeByID", s.Subtest(func(db database.Store, check *expects) {
5716+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
5717+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(context.Background(), database.InsertOAuth2ProviderDeviceCodeParams{
5718+
ClientID: app.ID,
5719+
DeviceCodePrefix: "testpref",
5720+
UserCode: "TEST1234",
5721+
VerificationUri: "http://example.com/device",
5722+
})
5723+
require.NoError(s.T(), err)
5724+
check.Args(deviceCode.ID).Asserts(deviceCode, policy.ActionDelete)
5725+
}))
5726+
s.Run("DeleteExpiredOAuth2ProviderDeviceCodes", s.Subtest(func(db database.Store, check *expects) {
5727+
check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete)
5728+
}))
5729+
}
5730+
56095731
func (s *MethodTestSuite) TestResourcesMonitor() {
56105732
createAgent := func(t *testing.T, db database.Store) (database.WorkspaceAgent, database.WorkspaceTable) {
56115733
t.Helper()

coderd/database/dbgen/dbgen.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
"github.com/google/uuid"
1919
"github.com/sqlc-dev/pqtype"
20+
"github.com/stretchr/testify/assert"
2021
"github.com/stretchr/testify/require"
2122
"golang.org/x/xerrors"
2223

@@ -1246,7 +1247,7 @@ func OAuth2ProviderAppCode(t testing.TB, db database.Store, seed database.OAuth2
12461247
code, err := db.InsertOAuth2ProviderAppCode(genCtx, database.InsertOAuth2ProviderAppCodeParams{
12471248
ID: takeFirst(seed.ID, uuid.New()),
12481249
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1249-
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1250+
ExpiresAt: takeFirst(seed.ExpiresAt, dbtime.Now().Add(24*time.Hour)),
12501251
SecretPrefix: takeFirstSlice(seed.SecretPrefix, []byte("prefix")),
12511252
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
12521253
AppID: takeFirst(seed.AppID, uuid.New()),
@@ -1263,7 +1264,7 @@ func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth
12631264
token, err := db.InsertOAuth2ProviderAppToken(genCtx, database.InsertOAuth2ProviderAppTokenParams{
12641265
ID: takeFirst(seed.ID, uuid.New()),
12651266
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1266-
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1267+
ExpiresAt: takeFirst(seed.ExpiresAt, dbtime.Now().Add(24*time.Hour)),
12671268
HashPrefix: takeFirstSlice(seed.HashPrefix, []byte("prefix")),
12681269
RefreshHash: takeFirstSlice(seed.RefreshHash, []byte("hashed-secret")),
12691270
AppSecretID: takeFirst(seed.AppSecretID, uuid.New()),
@@ -1275,6 +1276,26 @@ func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth
12751276
return token
12761277
}
12771278

1279+
func OAuth2ProviderDeviceCode(t testing.TB, db database.Store, seed database.OAuth2ProviderDeviceCode) database.OAuth2ProviderDeviceCode {
1280+
t.Helper()
1281+
deviceCode, err := db.InsertOAuth2ProviderDeviceCode(genCtx, database.InsertOAuth2ProviderDeviceCodeParams{
1282+
ID: takeFirst(seed.ID, uuid.New()),
1283+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1284+
ExpiresAt: takeFirst(seed.ExpiresAt, dbtime.Now().Add(24*time.Hour)),
1285+
DeviceCodeHash: takeFirstSlice(seed.DeviceCodeHash, []byte("device-hash")),
1286+
DeviceCodePrefix: takeFirst(seed.DeviceCodePrefix, testutil.GetRandomName(t)[:8]),
1287+
UserCode: takeFirst(seed.UserCode, testutil.GetRandomName(t)),
1288+
ClientID: takeFirst(seed.ClientID, uuid.New()),
1289+
VerificationUri: takeFirst(seed.VerificationUri, "https://example.com/device"),
1290+
VerificationUriComplete: seed.VerificationUriComplete,
1291+
Scope: seed.Scope,
1292+
ResourceUri: seed.ResourceUri,
1293+
PollingInterval: takeFirst(seed.PollingInterval, 5),
1294+
})
1295+
assert.NoError(t, err, "insert oauth2 device code")
1296+
return deviceCode
1297+
}
1298+
12781299
func WorkspaceAgentMemoryResourceMonitor(t testing.TB, db database.Store, seed database.WorkspaceAgentMemoryResourceMonitor) database.WorkspaceAgentMemoryResourceMonitor {
12791300
monitor, err := db.InsertMemoryResourceMonitor(genCtx, database.InsertMemoryResourceMonitorParams{
12801301
AgentID: takeFirst(seed.AgentID, uuid.New()),

coderd/database/dbmetrics/querymetrics.go

Lines changed: 20 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy