Skip to content

Commit d02f713

Browse files
committed
chore: add database dump and dbfake logging
1 parent e80f91e commit d02f713

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed

.github/workflows/ci.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,12 @@ jobs:
490490
gotestsum --format standard-quiet --packages "$PACKAGES" \
491491
-- -timeout=20m -v -p $NUM_PARALLEL_PACKAGES -parallel=$NUM_PARALLEL_TESTS $TESTCOUNT
492492
493+
- name: Upload failed test db dumps
494+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
495+
with:
496+
name: failed-test-db-dump-${{matrix.os}}
497+
path: "**/*.test.sql"
498+
493499
- name: Upload Go Build Cache
494500
uses: ./.github/actions/test-cache/upload
495501
with:

cli/agent_test.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cli_test
33
import (
44
"context"
55
"fmt"
6+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
67
"net/http"
78
"os"
89
"path/filepath"
@@ -67,7 +68,12 @@ func TestWorkspaceAgent(t *testing.T) {
6768
t.Parallel()
6869
instanceID := "instanceidentifier"
6970
certificates, metadataClient := coderdtest.NewAzureInstanceIdentity(t, instanceID)
70-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
71+
db, ps := dbtestutil.NewDB(t,
72+
dbtestutil.WithDumpOnFailure(),
73+
)
74+
client := coderdtest.New(t, &coderdtest.Options{
75+
Database: db,
76+
Pubsub: ps,
7177
AzureCertificates: certificates,
7278
})
7379
user := coderdtest.CreateFirstUser(t, client)
@@ -106,7 +112,12 @@ func TestWorkspaceAgent(t *testing.T) {
106112
t.Parallel()
107113
instanceID := "instanceidentifier"
108114
certificates, metadataClient := coderdtest.NewAWSInstanceIdentity(t, instanceID)
109-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
115+
db, ps := dbtestutil.NewDB(t,
116+
dbtestutil.WithDumpOnFailure(),
117+
)
118+
client := coderdtest.New(t, &coderdtest.Options{
119+
Database: db,
120+
Pubsub: ps,
110121
AWSCertificates: certificates,
111122
})
112123
user := coderdtest.CreateFirstUser(t, client)
@@ -146,7 +157,12 @@ func TestWorkspaceAgent(t *testing.T) {
146157
t.Parallel()
147158
instanceID := "instanceidentifier"
148159
validator, metadataClient := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false)
149-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
160+
db, ps := dbtestutil.NewDB(t,
161+
dbtestutil.WithDumpOnFailure(),
162+
)
163+
client := coderdtest.New(t, &coderdtest.Options{
164+
Database: db,
165+
Pubsub: ps,
150166
GoogleTokenValidator: validator,
151167
})
152168
owner := coderdtest.CreateFirstUser(t, client)
@@ -158,6 +174,7 @@ func TestWorkspaceAgent(t *testing.T) {
158174
agents[0].Auth = &proto.Agent_InstanceId{InstanceId: instanceID}
159175
return agents
160176
}).Do()
177+
t.FailNow()
161178

162179
inv, cfg := clitest.New(t, "agent", "--auth", "google-instance-identity", "--agent-url", client.URL.String())
163180
clitest.SetupConfig(t, member, cfg)

coderd/database/dbfake/dbfake.go

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dbfake
22

33
import (
4+
"cdr.dev/slog"
5+
"cdr.dev/slog/sloggers/slogtest"
46
"context"
57
"database/sql"
68
"encoding/json"
@@ -43,6 +45,7 @@ type WorkspaceResponse struct {
4345
// resources.
4446
type WorkspaceBuildBuilder struct {
4547
t testing.TB
48+
logger slog.Logger
4649
db database.Store
4750
ps pubsub.Pubsub
4851
ws database.WorkspaceTable
@@ -62,7 +65,10 @@ type workspaceBuildDisposition struct {
6265
// Omitting the template ID on a workspace will also generate a new template
6366
// with a template version.
6467
func WorkspaceBuild(t testing.TB, db database.Store, ws database.WorkspaceTable) WorkspaceBuildBuilder {
65-
return WorkspaceBuildBuilder{t: t, db: db, ws: ws}
68+
return WorkspaceBuildBuilder{
69+
t: t, db: db, ws: ws,
70+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug),
71+
}
6672
}
6773

6874
func (b WorkspaceBuildBuilder) Pubsub(ps pubsub.Pubsub) WorkspaceBuildBuilder {
@@ -131,6 +137,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
131137
AgentToken: b.agentToken,
132138
}
133139
if b.ws.TemplateID == uuid.Nil {
140+
b.logger.Debug(context.Background(), "creating template and version")
134141
resp.TemplateVersionResponse = TemplateVersion(b.t, b.db).
135142
Resources(b.resources...).
136143
Pubsub(b.ps).
@@ -145,6 +152,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
145152

146153
// If no template version is set assume the active version.
147154
if b.seed.TemplateVersionID == uuid.Nil {
155+
b.logger.Debug(context.Background(), "assuming active template version")
148156
template, err := b.db.GetTemplateByID(ownerCtx, b.ws.TemplateID)
149157
require.NoError(b.t, err)
150158
require.NotNil(b.t, template.ActiveVersionID, "active version ID unexpectedly nil")
@@ -156,6 +164,9 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
156164
// nolint: revive
157165
b.ws = dbgen.Workspace(b.t, b.db, b.ws)
158166
resp.Workspace = b.ws
167+
b.logger.Debug(context.Background(), "created workspace",
168+
slog.F("name", resp.Workspace.Name),
169+
slog.F("workspace_id", resp.Workspace.ID))
159170
}
160171
b.seed.WorkspaceID = b.ws.ID
161172
b.seed.InitiatorID = takeFirst(b.seed.InitiatorID, b.ws.OwnerID)
@@ -182,10 +193,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
182193
LogsOverflowed: false,
183194
})
184195
require.NoError(b.t, err, "insert job")
196+
b.logger.Debug(context.Background(), "inserted provisioner job", slog.F("job_id", job.ID))
185197

186198
if b.dispo.starting {
187199
// might need to do this multiple times if we got a template version
188200
// import job as well
201+
b.logger.Debug(context.Background(), "looping to acquire provisioner job")
189202
for {
190203
j, err := b.db.AcquireProvisionerJob(ownerCtx, database.AcquireProvisionerJobParams{
191204
OrganizationID: job.OrganizationID,
@@ -202,10 +215,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
202215
})
203216
require.NoError(b.t, err, "acquire starting job")
204217
if j.ID == job.ID {
218+
b.logger.Debug(context.Background(), "acquired provisioner job", slog.F("job_id", job.ID))
205219
break
206220
}
207221
}
208222
} else {
223+
b.logger.Debug(context.Background(), "completing the provisioner job")
209224
err = b.db.UpdateProvisionerJobWithCompleteByID(ownerCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
210225
ID: job.ID,
211226
UpdatedAt: dbtime.Now(),
@@ -221,18 +236,24 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
221236
}
222237

223238
resp.Build = dbgen.WorkspaceBuild(b.t, b.db, b.seed)
239+
b.logger.Debug(context.Background(), "created workspace build",
240+
slog.F("build_id", resp.Build.ID),
241+
slog.F("workspace_id", resp.Workspace.ID),
242+
slog.F("build_number", resp.Build.BuildNumber))
224243

225244
for i := range b.params {
226245
b.params[i].WorkspaceBuildID = resp.Build.ID
227246
}
228-
_ = dbgen.WorkspaceBuildParameters(b.t, b.db, b.params)
247+
params := dbgen.WorkspaceBuildParameters(b.t, b.db, b.params)
248+
b.logger.Debug(context.Background(), "created workspace build parameters", slog.F("count", len(params)))
229249

230250
if b.ws.Deleted {
231251
err = b.db.UpdateWorkspaceDeletedByID(ownerCtx, database.UpdateWorkspaceDeletedByIDParams{
232252
ID: b.ws.ID,
233253
Deleted: true,
234254
})
235255
require.NoError(b.t, err)
256+
b.logger.Debug(context.Background(), "deleted workspace", slog.F("workspace_id", resp.Workspace.ID))
236257
}
237258

238259
if b.ps != nil {
@@ -243,6 +264,9 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
243264
require.NoError(b.t, err)
244265
err = b.ps.Publish(wspubsub.WorkspaceEventChannel(resp.Workspace.OwnerID), msg)
245266
require.NoError(b.t, err)
267+
b.logger.Debug(context.Background(), "published workspace event",
268+
slog.F("owner_id", resp.Workspace.ID),
269+
slog.F("owner_id", resp.Workspace.OwnerID))
246270
}
247271

248272
agents, err := b.db.GetWorkspaceAgentsByWorkspaceAndBuildNumber(ownerCtx, database.GetWorkspaceAgentsByWorkspaceAndBuildNumberParams{
@@ -260,7 +284,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
260284
err = b.db.DeleteWorkspaceSubAgentByID(ownerCtx, subAgent.ID)
261285
require.NoError(b.t, err, "delete workspace agent subagent antagonist")
262286

263-
b.t.Logf("inserted deleted subagent antagonist %s (%v) for workspace agent %s (%v)", subAgent.Name, subAgent.ID, agent.Name, agent.ID)
287+
b.logger.Debug(context.Background(), "inserted deleted subagent antagonist",
288+
slog.F("subagent_name", subAgent.Name),
289+
slog.F("subagent_id", subAgent.ID),
290+
slog.F("agent_name", agent.Name),
291+
slog.F("agent_id", agent.ID),
292+
)
264293
}
265294
}
266295

@@ -269,6 +298,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
269298

270299
type ProvisionerJobResourcesBuilder struct {
271300
t testing.TB
301+
logger slog.Logger
272302
db database.Store
273303
jobID uuid.UUID
274304
transition database.WorkspaceTransition
@@ -281,6 +311,7 @@ func ProvisionerJobResources(
281311
) ProvisionerJobResourcesBuilder {
282312
return ProvisionerJobResourcesBuilder{
283313
t: t,
314+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug).With(slog.F("job_id", jobID)),
284315
db: db,
285316
jobID: jobID,
286317
transition: transition,
@@ -292,13 +323,17 @@ func (b ProvisionerJobResourcesBuilder) Do() {
292323
b.t.Helper()
293324
transition := b.transition
294325
if transition == "" {
295-
// Default to start!
326+
b.logger.Debug(context.Background(), "setting default transition to start")
296327
transition = database.WorkspaceTransitionStart
297328
}
298329
for _, resource := range b.resources {
299330
//nolint:gocritic // This is only used by tests.
300331
err := provisionerdserver.InsertWorkspaceResource(ownerCtx, b.db, b.jobID, transition, resource, &telemetry.Snapshot{})
301332
require.NoError(b.t, err)
333+
b.logger.Debug(context.Background(), "created workspace resource",
334+
slog.F("resource_name", resource.Name),
335+
slog.F("agent_count", len(resource.Agents)),
336+
)
302337
}
303338
}
304339

@@ -309,6 +344,7 @@ type TemplateVersionResponse struct {
309344

310345
type TemplateVersionBuilder struct {
311346
t testing.TB
347+
logger slog.Logger
312348
db database.Store
313349
seed database.TemplateVersion
314350
fileID uuid.UUID
@@ -326,6 +362,7 @@ type TemplateVersionBuilder struct {
326362
func TemplateVersion(t testing.TB, db database.Store) TemplateVersionBuilder {
327363
return TemplateVersionBuilder{
328364
t: t,
365+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug),
329366
db: db,
330367
promote: true,
331368
autoCreateTemplate: true,
@@ -396,20 +433,30 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
396433
Valid: true,
397434
UUID: resp.Template.ID,
398435
}
436+
t.logger.Debug(context.Background(), "created template",
437+
slog.F("organization_id", resp.Template.OrganizationID),
438+
slog.F("template_id", resp.Template.CreatedBy),
439+
)
399440
}
400441

401442
version := dbgen.TemplateVersion(t.t, t.db, t.seed)
443+
t.logger.Debug(context.Background(), "created template version",
444+
slog.F("template_version_id", version.ID),
445+
)
402446
if t.promote {
403447
err := t.db.UpdateTemplateActiveVersionByID(ownerCtx, database.UpdateTemplateActiveVersionByIDParams{
404448
ID: t.seed.TemplateID.UUID,
405449
ActiveVersionID: t.seed.ID,
406450
UpdatedAt: dbtime.Now(),
407451
})
408452
require.NoError(t.t, err)
453+
t.logger.Debug(context.Background(), "promoted template version",
454+
slog.F("template_version_id", t.seed.ID),
455+
)
409456
}
410457

411458
for _, preset := range t.presets {
412-
dbgen.Preset(t.t, t.db, database.InsertPresetParams{
459+
prst := dbgen.Preset(t.t, t.db, database.InsertPresetParams{
413460
ID: preset.ID,
414461
TemplateVersionID: version.ID,
415462
Name: preset.Name,
@@ -421,14 +468,19 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
421468
Description: preset.Description,
422469
Icon: preset.Icon,
423470
})
471+
t.logger.Debug(context.Background(), "added preset",
472+
slog.F("preset_id", prst.ID),
473+
slog.F("preset_name", prst.Name),
474+
)
424475
}
425476

426477
for _, presetParam := range t.presetParams {
427-
dbgen.PresetParameter(t.t, t.db, database.InsertPresetParametersParams{
478+
prm := dbgen.PresetParameter(t.t, t.db, database.InsertPresetParametersParams{
428479
TemplateVersionPresetID: presetParam.TemplateVersionPresetID,
429480
Names: []string{presetParam.Name},
430481
Values: []string{presetParam.Value},
431482
})
483+
t.logger.Debug(context.Background(), "added preset parameter", slog.F("param_name", prm[0].Name))
432484
}
433485

434486
payload, err := json.Marshal(provisionerdserver.TemplateVersionImportJob{
@@ -448,6 +500,7 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
448500
},
449501
FileID: t.fileID,
450502
})
503+
t.logger.Debug(context.Background(), "added template version import job", slog.F("job_id", job.ID))
451504

452505
t.seed.JobID = job.ID
453506

coderd/database/dbtestutil/db.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ func DumpOnFailure(t testing.TB, connectionURL string) {
206206
outPath := filepath.Join(cwd, snakeCaseName+"."+timeSuffix+".test.sql")
207207
dump, err := PGDump(connectionURL)
208208
if err != nil {
209-
t.Errorf("dump on failure: failed to run pg_dump")
209+
t.Errorf("dump on failure: failed to run pg_dump: %s", err.Error())
210210
return
211211
}
212212
if err := os.WriteFile(outPath, normalizeDump(dump), 0o600); err != nil {

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