Skip to content

Commit 5a2d6d0

Browse files
committed
chore: refactor ResolveAutostart tests to use dbfake
1 parent e23873f commit 5a2d6d0

File tree

7 files changed

+315
-139
lines changed

7 files changed

+315
-139
lines changed

coderd/database/dbfake/dbfake.go

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,23 @@ import (
1515
"github.com/coder/coder/v2/coderd/database/dbgen"
1616
"github.com/coder/coder/v2/coderd/database/dbtime"
1717
"github.com/coder/coder/v2/coderd/provisionerdserver"
18+
"github.com/coder/coder/v2/coderd/rbac"
1819
"github.com/coder/coder/v2/coderd/telemetry"
20+
"github.com/coder/coder/v2/provisionersdk/proto"
1921
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
2022
)
2123

24+
// All methods take in a 'seed' object. Any provided fields in the seed will be
25+
// maintained. Any fields omitted will have sensible defaults generated.
26+
27+
// genCtx is to give all generator functions permission if the db is a dbauthz db.
28+
var genCtx = dbauthz.As(context.Background(), rbac.Subject{
29+
ID: "owner",
30+
Roles: rbac.Roles(must(rbac.RoleNames{rbac.RoleOwner()}.Expand())),
31+
Groups: []string{},
32+
Scope: rbac.ExpandableScope(rbac.ScopeAll),
33+
})
34+
2235
// Workspace inserts a workspace into the database.
2336
func Workspace(t testing.TB, db database.Store, seed database.Workspace) database.Workspace {
2437
t.Helper()
@@ -37,6 +50,64 @@ func Workspace(t testing.TB, db database.Store, seed database.Workspace) databas
3750
return dbgen.Workspace(t, db, seed)
3851
}
3952

53+
func TemplateWithVersion(t testing.TB, db database.Store, tpl database.Template, tv database.TemplateVersion, resources ...*proto.Resource) (database.Template, database.TemplateVersion) {
54+
t.Helper()
55+
56+
template := dbgen.Template(t, db, tpl)
57+
58+
tv.TemplateID = takeFirst(tv.TemplateID, uuid.NullUUID{UUID: template.ID, Valid: true})
59+
tv.OrganizationID = takeFirst(tv.OrganizationID, template.OrganizationID)
60+
tv.CreatedBy = takeFirst(tv.CreatedBy, template.CreatedBy)
61+
version := TemplateVersion(t, db, tv, database.ProvisionerJob{}, resources...)
62+
63+
err := db.UpdateTemplateActiveVersionByID(genCtx, database.UpdateTemplateActiveVersionByIDParams{
64+
ID: template.ID,
65+
ActiveVersionID: version.ID,
66+
UpdatedAt: dbtime.Now(),
67+
})
68+
require.NoError(t, err)
69+
70+
return template, version
71+
}
72+
73+
func TemplateVersion(t testing.TB, db database.Store, tv database.TemplateVersion, job database.ProvisionerJob, resources ...*proto.Resource) database.TemplateVersion {
74+
templateVersion := dbgen.TemplateVersion(t, db, tv)
75+
payload, err := json.Marshal(provisionerdserver.TemplateVersionImportJob{
76+
TemplateVersionID: templateVersion.ID,
77+
})
78+
require.NoError(t, err)
79+
80+
job.ID = takeFirst(job.ID, templateVersion.JobID)
81+
job.OrganizationID = takeFirst(job.OrganizationID, templateVersion.OrganizationID)
82+
job.Input = takeFirstSlice(job.Input, payload)
83+
job.Type = takeFirst(job.Type, database.ProvisionerJobTypeTemplateVersionImport)
84+
job.CompletedAt = takeFirst(job.CompletedAt, sql.NullTime{
85+
Time: dbtime.Now(),
86+
Valid: true,
87+
})
88+
89+
job = dbgen.ProvisionerJob(t, db, nil, job)
90+
ProvisionerJobResources(t, db, job.ID, "", resources...)
91+
return templateVersion
92+
}
93+
94+
func TemplateVersionWithParams(t testing.TB, db database.Store, tv database.TemplateVersion, params []database.TemplateVersionParameter) (database.TemplateVersion, []database.TemplateVersionParameter) {
95+
t.Helper()
96+
97+
version := TemplateVersion(t, db, tv, database.ProvisionerJob{})
98+
tvps := make([]database.TemplateVersionParameter, 0, len(params))
99+
100+
for _, param := range params {
101+
if param.TemplateVersionID == uuid.Nil {
102+
param.TemplateVersionID = version.ID
103+
}
104+
tvp := dbgen.TemplateVersionParameter(t, db, param)
105+
tvps = append(tvps, tvp)
106+
}
107+
108+
return version, tvps
109+
}
110+
40111
// WorkspaceWithAgent is a helper that generates a workspace with a single resource
41112
// that has an agent attached to it. The agent token is returned.
42113
func WorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace) (database.Workspace, string) {
@@ -56,6 +127,19 @@ func WorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace
56127
return ws, authToken
57128
}
58129

130+
func WorkspaceBuildWithParameters(t testing.TB, db database.Store, ws database.Workspace, build database.WorkspaceBuild, params []database.WorkspaceBuildParameter, resources ...*sdkproto.Resource) (database.WorkspaceBuild, []database.WorkspaceBuildParameter) {
131+
t.Helper()
132+
133+
b := WorkspaceBuild(t, db, ws, build, resources...)
134+
135+
for i, param := range params {
136+
if param.WorkspaceBuildID == uuid.Nil {
137+
params[i].WorkspaceBuildID = b.ID
138+
}
139+
}
140+
return b, dbgen.WorkspaceBuildParameters(t, db, params)
141+
}
142+
59143
// WorkspaceBuild inserts a build and a successful job into the database.
60144
func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild {
61145
t.Helper()
@@ -69,9 +153,7 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed
69153
WorkspaceBuildID: seed.ID,
70154
})
71155
require.NoError(t, err)
72-
//nolint:gocritic // This is only used by tests.
73-
ctx := dbauthz.AsSystemRestricted(context.Background())
74-
job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
156+
job, err := db.InsertProvisionerJob(genCtx, database.InsertProvisionerJobParams{
75157
ID: jobID,
76158
CreatedAt: dbtime.Now(),
77159
UpdatedAt: dbtime.Now(),
@@ -86,7 +168,7 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed
86168
TraceMetadata: pqtype.NullRawMessage{},
87169
})
88170
require.NoError(t, err, "insert job")
89-
err = db.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{
171+
err = db.UpdateProvisionerJobWithCompleteByID(genCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
90172
ID: job.ID,
91173
UpdatedAt: dbtime.Now(),
92174
Error: sql.NullString{},
@@ -101,30 +183,14 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed
101183
// This intentionally fulfills the minimum requirements of the schema.
102184
// Tests can provide a custom version ID if necessary.
103185
if seed.TemplateVersionID == uuid.Nil {
104-
jobID := uuid.New()
105-
templateVersion := dbgen.TemplateVersion(t, db, database.TemplateVersion{
106-
JobID: jobID,
186+
templateVersion := TemplateVersion(t, db, database.TemplateVersion{
107187
OrganizationID: ws.OrganizationID,
108188
CreatedBy: ws.OwnerID,
109189
TemplateID: uuid.NullUUID{
110190
UUID: ws.TemplateID,
111191
Valid: true,
112192
},
113-
})
114-
payload, _ := json.Marshal(provisionerdserver.TemplateVersionImportJob{
115-
TemplateVersionID: templateVersion.ID,
116-
})
117-
dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{
118-
ID: jobID,
119-
OrganizationID: ws.OrganizationID,
120-
Input: payload,
121-
Type: database.ProvisionerJobTypeTemplateVersionImport,
122-
CompletedAt: sql.NullTime{
123-
Time: dbtime.Now(),
124-
Valid: true,
125-
},
126-
})
127-
ProvisionerJobResources(t, db, jobID, seed.Transition, resources...)
193+
}, database.ProvisionerJob{})
128194
seed.TemplateVersionID = templateVersion.ID
129195
}
130196
build := dbgen.WorkspaceBuild(t, db, seed)
@@ -145,3 +211,41 @@ func ProvisionerJobResources(t testing.TB, db database.Store, job uuid.UUID, tra
145211
require.NoError(t, err)
146212
}
147213
}
214+
215+
func must[V any](v V, err error) V {
216+
if err != nil {
217+
panic(err)
218+
}
219+
return v
220+
}
221+
222+
// takeFirstF takes the first value that returns true
223+
func takeFirstF[Value any](values []Value, take func(v Value) bool) Value {
224+
for _, v := range values {
225+
if take(v) {
226+
return v
227+
}
228+
}
229+
// If all empty, return the last element
230+
if len(values) > 0 {
231+
return values[len(values)-1]
232+
}
233+
var empty Value
234+
return empty
235+
}
236+
237+
// takeFirst will take the first non-empty value.
238+
func takeFirst[Value comparable](values ...Value) Value {
239+
var empty Value
240+
return takeFirstF(values, func(v Value) bool {
241+
return v != empty
242+
})
243+
}
244+
245+
// takeFirstSlice implements takeFirst for []any.
246+
// []any is not a comparable type.
247+
func takeFirstSlice[T any](values ...[]T) []T {
248+
return takeFirstF(values, func(v []T) bool {
249+
return len(v) != 0
250+
})
251+
}

coderd/database/dbgen/dbgen.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,42 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
229229
return build
230230
}
231231

232+
func WorkspaceBuildParameters(t testing.TB, db database.Store, orig []database.WorkspaceBuildParameter) []database.WorkspaceBuildParameter {
233+
if len(orig) == 0 {
234+
return nil
235+
}
236+
237+
var (
238+
names = make([]string, 0, len(orig))
239+
values = make([]string, 0, len(orig))
240+
params []database.WorkspaceBuildParameter
241+
)
242+
for _, param := range orig {
243+
names = append(names, param.Name)
244+
values = append(values, param.Value)
245+
}
246+
err := db.InTx(func(tx database.Store) error {
247+
id := takeFirst(orig[0].WorkspaceBuildID, uuid.New())
248+
err := tx.InsertWorkspaceBuildParameters(genCtx, database.InsertWorkspaceBuildParametersParams{
249+
WorkspaceBuildID: id,
250+
Name: names,
251+
Value: values,
252+
})
253+
if err != nil {
254+
return err
255+
}
256+
257+
params, err = tx.GetWorkspaceBuildParameters(genCtx, id)
258+
if err != nil {
259+
return err
260+
}
261+
return err
262+
263+
}, nil)
264+
require.NoError(t, err)
265+
return params
266+
}
267+
232268
func User(t testing.TB, db database.Store, orig database.User) database.User {
233269
user, err := db.InsertUser(genCtx, database.InsertUserParams{
234270
ID: takeFirst(orig.ID, uuid.New()),
@@ -584,6 +620,30 @@ func TemplateVersionVariable(t testing.TB, db database.Store, orig database.Temp
584620
return version
585621
}
586622

623+
func TemplateVersionParameter(t testing.TB, db database.Store, orig database.TemplateVersionParameter) database.TemplateVersionParameter {
624+
version, err := db.InsertTemplateVersionParameter(genCtx, database.InsertTemplateVersionParameterParams{
625+
TemplateVersionID: takeFirst(orig.TemplateVersionID, uuid.New()),
626+
Name: takeFirst(orig.Name, namesgenerator.GetRandomName(1)),
627+
Description: takeFirst(orig.Description, namesgenerator.GetRandomName(1)),
628+
Type: takeFirst(orig.Type, "string"),
629+
Mutable: takeFirst(orig.Mutable, false),
630+
DefaultValue: takeFirst(orig.DefaultValue, namesgenerator.GetRandomName(1)),
631+
Icon: takeFirst(orig.Icon, namesgenerator.GetRandomName(1)),
632+
Options: takeFirstSlice(orig.Options, []byte("[]")),
633+
ValidationRegex: takeFirst(orig.ValidationRegex, ""),
634+
ValidationMin: takeFirst(orig.ValidationMin, sql.NullInt32{}),
635+
ValidationMax: takeFirst(orig.ValidationMax, sql.NullInt32{}),
636+
ValidationError: takeFirst(orig.ValidationError, ""),
637+
ValidationMonotonic: takeFirst(orig.ValidationMonotonic, ""),
638+
Required: takeFirst(orig.Required, false),
639+
DisplayName: takeFirst(orig.DisplayName, namesgenerator.GetRandomName(1)),
640+
DisplayOrder: takeFirst(orig.DisplayOrder, 0),
641+
Ephemeral: takeFirst(orig.Ephemeral, false),
642+
})
643+
require.NoError(t, err, "insert template version parameter")
644+
return version
645+
}
646+
587647
func WorkspaceAgentStat(t testing.TB, db database.Store, orig database.WorkspaceAgentStat) database.WorkspaceAgentStat {
588648
if orig.ConnectionsByProto == nil {
589649
orig.ConnectionsByProto = json.RawMessage([]byte("{}"))

coderd/database/dbgen/dbgen_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,22 @@ func TestGenerator(t *testing.T) {
173173
exp := dbgen.GitSSHKey(t, db, database.GitSSHKey{})
174174
require.Equal(t, exp, must(db.GetGitSSHKey(context.Background(), exp.UserID)))
175175
})
176+
177+
t.Run("WorkspaceBuildParameters", func(t *testing.T) {
178+
t.Parallel()
179+
db := dbmem.New()
180+
exp := dbgen.WorkspaceBuildParameters(t, db, []database.WorkspaceBuildParameter{{}, {}, {}})
181+
require.Equal(t, exp, must(db.GetWorkspaceBuildParameters(context.Background(), exp[0].WorkspaceBuildID)))
182+
})
183+
184+
t.Run("TemplateVersionParameter", func(t *testing.T) {
185+
t.Parallel()
186+
db := dbmem.New()
187+
exp := dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{})
188+
actual := must(db.GetTemplateVersionParameters(context.Background(), exp.TemplateVersionID))
189+
require.Len(t, actual, 1)
190+
require.Equal(t, exp, actual[0])
191+
})
176192
}
177193

178194
func must[T any](value T, err error) T {

coderd/workspaces.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,7 @@ func (api *API) resolveAutostart(rw http.ResponseWriter, r *http.Request) {
10831083
templateAccessControl := (*(api.AccessControlStore.Load())).GetTemplateAccessControl(template)
10841084
useActiveVersion := templateAccessControl.RequireActiveVersion || workspace.AutomaticUpdates == database.AutomaticUpdatesAlways
10851085
if !useActiveVersion {
1086+
fmt.Println("NOACTIVE????")
10861087
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ResolveAutostartResponse{})
10871088
return
10881089
}
@@ -1097,6 +1098,7 @@ func (api *API) resolveAutostart(rw http.ResponseWriter, r *http.Request) {
10971098
}
10981099

10991100
if build.TemplateVersionID == template.ActiveVersionID {
1101+
fmt.Println("SHITTTT")
11001102
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ResolveAutostartResponse{})
11011103
return
11021104
}
@@ -1136,6 +1138,7 @@ func (api *API) resolveAutostart(rw http.ResponseWriter, r *http.Request) {
11361138
})
11371139
return
11381140
}
1141+
fmt.Println("build params: ", len(dbBuildParams))
11391142

11401143
resolver := codersdk.ParameterResolver{
11411144
Rich: db2sdk.WorkspaceBuildParameters(dbBuildParams),

0 commit comments

Comments
 (0)