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

Skip to content

feat: Implement joins with golang templates #6429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1979cde
feat: Implement view for workspace builds to include rbac info
Emyrk Feb 28, 2023
4c0cd84
chore: Use workspace build as RBAC object
Emyrk Feb 28, 2023
ef9936f
Merge remote-tracking branch 'origin/main' into stevenmasley/rbac_views
Emyrk Feb 28, 2023
0b98766
Remove uneeded extra code
Emyrk Feb 28, 2023
8a26947
UsePostFilter
Emyrk Feb 28, 2023
6bee9af
Remove some db round trips
Emyrk Feb 28, 2023
81165d5
Fix dbgen unit test
Emyrk Feb 28, 2023
e252c04
Fix compile issue
Emyrk Feb 28, 2023
961ffaf
Merge remote-tracking branch 'origin/main' into stevenmasley/rbac_views
Emyrk Feb 28, 2023
b698672
fix merge
Emyrk Feb 28, 2023
3ce72c5
rename migration file +1
Emyrk Feb 28, 2023
c3c2702
Merge remote-tracking branch 'origin/main' into stevenmasley/rbac_views
Emyrk Mar 1, 2023
c3218f7
fix fake
Emyrk Mar 1, 2023
67a5b4a
chore: Use golang templates instead of sqlc files
Emyrk Mar 2, 2023
6484021
Combine all queries into 1
Emyrk Mar 2, 2023
a8ceb72
Refactor sqlx to it's own package
Emyrk Mar 7, 2023
29d41ab
Use sqlx for workspace build queries
Emyrk Mar 7, 2023
b46813f
Pass arguments
Emyrk Mar 7, 2023
8dc8c42
Handle nonzero limit
Emyrk Mar 7, 2023
e907a0f
Fix sqlx unit test
Emyrk Mar 7, 2023
60871ab
Merge remote-tracking branch 'origin/main' into stevenmasley/build_wi…
Emyrk Mar 7, 2023
fe13549
Fix unit tests
Emyrk Mar 7, 2023
e91476d
Fix unit tests
Emyrk Mar 7, 2023
03547a3
cleanup
Emyrk Mar 8, 2023
4495962
Test fixes
Emyrk Mar 8, 2023
fd867d0
remove unused function
Emyrk Mar 8, 2023
3a116ee
Rename back to WorkspaceBuild
Emyrk Mar 8, 2023
fc838bf
Make fmt
Emyrk Mar 8, 2023
4dc0a34
Make gens and make fmts
Emyrk Mar 8, 2023
95bda31
Merge remote-tracking branch 'origin/main' into stevenmasley/build_wi…
Emyrk Mar 8, 2023
98f8c56
Make gen
Emyrk Mar 8, 2023
e0a09f0
fix linting errors
Emyrk Mar 8, 2023
7b448d1
Merge remote-tracking branch 'origin/main' into stevenmasley/build_wi…
Emyrk Mar 8, 2023
1eebb14
Make dump.sql
Emyrk Mar 8, 2023
b13f593
Handle transactions
Emyrk Mar 8, 2023
56b847e
Fix a unit ttest
Emyrk Mar 8, 2023
2cce422
Fix a unit ttest
Emyrk Mar 8, 2023
f5a87ca
Fix deadlock
Emyrk Mar 8, 2023
d80dd10
Panic instead of error
Emyrk Mar 9, 2023
2949513
Put back in error
Emyrk Mar 9, 2023
7f480fb
Remove generic function use
Emyrk Mar 9, 2023
7d6a0da
Panic when query loading fails
Emyrk Mar 10, 2023
91cf7a8
Merge remote-tracking branch 'origin/main' into stevenmasley/build_wi…
Emyrk Mar 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion coderd/audit/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Auditable interface {
database.User |
database.Workspace |
database.GitSSHKey |
database.WorkspaceBuild |
database.WorkspaceBuildRBAC |
database.AuditableGroup |
database.License
}
Expand Down
6 changes: 3 additions & 3 deletions coderd/audit/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func ResourceTarget[T Auditable](tgt T) string {
return typed.Username
case database.Workspace:
return typed.Name
case database.WorkspaceBuild:
case database.WorkspaceBuildRBAC:
// this isn't used
return ""
case database.GitSSHKey:
Expand All @@ -89,7 +89,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return typed.ID
case database.Workspace:
return typed.ID
case database.WorkspaceBuild:
case database.WorkspaceBuildRBAC:
return typed.ID
case database.GitSSHKey:
return typed.UserID
Expand All @@ -114,7 +114,7 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeUser
case database.Workspace:
return database.ResourceTypeWorkspace
case database.WorkspaceBuild:
case database.WorkspaceBuildRBAC:
return database.ResourceTypeWorkspaceBuild
case database.GitSSHKey:
return database.ResourceTypeGitSshKey
Expand Down
4 changes: 2 additions & 2 deletions coderd/autobuild/executor/lifecycle_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func isEligibleForAutoStartStop(ws database.Workspace) bool {

func getNextTransition(
ws database.Workspace,
priorHistory database.WorkspaceBuild,
priorHistory database.WorkspaceBuildRBAC,
priorJob database.ProvisionerJob,
) (
validTransition database.WorkspaceTransition,
Expand Down Expand Up @@ -239,7 +239,7 @@ func getNextTransition(

// TODO(cian): this function duplicates most of api.postWorkspaceBuilds. Refactor.
// See: https://github.com/coder/coder/issues/1401
func build(ctx context.Context, store database.Store, workspace database.Workspace, trans database.WorkspaceTransition, priorHistory database.WorkspaceBuild, priorJob database.ProvisionerJob) error {
func build(ctx context.Context, store database.Store, workspace database.Workspace, trans database.WorkspaceTransition, priorHistory database.WorkspaceBuildRBAC, priorJob database.ProvisionerJob) error {
template, err := store.GetTemplateByID(ctx, workspace.TemplateID)
if err != nil {
return xerrors.Errorf("get workspace template: %w", err)
Expand Down
7 changes: 3 additions & 4 deletions coderd/autobuild/executor/lifecycle_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ package executor_test

import (
"context"
"os"
"testing"
"time"

"go.uber.org/goleak"

"github.com/google/uuid"
"go.uber.org/goleak"

"github.com/coder/coder/coderd/autobuild/executor"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/dbtestutil"
"github.com/coder/coder/coderd/schedule"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
Expand Down Expand Up @@ -493,7 +492,7 @@ func TestExecutorWorkspaceAutostopNoWaitChangedMyMind(t *testing.T) {
}

func TestExecutorAutostartMultipleOK(t *testing.T) {
if os.Getenv("DB") == "" {
if !dbtestutil.UsingRealDatabase() {
t.Skip(`This test only really works when using a "real" database, similar to a HA setup`)
}

Expand Down
12 changes: 12 additions & 0 deletions coderd/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (

"github.com/jmoiron/sqlx"
"golang.org/x/xerrors"

"github.com/coder/coder/coderd/database/sqlxqueries"
)

// Store contains all queryable database functions.
Expand All @@ -37,11 +39,21 @@ type DBTX interface {
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
SelectContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error
GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error

// Extends the sqlx interface
sqlx.QueryerContext
}

// New creates a new database store using a SQL database connection.
func New(sdb *sql.DB) Store {
dbx := sqlx.NewDb(sdb, "postgres")
// Load the embedded queries. If this fails, some of our queries
// will never work. This is a fatal developer error that should never
// happen.
_, err := sqlxqueries.LoadQueries()
if err != nil {
panic(xerrors.Errorf("load queries: %w", err))
}
return &sqlQuerier{
db: dbx,
sdb: dbx,
Expand Down
86 changes: 25 additions & 61 deletions coderd/database/dbauthz/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -1167,25 +1167,12 @@ func (q *querier) GetWorkspaces(ctx context.Context, arg database.GetWorkspacesP
return q.db.GetAuthorizedWorkspaces(ctx, arg, prep)
}

func (q *querier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.WorkspaceBuild, error) {
if _, err := q.GetWorkspaceByID(ctx, workspaceID); err != nil {
return database.WorkspaceBuild{}, err
}
return q.db.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspaceID)
func (q *querier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.WorkspaceBuildRBAC, error) {
return fetch(q.log, q.auth, q.db.GetLatestWorkspaceBuildByWorkspaceID)(ctx, workspaceID)
}

func (q *querier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceBuild, error) {
// This is not ideal as not all builds will be returned if the workspace cannot be read.
// This should probably be handled differently? Maybe join workspace builds with workspace
// ownership properties and filter on that.
for _, id := range ids {
_, err := q.GetWorkspaceByID(ctx, id)
if err != nil {
return nil, err
}
}

return q.db.GetLatestWorkspaceBuildsByWorkspaceIDs(ctx, ids)
func (q *querier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceBuildRBAC, error) {
return fetchWithPostFilter(q.auth, q.db.GetLatestWorkspaceBuildsByWorkspaceIDs)(ctx, ids)
}

func (q *querier) GetWorkspaceAgentByID(ctx context.Context, id uuid.UUID) (database.WorkspaceAgent, error) {
Expand Down Expand Up @@ -1263,35 +1250,16 @@ func (q *querier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid.UU
return q.db.GetWorkspaceAppsByAgentID(ctx, agentID)
}

func (q *querier) GetWorkspaceBuildByID(ctx context.Context, buildID uuid.UUID) (database.WorkspaceBuild, error) {
build, err := q.db.GetWorkspaceBuildByID(ctx, buildID)
if err != nil {
return database.WorkspaceBuild{}, err
}
if _, err := q.GetWorkspaceByID(ctx, build.WorkspaceID); err != nil {
return database.WorkspaceBuild{}, err
}
return build, nil
func (q *querier) GetWorkspaceBuildByID(ctx context.Context, buildID uuid.UUID) (database.WorkspaceBuildRBAC, error) {
return fetch(q.log, q.auth, q.db.GetWorkspaceBuildByID)(ctx, buildID)
}

func (q *querier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UUID) (database.WorkspaceBuild, error) {
build, err := q.db.GetWorkspaceBuildByJobID(ctx, jobID)
if err != nil {
return database.WorkspaceBuild{}, err
}
// Authorized fetch
_, err = q.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return database.WorkspaceBuild{}, err
}
return build, nil
func (q *querier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UUID) (database.WorkspaceBuildRBAC, error) {
return fetch(q.log, q.auth, q.db.GetWorkspaceBuildByJobID)(ctx, jobID)
}

func (q *querier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Context, arg database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams) (database.WorkspaceBuild, error) {
if _, err := q.GetWorkspaceByID(ctx, arg.WorkspaceID); err != nil {
return database.WorkspaceBuild{}, err
}
return q.db.GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx, arg)
func (q *querier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Context, arg database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams) (database.WorkspaceBuildRBAC, error) {
return fetch(q.log, q.auth, q.db.GetWorkspaceBuildByWorkspaceIDAndBuildNumber)(ctx, arg)
}

func (q *querier) GetWorkspaceBuildParameters(ctx context.Context, workspaceBuildID uuid.UUID) ([]database.WorkspaceBuildParameter, error) {
Expand All @@ -1305,11 +1273,20 @@ func (q *querier) GetWorkspaceBuildParameters(ctx context.Context, workspaceBuil
return q.db.GetWorkspaceBuildParameters(ctx, workspaceBuildID)
}

func (q *querier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg database.GetWorkspaceBuildsByWorkspaceIDParams) ([]database.WorkspaceBuild, error) {
if _, err := q.GetWorkspaceByID(ctx, arg.WorkspaceID); err != nil {
func (q *querier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg database.GetWorkspaceBuildsByWorkspaceIDParams) ([]database.WorkspaceBuildRBAC, error) {
builds, err := q.db.GetWorkspaceBuildsByWorkspaceID(ctx, arg)
if err != nil {
return nil, err
}
if len(builds) == 0 {
return []database.WorkspaceBuildRBAC{}, nil
}
// All builds come from the same workspace, so we only need to check the first one.
err = q.authorizeContext(ctx, rbac.ActionRead, builds[0])
if err != nil {
return nil, err
}
return q.db.GetWorkspaceBuildsByWorkspaceID(ctx, arg)
return builds, nil
}

func (q *querier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.Workspace, error) {
Expand Down Expand Up @@ -1369,11 +1346,7 @@ func (q *querier) GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.U
if err != nil {
return nil, err
}
workspace, err := q.db.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return nil, err
}
obj = workspace
obj = build
default:
return nil, xerrors.Errorf("unknown job type: %s", job.Type)
}
Expand Down Expand Up @@ -1414,12 +1387,7 @@ func (q *querier) InsertWorkspaceBuildParameters(ctx context.Context, arg databa
return err
}

workspace, err := q.db.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return err
}

err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace)
err = q.authorizeContext(ctx, rbac.ActionUpdate, build)
if err != nil {
return err
}
Expand Down Expand Up @@ -1483,11 +1451,7 @@ func (q *querier) UpdateWorkspaceBuildByID(ctx context.Context, arg database.Upd
return database.WorkspaceBuild{}, err
}

workspace, err := q.db.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return database.WorkspaceBuild{}, err
}
err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace.RBACObject())
err = q.authorizeContext(ctx, rbac.ActionUpdate, build)
if err != nil {
return database.WorkspaceBuild{}, err
}
Expand Down
Loading