Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 34b46f9

Browse files
authored
feat(coderd/database): add support for presets (coder#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

+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

+164
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

+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)