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

Skip to content

Commit ca8a49c

Browse files
committed
adds support for workspace presets to the coderd database. Support in the API and web frontend will be added in subsequent pull requests. This is the smallest meaningful contribution that I could get passing tests for.
* Add workspace preset tables to the database in a migration * Add queries to manipulate workspace presets to the database * Generate db related code for the newly added queries * Implement new methods to satisfy the Querier interface in dbauthz, dbmem, dbmock and querymetrics * Implement the required tests for dbauthz * Update the audit table to track changes to the new column in workspace builds
1 parent 738a7f6 commit ca8a49c

File tree

17 files changed

+820
-125
lines changed

17 files changed

+820
-125
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,6 +1911,30 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
19111911
return q.db.GetParameterSchemasByJobID(ctx, jobID)
19121912
}
19131913

1914+
func (q *querier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceID uuid.UUID) (database.GetPresetByWorkspaceBuildIDRow, error) {
1915+
// TODO (sasswart): Double check when to and not to call .InOrg?
1916+
// TODO (sasswart): it makes sense to me that a caller can read a preset if they can read the template, but double check this.
1917+
// TODO (sasswart): apply these todos to GetPresetParametersByPresetID and GetPresetsByTemplateVersionID.
1918+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
1919+
return database.GetPresetByWorkspaceBuildIDRow{}, err
1920+
}
1921+
return q.db.GetPresetByWorkspaceBuildID(ctx, workspaceID)
1922+
}
1923+
1924+
func (q *querier) GetPresetParametersByPresetID(ctx context.Context, templateVersionPresetID uuid.UUID) ([]database.GetPresetParametersByPresetIDRow, error) {
1925+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
1926+
return nil, err
1927+
}
1928+
return q.db.GetPresetParametersByPresetID(ctx, templateVersionPresetID)
1929+
}
1930+
1931+
func (q *querier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.GetPresetsByTemplateVersionIDRow, error) {
1932+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
1933+
return nil, err
1934+
}
1935+
return q.db.GetPresetsByTemplateVersionID(ctx, templateVersionID)
1936+
}
1937+
19141938
func (q *querier) GetPreviousTemplateVersion(ctx context.Context, arg database.GetPreviousTemplateVersionParams) (database.TemplateVersion, error) {
19151939
// An actor can read the previous template version if they can read the related template.
19161940
// If no linked template exists, we check if the actor can read *a* template.
@@ -3043,6 +3067,13 @@ func (q *querier) InsertOrganizationMember(ctx context.Context, arg database.Ins
30433067
return insert(q.log, q.auth, obj, q.db.InsertOrganizationMember)(ctx, arg)
30443068
}
30453069

3070+
func (q *querier) InsertPreset(ctx context.Context, arg database.InsertPresetParams) (database.TemplateVersionPreset, error) {
3071+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceTemplate); err != nil {
3072+
return database.TemplateVersionPreset{}, err
3073+
}
3074+
return q.db.InsertPreset(ctx, arg)
3075+
}
3076+
30463077
// TODO: We need to create a ProvisionerJob resource type
30473078
func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
30483079
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,40 @@ 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+
params := database.InsertPresetParams{
889+
TemplateVersionID: workspaceBuild.TemplateVersionID,
890+
Name: "test",
891+
}
892+
_, err := db.InsertPreset(context.Background(), params)
893+
require.NoError(s.T(), err)
894+
check.Args(params).Asserts(rbac.ResourceTemplate, policy.ActionCreate)
895+
}))
862896
s.Run("DeleteOrganizationMember", s.Subtest(func(db database.Store, check *expects) {
863897
o := dbgen.Organization(s.T(), db, database.Organization{})
864898
u := dbgen.User(s.T(), db, database.User{})
@@ -3663,6 +3697,118 @@ func (s *MethodTestSuite) TestSystemFunctions() {
36633697
ErrorsWithInMemDB(sql.ErrNoRows).
36643698
Returns([]database.ParameterSchema{})
36653699
}))
3700+
s.Run("GetPresetByWorkspaceBuildID", s.Subtest(func(db database.Store, check *expects) {
3701+
org := dbgen.Organization(s.T(), db, database.Organization{})
3702+
user := dbgen.User(s.T(), db, database.User{})
3703+
template := dbgen.Template(s.T(), db, database.Template{
3704+
CreatedBy: user.ID,
3705+
OrganizationID: org.ID,
3706+
})
3707+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3708+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3709+
OrganizationID: org.ID,
3710+
CreatedBy: user.ID,
3711+
})
3712+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
3713+
OrganizationID: org.ID,
3714+
OwnerID: user.ID,
3715+
TemplateID: template.ID,
3716+
})
3717+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
3718+
OrganizationID: org.ID,
3719+
})
3720+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
3721+
WorkspaceID: workspace.ID,
3722+
TemplateVersionID: templateVersion.ID,
3723+
InitiatorID: user.ID,
3724+
JobID: job.ID,
3725+
})
3726+
_, err := db.InsertPreset(context.Background(), database.InsertPresetParams{
3727+
TemplateVersionID: workspaceBuild.TemplateVersionID,
3728+
Name: "test",
3729+
})
3730+
require.NoError(s.T(), err)
3731+
db.GetPresetByWorkspaceBuildID(context.Background(), workspaceBuild.ID)
3732+
check.Args(workspaceBuild.ID).Asserts(rbac.ResourceTemplate, policy.ActionRead)
3733+
}))
3734+
s.Run("GetPresetParametersByPresetID", s.Subtest(func(db database.Store, check *expects) {
3735+
org := dbgen.Organization(s.T(), db, database.Organization{})
3736+
user := dbgen.User(s.T(), db, database.User{})
3737+
template := dbgen.Template(s.T(), db, database.Template{
3738+
CreatedBy: user.ID,
3739+
OrganizationID: org.ID,
3740+
})
3741+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3742+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3743+
OrganizationID: org.ID,
3744+
CreatedBy: user.ID,
3745+
})
3746+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
3747+
OrganizationID: org.ID,
3748+
OwnerID: user.ID,
3749+
TemplateID: template.ID,
3750+
})
3751+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
3752+
OrganizationID: org.ID,
3753+
})
3754+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
3755+
WorkspaceID: workspace.ID,
3756+
TemplateVersionID: templateVersion.ID,
3757+
InitiatorID: user.ID,
3758+
JobID: job.ID,
3759+
})
3760+
_, err := db.InsertPreset(context.Background(), database.InsertPresetParams{
3761+
TemplateVersionID: workspaceBuild.TemplateVersionID,
3762+
Name: "test",
3763+
})
3764+
require.NoError(s.T(), err)
3765+
preset, err := db.InsertPreset(context.Background(), database.InsertPresetParams{
3766+
TemplateVersionID: workspaceBuild.TemplateVersionID,
3767+
Name: "test",
3768+
})
3769+
require.NoError(s.T(), err)
3770+
db.GetPresetParametersByPresetID(context.Background(), preset.ID)
3771+
check.Args(preset.ID).Asserts(rbac.ResourceTemplate, policy.ActionRead)
3772+
}))
3773+
s.Run("GetPresetsByTemplateVersionID", s.Subtest(func(db database.Store, check *expects) {
3774+
org := dbgen.Organization(s.T(), db, database.Organization{})
3775+
user := dbgen.User(s.T(), db, database.User{})
3776+
template := dbgen.Template(s.T(), db, database.Template{
3777+
CreatedBy: user.ID,
3778+
OrganizationID: org.ID,
3779+
})
3780+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
3781+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
3782+
OrganizationID: org.ID,
3783+
CreatedBy: user.ID,
3784+
})
3785+
workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
3786+
OrganizationID: org.ID,
3787+
OwnerID: user.ID,
3788+
TemplateID: template.ID,
3789+
})
3790+
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
3791+
OrganizationID: org.ID,
3792+
})
3793+
workspaceBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
3794+
WorkspaceID: workspace.ID,
3795+
TemplateVersionID: templateVersion.ID,
3796+
InitiatorID: user.ID,
3797+
JobID: job.ID,
3798+
})
3799+
_, err := db.InsertPreset(context.Background(), database.InsertPresetParams{
3800+
TemplateVersionID: workspaceBuild.TemplateVersionID,
3801+
Name: "test",
3802+
})
3803+
require.NoError(s.T(), err)
3804+
_, err = db.InsertPreset(context.Background(), database.InsertPresetParams{
3805+
TemplateVersionID: workspaceBuild.TemplateVersionID,
3806+
Name: "test",
3807+
})
3808+
require.NoError(s.T(), err)
3809+
db.GetPresetsByTemplateVersionID(context.Background(), templateVersion.ID)
3810+
check.Args(templateVersion.ID).Asserts(rbac.ResourceTemplate, policy.ActionRead)
3811+
}))
36663812
s.Run("GetWorkspaceAppsByAgentIDs", s.Subtest(func(db database.Store, check *expects) {
36673813
dbtestutil.DisableForeignKeysAndTriggers(s.T(), db)
36683814
aWs := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})

coderd/database/dbmem/dbmem.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ func New() database.Store {
8989
locks: map[int64]struct{}{},
9090
runtimeConfig: map[string]string{},
9191
userStatusChanges: make([]database.UserStatusChange, 0),
92+
presets: make([]database.TemplateVersionPreset, 0),
93+
presetParameters: make([]database.TemplateVersionPresetParameter, 0),
9294
},
9395
}
9496
// Always start with a default org. Matching migration 198.
@@ -258,6 +260,8 @@ type data struct {
258260
defaultProxyDisplayName string
259261
defaultProxyIconURL string
260262
userStatusChanges []database.UserStatusChange
263+
presets []database.TemplateVersionPreset
264+
presetParameters []database.TemplateVersionPresetParameter
261265
}
262266

263267
func tryPercentile(fs []float64, p float64) float64 {
@@ -3660,6 +3664,45 @@ func (q *FakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.U
36603664
return parameters, nil
36613665
}
36623666

3667+
func (q *FakeQuerier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceBuildID uuid.UUID) (database.GetPresetByWorkspaceBuildIDRow, error) {
3668+
panic("not implemented")
3669+
}
3670+
3671+
func (q *FakeQuerier) GetPresetParametersByPresetID(_ context.Context, templateVersionPresetID uuid.UUID) ([]database.GetPresetParametersByPresetIDRow, error) {
3672+
q.mutex.RLock()
3673+
defer q.mutex.RUnlock()
3674+
3675+
parameters := make([]database.GetPresetParametersByPresetIDRow, 0)
3676+
for _, parameter := range q.presetParameters {
3677+
if parameter.TemplateVersionPresetID == templateVersionPresetID {
3678+
parameters = append(parameters, database.GetPresetParametersByPresetIDRow{
3679+
ID: parameter.ID,
3680+
Name: parameter.Name,
3681+
Value: parameter.Value,
3682+
})
3683+
}
3684+
}
3685+
return parameters, nil
3686+
}
3687+
3688+
func (q *FakeQuerier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.GetPresetsByTemplateVersionIDRow, error) {
3689+
q.mutex.RLock()
3690+
defer q.mutex.RUnlock()
3691+
3692+
presets := make([]database.GetPresetsByTemplateVersionIDRow, 0)
3693+
for _, preset := range q.presets {
3694+
if preset.TemplateVersionID == templateVersionID {
3695+
presets = append(presets, database.GetPresetsByTemplateVersionIDRow{
3696+
ID: preset.ID,
3697+
Name: preset.Name,
3698+
CreatedAt: preset.CreatedAt,
3699+
UpdatedAt: preset.UpdatedAt,
3700+
})
3701+
}
3702+
}
3703+
return presets, nil
3704+
}
3705+
36633706
func (q *FakeQuerier) GetPreviousTemplateVersion(_ context.Context, arg database.GetPreviousTemplateVersionParams) (database.TemplateVersion, error) {
36643707
if err := validateDatabaseType(arg); err != nil {
36653708
return database.TemplateVersion{}, err
@@ -7846,6 +7889,26 @@ func (q *FakeQuerier) InsertOrganizationMember(_ context.Context, arg database.I
78467889
return organizationMember, nil
78477890
}
78487891

7892+
func (q *FakeQuerier) InsertPreset(ctx context.Context, arg database.InsertPresetParams) (database.TemplateVersionPreset, error) {
7893+
err := validateDatabaseType(arg)
7894+
if err != nil {
7895+
return database.TemplateVersionPreset{}, err
7896+
}
7897+
7898+
q.mutex.Lock()
7899+
defer q.mutex.Unlock()
7900+
7901+
preset := database.TemplateVersionPreset{
7902+
// TODO (sasswart): double check how we generate these IDs in postgres.
7903+
// They should not be params here.
7904+
Name: arg.Name,
7905+
CreatedAt: arg.CreatedAt,
7906+
UpdatedAt: arg.UpdatedAt,
7907+
}
7908+
q.presets = append(q.presets, preset)
7909+
return preset, nil
7910+
}
7911+
78497912
func (q *FakeQuerier) InsertProvisionerJob(_ context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
78507913
if err := validateDatabaseType(arg); err != nil {
78517914
return database.ProvisionerJob{}, err

coderd/database/dbmetrics/querymetrics.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)