Skip to content

Commit 801349f

Browse files
committed
feat(coderd/database): add support for presets
1 parent 695d552 commit 801349f

19 files changed

+939
-149
lines changed

coderd/database/dbauthz/dbauthz.go

+45
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,33 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
19301930
return q.db.GetParameterSchemasByJobID(ctx, jobID)
19311931
}
19321932

1933+
func (q *querier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceID uuid.UUID) (database.TemplateVersionPreset, error) {
1934+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
1935+
return database.TemplateVersionPreset{}, err
1936+
}
1937+
return q.db.GetPresetByWorkspaceBuildID(ctx, workspaceID)
1938+
}
1939+
1940+
func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPresetParameter, error) {
1941+
// An actor can read template version presets if they can read the related template version.
1942+
_, err := q.GetTemplateVersionByID(ctx, templateVersionID)
1943+
if err != nil {
1944+
return nil, err
1945+
}
1946+
1947+
return q.db.GetPresetParametersByTemplateVersionID(ctx, templateVersionID)
1948+
}
1949+
1950+
func (q *querier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPreset, error) {
1951+
// An actor can read template version presets if they can read the related template version.
1952+
_, err := q.GetTemplateVersionByID(ctx, templateVersionID)
1953+
if err != nil {
1954+
return nil, err
1955+
}
1956+
1957+
return q.db.GetPresetsByTemplateVersionID(ctx, templateVersionID)
1958+
}
1959+
19331960
func (q *querier) GetPreviousTemplateVersion(ctx context.Context, arg database.GetPreviousTemplateVersionParams) (database.TemplateVersion, error) {
19341961
// An actor can read the previous template version if they can read the related template.
19351962
// If no linked template exists, we check if the actor can read *a* template.
@@ -3088,6 +3115,24 @@ func (q *querier) InsertOrganizationMember(ctx context.Context, arg database.Ins
30883115
return insert(q.log, q.auth, obj, q.db.InsertOrganizationMember)(ctx, arg)
30893116
}
30903117

3118+
func (q *querier) InsertPreset(ctx context.Context, arg database.InsertPresetParams) (database.TemplateVersionPreset, error) {
3119+
err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate)
3120+
if err != nil {
3121+
return database.TemplateVersionPreset{}, err
3122+
}
3123+
3124+
return q.db.InsertPreset(ctx, arg)
3125+
}
3126+
3127+
func (q *querier) InsertPresetParameters(ctx context.Context, arg database.InsertPresetParametersParams) ([]database.TemplateVersionPresetParameter, error) {
3128+
err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate)
3129+
if err != nil {
3130+
return nil, err
3131+
}
3132+
3133+
return q.db.InsertPresetParameters(ctx, arg)
3134+
}
3135+
30913136
// TODO: We need to create a ProvisionerJob resource type
30923137
func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
30933138
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {

coderd/database/dbauthz/dbauthz_test.go

+166
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,82 @@ func (s *MethodTestSuite) TestOrganization() {
859859
rbac.ResourceAssignOrgRole.InOrg(o.ID), policy.ActionAssign,
860860
rbac.ResourceOrganizationMember.InOrg(o.ID).WithID(u.ID), policy.ActionCreate)
861861
}))
862+
s.Run("InsertPreset", s.Subtest(func(db database.Store, check *expects) {
863+
ctx := context.Background()
864+
org := dbgen.Organization(s.T(), db, database.Organization{})
865+
user := dbgen.User(s.T(), db, database.User{})
866+
template := dbgen.Template(s.T(), db, database.Template{
867+
CreatedBy: user.ID,
868+
OrganizationID: org.ID,
869+
})
870+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
871+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
872+
OrganizationID: org.ID,
873+
CreatedBy: user.ID,
874+
})
875+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
876+
OrganizationID: org.ID,
877+
OwnerID: user.ID,
878+
TemplateID: template.ID,
879+
})
880+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
881+
OrganizationID: org.ID,
882+
})
883+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
884+
WorkspaceID: workspace.ID,
885+
TemplateVersionID: templateVersion.ID,
886+
InitiatorID: user.ID,
887+
JobID: job.ID,
888+
})
889+
insertPresetParams := database.InsertPresetParams{
890+
TemplateVersionID: workspaceBuild.TemplateVersionID,
891+
Name: "test",
892+
}
893+
_, err := db.InsertPreset(ctx, insertPresetParams)
894+
require.NoError(s.T(), err)
895+
check.Args(insertPresetParams).Asserts(rbac.ResourceTemplate, policy.ActionUpdate)
896+
}))
897+
s.Run("InsertPresetParameters", s.Subtest(func(db database.Store, check *expects) {
898+
org := dbgen.Organization(s.T(), db, database.Organization{})
899+
user := dbgen.User(s.T(), db, database.User{})
900+
template := dbgen.Template(s.T(), db, database.Template{
901+
CreatedBy: user.ID,
902+
OrganizationID: org.ID,
903+
})
904+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
905+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
906+
OrganizationID: org.ID,
907+
CreatedBy: user.ID,
908+
})
909+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
910+
OrganizationID: org.ID,
911+
OwnerID: user.ID,
912+
TemplateID: template.ID,
913+
})
914+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
915+
OrganizationID: org.ID,
916+
})
917+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
918+
WorkspaceID: workspace.ID,
919+
TemplateVersionID: templateVersion.ID,
920+
InitiatorID: user.ID,
921+
JobID: job.ID,
922+
})
923+
insertPresetParams := database.InsertPresetParams{
924+
TemplateVersionID: workspaceBuild.TemplateVersionID,
925+
Name: "test",
926+
}
927+
preset, err := db.InsertPreset(context.Background(), insertPresetParams)
928+
require.NoError(s.T(), err)
929+
insertPresetParametersParams := database.InsertPresetParametersParams{
930+
TemplateVersionPresetID: preset.ID,
931+
Names: []string{"test"},
932+
Values: []string{"test"},
933+
}
934+
_, err = db.InsertPresetParameters(context.Background(), insertPresetParametersParams)
935+
require.NoError(s.T(), err)
936+
check.Args(insertPresetParametersParams).Asserts(rbac.ResourceTemplate, policy.ActionUpdate)
937+
}))
862938
s.Run("DeleteOrganizationMember", s.Subtest(func(db database.Store, check *expects) {
863939
o := dbgen.Organization(s.T(), db, database.Organization{})
864940
u := dbgen.User(s.T(), db, database.User{})
@@ -3695,6 +3771,96 @@ func (s *MethodTestSuite) TestSystemFunctions() {
36953771
ErrorsWithInMemDB(sql.ErrNoRows).
36963772
Returns([]database.ParameterSchema{})
36973773
}))
3774+
s.Run("GetPresetByWorkspaceBuildID", s.Subtest(func(db database.Store, check *expects) {
3775+
org := dbgen.Organization(s.T(), db, database.Organization{})
3776+
user := dbgen.User(s.T(), db, database.User{})
3777+
template := dbgen.Template(s.T(), db, database.Template{
3778+
CreatedBy: user.ID,
3779+
OrganizationID: org.ID,
3780+
})
3781+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3782+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3783+
OrganizationID: org.ID,
3784+
CreatedBy: user.ID,
3785+
})
3786+
preset, err := db.InsertPreset(context.Background(), database.InsertPresetParams{
3787+
TemplateVersionID: templateVersion.ID,
3788+
Name: "test",
3789+
})
3790+
require.NoError(s.T(), err)
3791+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
3792+
OrganizationID: org.ID,
3793+
OwnerID: user.ID,
3794+
TemplateID: template.ID,
3795+
})
3796+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
3797+
OrganizationID: org.ID,
3798+
})
3799+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
3800+
WorkspaceID: workspace.ID,
3801+
TemplateVersionID: templateVersion.ID,
3802+
TemplateVersionPresetID: uuid.NullUUID{UUID: preset.ID, Valid: true},
3803+
InitiatorID: user.ID,
3804+
JobID: job.ID,
3805+
})
3806+
_, err = db.GetPresetByWorkspaceBuildID(context.Background(), workspaceBuild.ID)
3807+
require.NoError(s.T(), err)
3808+
check.Args(workspaceBuild.ID).Asserts(rbac.ResourceTemplate, policy.ActionRead)
3809+
}))
3810+
s.Run("GetPresetParametersByTemplateVersionID", s.Subtest(func(db database.Store, check *expects) {
3811+
ctx := context.Background()
3812+
org := dbgen.Organization(s.T(), db, database.Organization{})
3813+
user := dbgen.User(s.T(), db, database.User{})
3814+
template := dbgen.Template(s.T(), db, database.Template{
3815+
CreatedBy: user.ID,
3816+
OrganizationID: org.ID,
3817+
})
3818+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3819+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3820+
OrganizationID: org.ID,
3821+
CreatedBy: user.ID,
3822+
})
3823+
preset, err := db.InsertPreset(ctx, database.InsertPresetParams{
3824+
TemplateVersionID: templateVersion.ID,
3825+
Name: "test",
3826+
})
3827+
require.NoError(s.T(), err)
3828+
_, err = db.InsertPresetParameters(ctx, database.InsertPresetParametersParams{
3829+
TemplateVersionPresetID: preset.ID,
3830+
Names: []string{"test"},
3831+
Values: []string{"test"},
3832+
})
3833+
require.NoError(s.T(), err)
3834+
presetParameters, err := db.GetPresetParametersByTemplateVersionID(ctx, templateVersion.ID)
3835+
require.NoError(s.T(), err)
3836+
3837+
check.Args(templateVersion.ID).Asserts(template.RBACObject(), policy.ActionRead).Returns(presetParameters)
3838+
}))
3839+
s.Run("GetPresetsByTemplateVersionID", s.Subtest(func(db database.Store, check *expects) {
3840+
ctx := context.Background()
3841+
org := dbgen.Organization(s.T(), db, database.Organization{})
3842+
user := dbgen.User(s.T(), db, database.User{})
3843+
template := dbgen.Template(s.T(), db, database.Template{
3844+
CreatedBy: user.ID,
3845+
OrganizationID: org.ID,
3846+
})
3847+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3848+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3849+
OrganizationID: org.ID,
3850+
CreatedBy: user.ID,
3851+
})
3852+
3853+
_, err := db.InsertPreset(ctx, database.InsertPresetParams{
3854+
TemplateVersionID: templateVersion.ID,
3855+
Name: "test",
3856+
})
3857+
require.NoError(s.T(), err)
3858+
3859+
presets, err := db.GetPresetsByTemplateVersionID(ctx, templateVersion.ID)
3860+
require.NoError(s.T(), err)
3861+
3862+
check.Args(templateVersion.ID).Asserts(template.RBACObject(), policy.ActionRead).Returns(presets)
3863+
}))
36983864
s.Run("GetWorkspaceAppsByAgentIDs", s.Subtest(func(db database.Store, check *expects) {
36993865
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
37003866
aWs := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})

coderd/database/dbgen/dbgen.go

+4
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
314314
Deadline: takeFirst(orig.Deadline, dbtime.Now().Add(time.Hour)),
315315
MaxDeadline: takeFirst(orig.MaxDeadline, time.Time{}),
316316
Reason: takeFirst(orig.Reason, database.BuildReasonInitiator),
317+
TemplateVersionPresetID: takeFirst(orig.TemplateVersionPresetID, uuid.NullUUID{
318+
UUID: uuid.UUID{},
319+
Valid: false,
320+
}),
317321
})
318322
if err != nil {
319323
return err

coderd/database/dbmem/dbmem.go

+102
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ func New() database.Store {
9090
runtimeConfig: map[string]string{},
9191
userStatusChanges: make([]database.UserStatusChange, 0),
9292
telemetryItems: make([]database.TelemetryItem, 0),
93+
presets: make([]database.TemplateVersionPreset, 0),
94+
presetParameters: make([]database.TemplateVersionPresetParameter, 0),
9395
},
9496
}
9597
// Always start with a default org. Matching migration 198.
@@ -262,6 +264,8 @@ type data struct {
262264
defaultProxyIconURL string
263265
userStatusChanges []database.UserStatusChange
264266
telemetryItems []database.TelemetryItem
267+
presets []database.TemplateVersionPreset
268+
presetParameters []database.TemplateVersionPresetParameter
265269
}
266270

267271
func tryPercentile(fs []float64, p float64) float64 {
@@ -3776,6 +3780,61 @@ func (q *FakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.U
37763780
return parameters, nil
37773781
}
37783782

3783+
func (q *FakeQuerier) GetPresetByWorkspaceBuildID(_ context.Context, workspaceBuildID uuid.UUID) (database.TemplateVersionPreset, error) {
3784+
q.mutex.RLock()
3785+
defer q.mutex.RUnlock()
3786+
3787+
for _, workspaceBuild := range q.workspaceBuilds {
3788+
if workspaceBuild.ID != workspaceBuildID {
3789+
continue
3790+
}
3791+
for _, preset := range q.presets {
3792+
if preset.TemplateVersionID == workspaceBuild.TemplateVersionID {
3793+
return preset, nil
3794+
}
3795+
}
3796+
}
3797+
return database.TemplateVersionPreset{}, sql.ErrNoRows
3798+
}
3799+
3800+
func (q *FakeQuerier) GetPresetParametersByTemplateVersionID(_ context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPresetParameter, error) {
3801+
q.mutex.RLock()
3802+
defer q.mutex.RUnlock()
3803+
3804+
presets := make([]database.TemplateVersionPreset, 0)
3805+
parameters := make([]database.TemplateVersionPresetParameter, 0)
3806+
for _, preset := range q.presets {
3807+
if preset.TemplateVersionID != templateVersionID {
3808+
continue
3809+
}
3810+
presets = append(presets, preset)
3811+
}
3812+
for _, parameter := range q.presetParameters {
3813+
for _, preset := range presets {
3814+
if parameter.TemplateVersionPresetID != preset.ID {
3815+
continue
3816+
}
3817+
parameters = append(parameters, parameter)
3818+
break
3819+
}
3820+
}
3821+
3822+
return parameters, nil
3823+
}
3824+
3825+
func (q *FakeQuerier) GetPresetsByTemplateVersionID(_ context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPreset, error) {
3826+
q.mutex.RLock()
3827+
defer q.mutex.RUnlock()
3828+
3829+
presets := make([]database.TemplateVersionPreset, 0)
3830+
for _, preset := range q.presets {
3831+
if preset.TemplateVersionID == templateVersionID {
3832+
presets = append(presets, preset)
3833+
}
3834+
}
3835+
return presets, nil
3836+
}
3837+
37793838
func (q *FakeQuerier) GetPreviousTemplateVersion(_ context.Context, arg database.GetPreviousTemplateVersionParams) (database.TemplateVersion, error) {
37803839
if err := validateDatabaseType(arg); err != nil {
37813840
return database.TemplateVersion{}, err
@@ -8081,6 +8140,49 @@ func (q *FakeQuerier) InsertOrganizationMember(_ context.Context, arg database.I
80818140
return organizationMember, nil
80828141
}
80838142

8143+
func (q *FakeQuerier) InsertPreset(_ context.Context, arg database.InsertPresetParams) (database.TemplateVersionPreset, error) {
8144+
err := validateDatabaseType(arg)
8145+
if err != nil {
8146+
return database.TemplateVersionPreset{}, err
8147+
}
8148+
8149+
q.mutex.Lock()
8150+
defer q.mutex.Unlock()
8151+
8152+
preset := database.TemplateVersionPreset{
8153+
ID: uuid.New(),
8154+
TemplateVersionID: arg.TemplateVersionID,
8155+
Name: arg.Name,
8156+
CreatedAt: arg.CreatedAt,
8157+
}
8158+
q.presets = append(q.presets, preset)
8159+
return preset, nil
8160+
}
8161+
8162+
func (q *FakeQuerier) InsertPresetParameters(_ context.Context, arg database.InsertPresetParametersParams) ([]database.TemplateVersionPresetParameter, error) {
8163+
err := validateDatabaseType(arg)
8164+
if err != nil {
8165+
return nil, err
8166+
}
8167+
8168+
q.mutex.Lock()
8169+
defer q.mutex.Unlock()
8170+
8171+
presetParameters := make([]database.TemplateVersionPresetParameter, 0, len(arg.Names))
8172+
for i, v := range arg.Names {
8173+
presetParameter := database.TemplateVersionPresetParameter{
8174+
ID: uuid.New(),
8175+
TemplateVersionPresetID: arg.TemplateVersionPresetID,
8176+
Name: v,
8177+
Value: arg.Values[i],
8178+
}
8179+
presetParameters = append(presetParameters, presetParameter)
8180+
q.presetParameters = append(q.presetParameters, presetParameter)
8181+
}
8182+
8183+
return presetParameters, nil
8184+
}
8185+
80848186
func (q *FakeQuerier) InsertProvisionerJob(_ context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
80858187
if err := validateDatabaseType(arg); err != nil {
80868188
return database.ProvisionerJob{}, err

0 commit comments

Comments
 (0)