Skip to content

Commit 34b46f9

Browse files
authored
feat(coderd/database): add support for presets (#16509)
This pull requests adds the necessary migrations and queries to support presets within the coderd database. Future PRs will build functionality to the provisioners and the frontend.
1 parent 0e728a7 commit 34b46f9

20 files changed

+948
-144
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 45 additions & 0 deletions
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

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

coderd/database/dbgen/dbgen.go

Lines changed: 4 additions & 0 deletions
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

Lines changed: 102 additions & 0 deletions
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)
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