chore: join owner, template, and org in new workspace view (#15116)

Joins in fields like `username`, `avatar_url`, `organization_name`,
`template_name` to `workspaces` via a **view**. 
The view must be maintained moving forward, but this prevents needing to
add RBAC permissions to fetch related workspace fields.
This commit is contained in:
Steven Masley
2024-10-22 09:20:54 -05:00
committed by GitHub
parent 5076161078
commit 343f8ec9ab
81 changed files with 1063 additions and 735 deletions
+6 -6
View File
@@ -35,7 +35,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}). }).
@@ -71,7 +71,7 @@ func TestWorkspaceAgent(t *testing.T) {
AzureCertificates: certificates, AzureCertificates: certificates,
}) })
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -110,7 +110,7 @@ func TestWorkspaceAgent(t *testing.T) {
AWSCertificates: certificates, AWSCertificates: certificates,
}) })
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -151,7 +151,7 @@ func TestWorkspaceAgent(t *testing.T) {
}) })
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -205,7 +205,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -279,7 +279,7 @@ func TestWorkspaceAgent(t *testing.T) {
} }
coderAPI.RootHandler.ServeHTTP(w, r) coderAPI.RootHandler.ServeHTTP(w, r)
})) }))
r := dbfake.WorkspaceBuild(t, coderAPI.Database, database.Workspace{ r := dbfake.WorkspaceBuild(t, coderAPI.Database, database.WorkspaceTable{
OrganizationID: memberUser.OrganizationIDs[0], OrganizationID: memberUser.OrganizationIDs[0],
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).WithAgent().Do() }).WithAgent().Do()
+3 -3
View File
@@ -83,7 +83,7 @@ func TestConfigSSH(t *testing.T) {
}) })
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -647,7 +647,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
if tt.hasAgent { if tt.hasAgent {
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -767,7 +767,7 @@ func TestConfigSSH_Hostnames(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).Resource(resources...).Do() }).Resource(resources...).Do()
+1 -1
View File
@@ -19,7 +19,7 @@ func TestFavoriteUnfavorite(t *testing.T) {
client, db = coderdtest.NewWithDatabase(t, nil) client, db = coderdtest.NewWithDatabase(t, nil)
owner = coderdtest.CreateFirstUser(t, client) owner = coderdtest.CreateFirstUser(t, client)
memberClient, member = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) memberClient, member = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
ws = dbfake.WorkspaceBuild(t, db, database.Workspace{OwnerID: member.ID, OrganizationID: owner.OrganizationID}).Do() ws = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{OwnerID: member.ID, OrganizationID: owner.OrganizationID}).Do()
) )
inv, root := clitest.New(t, "favorite", ws.Workspace.Name) inv, root := clitest.New(t, "favorite", ws.Workspace.Name)
+1 -1
View File
@@ -48,7 +48,7 @@ func prepareTestGitSSH(ctx context.Context, t *testing.T) (*agentsdk.Client, str
require.NoError(t, err) require.NoError(t, err)
// setup template // setup template
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
+2 -2
View File
@@ -26,7 +26,7 @@ func TestList(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// setup template // setup template
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -54,7 +54,7 @@ func TestList(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
}).WithAgent().Do() }).WithAgent().Do()
+2 -2
View File
@@ -290,12 +290,12 @@ func TestPortForward(t *testing.T) {
// runAgent creates a fake workspace and starts an agent locally for that // runAgent creates a fake workspace and starts an agent locally for that
// workspace. The agent will be cleaned up on test completion. // workspace. The agent will be cleaned up on test completion.
// nolint:unused // nolint:unused
func runAgent(t *testing.T, client *codersdk.Client, owner uuid.UUID, db database.Store) database.Workspace { func runAgent(t *testing.T, client *codersdk.Client, owner uuid.UUID, db database.Store) database.WorkspaceTable {
user, err := client.User(context.Background(), codersdk.Me) user, err := client.User(context.Background(), codersdk.Me)
require.NoError(t, err, "specified user does not exist") require.NoError(t, err, "specified user does not exist")
require.Greater(t, len(user.OrganizationIDs), 0, "user has no organizations") require.Greater(t, len(user.OrganizationIDs), 0, "user has no organizations")
orgID := user.OrganizationIDs[0] orgID := user.OrganizationIDs[0]
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: orgID, OrganizationID: orgID,
OwnerID: owner, OwnerID: owner,
}).WithAgent().Do() }).WithAgent().Do()
+4 -4
View File
@@ -38,7 +38,7 @@ func setupTestSchedule(t *testing.T, sched *cron.Schedule) (ownerClient, memberC
memberClient, memberUser := coderdtest.CreateAnotherUserMutators(t, ownerClient, owner.OrganizationID, nil, func(r *codersdk.CreateUserRequestWithOrgs) { memberClient, memberUser := coderdtest.CreateAnotherUserMutators(t, ownerClient, owner.OrganizationID, nil, func(r *codersdk.CreateUserRequestWithOrgs) {
r.Username = "testuser2" // ensure deterministic ordering r.Username = "testuser2" // ensure deterministic ordering
}) })
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "a-owner", Name: "a-owner",
OwnerID: owner.UserID, OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
@@ -46,19 +46,19 @@ func setupTestSchedule(t *testing.T, sched *cron.Schedule) (ownerClient, memberC
Ttl: sql.NullInt64{Int64: 8 * time.Hour.Nanoseconds(), Valid: true}, Ttl: sql.NullInt64{Int64: 8 * time.Hour.Nanoseconds(), Valid: true},
}).WithAgent().Do() }).WithAgent().Do()
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "b-owner", Name: "b-owner",
OwnerID: owner.UserID, OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
AutostartSchedule: sql.NullString{String: sched.String(), Valid: true}, AutostartSchedule: sql.NullString{String: sched.String(), Valid: true},
}).WithAgent().Do() }).WithAgent().Do()
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "c-member", Name: "c-member",
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
Ttl: sql.NullInt64{Int64: 8 * time.Hour.Nanoseconds(), Valid: true}, Ttl: sql.NullInt64{Int64: 8 * time.Hour.Nanoseconds(), Valid: true},
}).WithAgent().Do() }).WithAgent().Do()
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "d-member", Name: "d-member",
OwnerID: memberUser.ID, OwnerID: memberUser.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
+5 -5
View File
@@ -53,14 +53,14 @@ import (
"github.com/coder/coder/v2/testutil" "github.com/coder/coder/v2/testutil"
) )
func setupWorkspaceForAgent(t *testing.T, mutations ...func([]*proto.Agent) []*proto.Agent) (*codersdk.Client, database.Workspace, string) { func setupWorkspaceForAgent(t *testing.T, mutations ...func([]*proto.Agent) []*proto.Agent) (*codersdk.Client, database.WorkspaceTable, string) {
t.Helper() t.Helper()
client, store := coderdtest.NewWithDatabase(t, nil) client, store := coderdtest.NewWithDatabase(t, nil)
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug)) client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client) first := coderdtest.CreateFirstUser(t, client)
userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID) userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent(mutations...).Do() }).WithAgent(mutations...).Do()
@@ -260,7 +260,7 @@ func TestSSH(t *testing.T) {
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug)) client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client) first := coderdtest.CreateFirstUser(t, client)
userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID) userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -763,7 +763,7 @@ func TestSSH(t *testing.T) {
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug)) client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client) first := coderdtest.CreateFirstUser(t, client)
userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID) userClient, user := coderdtest.CreateAnotherUser(t, client, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1370,7 +1370,7 @@ func TestSSH(t *testing.T) {
admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug)) admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, admin) first := coderdtest.CreateFirstUser(t, admin)
client, user := coderdtest.CreateAnotherUser(t, admin, first.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, admin, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent().Do() }).WithAgent().Do()
+2 -2
View File
@@ -390,7 +390,7 @@ func TestStart_AlreadyRunning(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: member.ID, OwnerID: member.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
}).Do() }).Do()
@@ -417,7 +417,7 @@ func TestStart_Starting(t *testing.T) {
client := coderdtest.New(t, &coderdtest.Options{Pubsub: ps, Database: store}) client := coderdtest.New(t, &coderdtest.Options{Pubsub: ps, Database: store})
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OwnerID: member.ID, OwnerID: member.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
}). }).
+3 -3
View File
@@ -28,7 +28,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state") wantState := []byte("some state")
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID, OwnerID: taUser.ID,
}). }).
@@ -49,7 +49,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state") wantState := []byte("some state")
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID, OwnerID: taUser.ID,
}). }).
@@ -69,7 +69,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
_, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin()) _, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state") wantState := []byte("some state")
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID, OwnerID: taUser.ID,
}). }).
+3 -3
View File
@@ -53,7 +53,7 @@ func TestSupportBundle(t *testing.T) {
DeploymentValues: dc.Values, DeploymentValues: dc.Values,
}) })
owner := coderdtest.CreateFirstUser(t, client) owner := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: owner.UserID, OwnerID: owner.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -132,7 +132,7 @@ func TestSupportBundle(t *testing.T) {
DeploymentValues: dc.Values, DeploymentValues: dc.Values,
}) })
admin := coderdtest.CreateFirstUser(t, client) admin := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: admin.OrganizationID, OrganizationID: admin.OrganizationID,
OwnerID: admin.UserID, OwnerID: admin.UserID,
}).Do() // without agent! }).Do() // without agent!
@@ -151,7 +151,7 @@ func TestSupportBundle(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
memberClient, member := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) memberClient, member := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: member.ID, OwnerID: member.ID,
}).WithAgent().Do() }).WithAgent().Do()
+1 -1
View File
@@ -41,7 +41,7 @@ func TestVSCodeSSH(t *testing.T) {
admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug)) admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, admin) first := coderdtest.CreateFirstUser(t, admin)
client, user := coderdtest.CreateAnotherUser(t, admin, first.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, admin, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent().Do() }).WithAgent().Do()
+3 -3
View File
@@ -106,7 +106,7 @@ func New(opts Options) *API {
if err != nil { if err != nil {
return uuid.Nil, err return uuid.Nil, err
} }
return ws.Workspace.ID, nil return ws.ID, nil
}, },
} }
@@ -231,9 +231,9 @@ func (a *API) workspaceID(ctx context.Context, agent *database.WorkspaceAgent) (
} }
a.mu.Lock() a.mu.Lock()
a.cachedWorkspaceID = getWorkspaceAgentByIDRow.Workspace.ID a.cachedWorkspaceID = getWorkspaceAgentByIDRow.ID
a.mu.Unlock() a.mu.Unlock()
return getWorkspaceAgentByIDRow.Workspace.ID, nil return getWorkspaceAgentByIDRow.ID, nil
} }
func (a *API) publishWorkspaceUpdate(ctx context.Context, agent *database.WorkspaceAgent) error { func (a *API) publishWorkspaceUpdate(ctx context.Context, agent *database.WorkspaceAgent) error {
+1 -1
View File
@@ -50,7 +50,7 @@ func (a *StatsAPI) UpdateStats(ctx context.Context, req *agentproto.UpdateStatsR
if err != nil { if err != nil {
return nil, xerrors.Errorf("get workspace by agent ID %q: %w", workspaceAgent.ID, err) return nil, xerrors.Errorf("get workspace by agent ID %q: %w", workspaceAgent.ID, err)
} }
workspace := getWorkspaceAgentByIDRow.Workspace workspace := getWorkspaceAgentByIDRow
a.Log.Debug(ctx, "read stats report", a.Log.Debug(ctx, "read stats report",
slog.F("interval", a.AgentStatsRefreshInterval), slog.F("interval", a.AgentStatsRefreshInterval),
slog.F("workspace_id", workspace.ID), slog.F("workspace_id", workspace.ID),
+9 -20
View File
@@ -40,10 +40,11 @@ func TestUpdateStates(t *testing.T) {
Name: "tpl", Name: "tpl",
} }
workspace = database.Workspace{ workspace = database.Workspace{
ID: uuid.New(), ID: uuid.New(),
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
Name: "xyz", Name: "xyz",
TemplateName: template.Name,
} }
agent = database.WorkspaceAgent{ agent = database.WorkspaceAgent{
ID: uuid.New(), ID: uuid.New(),
@@ -127,10 +128,7 @@ func TestUpdateStates(t *testing.T) {
} }
// Workspace gets fetched. // Workspace gets fetched.
dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
Workspace: workspace,
TemplateName: template.Name,
}, nil)
// We expect an activity bump because ConnectionCount > 0. // We expect an activity bump because ConnectionCount > 0.
dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{ dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{
@@ -225,10 +223,7 @@ func TestUpdateStates(t *testing.T) {
} }
// Workspace gets fetched. // Workspace gets fetched.
dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
Workspace: workspace,
TemplateName: template.Name,
}, nil)
// Workspace last used at gets bumped. // Workspace last used at gets bumped.
dbM.EXPECT().UpdateWorkspaceLastUsedAt(gomock.Any(), database.UpdateWorkspaceLastUsedAtParams{ dbM.EXPECT().UpdateWorkspaceLastUsedAt(gomock.Any(), database.UpdateWorkspaceLastUsedAtParams{
@@ -350,10 +345,7 @@ func TestUpdateStates(t *testing.T) {
} }
// Workspace gets fetched. // Workspace gets fetched.
dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
Workspace: workspace,
TemplateName: template.Name,
}, nil)
// We expect an activity bump because ConnectionCount > 0. However, the // We expect an activity bump because ConnectionCount > 0. However, the
// next autostart time will be set on the bump. // next autostart time will be set on the bump.
@@ -461,10 +453,7 @@ func TestUpdateStates(t *testing.T) {
} }
// Workspace gets fetched. // Workspace gets fetched.
dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
Workspace: workspace,
TemplateName: template.Name,
}, nil)
// We expect an activity bump because ConnectionCount > 0. // We expect an activity bump because ConnectionCount > 0.
dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{ dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{
+1 -1
View File
@@ -12,7 +12,7 @@ type Auditable interface {
database.Template | database.Template |
database.TemplateVersion | database.TemplateVersion |
database.User | database.User |
database.Workspace | database.WorkspaceTable |
database.GitSSHKey | database.GitSSHKey |
database.WorkspaceBuild | database.WorkspaceBuild |
database.AuditableGroup | database.AuditableGroup |
+4 -4
View File
@@ -82,7 +82,7 @@ func ResourceTarget[T Auditable](tgt T) string {
return typed.Name return typed.Name
case database.User: case database.User:
return typed.Username return typed.Username
case database.Workspace: case database.WorkspaceTable:
return typed.Name return typed.Name
case database.WorkspaceBuild: case database.WorkspaceBuild:
// this isn't used // this isn't used
@@ -133,7 +133,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return typed.ID return typed.ID
case database.User: case database.User:
return typed.ID return typed.ID
case database.Workspace: case database.WorkspaceTable:
return typed.ID return typed.ID
case database.WorkspaceBuild: case database.WorkspaceBuild:
return typed.ID return typed.ID
@@ -181,7 +181,7 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeTemplateVersion return database.ResourceTypeTemplateVersion
case database.User: case database.User:
return database.ResourceTypeUser return database.ResourceTypeUser
case database.Workspace: case database.WorkspaceTable:
return database.ResourceTypeWorkspace return database.ResourceTypeWorkspace
case database.WorkspaceBuild: case database.WorkspaceBuild:
return database.ResourceTypeWorkspaceBuild return database.ResourceTypeWorkspaceBuild
@@ -225,7 +225,7 @@ func ResourceRequiresOrgID[T Auditable]() bool {
switch any(tgt).(type) { switch any(tgt).(type) {
case database.Template, database.TemplateVersion: case database.Template, database.TemplateVersion:
return true return true
case database.Workspace, database.WorkspaceBuild: case database.WorkspaceTable, database.WorkspaceBuild:
return true return true
case database.AuditableGroup: case database.AuditableGroup:
return true return true
+11 -9
View File
@@ -234,22 +234,24 @@ func (e *Executor) runOnce(t time.Time) Stats {
// threshold for inactivity. // threshold for inactivity.
if reason == database.BuildReasonDormancy { if reason == database.BuildReasonDormancy {
wsOld := ws wsOld := ws
ws, err = tx.UpdateWorkspaceDormantDeletingAt(e.ctx, database.UpdateWorkspaceDormantDeletingAtParams{ wsNew, err := tx.UpdateWorkspaceDormantDeletingAt(e.ctx, database.UpdateWorkspaceDormantDeletingAtParams{
ID: ws.ID, ID: ws.ID,
DormantAt: sql.NullTime{ DormantAt: sql.NullTime{
Time: dbtime.Now(), Time: dbtime.Now(),
Valid: true, Valid: true,
}, },
}) })
auditLog = &auditParams{
Old: wsOld,
New: ws,
}
if err != nil { if err != nil {
return xerrors.Errorf("update workspace dormant deleting at: %w", err) return xerrors.Errorf("update workspace dormant deleting at: %w", err)
} }
auditLog = &auditParams{
Old: wsOld.WorkspaceTable(),
New: wsNew,
}
// To keep the `ws` accurate without doing a sql fetch
ws.DormantAt = wsNew.DormantAt
shouldNotifyDormancy = true shouldNotifyDormancy = true
log.Info(e.ctx, "dormant workspace", log.Info(e.ctx, "dormant workspace",
@@ -510,8 +512,8 @@ func isEligibleForFailedStop(build database.WorkspaceBuild, job database.Provisi
} }
type auditParams struct { type auditParams struct {
Old database.Workspace Old database.WorkspaceTable
New database.Workspace New database.WorkspaceTable
Success bool Success bool
} }
@@ -521,7 +523,7 @@ func auditBuild(ctx context.Context, log slog.Logger, auditor audit.Auditor, par
status = http.StatusOK status = http.StatusOK
} }
audit.BackgroundAudit(ctx, &audit.BackgroundAuditParams[database.Workspace]{ audit.BackgroundAudit(ctx, &audit.BackgroundAuditParams[database.WorkspaceTable]{
Audit: auditor, Audit: auditor,
Log: log, Log: log,
UserID: params.New.OwnerID, UserID: params.New.OwnerID,
+1 -1
View File
@@ -355,7 +355,7 @@ func TestCSRFExempt(t *testing.T) {
// Create a workspace. // Create a workspace.
const agentSlug = "james" const agentSlug = "james"
const appSlug = "web" const appSlug = "web"
wrk := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{ wrk := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{
OwnerID: owner.ID, OwnerID: owner.ID,
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
}). }).
+18 -10
View File
@@ -2574,7 +2574,7 @@ func (q *querier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt
return q.db.GetWorkspaceBuildsCreatedAfter(ctx, createdAt) return q.db.GetWorkspaceBuildsCreatedAfter(ctx, createdAt)
} }
func (q *querier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.GetWorkspaceByAgentIDRow, error) { func (q *querier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.Workspace, error) {
return fetch(q.log, q.auth, q.db.GetWorkspaceByAgentID)(ctx, agentID) return fetch(q.log, q.auth, q.db.GetWorkspaceByAgentID)(ctx, agentID)
} }
@@ -2719,7 +2719,7 @@ func (q *querier) GetWorkspaces(ctx context.Context, arg database.GetWorkspacesP
return q.db.GetAuthorizedWorkspaces(ctx, arg, prep) return q.db.GetAuthorizedWorkspaces(ctx, arg, prep)
} }
func (q *querier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.Workspace, error) { func (q *querier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.WorkspaceTable, error) {
return q.db.GetWorkspacesEligibleForTransition(ctx, now) return q.db.GetWorkspacesEligibleForTransition(ctx, now)
} }
@@ -3009,7 +3009,7 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin
return q.db.InsertUserLink(ctx, arg) return q.db.InsertUserLink(ctx, arg)
} }
func (q *querier) InsertWorkspace(ctx context.Context, arg database.InsertWorkspaceParams) (database.Workspace, error) { func (q *querier) InsertWorkspace(ctx context.Context, arg database.InsertWorkspaceParams) (database.WorkspaceTable, error) {
obj := rbac.ResourceWorkspace.WithOwner(arg.OwnerID.String()).InOrg(arg.OrganizationID) obj := rbac.ResourceWorkspace.WithOwner(arg.OwnerID.String()).InOrg(arg.OrganizationID)
return insert(q.log, q.auth, obj, q.db.InsertWorkspace)(ctx, arg) return insert(q.log, q.auth, obj, q.db.InsertWorkspace)(ctx, arg)
} }
@@ -3751,9 +3751,13 @@ func (q *querier) UpdateUserStatus(ctx context.Context, arg database.UpdateUserS
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateUserStatus)(ctx, arg) return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateUserStatus)(ctx, arg)
} }
func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) { func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
fetch := func(ctx context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) { fetch := func(ctx context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
return q.db.GetWorkspaceByID(ctx, arg.ID) w, err := q.db.GetWorkspaceByID(ctx, arg.ID)
if err != nil {
return database.WorkspaceTable{}, err
}
return w.WorkspaceTable(), nil
} }
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspace)(ctx, arg) return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspace)(ctx, arg)
} }
@@ -3905,9 +3909,13 @@ func (q *querier) UpdateWorkspaceDeletedByID(ctx context.Context, arg database.U
return deleteQ(q.log, q.auth, fetch, q.db.UpdateWorkspaceDeletedByID)(ctx, arg) return deleteQ(q.log, q.auth, fetch, q.db.UpdateWorkspaceDeletedByID)(ctx, arg)
} }
func (q *querier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) { func (q *querier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
fetch := func(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) { fetch := func(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
return q.db.GetWorkspaceByID(ctx, arg.ID) w, err := q.db.GetWorkspaceByID(ctx, arg.ID)
if err != nil {
return database.WorkspaceTable{}, err
}
return w.WorkspaceTable(), nil
} }
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspaceDormantDeletingAt)(ctx, arg) return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspaceDormantDeletingAt)(ctx, arg)
} }
@@ -3940,7 +3948,7 @@ func (q *querier) UpdateWorkspaceTTL(ctx context.Context, arg database.UpdateWor
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceTTL)(ctx, arg) return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceTTL)(ctx, arg)
} }
func (q *querier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) { func (q *querier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.WorkspaceTable, error) {
template, err := q.db.GetTemplateByID(ctx, arg.TemplateID) template, err := q.db.GetTemplateByID(ctx, arg.TemplateID)
if err != nil { if err != nil {
return nil, xerrors.Errorf("get template by id: %w", err) return nil, xerrors.Errorf("get template by id: %w", err)
+77 -80
View File
@@ -90,7 +90,7 @@ func TestInTX(t *testing.T) {
Scope: rbac.ScopeAll, Scope: rbac.ScopeAll,
} }
w := dbgen.Workspace(t, db, database.Workspace{}) w := dbgen.Workspace(t, db, database.WorkspaceTable{})
ctx := dbauthz.As(context.Background(), actor) ctx := dbauthz.As(context.Background(), actor)
err := q.InTx(func(tx database.Store) error { err := q.InTx(func(tx database.Store) error {
// The inner tx should use the parent's authz // The inner tx should use the parent's authz
@@ -108,7 +108,7 @@ func TestNew(t *testing.T) {
var ( var (
db = dbmem.New() db = dbmem.New()
exp = dbgen.Workspace(t, db, database.Workspace{}) exp = dbgen.Workspace(t, db, database.WorkspaceTable{})
rec = &coderdtest.RecordingAuthorizer{ rec = &coderdtest.RecordingAuthorizer{
Wrapped: &coderdtest.FakeAuthorizer{}, Wrapped: &coderdtest.FakeAuthorizer{},
} }
@@ -123,7 +123,7 @@ func TestNew(t *testing.T) {
w, err := az.GetWorkspaceByID(ctx, exp.ID) w, err := az.GetWorkspaceByID(ctx, exp.ID)
require.NoError(t, err, "must not error") require.NoError(t, err, "must not error")
require.Equal(t, exp, w, "must be equal") require.Equal(t, exp, w.WorkspaceTable(), "must be equal")
rec.AssertActor(t, subj, rec.Pair(policy.ActionRead, exp)) rec.AssertActor(t, subj, rec.Pair(policy.ActionRead, exp))
require.NoError(t, rec.AllAsserted(), "should only be 1 rbac call") require.NoError(t, rec.AllAsserted(), "should only be 1 rbac call")
@@ -465,7 +465,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
}).Asserts(v.RBACObject(tpl), policy.ActionUpdate) }).Asserts(v.RBACObject(tpl), policy.ActionUpdate)
})) }))
s.Run("Build/GetProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) { s.Run("Build/GetProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
@@ -498,7 +498,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
})) }))
s.Run("Build/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { s.Run("Build/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: true}) tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: true})
w := dbgen.Workspace(s.T(), db, database.Workspace{TemplateID: tpl.ID}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{TemplateID: tpl.ID})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
@@ -507,7 +507,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
})) }))
s.Run("BuildFalseCancel/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { s.Run("BuildFalseCancel/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: false}) tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: false})
w := dbgen.Workspace(s.T(), db, database.Workspace{TemplateID: tpl.ID}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{TemplateID: tpl.ID})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
@@ -557,7 +557,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
check.Args([]uuid.UUID{a.ID, b.ID}).Asserts().Returns(slice.New(a, b)) check.Args([]uuid.UUID{a.ID, b.ID}).Asserts().Returns(slice.New(a, b))
})) }))
s.Run("GetProvisionerLogsAfterID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetProvisionerLogsAfterID", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
@@ -1455,29 +1455,29 @@ func (s *MethodTestSuite) TestUser() {
func (s *MethodTestSuite) TestWorkspace() { func (s *MethodTestSuite) TestWorkspace() {
s.Run("GetWorkspaceByID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(ws.ID).Asserts(ws, policy.ActionRead) check.Args(ws.ID).Asserts(ws, policy.ActionRead)
})) }))
s.Run("GetWorkspaces", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaces", s.Subtest(func(db database.Store, check *expects) {
_ = dbgen.Workspace(s.T(), db, database.Workspace{}) _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
_ = dbgen.Workspace(s.T(), db, database.Workspace{}) _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
// No asserts here because SQLFilter. // No asserts here because SQLFilter.
check.Args(database.GetWorkspacesParams{}).Asserts() check.Args(database.GetWorkspacesParams{}).Asserts()
})) }))
s.Run("GetAuthorizedWorkspaces", s.Subtest(func(db database.Store, check *expects) { s.Run("GetAuthorizedWorkspaces", s.Subtest(func(db database.Store, check *expects) {
_ = dbgen.Workspace(s.T(), db, database.Workspace{}) _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
_ = dbgen.Workspace(s.T(), db, database.Workspace{}) _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
// No asserts here because SQLFilter. // No asserts here because SQLFilter.
check.Args(database.GetWorkspacesParams{}, emptyPreparedAuthorized{}).Asserts() check.Args(database.GetWorkspacesParams{}, emptyPreparedAuthorized{}).Asserts()
})) }))
s.Run("GetLatestWorkspaceBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetLatestWorkspaceBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID})
check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns(b) check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns(b)
})) }))
s.Run("GetWorkspaceAgentByID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1487,7 +1487,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1497,7 +1497,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1515,7 +1515,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAgentByInstanceID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentByInstanceID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1525,7 +1525,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("UpdateWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1538,7 +1538,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("UpdateWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1550,7 +1550,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("UpdateWorkspaceAgentLogOverflowByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAgentLogOverflowByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1563,7 +1563,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("UpdateWorkspaceAgentStartupByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAgentStartupByID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1578,7 +1578,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAgentLogsAfter", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentLogsAfter", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1590,7 +1590,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAppByAgentIDAndSlug", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAppByAgentIDAndSlug", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1605,7 +1605,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceAppsByAgentID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAppsByAgentID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1617,17 +1617,17 @@ func (s *MethodTestSuite) TestWorkspace() {
check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(slice.New(a, b)) check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(slice.New(a, b))
})) }))
s.Run("GetWorkspaceBuildByID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceBuildByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID})
check.Args(build.ID).Asserts(ws, policy.ActionRead).Returns(build) check.Args(build.ID).Asserts(ws, policy.ActionRead).Returns(build)
})) }))
s.Run("GetWorkspaceBuildByJobID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceBuildByJobID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID})
check.Args(build.JobID).Asserts(ws, policy.ActionRead).Returns(build) check.Args(build.JobID).Asserts(ws, policy.ActionRead).Returns(build)
})) }))
s.Run("GetWorkspaceBuildByWorkspaceIDAndBuildNumber", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceBuildByWorkspaceIDAndBuildNumber", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 10}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 10})
check.Args(database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{ check.Args(database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{
WorkspaceID: ws.ID, WorkspaceID: ws.ID,
@@ -1635,13 +1635,13 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionRead).Returns(build) }).Asserts(ws, policy.ActionRead).Returns(build)
})) }))
s.Run("GetWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID})
check.Args(build.ID).Asserts(ws, policy.ActionRead). check.Args(build.ID).Asserts(ws, policy.ActionRead).
Returns([]database.WorkspaceBuildParameter{}) Returns([]database.WorkspaceBuildParameter{})
})) }))
s.Run("GetWorkspaceBuildsByWorkspaceID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceBuildsByWorkspaceID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
_ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 1}) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 1})
_ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 2}) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 2})
_ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 3}) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 3})
@@ -1649,20 +1649,17 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("GetWorkspaceByAgentID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceByAgentID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(database.GetWorkspaceByAgentIDRow{ check.Args(agt.ID).Asserts(ws, policy.ActionRead)
Workspace: ws,
TemplateName: tpl.Name,
})
})) }))
s.Run("GetWorkspaceAgentsInLatestBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentsInLatestBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
@@ -1671,22 +1668,22 @@ func (s *MethodTestSuite) TestWorkspace() {
check.Args(ws.ID).Asserts(ws, policy.ActionRead) check.Args(ws.ID).Asserts(ws, policy.ActionRead)
})) }))
s.Run("GetWorkspaceByOwnerIDAndName", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceByOwnerIDAndName", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.GetWorkspaceByOwnerIDAndNameParams{ check.Args(database.GetWorkspaceByOwnerIDAndNameParams{
OwnerID: ws.OwnerID, OwnerID: ws.OwnerID,
Deleted: ws.Deleted, Deleted: ws.Deleted,
Name: ws.Name, Name: ws.Name,
}).Asserts(ws, policy.ActionRead).Returns(ws) }).Asserts(ws, policy.ActionRead)
})) }))
s.Run("GetWorkspaceResourceByID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceResourceByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
_ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) _ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
check.Args(res.ID).Asserts(ws, policy.ActionRead).Returns(res) check.Args(res.ID).Asserts(ws, policy.ActionRead).Returns(res)
})) }))
s.Run("Build/GetWorkspaceResourcesByJobID", s.Subtest(func(db database.Store, check *expects) { s.Run("Build/GetWorkspaceResourcesByJobID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
check.Args(job.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceResource{}) check.Args(job.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceResource{})
@@ -1709,7 +1706,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("Start/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { s.Run("Start/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
t := dbgen.Template(s.T(), db, database.Template{}) t := dbgen.Template(s.T(), db, database.Template{})
w := dbgen.Workspace(s.T(), db, database.Workspace{ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: t.ID, TemplateID: t.ID,
}) })
check.Args(database.InsertWorkspaceBuildParams{ check.Args(database.InsertWorkspaceBuildParams{
@@ -1720,7 +1717,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("Stop/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { s.Run("Stop/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
t := dbgen.Template(s.T(), db, database.Template{}) t := dbgen.Template(s.T(), db, database.Template{})
w := dbgen.Workspace(s.T(), db, database.Workspace{ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: t.ID, TemplateID: t.ID,
}) })
check.Args(database.InsertWorkspaceBuildParams{ check.Args(database.InsertWorkspaceBuildParams{
@@ -1740,7 +1737,7 @@ func (s *MethodTestSuite) TestWorkspace() {
v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
TemplateID: uuid.NullUUID{UUID: t.ID}, TemplateID: uuid.NullUUID{UUID: t.ID},
}) })
w := dbgen.Workspace(s.T(), db, database.Workspace{ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: t.ID, TemplateID: t.ID,
}) })
check.Args(database.InsertWorkspaceBuildParams{ check.Args(database.InsertWorkspaceBuildParams{
@@ -1766,7 +1763,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}) })
require.NoError(s.T(), err) require.NoError(s.T(), err)
w := dbgen.Workspace(s.T(), db, database.Workspace{ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: t.ID, TemplateID: t.ID,
}) })
// Assert that we do not check for template update permissions // Assert that we do not check for template update permissions
@@ -1781,7 +1778,7 @@ func (s *MethodTestSuite) TestWorkspace() {
) )
})) }))
s.Run("Delete/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { s.Run("Delete/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.InsertWorkspaceBuildParams{ check.Args(database.InsertWorkspaceBuildParams{
WorkspaceID: w.ID, WorkspaceID: w.ID,
Transition: database.WorkspaceTransitionDelete, Transition: database.WorkspaceTransitionDelete,
@@ -1789,7 +1786,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionDelete) }).Asserts(w, policy.ActionDelete)
})) }))
s.Run("InsertWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) { s.Run("InsertWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: w.ID}) b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: w.ID})
check.Args(database.InsertWorkspaceBuildParametersParams{ check.Args(database.InsertWorkspaceBuildParametersParams{
WorkspaceBuildID: b.ID, WorkspaceBuildID: b.ID,
@@ -1798,7 +1795,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionUpdate) }).Asserts(w, policy.ActionUpdate)
})) }))
s.Run("UpdateWorkspace", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspace", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
expected := w expected := w
expected.Name = "" expected.Name = ""
check.Args(database.UpdateWorkspaceParams{ check.Args(database.UpdateWorkspaceParams{
@@ -1806,20 +1803,20 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionUpdate).Returns(expected) }).Asserts(w, policy.ActionUpdate).Returns(expected)
})) }))
s.Run("UpdateWorkspaceDormantDeletingAt", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceDormantDeletingAt", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.UpdateWorkspaceDormantDeletingAtParams{ check.Args(database.UpdateWorkspaceDormantDeletingAtParams{
ID: w.ID, ID: w.ID,
}).Asserts(w, policy.ActionUpdate) }).Asserts(w, policy.ActionUpdate)
})) }))
s.Run("UpdateWorkspaceAutomaticUpdates", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAutomaticUpdates", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.UpdateWorkspaceAutomaticUpdatesParams{ check.Args(database.UpdateWorkspaceAutomaticUpdatesParams{
ID: w.ID, ID: w.ID,
AutomaticUpdates: database.AutomaticUpdatesAlways, AutomaticUpdates: database.AutomaticUpdatesAlways,
}).Asserts(w, policy.ActionUpdate) }).Asserts(w, policy.ActionUpdate)
})) }))
s.Run("UpdateWorkspaceAppHealthByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAppHealthByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
@@ -1830,13 +1827,13 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionUpdate).Returns() }).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
s.Run("UpdateWorkspaceAutostart", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAutostart", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.UpdateWorkspaceAutostartParams{ check.Args(database.UpdateWorkspaceAutostartParams{
ID: ws.ID, ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns() }).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
s.Run("UpdateWorkspaceBuildDeadlineByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceBuildDeadlineByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
check.Args(database.UpdateWorkspaceBuildDeadlineByIDParams{ check.Args(database.UpdateWorkspaceBuildDeadlineByIDParams{
ID: build.ID, ID: build.ID,
@@ -1845,46 +1842,46 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionUpdate) }).Asserts(ws, policy.ActionUpdate)
})) }))
s.Run("SoftDeleteWorkspaceByID", s.Subtest(func(db database.Store, check *expects) { s.Run("SoftDeleteWorkspaceByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
ws.Deleted = true ws.Deleted = true
check.Args(ws.ID).Asserts(ws, policy.ActionDelete).Returns() check.Args(ws.ID).Asserts(ws, policy.ActionDelete).Returns()
})) }))
s.Run("UpdateWorkspaceDeletedByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceDeletedByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{Deleted: true}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{Deleted: true})
check.Args(database.UpdateWorkspaceDeletedByIDParams{ check.Args(database.UpdateWorkspaceDeletedByIDParams{
ID: ws.ID, ID: ws.ID,
Deleted: true, Deleted: true,
}).Asserts(ws, policy.ActionDelete).Returns() }).Asserts(ws, policy.ActionDelete).Returns()
})) }))
s.Run("UpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.UpdateWorkspaceLastUsedAtParams{ check.Args(database.UpdateWorkspaceLastUsedAtParams{
ID: ws.ID, ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns() }).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
s.Run("BatchUpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) { s.Run("BatchUpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) {
ws1 := dbgen.Workspace(s.T(), db, database.Workspace{}) ws1 := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
ws2 := dbgen.Workspace(s.T(), db, database.Workspace{}) ws2 := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.BatchUpdateWorkspaceLastUsedAtParams{ check.Args(database.BatchUpdateWorkspaceLastUsedAtParams{
IDs: []uuid.UUID{ws1.ID, ws2.ID}, IDs: []uuid.UUID{ws1.ID, ws2.ID},
}).Asserts(rbac.ResourceWorkspace.All(), policy.ActionUpdate).Returns() }).Asserts(rbac.ResourceWorkspace.All(), policy.ActionUpdate).Returns()
})) }))
s.Run("UpdateWorkspaceTTL", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceTTL", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.UpdateWorkspaceTTLParams{ check.Args(database.UpdateWorkspaceTTLParams{
ID: ws.ID, ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns() }).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
s.Run("GetWorkspaceByWorkspaceAppID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceByWorkspaceAppID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
app := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID}) app := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID})
check.Args(app.ID).Asserts(ws, policy.ActionRead).Returns(ws) check.Args(app.ID).Asserts(ws, policy.ActionRead)
})) }))
s.Run("ActivityBumpWorkspace", s.Subtest(func(db database.Store, check *expects) { s.Run("ActivityBumpWorkspace", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
check.Args(database.ActivityBumpWorkspaceParams{ check.Args(database.ActivityBumpWorkspaceParams{
@@ -1893,12 +1890,12 @@ func (s *MethodTestSuite) TestWorkspace() {
})) }))
s.Run("FavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) { s.Run("FavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns() check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
s.Run("UnfavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) { s.Run("UnfavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns() check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns()
})) }))
} }
@@ -1906,7 +1903,7 @@ func (s *MethodTestSuite) TestWorkspace() {
func (s *MethodTestSuite) TestWorkspacePortSharing() { func (s *MethodTestSuite) TestWorkspacePortSharing() {
s.Run("UpsertWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) { s.Run("UpsertWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
//nolint:gosimple // casting is not a simplification //nolint:gosimple // casting is not a simplification
check.Args(database.UpsertWorkspaceAgentPortShareParams{ check.Args(database.UpsertWorkspaceAgentPortShareParams{
@@ -1919,7 +1916,7 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
})) }))
s.Run("GetWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
check.Args(database.GetWorkspaceAgentPortShareParams{ check.Args(database.GetWorkspaceAgentPortShareParams{
WorkspaceID: ps.WorkspaceID, WorkspaceID: ps.WorkspaceID,
@@ -1929,13 +1926,13 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
})) }))
s.Run("ListWorkspaceAgentPortShares", s.Subtest(func(db database.Store, check *expects) { s.Run("ListWorkspaceAgentPortShares", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceAgentPortShare{ps}) check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceAgentPortShare{ps})
})) }))
s.Run("DeleteWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) { s.Run("DeleteWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID})
ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
check.Args(database.DeleteWorkspaceAgentPortShareParams{ check.Args(database.DeleteWorkspaceAgentPortShareParams{
WorkspaceID: ps.WorkspaceID, WorkspaceID: ps.WorkspaceID,
@@ -1946,14 +1943,14 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
s.Run("DeleteWorkspaceAgentPortSharesByTemplate", s.Subtest(func(db database.Store, check *expects) { s.Run("DeleteWorkspaceAgentPortSharesByTemplate", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
t := dbgen.Template(s.T(), db, database.Template{}) t := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID, TemplateID: t.ID})
_ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) _ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns() check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns()
})) }))
s.Run("ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate", s.Subtest(func(db database.Store, check *expects) { s.Run("ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{}) u := dbgen.User(s.T(), db, database.User{})
t := dbgen.Template(s.T(), db, database.Template{}) t := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OwnerID: u.ID, TemplateID: t.ID})
_ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) _ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns() check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns()
})) }))
@@ -2305,7 +2302,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns(l) }).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns(l)
})) }))
s.Run("GetLatestWorkspaceBuildsByWorkspaceIDs", s.Subtest(func(db database.Store, check *expects) { s.Run("GetLatestWorkspaceBuildsByWorkspaceIDs", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID})
check.Args([]uuid.UUID{ws.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(slice.New(b)) check.Args([]uuid.UUID{ws.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(slice.New(b))
})) }))
@@ -2388,7 +2385,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionUpdate) }).Asserts(rbac.ResourceSystem, policy.ActionUpdate)
})) }))
s.Run("UpdateWorkspaceBuildProvisionerStateByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceBuildProvisionerStateByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
check.Args(database.UpdateWorkspaceBuildProvisionerStateByIDParams{ check.Args(database.UpdateWorkspaceBuildProvisionerStateByIDParams{
ID: build.ID, ID: build.ID,
@@ -2457,13 +2454,13 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Asserts(tpl, policy.ActionRead).Errors(sql.ErrNoRows) Asserts(tpl, policy.ActionRead).Errors(sql.ErrNoRows)
})) }))
s.Run("GetWorkspaceAppsByAgentIDs", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAppsByAgentIDs", s.Subtest(func(db database.Store, check *expects) {
aWs := dbgen.Workspace(s.T(), db, database.Workspace{}) aWs := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
aBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: aWs.ID, JobID: uuid.New()}) aBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: aWs.ID, JobID: uuid.New()})
aRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: aBuild.JobID}) aRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: aBuild.JobID})
aAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: aRes.ID}) aAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: aRes.ID})
a := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: aAgt.ID}) a := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: aAgt.ID})
bWs := dbgen.Workspace(s.T(), db, database.Workspace{}) bWs := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
bBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: bWs.ID, JobID: uuid.New()}) bBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: bWs.ID, JobID: uuid.New()})
bRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: bBuild.JobID}) bRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: bBuild.JobID})
bAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: bRes.ID}) bAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: bRes.ID})
@@ -2478,7 +2475,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, JobID: uuid.New()}) v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, JobID: uuid.New()})
tJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: v.JobID, Type: database.ProvisionerJobTypeTemplateVersionImport}) tJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: v.JobID, Type: database.ProvisionerJobTypeTemplateVersionImport})
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
wJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) wJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
check.Args([]uuid.UUID{tJob.ID, wJob.ID}). check.Args([]uuid.UUID{tJob.ID, wJob.ID}).
@@ -2486,7 +2483,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Returns([]database.WorkspaceResource{}) Returns([]database.WorkspaceResource{})
})) }))
s.Run("GetWorkspaceResourceMetadataByResourceIDs", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceResourceMetadataByResourceIDs", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
_ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) _ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
a := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) a := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
@@ -2495,7 +2492,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Asserts(rbac.ResourceSystem, policy.ActionRead) Asserts(rbac.ResourceSystem, policy.ActionRead)
})) }))
s.Run("GetWorkspaceAgentsByResourceIDs", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentsByResourceIDs", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
@@ -2529,7 +2526,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionCreate) }).Asserts(rbac.ResourceSystem, policy.ActionCreate)
})) }))
s.Run("UpdateWorkspaceAgentConnectionByID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpdateWorkspaceAgentConnectionByID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
@@ -2772,7 +2769,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead) check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead)
})) }))
s.Run("GetJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) {
ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
agent := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{}) agent := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{})
err := db.UpsertJFrogXrayScanByWorkspaceAndAgentID(context.Background(), database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{ err := db.UpsertJFrogXrayScanByWorkspaceAndAgentID(context.Background(), database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{
@@ -2801,7 +2798,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
})) }))
s.Run("UpsertJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) { s.Run("UpsertJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) {
tpl := dbgen.Template(s.T(), db, database.Template{}) tpl := dbgen.Template(s.T(), db, database.Template{})
ws := dbgen.Workspace(s.T(), db, database.Workspace{ ws := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
check.Args(database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{ check.Args(database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{
@@ -2848,7 +2845,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionCreate) }).Asserts(rbac.ResourceSystem, policy.ActionCreate)
})) }))
s.Run("GetProvisionerJobTimingsByJobID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetProvisionerJobTimingsByJobID", s.Subtest(func(db database.Store, check *expects) {
w := dbgen.Workspace(s.T(), db, database.Workspace{}) w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
@@ -2857,7 +2854,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
check.Args(j.ID).Asserts(w, policy.ActionRead).Returns(t) check.Args(j.ID).Asserts(w, policy.ActionRead).Returns(t)
})) }))
s.Run("GetWorkspaceAgentScriptTimingsByBuildID", s.Subtest(func(db database.Store, check *expects) { s.Run("GetWorkspaceAgentScriptTimingsByBuildID", s.Subtest(func(db database.Store, check *expects) {
workspace := dbgen.Workspace(s.T(), db, database.Workspace{}) workspace := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild, Type: database.ProvisionerJobTypeWorkspaceBuild,
}) })
+3 -3
View File
@@ -32,7 +32,7 @@ var ownerCtx = dbauthz.As(context.Background(), rbac.Subject{
}) })
type WorkspaceResponse struct { type WorkspaceResponse struct {
Workspace database.Workspace Workspace database.WorkspaceTable
Build database.WorkspaceBuild Build database.WorkspaceBuild
AgentToken string AgentToken string
TemplateVersionResponse TemplateVersionResponse
@@ -44,7 +44,7 @@ type WorkspaceBuildBuilder struct {
t testing.TB t testing.TB
db database.Store db database.Store
ps pubsub.Pubsub ps pubsub.Pubsub
ws database.Workspace ws database.WorkspaceTable
seed database.WorkspaceBuild seed database.WorkspaceBuild
resources []*sdkproto.Resource resources []*sdkproto.Resource
params []database.WorkspaceBuildParameter params []database.WorkspaceBuildParameter
@@ -60,7 +60,7 @@ type workspaceBuildDisposition struct {
// Pass a database.Workspace{} with a nil ID to also generate a new workspace. // Pass a database.Workspace{} with a nil ID to also generate a new workspace.
// Omitting the template ID on a workspace will also generate a new template // Omitting the template ID on a workspace will also generate a new template
// with a template version. // with a template version.
func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace) WorkspaceBuildBuilder { func WorkspaceBuild(t testing.TB, db database.Store, ws database.WorkspaceTable) WorkspaceBuildBuilder {
return WorkspaceBuildBuilder{t: t, db: db, ws: ws} return WorkspaceBuildBuilder{t: t, db: db, ws: ws}
} }
+1 -1
View File
@@ -232,7 +232,7 @@ func WorkspaceAgentScriptTiming(t testing.TB, db database.Store, orig database.W
return timing return timing
} }
func Workspace(t testing.TB, db database.Store, orig database.Workspace) database.Workspace { func Workspace(t testing.TB, db database.Store, orig database.WorkspaceTable) database.WorkspaceTable {
t.Helper() t.Helper()
workspace, err := db.InsertWorkspace(genCtx, database.InsertWorkspaceParams{ workspace, err := db.InsertWorkspace(genCtx, database.InsertWorkspaceParams{
+2 -2
View File
@@ -128,8 +128,8 @@ func TestGenerator(t *testing.T) {
t.Run("Workspace", func(t *testing.T) { t.Run("Workspace", func(t *testing.T) {
t.Parallel() t.Parallel()
db := dbmem.New() db := dbmem.New()
exp := dbgen.Workspace(t, db, database.Workspace{}) exp := dbgen.Workspace(t, db, database.WorkspaceTable{})
require.Equal(t, exp, must(db.GetWorkspaceByID(context.Background(), exp.ID))) require.Equal(t, exp, must(db.GetWorkspaceByID(context.Background(), exp.ID)).WorkspaceTable())
}) })
t.Run("WorkspaceAgent", func(t *testing.T) { t.Run("WorkspaceAgent", func(t *testing.T) {
+102 -60
View File
@@ -81,7 +81,7 @@ func New() database.Store {
workspaceAgentLogs: make([]database.WorkspaceAgentLog, 0), workspaceAgentLogs: make([]database.WorkspaceAgentLog, 0),
workspaceBuilds: make([]database.WorkspaceBuild, 0), workspaceBuilds: make([]database.WorkspaceBuild, 0),
workspaceApps: make([]database.WorkspaceApp, 0), workspaceApps: make([]database.WorkspaceApp, 0),
workspaces: make([]database.Workspace, 0), workspaces: make([]database.WorkspaceTable, 0),
licenses: make([]database.License, 0), licenses: make([]database.License, 0),
workspaceProxies: make([]database.WorkspaceProxy, 0), workspaceProxies: make([]database.WorkspaceProxy, 0),
customRoles: make([]database.CustomRole, 0), customRoles: make([]database.CustomRole, 0),
@@ -232,7 +232,7 @@ type data struct {
workspaceBuildParameters []database.WorkspaceBuildParameter workspaceBuildParameters []database.WorkspaceBuildParameter
workspaceResourceMetadata []database.WorkspaceResourceMetadatum workspaceResourceMetadata []database.WorkspaceResourceMetadatum
workspaceResources []database.WorkspaceResource workspaceResources []database.WorkspaceResource
workspaces []database.Workspace workspaces []database.WorkspaceTable
workspaceProxies []database.WorkspaceProxy workspaceProxies []database.WorkspaceProxy
customRoles []database.CustomRole customRoles []database.CustomRole
provisionerJobTimings []database.ProvisionerJobTiming provisionerJobTimings []database.ProvisionerJobTiming
@@ -445,9 +445,11 @@ func mapAgentStatus(dbAgent database.WorkspaceAgent, agentInactiveDisconnectTime
return status return status
} }
func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspaces []database.Workspace, count int64, withSummary bool) []database.GetWorkspacesRow { //nolint:revive // withSummary flag ensures the extra technical row func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspaces []database.WorkspaceTable, count int64, withSummary bool) []database.GetWorkspacesRow { //nolint:revive // withSummary flag ensures the extra technical row
rows := make([]database.GetWorkspacesRow, 0, len(workspaces)) rows := make([]database.GetWorkspacesRow, 0, len(workspaces))
for _, w := range workspaces { for _, w := range workspaces {
extended := q.extendWorkspace(w)
wr := database.GetWorkspacesRow{ wr := database.GetWorkspacesRow{
ID: w.ID, ID: w.ID,
CreatedAt: w.CreatedAt, CreatedAt: w.CreatedAt,
@@ -462,16 +464,33 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
LastUsedAt: w.LastUsedAt, LastUsedAt: w.LastUsedAt,
DormantAt: w.DormantAt, DormantAt: w.DormantAt,
DeletingAt: w.DeletingAt, DeletingAt: w.DeletingAt,
Count: count,
AutomaticUpdates: w.AutomaticUpdates, AutomaticUpdates: w.AutomaticUpdates,
Favorite: w.Favorite, Favorite: w.Favorite,
}
for _, t := range q.templates { OwnerAvatarUrl: extended.OwnerAvatarUrl,
if t.ID == w.TemplateID { OwnerUsername: extended.OwnerUsername,
wr.TemplateName = t.Name
break OrganizationName: extended.OrganizationName,
} OrganizationDisplayName: extended.OrganizationDisplayName,
OrganizationIcon: extended.OrganizationIcon,
OrganizationDescription: extended.OrganizationDescription,
TemplateName: extended.TemplateName,
TemplateDisplayName: extended.TemplateDisplayName,
TemplateIcon: extended.TemplateIcon,
TemplateDescription: extended.TemplateDescription,
Count: count,
// These fields are missing!
// Try to resolve them below
TemplateVersionID: uuid.UUID{},
TemplateVersionName: sql.NullString{},
LatestBuildCompletedAt: sql.NullTime{},
LatestBuildCanceledAt: sql.NullTime{},
LatestBuildError: sql.NullString{},
LatestBuildTransition: "",
LatestBuildStatus: "",
} }
if build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, w.ID); err == nil { if build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, w.ID); err == nil {
@@ -488,15 +507,14 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
if pj, err := q.getProvisionerJobByIDNoLock(ctx, build.JobID); err == nil { if pj, err := q.getProvisionerJobByIDNoLock(ctx, build.JobID); err == nil {
wr.LatestBuildStatus = pj.JobStatus wr.LatestBuildStatus = pj.JobStatus
wr.LatestBuildCanceledAt = pj.CanceledAt
wr.LatestBuildCompletedAt = pj.CompletedAt
wr.LatestBuildError = pj.Error
} }
wr.LatestBuildTransition = build.Transition wr.LatestBuildTransition = build.Transition
} }
if u, err := q.getUserByIDNoLock(w.OwnerID); err == nil {
wr.Username = u.Username
}
rows = append(rows, wr) rows = append(rows, wr)
} }
if withSummary { if withSummary {
@@ -509,14 +527,50 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
} }
func (q *FakeQuerier) getWorkspaceByIDNoLock(_ context.Context, id uuid.UUID) (database.Workspace, error) { func (q *FakeQuerier) getWorkspaceByIDNoLock(_ context.Context, id uuid.UUID) (database.Workspace, error) {
for _, workspace := range q.workspaces { return q.getWorkspaceNoLock(func(w database.WorkspaceTable) bool {
if workspace.ID == id { return w.ID == id
return workspace, nil })
} }
func (q *FakeQuerier) getWorkspaceNoLock(find func(w database.WorkspaceTable) bool) (database.Workspace, error) {
w, found := slice.Find(q.workspaces, find)
if found {
return q.extendWorkspace(w), nil
} }
return database.Workspace{}, sql.ErrNoRows return database.Workspace{}, sql.ErrNoRows
} }
func (q *FakeQuerier) extendWorkspace(w database.WorkspaceTable) database.Workspace {
var extended database.Workspace
// This is a cheeky way to copy the fields over without explicitly listing them all.
d, _ := json.Marshal(w)
_ = json.Unmarshal(d, &extended)
org, _ := slice.Find(q.organizations, func(o database.Organization) bool {
return o.ID == w.OrganizationID
})
extended.OrganizationName = org.Name
extended.OrganizationDescription = org.Description
extended.OrganizationDisplayName = org.DisplayName
extended.OrganizationIcon = org.Icon
tpl, _ := slice.Find(q.templates, func(t database.TemplateTable) bool {
return t.ID == w.TemplateID
})
extended.TemplateName = tpl.Name
extended.TemplateDisplayName = tpl.DisplayName
extended.TemplateDescription = tpl.Description
extended.TemplateIcon = tpl.Icon
owner, _ := slice.Find(q.users, func(u database.User) bool {
return u.ID == w.OwnerID
})
extended.OwnerUsername = owner.Username
extended.OwnerAvatarUrl = owner.AvatarURL
return extended
}
func (q *FakeQuerier) getWorkspaceByAgentIDNoLock(_ context.Context, agentID uuid.UUID) (database.Workspace, error) { func (q *FakeQuerier) getWorkspaceByAgentIDNoLock(_ context.Context, agentID uuid.UUID) (database.Workspace, error) {
var agent database.WorkspaceAgent var agent database.WorkspaceAgent
for _, _agent := range q.workspaceAgents { for _, _agent := range q.workspaceAgents {
@@ -551,13 +605,9 @@ func (q *FakeQuerier) getWorkspaceByAgentIDNoLock(_ context.Context, agentID uui
return database.Workspace{}, sql.ErrNoRows return database.Workspace{}, sql.ErrNoRows
} }
for _, workspace := range q.workspaces { return q.getWorkspaceNoLock(func(w database.WorkspaceTable) bool {
if workspace.ID == build.WorkspaceID { return w.ID == build.WorkspaceID
return workspace, nil })
}
}
return database.Workspace{}, sql.ErrNoRows
} }
func (q *FakeQuerier) getWorkspaceBuildByIDNoLock(_ context.Context, id uuid.UUID) (database.WorkspaceBuild, error) { func (q *FakeQuerier) getWorkspaceBuildByIDNoLock(_ context.Context, id uuid.UUID) (database.WorkspaceBuild, error) {
@@ -986,14 +1036,14 @@ func (q *FakeQuerier) getLatestWorkspaceAppByTemplateIDUserIDSlugNoLock(ctx cont
LIMIT 1 LIMIT 1
*/ */
var workspaces []database.Workspace var workspaces []database.WorkspaceTable
for _, w := range q.workspaces { for _, w := range q.workspaces {
if w.TemplateID != templateID || w.OwnerID != userID { if w.TemplateID != templateID || w.OwnerID != userID {
continue continue
} }
workspaces = append(workspaces, w) workspaces = append(workspaces, w)
} }
slices.SortFunc(workspaces, func(a, b database.Workspace) int { slices.SortFunc(workspaces, func(a, b database.WorkspaceTable) int {
if a.CreatedAt.Before(b.CreatedAt) { if a.CreatedAt.Before(b.CreatedAt) {
return 1 return 1
} else if a.CreatedAt.Equal(b.CreatedAt) { } else if a.CreatedAt.Equal(b.CreatedAt) {
@@ -5644,7 +5694,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
continue continue
} }
row := database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{ row := database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{
Workspace: database.Workspace{ WorkspaceTable: database.WorkspaceTable{
ID: ws.ID, ID: ws.ID,
TemplateID: ws.TemplateID, TemplateID: ws.TemplateID,
}, },
@@ -5655,7 +5705,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
if err != nil { if err != nil {
return database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{}, sql.ErrNoRows return database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{}, sql.ErrNoRows
} }
row.Workspace.OwnerID = usr.ID row.WorkspaceTable.OwnerID = usr.ID
// Keep track of the latest build number // Keep track of the latest build number
rows = append(rows, row) rows = append(rows, row)
@@ -5672,7 +5722,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
continue continue
} }
if rows[i].WorkspaceBuild.BuildNumber != latestBuildNumber[rows[i].Workspace.ID] { if rows[i].WorkspaceBuild.BuildNumber != latestBuildNumber[rows[i].WorkspaceTable.ID] {
continue continue
} }
@@ -6514,24 +6564,16 @@ func (q *FakeQuerier) GetWorkspaceBuildsCreatedAfter(_ context.Context, after ti
return workspaceBuilds, nil return workspaceBuilds, nil
} }
func (q *FakeQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.GetWorkspaceByAgentIDRow, error) { func (q *FakeQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.Workspace, error) {
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
w, err := q.getWorkspaceByAgentIDNoLock(ctx, agentID) w, err := q.getWorkspaceByAgentIDNoLock(ctx, agentID)
if err != nil { if err != nil {
return database.GetWorkspaceByAgentIDRow{}, err return database.Workspace{}, err
} }
tpl, err := q.getTemplateByIDNoLock(ctx, w.TemplateID) return w, nil
if err != nil {
return database.GetWorkspaceByAgentIDRow{}, err
}
return database.GetWorkspaceByAgentIDRow{
Workspace: w,
TemplateName: tpl.Name,
}, nil
} }
func (q *FakeQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (database.Workspace, error) { func (q *FakeQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (database.Workspace, error) {
@@ -6549,7 +6591,7 @@ func (q *FakeQuerier) GetWorkspaceByOwnerIDAndName(_ context.Context, arg databa
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
var found *database.Workspace var found *database.WorkspaceTable
for _, workspace := range q.workspaces { for _, workspace := range q.workspaces {
workspace := workspace workspace := workspace
if workspace.OwnerID != arg.OwnerID { if workspace.OwnerID != arg.OwnerID {
@@ -6568,7 +6610,7 @@ func (q *FakeQuerier) GetWorkspaceByOwnerIDAndName(_ context.Context, arg databa
} }
} }
if found != nil { if found != nil {
return *found, nil return q.extendWorkspace(*found), nil
} }
return database.Workspace{}, sql.ErrNoRows return database.Workspace{}, sql.ErrNoRows
} }
@@ -6794,11 +6836,11 @@ func (q *FakeQuerier) GetWorkspaces(ctx context.Context, arg database.GetWorkspa
return workspaceRows, err return workspaceRows, err
} }
func (q *FakeQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.Workspace, error) { func (q *FakeQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.WorkspaceTable, error) {
q.mutex.RLock() q.mutex.RLock()
defer q.mutex.RUnlock() defer q.mutex.RUnlock()
workspaces := []database.Workspace{} workspaces := []database.WorkspaceTable{}
for _, workspace := range q.workspaces { for _, workspace := range q.workspaces {
build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, workspace.ID) build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, workspace.ID)
if err != nil { if err != nil {
@@ -7759,16 +7801,16 @@ func (q *FakeQuerier) InsertUserLink(_ context.Context, args database.InsertUser
return link, nil return link, nil
} }
func (q *FakeQuerier) InsertWorkspace(_ context.Context, arg database.InsertWorkspaceParams) (database.Workspace, error) { func (q *FakeQuerier) InsertWorkspace(_ context.Context, arg database.InsertWorkspaceParams) (database.WorkspaceTable, error) {
if err := validateDatabaseType(arg); err != nil { if err := validateDatabaseType(arg); err != nil {
return database.Workspace{}, err return database.WorkspaceTable{}, err
} }
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()
//nolint:gosimple //nolint:gosimple
workspace := database.Workspace{ workspace := database.WorkspaceTable{
ID: arg.ID, ID: arg.ID,
CreatedAt: arg.CreatedAt, CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt, UpdatedAt: arg.UpdatedAt,
@@ -9408,9 +9450,9 @@ func (q *FakeQuerier) UpdateUserStatus(_ context.Context, arg database.UpdateUse
return database.User{}, sql.ErrNoRows return database.User{}, sql.ErrNoRows
} }
func (q *FakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) { func (q *FakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
if err := validateDatabaseType(arg); err != nil { if err := validateDatabaseType(arg); err != nil {
return database.Workspace{}, err return database.WorkspaceTable{}, err
} }
q.mutex.Lock() q.mutex.Lock()
@@ -9425,7 +9467,7 @@ func (q *FakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWork
continue continue
} }
if other.Name == arg.Name { if other.Name == arg.Name {
return database.Workspace{}, errUniqueConstraint return database.WorkspaceTable{}, errUniqueConstraint
} }
} }
@@ -9435,7 +9477,7 @@ func (q *FakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWork
return workspace, nil return workspace, nil
} }
return database.Workspace{}, sql.ErrNoRows return database.WorkspaceTable{}, sql.ErrNoRows
} }
func (q *FakeQuerier) UpdateWorkspaceAgentConnectionByID(_ context.Context, arg database.UpdateWorkspaceAgentConnectionByIDParams) error { func (q *FakeQuerier) UpdateWorkspaceAgentConnectionByID(_ context.Context, arg database.UpdateWorkspaceAgentConnectionByIDParams) error {
@@ -9700,9 +9742,9 @@ func (q *FakeQuerier) UpdateWorkspaceDeletedByID(_ context.Context, arg database
return sql.ErrNoRows return sql.ErrNoRows
} }
func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) { func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
if err := validateDatabaseType(arg); err != nil { if err := validateDatabaseType(arg); err != nil {
return database.Workspace{}, err return database.WorkspaceTable{}, err
} }
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()
@@ -9724,7 +9766,7 @@ func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg da
} }
} }
if template.ID == uuid.Nil { if template.ID == uuid.Nil {
return database.Workspace{}, xerrors.Errorf("unable to find workspace template") return database.WorkspaceTable{}, xerrors.Errorf("unable to find workspace template")
} }
if template.TimeTilDormantAutoDelete > 0 { if template.TimeTilDormantAutoDelete > 0 {
workspace.DeletingAt = sql.NullTime{ workspace.DeletingAt = sql.NullTime{
@@ -9736,7 +9778,7 @@ func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg da
q.workspaces[index] = workspace q.workspaces[index] = workspace
return workspace, nil return workspace, nil
} }
return database.Workspace{}, sql.ErrNoRows return database.WorkspaceTable{}, sql.ErrNoRows
} }
func (q *FakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.UpdateWorkspaceLastUsedAtParams) error { func (q *FakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.UpdateWorkspaceLastUsedAtParams) error {
@@ -9819,7 +9861,7 @@ func (q *FakeQuerier) UpdateWorkspaceTTL(_ context.Context, arg database.UpdateW
return sql.ErrNoRows return sql.ErrNoRows
} }
func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) { func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.WorkspaceTable, error) {
q.mutex.Lock() q.mutex.Lock()
defer q.mutex.Unlock() defer q.mutex.Unlock()
@@ -9828,7 +9870,7 @@ func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Co
return nil, err return nil, err
} }
affectedRows := []database.Workspace{} affectedRows := []database.WorkspaceTable{}
for i, ws := range q.workspaces { for i, ws := range q.workspaces {
if ws.TemplateID != arg.TemplateID { if ws.TemplateID != arg.TemplateID {
continue continue
@@ -10863,7 +10905,7 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
} }
} }
workspaces := make([]database.Workspace, 0) workspaces := make([]database.WorkspaceTable, 0)
for _, workspace := range q.workspaces { for _, workspace := range q.workspaces {
if arg.OwnerID != uuid.Nil && workspace.OwnerID != arg.OwnerID { if arg.OwnerID != uuid.Nil && workspace.OwnerID != arg.OwnerID {
continue continue
@@ -11159,7 +11201,7 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
if arg.Offset > 0 { if arg.Offset > 0 {
if int(arg.Offset) > len(workspaces) { if int(arg.Offset) > len(workspaces) {
return q.convertToWorkspaceRowsNoLock(ctx, []database.Workspace{}, int64(beforePageCount), arg.WithSummary), nil return q.convertToWorkspaceRowsNoLock(ctx, []database.WorkspaceTable{}, int64(beforePageCount), arg.WithSummary), nil
} }
workspaces = workspaces[arg.Offset:] workspaces = workspaces[arg.Offset:]
} }
+6 -6
View File
@@ -1544,7 +1544,7 @@ func (m metricsStore) GetWorkspaceBuildsCreatedAfter(ctx context.Context, create
return builds, err return builds, err
} }
func (m metricsStore) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.GetWorkspaceByAgentIDRow, error) { func (m metricsStore) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (database.Workspace, error) {
start := time.Now() start := time.Now()
workspace, err := m.s.GetWorkspaceByAgentID(ctx, agentID) workspace, err := m.s.GetWorkspaceByAgentID(ctx, agentID)
m.queryLatencies.WithLabelValues("GetWorkspaceByAgentID").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("GetWorkspaceByAgentID").Observe(time.Since(start).Seconds())
@@ -1656,7 +1656,7 @@ func (m metricsStore) GetWorkspaces(ctx context.Context, arg database.GetWorkspa
return workspaces, err return workspaces, err
} }
func (m metricsStore) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.Workspace, error) { func (m metricsStore) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]database.WorkspaceTable, error) {
start := time.Now() start := time.Now()
workspaces, err := m.s.GetWorkspacesEligibleForTransition(ctx, now) workspaces, err := m.s.GetWorkspacesEligibleForTransition(ctx, now)
m.queryLatencies.WithLabelValues("GetWorkspacesEligibleForAutoStartStop").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("GetWorkspacesEligibleForAutoStartStop").Observe(time.Since(start).Seconds())
@@ -1908,7 +1908,7 @@ func (m metricsStore) InsertUserLink(ctx context.Context, arg database.InsertUse
return link, err return link, err
} }
func (m metricsStore) InsertWorkspace(ctx context.Context, arg database.InsertWorkspaceParams) (database.Workspace, error) { func (m metricsStore) InsertWorkspace(ctx context.Context, arg database.InsertWorkspaceParams) (database.WorkspaceTable, error) {
start := time.Now() start := time.Now()
workspace, err := m.s.InsertWorkspace(ctx, arg) workspace, err := m.s.InsertWorkspace(ctx, arg)
m.queryLatencies.WithLabelValues("InsertWorkspace").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("InsertWorkspace").Observe(time.Since(start).Seconds())
@@ -2391,7 +2391,7 @@ func (m metricsStore) UpdateUserStatus(ctx context.Context, arg database.UpdateU
return user, err return user, err
} }
func (m metricsStore) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) { func (m metricsStore) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
start := time.Now() start := time.Now()
workspace, err := m.s.UpdateWorkspace(ctx, arg) workspace, err := m.s.UpdateWorkspace(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspace").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("UpdateWorkspace").Observe(time.Since(start).Seconds())
@@ -2482,7 +2482,7 @@ func (m metricsStore) UpdateWorkspaceDeletedByID(ctx context.Context, arg databa
return err return err
} }
func (m metricsStore) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) { func (m metricsStore) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
start := time.Now() start := time.Now()
ws, r0 := m.s.UpdateWorkspaceDormantDeletingAt(ctx, arg) ws, r0 := m.s.UpdateWorkspaceDormantDeletingAt(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspaceDormantDeletingAt").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("UpdateWorkspaceDormantDeletingAt").Observe(time.Since(start).Seconds())
@@ -2517,7 +2517,7 @@ func (m metricsStore) UpdateWorkspaceTTL(ctx context.Context, arg database.Updat
return r0 return r0
} }
func (m metricsStore) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) { func (m metricsStore) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.WorkspaceTable, error) {
start := time.Now() start := time.Now()
r0, r1 := m.s.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg) r0, r1 := m.s.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspacesDormantDeletingAtByTemplateID").Observe(time.Since(start).Seconds()) m.queryLatencies.WithLabelValues("UpdateWorkspacesDormantDeletingAtByTemplateID").Observe(time.Since(start).Seconds())
+12 -12
View File
@@ -3234,10 +3234,10 @@ func (mr *MockStoreMockRecorder) GetWorkspaceBuildsCreatedAfter(arg0, arg1 any)
} }
// GetWorkspaceByAgentID mocks base method. // GetWorkspaceByAgentID mocks base method.
func (m *MockStore) GetWorkspaceByAgentID(arg0 context.Context, arg1 uuid.UUID) (database.GetWorkspaceByAgentIDRow, error) { func (m *MockStore) GetWorkspaceByAgentID(arg0 context.Context, arg1 uuid.UUID) (database.Workspace, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetWorkspaceByAgentID", arg0, arg1) ret := m.ctrl.Call(m, "GetWorkspaceByAgentID", arg0, arg1)
ret0, _ := ret[0].(database.GetWorkspaceByAgentIDRow) ret0, _ := ret[0].(database.Workspace)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@@ -3474,10 +3474,10 @@ func (mr *MockStoreMockRecorder) GetWorkspaces(arg0, arg1 any) *gomock.Call {
} }
// GetWorkspacesEligibleForTransition mocks base method. // GetWorkspacesEligibleForTransition mocks base method.
func (m *MockStore) GetWorkspacesEligibleForTransition(arg0 context.Context, arg1 time.Time) ([]database.Workspace, error) { func (m *MockStore) GetWorkspacesEligibleForTransition(arg0 context.Context, arg1 time.Time) ([]database.WorkspaceTable, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetWorkspacesEligibleForTransition", arg0, arg1) ret := m.ctrl.Call(m, "GetWorkspacesEligibleForTransition", arg0, arg1)
ret0, _ := ret[0].([]database.Workspace) ret0, _ := ret[0].([]database.WorkspaceTable)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@@ -4021,10 +4021,10 @@ func (mr *MockStoreMockRecorder) InsertUserLink(arg0, arg1 any) *gomock.Call {
} }
// InsertWorkspace mocks base method. // InsertWorkspace mocks base method.
func (m *MockStore) InsertWorkspace(arg0 context.Context, arg1 database.InsertWorkspaceParams) (database.Workspace, error) { func (m *MockStore) InsertWorkspace(arg0 context.Context, arg1 database.InsertWorkspaceParams) (database.WorkspaceTable, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InsertWorkspace", arg0, arg1) ret := m.ctrl.Call(m, "InsertWorkspace", arg0, arg1)
ret0, _ := ret[0].(database.Workspace) ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@@ -5041,10 +5041,10 @@ func (mr *MockStoreMockRecorder) UpdateUserStatus(arg0, arg1 any) *gomock.Call {
} }
// UpdateWorkspace mocks base method. // UpdateWorkspace mocks base method.
func (m *MockStore) UpdateWorkspace(arg0 context.Context, arg1 database.UpdateWorkspaceParams) (database.Workspace, error) { func (m *MockStore) UpdateWorkspace(arg0 context.Context, arg1 database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateWorkspace", arg0, arg1) ret := m.ctrl.Call(m, "UpdateWorkspace", arg0, arg1)
ret0, _ := ret[0].(database.Workspace) ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@@ -5224,10 +5224,10 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceDeletedByID(arg0, arg1 any) *gom
} }
// UpdateWorkspaceDormantDeletingAt mocks base method. // UpdateWorkspaceDormantDeletingAt mocks base method.
func (m *MockStore) UpdateWorkspaceDormantDeletingAt(arg0 context.Context, arg1 database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) { func (m *MockStore) UpdateWorkspaceDormantDeletingAt(arg0 context.Context, arg1 database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateWorkspaceDormantDeletingAt", arg0, arg1) ret := m.ctrl.Call(m, "UpdateWorkspaceDormantDeletingAt", arg0, arg1)
ret0, _ := ret[0].(database.Workspace) ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@@ -5296,10 +5296,10 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceTTL(arg0, arg1 any) *gomock.Call
} }
// UpdateWorkspacesDormantDeletingAtByTemplateID mocks base method. // UpdateWorkspacesDormantDeletingAtByTemplateID mocks base method.
func (m *MockStore) UpdateWorkspacesDormantDeletingAtByTemplateID(arg0 context.Context, arg1 database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.Workspace, error) { func (m *MockStore) UpdateWorkspacesDormantDeletingAtByTemplateID(arg0 context.Context, arg1 database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]database.WorkspaceTable, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateWorkspacesDormantDeletingAtByTemplateID", arg0, arg1) ret := m.ctrl.Call(m, "UpdateWorkspacesDormantDeletingAtByTemplateID", arg0, arg1)
ret0, _ := ret[0].([]database.Workspace) ret0, _ := ret[0].([]database.WorkspaceTable)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
+5 -5
View File
@@ -195,7 +195,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
// Workspace A was built twice before the threshold, and never connected on // Workspace A was built twice before the threshold, and never connected on
// either attempt. // either attempt.
wsA := dbgen.Workspace(t, db, database.Workspace{Name: "a", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID}) wsA := dbgen.Workspace(t, db, database.WorkspaceTable{Name: "a", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID})
wbA1 := mustCreateWorkspaceBuild(t, db, org, tv, wsA.ID, beforeThreshold, 1) wbA1 := mustCreateWorkspaceBuild(t, db, org, tv, wsA.ID, beforeThreshold, 1)
wbA2 := mustCreateWorkspaceBuild(t, db, org, tv, wsA.ID, beforeThreshold, 2) wbA2 := mustCreateWorkspaceBuild(t, db, org, tv, wsA.ID, beforeThreshold, 2)
agentA1 := mustCreateAgent(t, db, wbA1) agentA1 := mustCreateAgent(t, db, wbA1)
@@ -204,7 +204,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
mustCreateAgentLogs(ctx, t, db, agentA2, nil, "agent a2 logs should be retained") mustCreateAgentLogs(ctx, t, db, agentA2, nil, "agent a2 logs should be retained")
// Workspace B was built twice before the threshold. // Workspace B was built twice before the threshold.
wsB := dbgen.Workspace(t, db, database.Workspace{Name: "b", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID}) wsB := dbgen.Workspace(t, db, database.WorkspaceTable{Name: "b", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID})
wbB1 := mustCreateWorkspaceBuild(t, db, org, tv, wsB.ID, beforeThreshold, 1) wbB1 := mustCreateWorkspaceBuild(t, db, org, tv, wsB.ID, beforeThreshold, 1)
wbB2 := mustCreateWorkspaceBuild(t, db, org, tv, wsB.ID, beforeThreshold, 2) wbB2 := mustCreateWorkspaceBuild(t, db, org, tv, wsB.ID, beforeThreshold, 2)
agentB1 := mustCreateAgent(t, db, wbB1) agentB1 := mustCreateAgent(t, db, wbB1)
@@ -213,7 +213,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
mustCreateAgentLogs(ctx, t, db, agentB2, &beforeThreshold, "agent b2 logs should be retained") mustCreateAgentLogs(ctx, t, db, agentB2, &beforeThreshold, "agent b2 logs should be retained")
// Workspace C was built once before the threshold, and once after. // Workspace C was built once before the threshold, and once after.
wsC := dbgen.Workspace(t, db, database.Workspace{Name: "c", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID}) wsC := dbgen.Workspace(t, db, database.WorkspaceTable{Name: "c", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID})
wbC1 := mustCreateWorkspaceBuild(t, db, org, tv, wsC.ID, beforeThreshold, 1) wbC1 := mustCreateWorkspaceBuild(t, db, org, tv, wsC.ID, beforeThreshold, 1)
wbC2 := mustCreateWorkspaceBuild(t, db, org, tv, wsC.ID, afterThreshold, 2) wbC2 := mustCreateWorkspaceBuild(t, db, org, tv, wsC.ID, afterThreshold, 2)
agentC1 := mustCreateAgent(t, db, wbC1) agentC1 := mustCreateAgent(t, db, wbC1)
@@ -222,7 +222,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
mustCreateAgentLogs(ctx, t, db, agentC2, &afterThreshold, "agent c2 logs should be retained") mustCreateAgentLogs(ctx, t, db, agentC2, &afterThreshold, "agent c2 logs should be retained")
// Workspace D was built twice after the threshold. // Workspace D was built twice after the threshold.
wsD := dbgen.Workspace(t, db, database.Workspace{Name: "d", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID}) wsD := dbgen.Workspace(t, db, database.WorkspaceTable{Name: "d", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID})
wbD1 := mustCreateWorkspaceBuild(t, db, org, tv, wsD.ID, afterThreshold, 1) wbD1 := mustCreateWorkspaceBuild(t, db, org, tv, wsD.ID, afterThreshold, 1)
wbD2 := mustCreateWorkspaceBuild(t, db, org, tv, wsD.ID, afterThreshold, 2) wbD2 := mustCreateWorkspaceBuild(t, db, org, tv, wsD.ID, afterThreshold, 2)
agentD1 := mustCreateAgent(t, db, wbD1) agentD1 := mustCreateAgent(t, db, wbD1)
@@ -231,7 +231,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
mustCreateAgentLogs(ctx, t, db, agentD2, &afterThreshold, "agent d2 logs should be retained") mustCreateAgentLogs(ctx, t, db, agentD2, &afterThreshold, "agent d2 logs should be retained")
// Workspace E was build once after threshold but never connected. // Workspace E was build once after threshold but never connected.
wsE := dbgen.Workspace(t, db, database.Workspace{Name: "e", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID}) wsE := dbgen.Workspace(t, db, database.WorkspaceTable{Name: "e", OwnerID: user.ID, OrganizationID: org.ID, TemplateID: tmpl.ID})
wbE1 := mustCreateWorkspaceBuild(t, db, org, tv, wsE.ID, beforeThreshold, 1) wbE1 := mustCreateWorkspaceBuild(t, db, org, tv, wsE.ID, beforeThreshold, 1)
agentE1 := mustCreateAgent(t, db, wbE1) agentE1 := mustCreateAgent(t, db, wbE1)
mustCreateAgentLogs(ctx, t, db, agentE1, nil, "agent e1 logs should be retained") mustCreateAgentLogs(ctx, t, db, agentE1, nil, "agent e1 logs should be retained")
+2 -2
View File
@@ -64,7 +64,7 @@ func TestRollup_TwoInstancesUseLocking(t *testing.T) {
user = dbgen.User(t, db, database.User{Name: "user1"}) user = dbgen.User(t, db, database.User{Name: "user1"})
tpl = dbgen.Template(t, db, database.Template{OrganizationID: org.ID, CreatedBy: user.ID}) tpl = dbgen.Template(t, db, database.Template{OrganizationID: org.ID, CreatedBy: user.ID})
ver = dbgen.TemplateVersion(t, db, database.TemplateVersion{OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, CreatedBy: user.ID}) ver = dbgen.TemplateVersion(t, db, database.TemplateVersion{OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, CreatedBy: user.ID})
ws = dbgen.Workspace(t, db, database.Workspace{OrganizationID: org.ID, TemplateID: tpl.ID, OwnerID: user.ID}) ws = dbgen.Workspace(t, db, database.WorkspaceTable{OrganizationID: org.ID, TemplateID: tpl.ID, OwnerID: user.ID})
job = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID}) job = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID})
build = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: job.ID, TemplateVersionID: ver.ID}) build = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: job.ID, TemplateVersionID: ver.ID})
res = dbgen.WorkspaceResource(t, db, database.WorkspaceResource{JobID: build.JobID}) res = dbgen.WorkspaceResource(t, db, database.WorkspaceResource{JobID: build.JobID})
@@ -151,7 +151,7 @@ func TestRollupTemplateUsageStats(t *testing.T) {
user = dbgen.User(t, db, database.User{Name: "user1"}) user = dbgen.User(t, db, database.User{Name: "user1"})
tpl = dbgen.Template(t, db, database.Template{OrganizationID: org.ID, CreatedBy: user.ID}) tpl = dbgen.Template(t, db, database.Template{OrganizationID: org.ID, CreatedBy: user.ID})
ver = dbgen.TemplateVersion(t, db, database.TemplateVersion{OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, CreatedBy: user.ID}) ver = dbgen.TemplateVersion(t, db, database.TemplateVersion{OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, CreatedBy: user.ID})
ws = dbgen.Workspace(t, db, database.Workspace{OrganizationID: org.ID, TemplateID: tpl.ID, OwnerID: user.ID}) ws = dbgen.Workspace(t, db, database.WorkspaceTable{OrganizationID: org.ID, TemplateID: tpl.ID, OwnerID: user.ID})
job = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID}) job = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID})
build = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: job.ID, TemplateVersionID: ver.ID}) build = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: job.ID, TemplateVersionID: ver.ID})
res = dbgen.WorkspaceResource(t, db, database.WorkspaceResource{JobID: build.JobID}) res = dbgen.WorkspaceResource(t, db, database.WorkspaceResource{JobID: build.JobID})
+33
View File
@@ -1701,6 +1701,39 @@ CREATE TABLE workspaces (
COMMENT ON COLUMN workspaces.favorite IS 'Favorite is true if the workspace owner has favorited the workspace.'; COMMENT ON COLUMN workspaces.favorite IS 'Favorite is true if the workspace owner has favorited the workspace.';
CREATE VIEW workspaces_expanded AS
SELECT workspaces.id,
workspaces.created_at,
workspaces.updated_at,
workspaces.owner_id,
workspaces.organization_id,
workspaces.template_id,
workspaces.deleted,
workspaces.name,
workspaces.autostart_schedule,
workspaces.ttl,
workspaces.last_used_at,
workspaces.dormant_at,
workspaces.deleting_at,
workspaces.automatic_updates,
workspaces.favorite,
visible_users.avatar_url AS owner_avatar_url,
visible_users.username AS owner_username,
organizations.name AS organization_name,
organizations.display_name AS organization_display_name,
organizations.icon AS organization_icon,
organizations.description AS organization_description,
templates.name AS template_name,
templates.display_name AS template_display_name,
templates.icon AS template_icon,
templates.description AS template_description
FROM (((workspaces
JOIN visible_users ON ((workspaces.owner_id = visible_users.id)))
JOIN organizations ON ((workspaces.organization_id = organizations.id)))
JOIN templates ON ((workspaces.template_id = templates.id)));
COMMENT ON VIEW workspaces_expanded IS 'Joins in the display name information such as username, avatar, and organization name.';
ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('licenses_id_seq'::regclass); ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('licenses_id_seq'::regclass);
ALTER TABLE ONLY provisioner_job_logs ALTER COLUMN id SET DEFAULT nextval('provisioner_job_logs_id_seq'::regclass); ALTER TABLE ONLY provisioner_job_logs ALTER COLUMN id SET DEFAULT nextval('provisioner_job_logs_id_seq'::regclass);
+14
View File
@@ -65,6 +65,20 @@ func TestViewSubsetWorkspaceBuild(t *testing.T) {
} }
} }
// TestViewSubsetWorkspace ensures WorkspaceTable is a subset of Workspace
func TestViewSubsetWorkspace(t *testing.T) {
t.Parallel()
table := reflect.TypeOf(database.WorkspaceTable{})
joined := reflect.TypeOf(database.Workspace{})
tableFields := allFields(table)
joinedFields := allFields(joined)
if !assert.Subset(t, fieldNames(joinedFields), fieldNames(tableFields), "table is not subset") {
t.Log("Some fields were added to the Workspace Table without updating the 'workspaces_expanded' view.")
t.Log("See migration 000262_workspace_with_names.up.sql to create the view.")
}
}
func fieldNames(fields []reflect.StructField) []string { func fieldNames(fields []reflect.StructField) []string {
names := make([]string, len(fields)) names := make([]string, len(fields))
for i, field := range fields { for i, field := range fields {
@@ -0,0 +1 @@
DROP VIEW workspaces_expanded;
@@ -0,0 +1,33 @@
CREATE VIEW
workspaces_expanded
AS
SELECT
workspaces.*,
-- Owner
visible_users.avatar_url AS owner_avatar_url,
visible_users.username AS owner_username,
-- Organization
organizations.name AS organization_name,
organizations.display_name AS organization_display_name,
organizations.icon AS organization_icon,
organizations.description AS organization_description,
-- Template
templates.name AS template_name,
templates.display_name AS template_display_name,
templates.icon AS template_icon,
templates.description AS template_description
FROM
workspaces
INNER JOIN
visible_users
ON
workspaces.owner_id = visible_users.id
INNER JOIN
organizations
ON workspaces.organization_id = organizations.id
INNER JOIN
templates
ON workspaces.template_id = templates.id
;
COMMENT ON VIEW workspaces_expanded IS 'Joins in the display name information such as username, avatar, and organization name.';
+53 -19
View File
@@ -192,12 +192,36 @@ func (gm GroupMember) RBACObject() rbac.Object {
return rbac.ResourceGroupMember.WithID(gm.UserID).InOrg(gm.OrganizationID).WithOwner(gm.UserID.String()) return rbac.ResourceGroupMember.WithID(gm.UserID).InOrg(gm.OrganizationID).WithOwner(gm.UserID.String())
} }
func (w GetWorkspaceByAgentIDRow) RBACObject() rbac.Object { // WorkspaceTable converts a Workspace to it's reduced version.
return w.Workspace.RBACObject() // A more generalized solution is to use json marshaling to
// consistently keep these two structs in sync.
// That would be a lot of overhead, and a more costly unit test is
// written to make sure these match up.
func (w Workspace) WorkspaceTable() WorkspaceTable {
return WorkspaceTable{
ID: w.ID,
CreatedAt: w.CreatedAt,
UpdatedAt: w.UpdatedAt,
OwnerID: w.OwnerID,
OrganizationID: w.OrganizationID,
TemplateID: w.TemplateID,
Deleted: w.Deleted,
Name: w.Name,
AutostartSchedule: w.AutostartSchedule,
Ttl: w.Ttl,
LastUsedAt: w.LastUsedAt,
DormantAt: w.DormantAt,
DeletingAt: w.DeletingAt,
AutomaticUpdates: w.AutomaticUpdates,
Favorite: w.Favorite,
}
} }
func (w Workspace) RBACObject() rbac.Object { func (w Workspace) RBACObject() rbac.Object {
// If a workspace is locked it cannot be accessed. return w.WorkspaceTable().RBACObject()
}
func (w WorkspaceTable) RBACObject() rbac.Object {
if w.DormantAt.Valid { if w.DormantAt.Valid {
return w.DormantRBAC() return w.DormantRBAC()
} }
@@ -207,7 +231,7 @@ func (w Workspace) RBACObject() rbac.Object {
WithOwner(w.OwnerID.String()) WithOwner(w.OwnerID.String())
} }
func (w Workspace) DormantRBAC() rbac.Object { func (w WorkspaceTable) DormantRBAC() rbac.Object {
return rbac.ResourceWorkspaceDormant. return rbac.ResourceWorkspaceDormant.
WithID(w.ID). WithID(w.ID).
InOrg(w.OrganizationID). InOrg(w.OrganizationID).
@@ -389,21 +413,31 @@ func ConvertWorkspaceRows(rows []GetWorkspacesRow) []Workspace {
workspaces := make([]Workspace, len(rows)) workspaces := make([]Workspace, len(rows))
for i, r := range rows { for i, r := range rows {
workspaces[i] = Workspace{ workspaces[i] = Workspace{
ID: r.ID, ID: r.ID,
CreatedAt: r.CreatedAt, CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt, UpdatedAt: r.UpdatedAt,
OwnerID: r.OwnerID, OwnerID: r.OwnerID,
OrganizationID: r.OrganizationID, OrganizationID: r.OrganizationID,
TemplateID: r.TemplateID, TemplateID: r.TemplateID,
Deleted: r.Deleted, Deleted: r.Deleted,
Name: r.Name, Name: r.Name,
AutostartSchedule: r.AutostartSchedule, AutostartSchedule: r.AutostartSchedule,
Ttl: r.Ttl, Ttl: r.Ttl,
LastUsedAt: r.LastUsedAt, LastUsedAt: r.LastUsedAt,
DormantAt: r.DormantAt, DormantAt: r.DormantAt,
DeletingAt: r.DeletingAt, DeletingAt: r.DeletingAt,
AutomaticUpdates: r.AutomaticUpdates, AutomaticUpdates: r.AutomaticUpdates,
Favorite: r.Favorite, Favorite: r.Favorite,
OwnerAvatarUrl: r.OwnerAvatarUrl,
OwnerUsername: r.OwnerUsername,
OrganizationName: r.OrganizationName,
OrganizationDisplayName: r.OrganizationDisplayName,
OrganizationIcon: r.OrganizationIcon,
OrganizationDescription: r.OrganizationDescription,
TemplateName: r.TemplateName,
TemplateDisplayName: r.TemplateDisplayName,
TemplateIcon: r.TemplateIcon,
TemplateDescription: r.TemplateDescription,
} }
} }
+9 -1
View File
@@ -288,10 +288,18 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
&i.DeletingAt, &i.DeletingAt,
&i.AutomaticUpdates, &i.AutomaticUpdates,
&i.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName, &i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
&i.TemplateVersionID, &i.TemplateVersionID,
&i.TemplateVersionName, &i.TemplateVersionName,
&i.Username,
&i.LatestBuildCompletedAt, &i.LatestBuildCompletedAt,
&i.LatestBuildCanceledAt, &i.LatestBuildCanceledAt,
&i.LatestBuildError, &i.LatestBuildError,
@@ -2,8 +2,11 @@ package database
import ( import (
"testing" "testing"
"time"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coder/coder/v2/testutil"
) )
func TestIsAuthorizedQuery(t *testing.T) { func TestIsAuthorizedQuery(t *testing.T) {
@@ -13,3 +16,41 @@ func TestIsAuthorizedQuery(t *testing.T) {
_, err := insertAuthorizedFilter(query, "") _, err := insertAuthorizedFilter(query, "")
require.ErrorContains(t, err, "does not contain authorized replace string", "ensure replace string") require.ErrorContains(t, err, "does not contain authorized replace string", "ensure replace string")
} }
// TestWorkspaceTableConvert verifies all workspace fields are converted
// when reducing a `Workspace` to a `WorkspaceTable`.
// This test is a guard rail to prevent developer oversight mistakes.
func TestWorkspaceTableConvert(t *testing.T) {
t.Parallel()
staticRandoms := &testutil.Random{
String: func() string { return "foo" },
Bool: func() bool { return true },
Int: func() int64 { return 500 },
Uint: func() uint64 { return 126 },
Float: func() float64 { return 3.14 },
Complex: func() complex128 { return 6.24 },
Time: func() time.Time {
return time.Date(2020, 5, 2, 5, 19, 21, 30, time.UTC)
},
}
// This feels a bit janky, but it works.
// If you use 'PopulateStruct' to create 2 workspaces, using the same
// "random" values for each type. Then they should be identical.
//
// So if 'workspace.WorkspaceTable()' was missing any fields in its
// conversion, the comparison would fail.
var workspace Workspace
err := testutil.PopulateStruct(&workspace, staticRandoms)
require.NoError(t, err)
var subset WorkspaceTable
err = testutil.PopulateStruct(&subset, staticRandoms)
require.NoError(t, err)
require.Equal(t, workspace.WorkspaceTable(), subset,
"'workspace.WorkspaceTable()' is not missing at least 1 field when converting to 'WorkspaceTable'. "+
"To resolve this, go to the 'func (w Workspace) WorkspaceTable()' and ensure all fields are converted.")
}
+45 -16
View File
@@ -2902,23 +2902,33 @@ type VisibleUser struct {
AvatarURL string `db:"avatar_url" json:"avatar_url"` AvatarURL string `db:"avatar_url" json:"avatar_url"`
} }
// Joins in the display name information such as username, avatar, and organization name.
type Workspace struct { type Workspace struct {
ID uuid.UUID `db:"id" json:"id"` ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"` OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
TemplateID uuid.UUID `db:"template_id" json:"template_id"` TemplateID uuid.UUID `db:"template_id" json:"template_id"`
Deleted bool `db:"deleted" json:"deleted"` Deleted bool `db:"deleted" json:"deleted"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"` AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"`
Ttl sql.NullInt64 `db:"ttl" json:"ttl"` Ttl sql.NullInt64 `db:"ttl" json:"ttl"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"` LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"` DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"` DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"` AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
// Favorite is true if the workspace owner has favorited the workspace. Favorite bool `db:"favorite" json:"favorite"`
Favorite bool `db:"favorite" json:"favorite"` OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OrganizationName string `db:"organization_name" json:"organization_name"`
OrganizationDisplayName string `db:"organization_display_name" json:"organization_display_name"`
OrganizationIcon string `db:"organization_icon" json:"organization_icon"`
OrganizationDescription string `db:"organization_description" json:"organization_description"`
TemplateName string `db:"template_name" json:"template_name"`
TemplateDisplayName string `db:"template_display_name" json:"template_display_name"`
TemplateIcon string `db:"template_icon" json:"template_icon"`
TemplateDescription string `db:"template_description" json:"template_description"`
} }
type WorkspaceAgent struct { type WorkspaceAgent struct {
@@ -3184,3 +3194,22 @@ type WorkspaceResourceMetadatum struct {
Sensitive bool `db:"sensitive" json:"sensitive"` Sensitive bool `db:"sensitive" json:"sensitive"`
ID int64 `db:"id" json:"id"` ID int64 `db:"id" json:"id"`
} }
type WorkspaceTable struct {
ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
Deleted bool `db:"deleted" json:"deleted"`
Name string `db:"name" json:"name"`
AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"`
Ttl sql.NullInt64 `db:"ttl" json:"ttl"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
// Favorite is true if the workspace owner has favorited the workspace.
Favorite bool `db:"favorite" json:"favorite"`
}
+6 -6
View File
@@ -319,7 +319,7 @@ type sqlcQuerier interface {
GetWorkspaceBuildStatsByTemplates(ctx context.Context, since time.Time) ([]GetWorkspaceBuildStatsByTemplatesRow, error) GetWorkspaceBuildStatsByTemplates(ctx context.Context, since time.Time) ([]GetWorkspaceBuildStatsByTemplatesRow, error)
GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildsByWorkspaceIDParams) ([]WorkspaceBuild, error) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildsByWorkspaceIDParams) ([]WorkspaceBuild, error)
GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error)
GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (GetWorkspaceByAgentIDRow, error) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (Workspace, error)
GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Workspace, error) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Workspace, error)
GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (Workspace, error) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (Workspace, error)
GetWorkspaceByWorkspaceAppID(ctx context.Context, workspaceAppID uuid.UUID) (Workspace, error) GetWorkspaceByWorkspaceAppID(ctx context.Context, workspaceAppID uuid.UUID) (Workspace, error)
@@ -345,7 +345,7 @@ type sqlcQuerier interface {
// It has to be a CTE because the set returning function 'unnest' cannot // It has to be a CTE because the set returning function 'unnest' cannot
// be used in a WHERE clause. // be used in a WHERE clause.
GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) ([]GetWorkspacesRow, error) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) ([]GetWorkspacesRow, error)
GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]Workspace, error) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]WorkspaceTable, error)
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error) InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
// We use the organization_id as the id // We use the organization_id as the id
// for simplicity since all users is // for simplicity since all users is
@@ -391,7 +391,7 @@ type sqlcQuerier interface {
// InsertUserGroupsByName adds a user to all provided groups, if they exist. // InsertUserGroupsByName adds a user to all provided groups, if they exist.
InsertUserGroupsByName(ctx context.Context, arg InsertUserGroupsByNameParams) error InsertUserGroupsByName(ctx context.Context, arg InsertUserGroupsByNameParams) error
InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error) InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error)
InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error) InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (WorkspaceTable, error)
InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error) InsertWorkspaceAgent(ctx context.Context, arg InsertWorkspaceAgentParams) (WorkspaceAgent, error)
InsertWorkspaceAgentLogSources(ctx context.Context, arg InsertWorkspaceAgentLogSourcesParams) ([]WorkspaceAgentLogSource, error) InsertWorkspaceAgentLogSources(ctx context.Context, arg InsertWorkspaceAgentLogSourcesParams) ([]WorkspaceAgentLogSource, error)
InsertWorkspaceAgentLogs(ctx context.Context, arg InsertWorkspaceAgentLogsParams) ([]WorkspaceAgentLog, error) InsertWorkspaceAgentLogs(ctx context.Context, arg InsertWorkspaceAgentLogsParams) ([]WorkspaceAgentLog, error)
@@ -469,7 +469,7 @@ type sqlcQuerier interface {
UpdateUserQuietHoursSchedule(ctx context.Context, arg UpdateUserQuietHoursScheduleParams) (User, error) UpdateUserQuietHoursSchedule(ctx context.Context, arg UpdateUserQuietHoursScheduleParams) (User, error)
UpdateUserRoles(ctx context.Context, arg UpdateUserRolesParams) (User, error) UpdateUserRoles(ctx context.Context, arg UpdateUserRolesParams) (User, error)
UpdateUserStatus(ctx context.Context, arg UpdateUserStatusParams) (User, error) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusParams) (User, error)
UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (Workspace, error) UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (WorkspaceTable, error)
UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg UpdateWorkspaceAgentConnectionByIDParams) error UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg UpdateWorkspaceAgentConnectionByIDParams) error
UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context, arg UpdateWorkspaceAgentLifecycleStateByIDParams) error UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context, arg UpdateWorkspaceAgentLifecycleStateByIDParams) error
UpdateWorkspaceAgentLogOverflowByID(ctx context.Context, arg UpdateWorkspaceAgentLogOverflowByIDParams) error UpdateWorkspaceAgentLogOverflowByID(ctx context.Context, arg UpdateWorkspaceAgentLogOverflowByIDParams) error
@@ -482,13 +482,13 @@ type sqlcQuerier interface {
UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg UpdateWorkspaceBuildDeadlineByIDParams) error UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg UpdateWorkspaceBuildDeadlineByIDParams) error
UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg UpdateWorkspaceBuildProvisionerStateByIDParams) error UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg UpdateWorkspaceBuildProvisionerStateByIDParams) error
UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error
UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg UpdateWorkspaceDormantDeletingAtParams) (Workspace, error) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg UpdateWorkspaceDormantDeletingAtParams) (WorkspaceTable, error)
UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error
// This allows editing the properties of a workspace proxy. // This allows editing the properties of a workspace proxy.
UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error) UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error)
UpdateWorkspaceProxyDeleted(ctx context.Context, arg UpdateWorkspaceProxyDeletedParams) error UpdateWorkspaceProxyDeleted(ctx context.Context, arg UpdateWorkspaceProxyDeletedParams) error
UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspaceTTLParams) error UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspaceTTLParams) error
UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]Workspace, error) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]WorkspaceTable, error)
UpsertAnnouncementBanners(ctx context.Context, value string) error UpsertAnnouncementBanners(ctx context.Context, value string) error
UpsertAppSecurityKey(ctx context.Context, value string) error UpsertAppSecurityKey(ctx context.Context, value string) error
UpsertApplicationName(ctx context.Context, value string) error UpsertApplicationName(ctx context.Context, value string) error
+4 -4
View File
@@ -416,7 +416,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
OrganizationID: org.ID, OrganizationID: org.ID,
CreatedBy: user1.ID, CreatedBy: user1.ID,
}) })
workspace1 := dbgen.Workspace(t, db, database.Workspace{ workspace1 := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user1.ID, OwnerID: user1.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template1.ID, TemplateID: template1.ID,
@@ -435,7 +435,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
CreatedBy: user1.ID, CreatedBy: user1.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
}) })
workspace2 := dbgen.Workspace(t, db, database.Workspace{ workspace2 := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user2.ID, OwnerID: user2.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template2.ID, TemplateID: template2.ID,
@@ -577,7 +577,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
OrganizationID: org.ID, OrganizationID: org.ID,
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -1596,7 +1596,7 @@ func createTemplateVersion(t testing.TB, db database.Store, tpl database.Templat
dbgen.ProvisionerJob(t, db, nil, j) dbgen.ProvisionerJob(t, db, nil, j)
if args.CreateWorkspace { if args.CreateWorkspace {
wrk := dbgen.Workspace(t, db, database.Workspace{ wrk := dbgen.Workspace(t, db, database.WorkspaceTable{
CreatedAt: time.Time{}, CreatedAt: time.Time{},
UpdatedAt: time.Time{}, UpdatedAt: time.Time{},
OwnerID: tpl.CreatedBy, OwnerID: tpl.CreatedBy,
+151 -98
View File
@@ -11117,7 +11117,7 @@ WHERE
` `
type GetWorkspaceAgentAndLatestBuildByAuthTokenRow struct { type GetWorkspaceAgentAndLatestBuildByAuthTokenRow struct {
Workspace Workspace `db:"workspace" json:"workspace"` WorkspaceTable WorkspaceTable `db:"workspace_table" json:"workspace_table"`
WorkspaceAgent WorkspaceAgent `db:"workspace_agent" json:"workspace_agent"` WorkspaceAgent WorkspaceAgent `db:"workspace_agent" json:"workspace_agent"`
WorkspaceBuild WorkspaceBuild `db:"workspace_build" json:"workspace_build"` WorkspaceBuild WorkspaceBuild `db:"workspace_build" json:"workspace_build"`
} }
@@ -11126,21 +11126,21 @@ func (q *sqlQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(ctx context.Cont
row := q.db.QueryRowContext(ctx, getWorkspaceAgentAndLatestBuildByAuthToken, authToken) row := q.db.QueryRowContext(ctx, getWorkspaceAgentAndLatestBuildByAuthToken, authToken)
var i GetWorkspaceAgentAndLatestBuildByAuthTokenRow var i GetWorkspaceAgentAndLatestBuildByAuthTokenRow
err := row.Scan( err := row.Scan(
&i.Workspace.ID, &i.WorkspaceTable.ID,
&i.Workspace.CreatedAt, &i.WorkspaceTable.CreatedAt,
&i.Workspace.UpdatedAt, &i.WorkspaceTable.UpdatedAt,
&i.Workspace.OwnerID, &i.WorkspaceTable.OwnerID,
&i.Workspace.OrganizationID, &i.WorkspaceTable.OrganizationID,
&i.Workspace.TemplateID, &i.WorkspaceTable.TemplateID,
&i.Workspace.Deleted, &i.WorkspaceTable.Deleted,
&i.Workspace.Name, &i.WorkspaceTable.Name,
&i.Workspace.AutostartSchedule, &i.WorkspaceTable.AutostartSchedule,
&i.Workspace.Ttl, &i.WorkspaceTable.Ttl,
&i.Workspace.LastUsedAt, &i.WorkspaceTable.LastUsedAt,
&i.Workspace.DormantAt, &i.WorkspaceTable.DormantAt,
&i.Workspace.DeletingAt, &i.WorkspaceTable.DeletingAt,
&i.Workspace.AutomaticUpdates, &i.WorkspaceTable.AutomaticUpdates,
&i.Workspace.Favorite, &i.WorkspaceTable.Favorite,
&i.WorkspaceAgent.ID, &i.WorkspaceAgent.ID,
&i.WorkspaceAgent.CreatedAt, &i.WorkspaceAgent.CreatedAt,
&i.WorkspaceAgent.UpdatedAt, &i.WorkspaceAgent.UpdatedAt,
@@ -14539,12 +14539,9 @@ func (q *sqlQuerier) GetDeploymentWorkspaceStats(ctx context.Context) (GetDeploy
const getWorkspaceByAgentID = `-- name: GetWorkspaceByAgentID :one const getWorkspaceByAgentID = `-- name: GetWorkspaceByAgentID :one
SELECT SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite, owner_avatar_url, owner_username, organization_name, organization_display_name, organization_icon, organization_description, template_name, template_display_name, template_icon, template_description
templates.name as template_name
FROM FROM
workspaces workspaces_expanded as workspaces
INNER JOIN
templates ON workspaces.template_id = templates.id
WHERE WHERE
workspaces.id = ( workspaces.id = (
SELECT SELECT
@@ -14570,40 +14567,44 @@ WHERE
) )
` `
type GetWorkspaceByAgentIDRow struct { func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (Workspace, error) {
Workspace Workspace `db:"workspace" json:"workspace"`
TemplateName string `db:"template_name" json:"template_name"`
}
func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (GetWorkspaceByAgentIDRow, error) {
row := q.db.QueryRowContext(ctx, getWorkspaceByAgentID, agentID) row := q.db.QueryRowContext(ctx, getWorkspaceByAgentID, agentID)
var i GetWorkspaceByAgentIDRow var i Workspace
err := row.Scan( err := row.Scan(
&i.Workspace.ID, &i.ID,
&i.Workspace.CreatedAt, &i.CreatedAt,
&i.Workspace.UpdatedAt, &i.UpdatedAt,
&i.Workspace.OwnerID, &i.OwnerID,
&i.Workspace.OrganizationID, &i.OrganizationID,
&i.Workspace.TemplateID, &i.TemplateID,
&i.Workspace.Deleted, &i.Deleted,
&i.Workspace.Name, &i.Name,
&i.Workspace.AutostartSchedule, &i.AutostartSchedule,
&i.Workspace.Ttl, &i.Ttl,
&i.Workspace.LastUsedAt, &i.LastUsedAt,
&i.Workspace.DormantAt, &i.DormantAt,
&i.Workspace.DeletingAt, &i.DeletingAt,
&i.Workspace.AutomaticUpdates, &i.AutomaticUpdates,
&i.Workspace.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName, &i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
) )
return i, err return i, err
} }
const getWorkspaceByID = `-- name: GetWorkspaceByID :one const getWorkspaceByID = `-- name: GetWorkspaceByID :one
SELECT SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite, owner_avatar_url, owner_username, organization_name, organization_display_name, organization_icon, organization_description, template_name, template_display_name, template_icon, template_description
FROM FROM
workspaces workspaces_expanded
WHERE WHERE
id = $1 id = $1
LIMIT LIMIT
@@ -14629,15 +14630,25 @@ func (q *sqlQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Worksp
&i.DeletingAt, &i.DeletingAt,
&i.AutomaticUpdates, &i.AutomaticUpdates,
&i.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
) )
return i, err return i, err
} }
const getWorkspaceByOwnerIDAndName = `-- name: GetWorkspaceByOwnerIDAndName :one const getWorkspaceByOwnerIDAndName = `-- name: GetWorkspaceByOwnerIDAndName :one
SELECT SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite, owner_avatar_url, owner_username, organization_name, organization_display_name, organization_icon, organization_description, template_name, template_display_name, template_icon, template_description
FROM FROM
workspaces workspaces_expanded as workspaces
WHERE WHERE
owner_id = $1 owner_id = $1
AND deleted = $2 AND deleted = $2
@@ -14670,15 +14681,25 @@ func (q *sqlQuerier) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWo
&i.DeletingAt, &i.DeletingAt,
&i.AutomaticUpdates, &i.AutomaticUpdates,
&i.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
) )
return i, err return i, err
} }
const getWorkspaceByWorkspaceAppID = `-- name: GetWorkspaceByWorkspaceAppID :one const getWorkspaceByWorkspaceAppID = `-- name: GetWorkspaceByWorkspaceAppID :one
SELECT SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite, owner_avatar_url, owner_username, organization_name, organization_display_name, organization_icon, organization_description, template_name, template_display_name, template_icon, template_description
FROM FROM
workspaces workspaces_expanded as workspaces
WHERE WHERE
workspaces.id = ( workspaces.id = (
SELECT SELECT
@@ -14730,6 +14751,16 @@ func (q *sqlQuerier) GetWorkspaceByWorkspaceAppID(ctx context.Context, workspace
&i.DeletingAt, &i.DeletingAt,
&i.AutomaticUpdates, &i.AutomaticUpdates,
&i.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
) )
return i, err return i, err
} }
@@ -14781,18 +14812,16 @@ SELECT
), ),
filtered_workspaces AS ( filtered_workspaces AS (
SELECT SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, workspaces.owner_avatar_url, workspaces.owner_username, workspaces.organization_name, workspaces.organization_display_name, workspaces.organization_icon, workspaces.organization_description, workspaces.template_name, workspaces.template_display_name, workspaces.template_icon, workspaces.template_description,
COALESCE(template.name, 'unknown') as template_name,
latest_build.template_version_id, latest_build.template_version_id,
latest_build.template_version_name, latest_build.template_version_name,
users.username as username,
latest_build.completed_at as latest_build_completed_at, latest_build.completed_at as latest_build_completed_at,
latest_build.canceled_at as latest_build_canceled_at, latest_build.canceled_at as latest_build_canceled_at,
latest_build.error as latest_build_error, latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition, latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status latest_build.job_status as latest_build_status
FROM FROM
workspaces workspaces_expanded as workspaces
JOIN JOIN
users users
ON ON
@@ -14931,7 +14960,7 @@ WHERE
-- Filter by owner_name -- Filter by owner_name
AND CASE AND CASE
WHEN $8 :: text != '' THEN WHEN $8 :: text != '' THEN
workspaces.owner_id = (SELECT id FROM users WHERE lower(username) = lower($8) AND deleted = false) workspaces.owner_id = (SELECT id FROM users WHERE lower(owner_username) = lower($8) AND deleted = false)
ELSE true ELSE true
END END
-- Filter by template_name -- Filter by template_name
@@ -15023,7 +15052,7 @@ WHERE
-- @authorize_filter -- @authorize_filter
), filtered_workspaces_order AS ( ), filtered_workspaces_order AS (
SELECT SELECT
fw.id, fw.created_at, fw.updated_at, fw.owner_id, fw.organization_id, fw.template_id, fw.deleted, fw.name, fw.autostart_schedule, fw.ttl, fw.last_used_at, fw.dormant_at, fw.deleting_at, fw.automatic_updates, fw.favorite, fw.template_name, fw.template_version_id, fw.template_version_name, fw.username, fw.latest_build_completed_at, fw.latest_build_canceled_at, fw.latest_build_error, fw.latest_build_transition, fw.latest_build_status fw.id, fw.created_at, fw.updated_at, fw.owner_id, fw.organization_id, fw.template_id, fw.deleted, fw.name, fw.autostart_schedule, fw.ttl, fw.last_used_at, fw.dormant_at, fw.deleting_at, fw.automatic_updates, fw.favorite, fw.owner_avatar_url, fw.owner_username, fw.organization_name, fw.organization_display_name, fw.organization_icon, fw.organization_description, fw.template_name, fw.template_display_name, fw.template_icon, fw.template_description, fw.template_version_id, fw.template_version_name, fw.latest_build_completed_at, fw.latest_build_canceled_at, fw.latest_build_error, fw.latest_build_transition, fw.latest_build_status
FROM FROM
filtered_workspaces fw filtered_workspaces fw
ORDER BY ORDER BY
@@ -15033,7 +15062,7 @@ WHERE
latest_build_canceled_at IS NULL AND latest_build_canceled_at IS NULL AND
latest_build_error IS NULL AND latest_build_error IS NULL AND
latest_build_transition = 'start'::workspace_transition) DESC, latest_build_transition = 'start'::workspace_transition) DESC,
LOWER(username) ASC, LOWER(owner_username) ASC,
LOWER(name) ASC LOWER(name) ASC
LIMIT LIMIT
CASE CASE
@@ -15044,7 +15073,7 @@ WHERE
$20 $20
), filtered_workspaces_order_with_summary AS ( ), filtered_workspaces_order_with_summary AS (
SELECT SELECT
fwo.id, fwo.created_at, fwo.updated_at, fwo.owner_id, fwo.organization_id, fwo.template_id, fwo.deleted, fwo.name, fwo.autostart_schedule, fwo.ttl, fwo.last_used_at, fwo.dormant_at, fwo.deleting_at, fwo.automatic_updates, fwo.favorite, fwo.template_name, fwo.template_version_id, fwo.template_version_name, fwo.username, fwo.latest_build_completed_at, fwo.latest_build_canceled_at, fwo.latest_build_error, fwo.latest_build_transition, fwo.latest_build_status fwo.id, fwo.created_at, fwo.updated_at, fwo.owner_id, fwo.organization_id, fwo.template_id, fwo.deleted, fwo.name, fwo.autostart_schedule, fwo.ttl, fwo.last_used_at, fwo.dormant_at, fwo.deleting_at, fwo.automatic_updates, fwo.favorite, fwo.owner_avatar_url, fwo.owner_username, fwo.organization_name, fwo.organization_display_name, fwo.organization_icon, fwo.organization_description, fwo.template_name, fwo.template_display_name, fwo.template_icon, fwo.template_description, fwo.template_version_id, fwo.template_version_name, fwo.latest_build_completed_at, fwo.latest_build_canceled_at, fwo.latest_build_error, fwo.latest_build_transition, fwo.latest_build_status
FROM FROM
filtered_workspaces_order fwo filtered_workspaces_order fwo
-- Return a technical summary row with total count of workspaces. -- Return a technical summary row with total count of workspaces.
@@ -15066,11 +15095,19 @@ WHERE
'0001-01-01 00:00:00+00'::timestamptz, -- deleting_at '0001-01-01 00:00:00+00'::timestamptz, -- deleting_at
'never'::automatic_updates, -- automatic_updates 'never'::automatic_updates, -- automatic_updates
false, -- favorite false, -- favorite
-- Extra columns added to ` + "`" + `filtered_workspaces` + "`" + ` '', -- owner_avatar_url
'', -- owner_username
'', -- organization_name
'', -- organization_display_name
'', -- organization_icon
'', -- organization_description
'', -- template_name '', -- template_name
'', -- template_display_name
'', -- template_icon
'', -- template_description
-- Extra columns added to ` + "`" + `filtered_workspaces` + "`" + `
'00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id '00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id
'', -- template_version_name '', -- template_version_name
'', -- username
'0001-01-01 00:00:00+00'::timestamptz, -- latest_build_completed_at, '0001-01-01 00:00:00+00'::timestamptz, -- latest_build_completed_at,
'0001-01-01 00:00:00+00'::timestamptz, -- latest_build_canceled_at, '0001-01-01 00:00:00+00'::timestamptz, -- latest_build_canceled_at,
'', -- latest_build_error '', -- latest_build_error
@@ -15085,7 +15122,7 @@ WHERE
filtered_workspaces filtered_workspaces
) )
SELECT SELECT
fwos.id, fwos.created_at, fwos.updated_at, fwos.owner_id, fwos.organization_id, fwos.template_id, fwos.deleted, fwos.name, fwos.autostart_schedule, fwos.ttl, fwos.last_used_at, fwos.dormant_at, fwos.deleting_at, fwos.automatic_updates, fwos.favorite, fwos.template_name, fwos.template_version_id, fwos.template_version_name, fwos.username, fwos.latest_build_completed_at, fwos.latest_build_canceled_at, fwos.latest_build_error, fwos.latest_build_transition, fwos.latest_build_status, fwos.id, fwos.created_at, fwos.updated_at, fwos.owner_id, fwos.organization_id, fwos.template_id, fwos.deleted, fwos.name, fwos.autostart_schedule, fwos.ttl, fwos.last_used_at, fwos.dormant_at, fwos.deleting_at, fwos.automatic_updates, fwos.favorite, fwos.owner_avatar_url, fwos.owner_username, fwos.organization_name, fwos.organization_display_name, fwos.organization_icon, fwos.organization_description, fwos.template_name, fwos.template_display_name, fwos.template_icon, fwos.template_description, fwos.template_version_id, fwos.template_version_name, fwos.latest_build_completed_at, fwos.latest_build_canceled_at, fwos.latest_build_error, fwos.latest_build_transition, fwos.latest_build_status,
tc.count tc.count
FROM FROM
filtered_workspaces_order_with_summary fwos filtered_workspaces_order_with_summary fwos
@@ -15119,31 +15156,39 @@ type GetWorkspacesParams struct {
} }
type GetWorkspacesRow struct { type GetWorkspacesRow struct {
ID uuid.UUID `db:"id" json:"id"` ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"` OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
TemplateID uuid.UUID `db:"template_id" json:"template_id"` TemplateID uuid.UUID `db:"template_id" json:"template_id"`
Deleted bool `db:"deleted" json:"deleted"` Deleted bool `db:"deleted" json:"deleted"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"` AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"`
Ttl sql.NullInt64 `db:"ttl" json:"ttl"` Ttl sql.NullInt64 `db:"ttl" json:"ttl"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"` LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"` DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"` DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"` AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
Favorite bool `db:"favorite" json:"favorite"` Favorite bool `db:"favorite" json:"favorite"`
TemplateName string `db:"template_name" json:"template_name"` OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"` OwnerUsername string `db:"owner_username" json:"owner_username"`
TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"` OrganizationName string `db:"organization_name" json:"organization_name"`
Username string `db:"username" json:"username"` OrganizationDisplayName string `db:"organization_display_name" json:"organization_display_name"`
LatestBuildCompletedAt sql.NullTime `db:"latest_build_completed_at" json:"latest_build_completed_at"` OrganizationIcon string `db:"organization_icon" json:"organization_icon"`
LatestBuildCanceledAt sql.NullTime `db:"latest_build_canceled_at" json:"latest_build_canceled_at"` OrganizationDescription string `db:"organization_description" json:"organization_description"`
LatestBuildError sql.NullString `db:"latest_build_error" json:"latest_build_error"` TemplateName string `db:"template_name" json:"template_name"`
LatestBuildTransition WorkspaceTransition `db:"latest_build_transition" json:"latest_build_transition"` TemplateDisplayName string `db:"template_display_name" json:"template_display_name"`
LatestBuildStatus ProvisionerJobStatus `db:"latest_build_status" json:"latest_build_status"` TemplateIcon string `db:"template_icon" json:"template_icon"`
Count int64 `db:"count" json:"count"` TemplateDescription string `db:"template_description" json:"template_description"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"`
LatestBuildCompletedAt sql.NullTime `db:"latest_build_completed_at" json:"latest_build_completed_at"`
LatestBuildCanceledAt sql.NullTime `db:"latest_build_canceled_at" json:"latest_build_canceled_at"`
LatestBuildError sql.NullString `db:"latest_build_error" json:"latest_build_error"`
LatestBuildTransition WorkspaceTransition `db:"latest_build_transition" json:"latest_build_transition"`
LatestBuildStatus ProvisionerJobStatus `db:"latest_build_status" json:"latest_build_status"`
Count int64 `db:"count" json:"count"`
} }
// build_params is used to filter by build parameters if present. // build_params is used to filter by build parameters if present.
@@ -15197,10 +15242,18 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
&i.DeletingAt, &i.DeletingAt,
&i.AutomaticUpdates, &i.AutomaticUpdates,
&i.Favorite, &i.Favorite,
&i.OwnerAvatarUrl,
&i.OwnerUsername,
&i.OrganizationName,
&i.OrganizationDisplayName,
&i.OrganizationIcon,
&i.OrganizationDescription,
&i.TemplateName, &i.TemplateName,
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
&i.TemplateVersionID, &i.TemplateVersionID,
&i.TemplateVersionName, &i.TemplateVersionName,
&i.Username,
&i.LatestBuildCompletedAt, &i.LatestBuildCompletedAt,
&i.LatestBuildCanceledAt, &i.LatestBuildCanceledAt,
&i.LatestBuildError, &i.LatestBuildError,
@@ -15295,15 +15348,15 @@ WHERE
) AND workspaces.deleted = 'false' ) AND workspaces.deleted = 'false'
` `
func (q *sqlQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]Workspace, error) { func (q *sqlQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]WorkspaceTable, error) {
rows, err := q.db.QueryContext(ctx, getWorkspacesEligibleForTransition, now) rows, err := q.db.QueryContext(ctx, getWorkspacesEligibleForTransition, now)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []Workspace var items []WorkspaceTable
for rows.Next() { for rows.Next() {
var i Workspace var i WorkspaceTable
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.CreatedAt, &i.CreatedAt,
@@ -15367,7 +15420,7 @@ type InsertWorkspaceParams struct {
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"` AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
} }
func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (Workspace, error) { func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspaceParams) (WorkspaceTable, error) {
row := q.db.QueryRowContext(ctx, insertWorkspace, row := q.db.QueryRowContext(ctx, insertWorkspace,
arg.ID, arg.ID,
arg.CreatedAt, arg.CreatedAt,
@@ -15381,7 +15434,7 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar
arg.LastUsedAt, arg.LastUsedAt,
arg.AutomaticUpdates, arg.AutomaticUpdates,
) )
var i Workspace var i WorkspaceTable
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.CreatedAt, &i.CreatedAt,
@@ -15445,9 +15498,9 @@ type UpdateWorkspaceParams struct {
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
} }
func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (Workspace, error) { func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (WorkspaceTable, error) {
row := q.db.QueryRowContext(ctx, updateWorkspace, arg.ID, arg.Name) row := q.db.QueryRowContext(ctx, updateWorkspace, arg.ID, arg.Name)
var i Workspace var i WorkspaceTable
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.CreatedAt, &i.CreatedAt,
@@ -15558,9 +15611,9 @@ type UpdateWorkspaceDormantDeletingAtParams struct {
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"` DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
} }
func (q *sqlQuerier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg UpdateWorkspaceDormantDeletingAtParams) (Workspace, error) { func (q *sqlQuerier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg UpdateWorkspaceDormantDeletingAtParams) (WorkspaceTable, error) {
row := q.db.QueryRowContext(ctx, updateWorkspaceDormantDeletingAt, arg.ID, arg.DormantAt) row := q.db.QueryRowContext(ctx, updateWorkspaceDormantDeletingAt, arg.ID, arg.DormantAt)
var i Workspace var i WorkspaceTable
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.CreatedAt, &i.CreatedAt,
@@ -15641,15 +15694,15 @@ type UpdateWorkspacesDormantDeletingAtByTemplateIDParams struct {
TemplateID uuid.UUID `db:"template_id" json:"template_id"` TemplateID uuid.UUID `db:"template_id" json:"template_id"`
} }
func (q *sqlQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]Workspace, error) { func (q *sqlQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Context, arg UpdateWorkspacesDormantDeletingAtByTemplateIDParams) ([]WorkspaceTable, error) {
rows, err := q.db.QueryContext(ctx, updateWorkspacesDormantDeletingAtByTemplateID, arg.TimeTilDormantAutodeleteMs, arg.DormantAt, arg.TemplateID) rows, err := q.db.QueryContext(ctx, updateWorkspacesDormantDeletingAtByTemplateID, arg.TimeTilDormantAutodeleteMs, arg.DormantAt, arg.TemplateID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []Workspace var items []WorkspaceTable
for rows.Next() { for rows.Next() {
var i Workspace var i WorkspaceTable
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.CreatedAt, &i.CreatedAt,
+18 -15
View File
@@ -2,7 +2,7 @@
SELECT SELECT
* *
FROM FROM
workspaces workspaces_expanded
WHERE WHERE
id = $1 id = $1
LIMIT LIMIT
@@ -12,7 +12,7 @@ LIMIT
SELECT SELECT
* *
FROM FROM
workspaces workspaces_expanded as workspaces
WHERE WHERE
workspaces.id = ( workspaces.id = (
SELECT SELECT
@@ -46,12 +46,9 @@ WHERE
-- name: GetWorkspaceByAgentID :one -- name: GetWorkspaceByAgentID :one
SELECT SELECT
sqlc.embed(workspaces), *
templates.name as template_name
FROM FROM
workspaces workspaces_expanded as workspaces
INNER JOIN
templates ON workspaces.template_id = templates.id
WHERE WHERE
workspaces.id = ( workspaces.id = (
SELECT SELECT
@@ -89,17 +86,15 @@ SELECT
filtered_workspaces AS ( filtered_workspaces AS (
SELECT SELECT
workspaces.*, workspaces.*,
COALESCE(template.name, 'unknown') as template_name,
latest_build.template_version_id, latest_build.template_version_id,
latest_build.template_version_name, latest_build.template_version_name,
users.username as username,
latest_build.completed_at as latest_build_completed_at, latest_build.completed_at as latest_build_completed_at,
latest_build.canceled_at as latest_build_canceled_at, latest_build.canceled_at as latest_build_canceled_at,
latest_build.error as latest_build_error, latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition, latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status latest_build.job_status as latest_build_status
FROM FROM
workspaces workspaces_expanded as workspaces
JOIN JOIN
users users
ON ON
@@ -238,7 +233,7 @@ WHERE
-- Filter by owner_name -- Filter by owner_name
AND CASE AND CASE
WHEN @owner_username :: text != '' THEN WHEN @owner_username :: text != '' THEN
workspaces.owner_id = (SELECT id FROM users WHERE lower(username) = lower(@owner_username) AND deleted = false) workspaces.owner_id = (SELECT id FROM users WHERE lower(owner_username) = lower(@owner_username) AND deleted = false)
ELSE true ELSE true
END END
-- Filter by template_name -- Filter by template_name
@@ -340,7 +335,7 @@ WHERE
latest_build_canceled_at IS NULL AND latest_build_canceled_at IS NULL AND
latest_build_error IS NULL AND latest_build_error IS NULL AND
latest_build_transition = 'start'::workspace_transition) DESC, latest_build_transition = 'start'::workspace_transition) DESC,
LOWER(username) ASC, LOWER(owner_username) ASC,
LOWER(name) ASC LOWER(name) ASC
LIMIT LIMIT
CASE CASE
@@ -373,11 +368,19 @@ WHERE
'0001-01-01 00:00:00+00'::timestamptz, -- deleting_at '0001-01-01 00:00:00+00'::timestamptz, -- deleting_at
'never'::automatic_updates, -- automatic_updates 'never'::automatic_updates, -- automatic_updates
false, -- favorite false, -- favorite
-- Extra columns added to `filtered_workspaces` '', -- owner_avatar_url
'', -- owner_username
'', -- organization_name
'', -- organization_display_name
'', -- organization_icon
'', -- organization_description
'', -- template_name '', -- template_name
'', -- template_display_name
'', -- template_icon
'', -- template_description
-- Extra columns added to `filtered_workspaces`
'00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id '00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id
'', -- template_version_name '', -- template_version_name
'', -- username
'0001-01-01 00:00:00+00'::timestamptz, -- latest_build_completed_at, '0001-01-01 00:00:00+00'::timestamptz, -- latest_build_completed_at,
'0001-01-01 00:00:00+00'::timestamptz, -- latest_build_canceled_at, '0001-01-01 00:00:00+00'::timestamptz, -- latest_build_canceled_at,
'', -- latest_build_error '', -- latest_build_error
@@ -403,7 +406,7 @@ CROSS JOIN
SELECT SELECT
* *
FROM FROM
workspaces workspaces_expanded as workspaces
WHERE WHERE
owner_id = @owner_id owner_id = @owner_id
AND deleted = @deleted AND deleted = @deleted
+2
View File
@@ -83,6 +83,8 @@ sql:
template_with_name: Template template_with_name: Template
workspace_build: WorkspaceBuildTable workspace_build: WorkspaceBuildTable
workspace_build_with_user: WorkspaceBuild workspace_build_with_user: WorkspaceBuild
workspace: WorkspaceTable
workspaces_expanded: Workspace
template_version: TemplateVersionTable template_version: TemplateVersionTable
template_version_with_user: TemplateVersion template_version_with_user: TemplateVersion
api_key: APIKey api_key: APIKey
+5 -5
View File
@@ -110,7 +110,7 @@ func ExtractWorkspaceAgentAndLatestBuild(opts ExtractWorkspaceAgentAndLatestBuil
} }
//nolint:gocritic // System needs to be able to get owner roles. //nolint:gocritic // System needs to be able to get owner roles.
roles, err := opts.DB.GetAuthorizationUserRoles(dbauthz.AsSystemRestricted(ctx), row.Workspace.OwnerID) roles, err := opts.DB.GetAuthorizationUserRoles(dbauthz.AsSystemRestricted(ctx), row.WorkspaceTable.OwnerID)
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error checking workspace agent authorization.", Message: "Internal error checking workspace agent authorization.",
@@ -129,13 +129,13 @@ func ExtractWorkspaceAgentAndLatestBuild(opts ExtractWorkspaceAgentAndLatestBuil
} }
subject := rbac.Subject{ subject := rbac.Subject{
ID: row.Workspace.OwnerID.String(), ID: row.WorkspaceTable.OwnerID.String(),
Roles: rbac.RoleIdentifiers(roleNames), Roles: rbac.RoleIdentifiers(roleNames),
Groups: roles.Groups, Groups: roles.Groups,
Scope: rbac.WorkspaceAgentScope(rbac.WorkspaceAgentScopeParams{ Scope: rbac.WorkspaceAgentScope(rbac.WorkspaceAgentScopeParams{
WorkspaceID: row.Workspace.ID, WorkspaceID: row.WorkspaceTable.ID,
OwnerID: row.Workspace.OwnerID, OwnerID: row.WorkspaceTable.OwnerID,
TemplateID: row.Workspace.TemplateID, TemplateID: row.WorkspaceTable.TemplateID,
VersionID: row.WorkspaceBuild.TemplateVersionID, VersionID: row.WorkspaceBuild.TemplateVersionID,
}), }),
}.WithCachedASTValue() }.WithCachedASTValue()
+2 -2
View File
@@ -97,7 +97,7 @@ func TestWorkspaceAgent(t *testing.T) {
}) })
} }
func setup(t testing.TB, db database.Store, authToken uuid.UUID, mw func(http.Handler) http.Handler) (*http.Request, http.Handler, database.Workspace, database.TemplateVersion) { func setup(t testing.TB, db database.Store, authToken uuid.UUID, mw func(http.Handler) http.Handler) (*http.Request, http.Handler, database.WorkspaceTable, database.TemplateVersion) {
t.Helper() t.Helper()
org := dbgen.Organization(t, db, database.Organization{}) org := dbgen.Organization(t, db, database.Organization{})
user := dbgen.User(t, db, database.User{ user := dbgen.User(t, db, database.User{
@@ -116,7 +116,7 @@ func setup(t testing.TB, db database.Store, authToken uuid.UUID, mw func(http.Ha
ActiveVersionID: templateVersion.ID, ActiveVersionID: templateVersion.ID,
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
+1 -1
View File
@@ -31,7 +31,7 @@ func TestWorkspaceAgentParam(t *testing.T) {
UserID: user.ID, UserID: user.ID,
}) })
tpl = dbgen.Template(t, db, database.Template{}) tpl = dbgen.Template(t, db, database.Template{})
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: tpl.ID, TemplateID: tpl.ID,
}) })
+2 -2
View File
@@ -20,13 +20,13 @@ import (
func TestWorkspaceBuildParam(t *testing.T) { func TestWorkspaceBuildParam(t *testing.T) {
t.Parallel() t.Parallel()
setupAuthentication := func(db database.Store) (*http.Request, database.Workspace) { setupAuthentication := func(db database.Store) (*http.Request, database.WorkspaceTable) {
var ( var (
user = dbgen.User(t, db, database.User{}) user = dbgen.User(t, db, database.User{})
_, token = dbgen.APIKey(t, db, database.APIKey{ _, token = dbgen.APIKey(t, db, database.APIKey{
UserID: user.ID, UserID: user.ID,
}) })
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
}) })
) )
+1 -1
View File
@@ -355,7 +355,7 @@ func setupWorkspaceWithAgents(t testing.TB, cfg setupConfig) (database.Store, *h
_, token = dbgen.APIKey(t, db, database.APIKey{ _, token = dbgen.APIKey(t, db, database.APIKey{
UserID: user.ID, UserID: user.ID,
}) })
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
Name: cfg.WorkspaceName, Name: cfg.WorkspaceName,
}) })
+3 -3
View File
@@ -49,7 +49,7 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
"TemplateWorkspaceOwners never populated 0 owners", "TemplateWorkspaceOwners never populated 0 owners",
) )
dbgen.Workspace(t, db, database.Workspace{ dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user1.ID, OwnerID: user1.ID,
}) })
@@ -61,7 +61,7 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
"TemplateWorkspaceOwners never populated 1 owner", "TemplateWorkspaceOwners never populated 1 owner",
) )
workspace2 := dbgen.Workspace(t, db, database.Workspace{ workspace2 := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user2.ID, OwnerID: user2.ID,
}) })
@@ -74,7 +74,7 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
) )
// 3rd workspace should not be counted since we have the same owner as workspace2. // 3rd workspace should not be counted since we have the same owner as workspace2.
dbgen.Workspace(t, db, database.Workspace{ dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user1.ID, OwnerID: user1.ID,
}) })
@@ -90,7 +90,7 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
t1v1 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-1", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()}) t1v1 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-1", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()})
// Workspaces // Workspaces
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID}) w1 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
w1wb1pj := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID, Error: jobError, ErrorCode: jobErrorCode, CompletedAt: sql.NullTime{Time: now.Add(-6 * dayDuration), Valid: true}}) w1wb1pj := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID, Error: jobError, ErrorCode: jobErrorCode, CompletedAt: sql.NullTime{Time: now.Add(-6 * dayDuration), Valid: true}})
_ = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: w1.ID, BuildNumber: 1, TemplateVersionID: t1v1.ID, JobID: w1wb1pj.ID, CreatedAt: now.Add(-2 * dayDuration), Transition: database.WorkspaceTransitionStart, Reason: database.BuildReasonInitiator}) _ = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: w1.ID, BuildNumber: 1, TemplateVersionID: t1v1.ID, JobID: w1wb1pj.ID, CreatedAt: now.Add(-2 * dayDuration), Transition: database.WorkspaceTransitionStart, Reason: database.BuildReasonInitiator})
@@ -164,10 +164,10 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
t2v2 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-2-version-2", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t2.ID, Valid: true}, JobID: uuid.New()}) t2v2 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-2-version-2", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t2.ID, Valid: true}, JobID: uuid.New()})
// Workspaces // Workspaces
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID}) w1 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
w2 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID}) w2 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID})
w3 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID}) w3 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
w4 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID}) w4 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID})
// When: first run // When: first run
notifEnq.Clear() notifEnq.Clear()
@@ -330,7 +330,7 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
t1v2 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-2", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()}) t1v2 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-2", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()})
// Workspaces // Workspaces
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID}) w1 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
// When: first run // When: first run
notifEnq.Clear() notifEnq.Clear()
@@ -427,7 +427,7 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
t1v1 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-1", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()}) t1v1 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-1", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()})
// Workspaces // Workspaces
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID}) w1 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
// When: first run // When: first run
notifEnq.Clear() notifEnq.Clear()
@@ -63,8 +63,8 @@ func TestCollectInsights(t *testing.T) {
param1 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "first_parameter"}) param1 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "first_parameter"})
param2 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "second_parameter", Type: "bool"}) param2 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "second_parameter", Type: "bool"})
param3 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "third_parameter", Type: "number"}) param3 = dbgen.TemplateVersionParameter(t, db, database.TemplateVersionParameter{TemplateVersionID: ver.ID, Name: "third_parameter", Type: "number"})
workspace1 = dbgen.Workspace(t, db, database.Workspace{OrganizationID: orgID, TemplateID: tpl.ID, OwnerID: user.ID}) workspace1 = dbgen.Workspace(t, db, database.WorkspaceTable{OrganizationID: orgID, TemplateID: tpl.ID, OwnerID: user.ID})
workspace2 = dbgen.Workspace(t, db, database.Workspace{OrganizationID: orgID, TemplateID: tpl.ID, OwnerID: user.ID}) workspace2 = dbgen.Workspace(t, db, database.WorkspaceTable{OrganizationID: orgID, TemplateID: tpl.ID, OwnerID: user.ID})
job1 = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: orgID}) job1 = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: orgID})
job2 = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: orgID}) job2 = dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: orgID})
build1 = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{TemplateVersionID: ver.ID, WorkspaceID: workspace1.ID, JobID: job1.ID}) build1 = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{TemplateVersionID: ver.ID, WorkspaceID: workspace1.ID, JobID: job1.ID})
@@ -166,7 +166,7 @@ func Workspaces(ctx context.Context, logger slog.Logger, registerer prometheus.R
workspaceLatestBuildStatuses.Reset() workspaceLatestBuildStatuses.Reset()
for _, w := range ws { for _, w := range ws {
workspaceLatestBuildStatuses.WithLabelValues(string(w.LatestBuildStatus), w.TemplateName, w.TemplateVersionName.String, w.Username, string(w.LatestBuildTransition)).Add(1) workspaceLatestBuildStatuses.WithLabelValues(string(w.LatestBuildStatus), w.TemplateName, w.TemplateVersionName.String, w.OwnerUsername, string(w.LatestBuildTransition)).Add(1)
} }
} }
@@ -1406,7 +1406,7 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
TemplateScheduleStore: *s.TemplateScheduleStore.Load(), TemplateScheduleStore: *s.TemplateScheduleStore.Load(),
UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(), UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(),
Now: now, Now: now,
Workspace: workspace, Workspace: workspace.WorkspaceTable(),
// Allowed to be the empty string. // Allowed to be the empty string.
WorkspaceAutostart: workspace.AutostartSchedule.String, WorkspaceAutostart: workspace.AutostartSchedule.String,
}) })
@@ -267,7 +267,7 @@ func TestAcquireJob(t *testing.T) {
Required: true, Required: true,
Sensitive: false, Sensitive: false,
}) })
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: pd.OrganizationID, OrganizationID: pd.OrganizationID,
@@ -1263,7 +1263,7 @@ func TestCompleteJob(t *testing.T) {
Valid: true, Valid: true,
} }
} }
workspace := dbgen.Workspace(t, db, database.Workspace{ workspaceTable := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
Ttl: workspaceTTL, Ttl: workspaceTTL,
OwnerID: user.ID, OwnerID: user.ID,
@@ -1278,7 +1278,7 @@ func TestCompleteJob(t *testing.T) {
JobID: uuid.New(), JobID: uuid.New(),
}) })
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
WorkspaceID: workspace.ID, WorkspaceID: workspaceTable.ID,
TemplateVersionID: version.ID, TemplateVersionID: version.ID,
Transition: c.transition, Transition: c.transition,
Reason: database.BuildReasonInitiator, Reason: database.BuildReasonInitiator,
@@ -1331,7 +1331,7 @@ func TestCompleteJob(t *testing.T) {
<-publishedWorkspace <-publishedWorkspace
<-publishedLogs <-publishedLogs
workspace, err = db.GetWorkspaceByID(ctx, workspace.ID) workspace, err := db.GetWorkspaceByID(ctx, workspaceTable.ID)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, c.transition == database.WorkspaceTransitionDelete, workspace.Deleted) require.Equal(t, c.transition == database.WorkspaceTransitionDelete, workspace.Deleted)
@@ -1622,7 +1622,7 @@ func TestNotifications(t *testing.T) {
template, err := db.GetTemplateByID(ctx, template.ID) template, err := db.GetTemplateByID(ctx, template.ID)
require.NoError(t, err) require.NoError(t, err)
file := dbgen.File(t, db, database.File{CreatedBy: user.ID}) file := dbgen.File(t, db, database.File{CreatedBy: user.ID})
workspace := dbgen.Workspace(t, db, database.Workspace{ workspaceTable := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: pd.OrganizationID, OrganizationID: pd.OrganizationID,
@@ -1636,7 +1636,7 @@ func TestNotifications(t *testing.T) {
JobID: uuid.New(), JobID: uuid.New(),
}) })
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
WorkspaceID: workspace.ID, WorkspaceID: workspaceTable.ID,
TemplateVersionID: version.ID, TemplateVersionID: version.ID,
InitiatorID: initiator.ID, InitiatorID: initiator.ID,
Transition: database.WorkspaceTransitionDelete, Transition: database.WorkspaceTransitionDelete,
@@ -1674,7 +1674,7 @@ func TestNotifications(t *testing.T) {
}) })
require.NoError(t, err) require.NoError(t, err)
workspace, err = db.GetWorkspaceByID(ctx, workspace.ID) workspace, err := db.GetWorkspaceByID(ctx, workspaceTable.ID)
require.NoError(t, err) require.NoError(t, err)
require.True(t, workspace.Deleted) require.True(t, workspace.Deleted)
@@ -1740,7 +1740,7 @@ func TestNotifications(t *testing.T) {
OrganizationID: pd.OrganizationID, OrganizationID: pd.OrganizationID,
}) })
file := dbgen.File(t, db, database.File{CreatedBy: user.ID}) file := dbgen.File(t, db, database.File{CreatedBy: user.ID})
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: pd.OrganizationID, OrganizationID: pd.OrganizationID,
@@ -1822,7 +1822,7 @@ func TestNotifications(t *testing.T) {
template := dbgen.Template(t, db, database.Template{ template := dbgen.Template(t, db, database.Template{
Name: "template", DisplayName: "William's Template", Provisioner: database.ProvisionerTypeEcho, OrganizationID: pd.OrganizationID, Name: "template", DisplayName: "William's Template", Provisioner: database.ProvisionerTypeEcho, OrganizationID: pd.OrganizationID,
}) })
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, OwnerID: user.ID, OrganizationID: pd.OrganizationID, TemplateID: template.ID, OwnerID: user.ID, OrganizationID: pd.OrganizationID,
}) })
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
+1 -1
View File
@@ -51,7 +51,7 @@ type CalculateAutostopParams struct {
WorkspaceAutostart string WorkspaceAutostart string
Now time.Time Now time.Time
Workspace database.Workspace Workspace database.WorkspaceTable
} }
type AutostopTime struct { type AutostopTime struct {
+1 -1
View File
@@ -561,7 +561,7 @@ func TestCalculateAutoStop(t *testing.T) {
Valid: true, Valid: true,
} }
} }
workspace := dbgen.Workspace(t, db, database.Workspace{ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
OwnerID: user.ID, OwnerID: user.ID,
+1 -1
View File
@@ -50,7 +50,7 @@ func TestTelemetry(t *testing.T) {
}) })
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{}) _ = dbgen.TemplateVersion(t, db, database.TemplateVersion{})
user := dbgen.User(t, db, database.User{}) user := dbgen.User(t, db, database.User{})
_ = dbgen.Workspace(t, db, database.Workspace{}) _ = dbgen.Workspace(t, db, database.WorkspaceTable{})
_ = dbgen.WorkspaceApp(t, db, database.WorkspaceApp{ _ = dbgen.WorkspaceApp(t, db, database.WorkspaceApp{
SharingLevel: database.AppSharingLevelOwner, SharingLevel: database.AppSharingLevelOwner,
Health: database.WorkspaceAppHealthDisabled, Health: database.WorkspaceAppHealthDisabled,
+3 -3
View File
@@ -133,7 +133,7 @@ func TestDetectorHungWorkspaceBuild(t *testing.T) {
}, },
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -255,7 +255,7 @@ func TestDetectorHungWorkspaceBuildNoOverrideState(t *testing.T) {
}, },
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -377,7 +377,7 @@ func TestDetectorHungWorkspaceBuildNoOverrideStateIfNoExistingBuild(t *testing.T
}, },
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
workspace = dbgen.Workspace(t, db, database.Workspace{ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
-9
View File
@@ -1461,15 +1461,6 @@ func userOrganizationIDs(ctx context.Context, api *API, user database.User) ([]u
return member.OrganizationIDs, nil return member.OrganizationIDs, nil
} }
func userByID(id uuid.UUID, users []database.User) (database.User, bool) {
for _, user := range users {
if id == user.ID {
return user, true
}
}
return database.User{}, false
}
func convertAPIKey(k database.APIKey) codersdk.APIKey { func convertAPIKey(k database.APIKey) codersdk.APIKey {
return codersdk.APIKey{ return codersdk.APIKey{
ID: k.ID, ID: k.ID,
+2 -2
View File
@@ -1936,7 +1936,7 @@ func TestUserAutofillParameters(t *testing.T) {
}, },
).Do() ).Do()
dbfake.WorkspaceBuild(t, db, database.Workspace{ dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: u2.ID, OwnerID: u2.ID,
TemplateID: version.Template.ID, TemplateID: version.Template.ID,
OrganizationID: u1.OrganizationID, OrganizationID: u1.OrganizationID,
@@ -1969,7 +1969,7 @@ func TestUserAutofillParameters(t *testing.T) {
require.Equal(t, "foo", params[0].Value) require.Equal(t, "foo", params[0].Value)
// Verify that latest parameter value is returned. // Verify that latest parameter value is returned.
dbfake.WorkspaceBuild(t, db, database.Workspace{ dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: u1.OrganizationID, OrganizationID: u1.OrganizationID,
OwnerID: u2.ID, OwnerID: u2.ID,
TemplateID: version.Template.ID, TemplateID: version.Template.ID,
+11
View File
@@ -55,6 +55,17 @@ func Contains[T comparable](haystack []T, needle T) bool {
}) })
} }
// Find returns the first element that satisfies the condition.
func Find[T any](haystack []T, cond func(T) bool) (T, bool) {
for _, hay := range haystack {
if cond(hay) {
return hay, true
}
}
var empty T
return empty, false
}
// Overlap returns if the 2 sets have any overlap (element(s) in common) // Overlap returns if the 2 sets have any overlap (element(s) in common)
func Overlap[T comparable](a []T, b []T) bool { func Overlap[T comparable](a []T, b []T) bool {
return OverlapCompare(a, b, func(a, b T) bool { return OverlapCompare(a, b, func(a, b T) bool {
+3 -3
View File
@@ -24,7 +24,7 @@ func TestPostWorkspaceAgentPortShare(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir() tmpDir := t.TempDir()
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -141,7 +141,7 @@ func TestGetWorkspaceAgentPortShares(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir() tmpDir := t.TempDir()
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -177,7 +177,7 @@ func TestDeleteWorkspaceAgentPortShare(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir() tmpDir := t.TempDir()
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
+1 -2
View File
@@ -366,7 +366,7 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
return return
} }
row, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID) workspace, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace by agent id.", Message: "Internal error fetching workspace by agent id.",
@@ -374,7 +374,6 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
}) })
return return
} }
workspace := row.Workspace
api.WebsocketWaitMutex.Lock() api.WebsocketWaitMutex.Lock()
api.WebsocketWaitGroup.Add(1) api.WebsocketWaitGroup.Add(1)
+25 -25
View File
@@ -57,7 +57,7 @@ func TestWorkspaceAgent(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: anotherUser.ID, OwnerID: anotherUser.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -79,7 +79,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
tmpDir := t.TempDir() tmpDir := t.TempDir()
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -107,7 +107,7 @@ func TestWorkspaceAgent(t *testing.T) {
wantTroubleshootingURL := "https://example.com/troubleshoot" wantTroubleshootingURL := "https://example.com/troubleshoot"
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -148,7 +148,7 @@ func TestWorkspaceAgent(t *testing.T) {
PortForwardingHelper: true, PortForwardingHelper: true,
SshHelper: true, SshHelper: true,
} }
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -181,7 +181,7 @@ func TestWorkspaceAgent(t *testing.T) {
apps.WebTerminal = false apps.WebTerminal = false
// Creating another workspace is easier // Creating another workspace is easier
r = dbfake.WorkspaceBuild(t, db, database.Workspace{ r = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -205,7 +205,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -247,7 +247,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -289,7 +289,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium) ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -332,7 +332,7 @@ func TestWorkspaceAgentConnectRPC(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -420,7 +420,7 @@ func TestWorkspaceAgentConnectRPC(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
// Given: a workspace exists // Given: a workspace exists
seed := database.Workspace{OrganizationID: user.OrganizationID, OwnerID: user.UserID} seed := database.WorkspaceTable{OrganizationID: user.OrganizationID, OwnerID: user.UserID}
wsb := dbfake.WorkspaceBuild(t, db, seed).WithAgent().Do() wsb := dbfake.WorkspaceBuild(t, db, seed).WithAgent().Do()
// When: the workspace is marked as soft-deleted // When: the workspace is marked as soft-deleted
// nolint:gocritic // this is a test // nolint:gocritic // this is a test
@@ -446,7 +446,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -486,7 +486,7 @@ func TestWorkspaceAgentClientCoordinate_BadVersion(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -571,7 +571,7 @@ func TestWorkspaceAgentClientCoordinate_ResumeToken(t *testing.T) {
// Create a workspace with an agent. No need to connect it since clients can // Create a workspace with an agent. No need to connect it since clients can
// still connect to the coordinator while the agent isn't connected. // still connect to the coordinator while the agent isn't connected.
r := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{ r := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -679,7 +679,7 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) {
DeploymentValues: dv, DeploymentValues: dv,
}) })
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -750,7 +750,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1006,7 +1006,7 @@ func TestWorkspaceAgentAppHealth(t *testing.T) {
}, },
}, },
} }
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1088,7 +1088,7 @@ func TestWorkspaceAgentPostLogSource(t *testing.T) {
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitShort) ctx := testutil.Context(t, testutil.WaitShort)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1130,7 +1130,7 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1203,7 +1203,7 @@ func TestWorkspaceAgent_Metadata(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1368,7 +1368,7 @@ func TestWorkspaceAgent_Metadata_DisplayOrder(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1475,7 +1475,7 @@ func TestWorkspaceAgent_Metadata_CatchMemoryLeak(t *testing.T) {
Logger: &logger, Logger: &logger,
}) })
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1607,7 +1607,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1653,7 +1653,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1698,7 +1698,7 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) {
api.DERPMapper.Store(&derpMapFn) api.DERPMapper.Store(&derpMapFn)
// Start workspace a workspace agent. // Start workspace a workspace agent.
r := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{ r := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -1815,7 +1815,7 @@ func TestWorkspaceAgentExternalAuthListen(t *testing.T) {
tmpDir := t.TempDir() tmpDir := t.TempDir()
client, user := coderdtest.CreateAnotherUser(t, ownerClient, first.OrganizationID) client, user := coderdtest.CreateAnotherUser(t, ownerClient, first.OrganizationID)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: first.OrganizationID, OrganizationID: first.OrganizationID,
OwnerID: user.ID, OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
+2 -2
View File
@@ -22,7 +22,7 @@ func TestWorkspaceAgentReportStats(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -72,7 +72,7 @@ func TestAgentAPI_LargeManifest(t *testing.T) {
for i := range longScript { for i := range longScript {
longScript[i] = 'q' longScript[i] = 'q'
} }
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: adminUser.OrganizationID, OrganizationID: adminUser.OrganizationID,
OwnerID: adminUser.UserID, OwnerID: adminUser.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
+7 -71
View File
@@ -46,7 +46,7 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
workspaceBuild := httpmw.WorkspaceBuildParam(r) workspaceBuild := httpmw.WorkspaceBuildParam(r)
workspace := httpmw.WorkspaceParam(r) workspace := httpmw.WorkspaceParam(r)
data, err := api.workspaceBuildsData(ctx, []database.Workspace{workspace}, []database.WorkspaceBuild{workspaceBuild}) data, err := api.workspaceBuildsData(ctx, []database.WorkspaceBuild{workspaceBuild})
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.", Message: "Internal error getting workspace build data.",
@@ -72,21 +72,11 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
}) })
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting workspace build.",
Detail: "owner not found for workspace",
})
return
}
apiBuild, err := api.convertWorkspaceBuild( apiBuild, err := api.convertWorkspaceBuild(
workspaceBuild, workspaceBuild,
workspace, workspace,
data.jobs[0], data.jobs[0],
owner.Username,
owner.AvatarURL,
data.resources, data.resources,
data.metadata, data.metadata,
data.agents, data.agents,
@@ -189,7 +179,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
return return
} }
data, err := api.workspaceBuildsData(ctx, []database.Workspace{workspace}, workspaceBuilds) data, err := api.workspaceBuildsData(ctx, workspaceBuilds)
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.", Message: "Internal error getting workspace build data.",
@@ -202,7 +192,6 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
workspaceBuilds, workspaceBuilds,
[]database.Workspace{workspace}, []database.Workspace{workspace},
data.jobs, data.jobs,
data.users,
data.resources, data.resources,
data.metadata, data.metadata,
data.agents, data.agents,
@@ -279,7 +268,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
return return
} }
data, err := api.workspaceBuildsData(ctx, []database.Workspace{workspace}, []database.WorkspaceBuild{workspaceBuild}) data, err := api.workspaceBuildsData(ctx, []database.WorkspaceBuild{workspaceBuild})
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.", Message: "Internal error getting workspace build data.",
@@ -287,21 +276,11 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
}) })
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting workspace build.",
Detail: "owner not found for workspace",
})
return
}
apiBuild, err := api.convertWorkspaceBuild( apiBuild, err := api.convertWorkspaceBuild(
workspaceBuild, workspaceBuild,
workspace, workspace,
data.jobs[0], data.jobs[0],
owner.Username,
owner.AvatarURL,
data.resources, data.resources,
data.metadata, data.metadata,
data.agents, data.agents,
@@ -410,26 +389,6 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
api.Logger.Error(ctx, "failed to post provisioner job to pubsub", slog.Error(err)) api.Logger.Error(ctx, "failed to post provisioner job to pubsub", slog.Error(err))
} }
users, err := api.Database.GetUsersByIDs(ctx, []uuid.UUID{
workspace.OwnerID,
workspaceBuild.InitiatorID,
})
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting user.",
Detail: err.Error(),
})
return
}
owner, exists := userByID(workspace.OwnerID, users)
if !exists {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error converting workspace build.",
Detail: "owner not found for workspace",
})
return
}
apiBuild, err := api.convertWorkspaceBuild( apiBuild, err := api.convertWorkspaceBuild(
*workspaceBuild, *workspaceBuild,
workspace, workspace,
@@ -437,8 +396,6 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
ProvisionerJob: *provisionerJob, ProvisionerJob: *provisionerJob,
QueuePosition: 0, QueuePosition: 0,
}, },
owner.Username,
owner.AvatarURL,
[]database.WorkspaceResource{}, []database.WorkspaceResource{},
[]database.WorkspaceResourceMetadatum{}, []database.WorkspaceResourceMetadatum{},
[]database.WorkspaceAgent{}, []database.WorkspaceAgent{},
@@ -674,7 +631,6 @@ func (api *API) workspaceBuildTimings(rw http.ResponseWriter, r *http.Request) {
} }
type workspaceBuildsData struct { type workspaceBuildsData struct {
users []database.User
jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow
templateVersions []database.TemplateVersion templateVersions []database.TemplateVersion
resources []database.WorkspaceResource resources []database.WorkspaceResource
@@ -685,16 +641,7 @@ type workspaceBuildsData struct {
logSources []database.WorkspaceAgentLogSource logSources []database.WorkspaceAgentLogSource
} }
func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.Workspace, workspaceBuilds []database.WorkspaceBuild) (workspaceBuildsData, error) { func (api *API) workspaceBuildsData(ctx context.Context, workspaceBuilds []database.WorkspaceBuild) (workspaceBuildsData, error) {
userIDs := make([]uuid.UUID, 0, len(workspaceBuilds))
for _, workspace := range workspaces {
userIDs = append(userIDs, workspace.OwnerID)
}
users, err := api.Database.GetUsersByIDs(ctx, userIDs)
if err != nil {
return workspaceBuildsData{}, xerrors.Errorf("get users: %w", err)
}
jobIDs := make([]uuid.UUID, 0, len(workspaceBuilds)) jobIDs := make([]uuid.UUID, 0, len(workspaceBuilds))
for _, build := range workspaceBuilds { for _, build := range workspaceBuilds {
jobIDs = append(jobIDs, build.JobID) jobIDs = append(jobIDs, build.JobID)
@@ -723,7 +670,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
if len(resources) == 0 { if len(resources) == 0 {
return workspaceBuildsData{ return workspaceBuildsData{
users: users,
jobs: jobs, jobs: jobs,
templateVersions: templateVersions, templateVersions: templateVersions,
}, nil }, nil
@@ -748,7 +694,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
if len(resources) == 0 { if len(resources) == 0 {
return workspaceBuildsData{ return workspaceBuildsData{
users: users,
jobs: jobs, jobs: jobs,
templateVersions: templateVersions, templateVersions: templateVersions,
resources: resources, resources: resources,
@@ -789,7 +734,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
} }
return workspaceBuildsData{ return workspaceBuildsData{
users: users,
jobs: jobs, jobs: jobs,
templateVersions: templateVersions, templateVersions: templateVersions,
resources: resources, resources: resources,
@@ -805,7 +749,6 @@ func (api *API) convertWorkspaceBuilds(
workspaceBuilds []database.WorkspaceBuild, workspaceBuilds []database.WorkspaceBuild,
workspaces []database.Workspace, workspaces []database.Workspace,
jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow, jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow,
users []database.User,
workspaceResources []database.WorkspaceResource, workspaceResources []database.WorkspaceResource,
resourceMetadata []database.WorkspaceResourceMetadatum, resourceMetadata []database.WorkspaceResourceMetadatum,
resourceAgents []database.WorkspaceAgent, resourceAgents []database.WorkspaceAgent,
@@ -842,17 +785,11 @@ func (api *API) convertWorkspaceBuilds(
if !exists { if !exists {
return nil, xerrors.New("template version not found") return nil, xerrors.New("template version not found")
} }
owner, exists := userByID(workspace.OwnerID, users)
if !exists {
return nil, xerrors.Errorf("owner not found for workspace: %q", workspace.Name)
}
apiBuild, err := api.convertWorkspaceBuild( apiBuild, err := api.convertWorkspaceBuild(
build, build,
workspace, workspace,
job, job,
owner.Username,
owner.AvatarURL,
workspaceResources, workspaceResources,
resourceMetadata, resourceMetadata,
resourceAgents, resourceAgents,
@@ -875,7 +812,6 @@ func (api *API) convertWorkspaceBuild(
build database.WorkspaceBuild, build database.WorkspaceBuild,
workspace database.Workspace, workspace database.Workspace,
job database.GetProvisionerJobsByIDsWithQueuePositionRow, job database.GetProvisionerJobsByIDsWithQueuePositionRow,
username, avatarURL string,
workspaceResources []database.WorkspaceResource, workspaceResources []database.WorkspaceResource,
resourceMetadata []database.WorkspaceResourceMetadatum, resourceMetadata []database.WorkspaceResourceMetadatum,
resourceAgents []database.WorkspaceAgent, resourceAgents []database.WorkspaceAgent,
@@ -931,7 +867,7 @@ func (api *API) convertWorkspaceBuild(
scripts := scriptsByAgentID[agent.ID] scripts := scriptsByAgentID[agent.ID]
logSources := logSourcesByAgentID[agent.ID] logSources := logSourcesByAgentID[agent.ID]
apiAgent, err := db2sdk.WorkspaceAgent( apiAgent, err := db2sdk.WorkspaceAgent(
api.DERPMap(), *api.TailnetCoordinator.Load(), agent, db2sdk.Apps(apps, agent, username, workspace), convertScripts(scripts), convertLogSources(logSources), api.AgentInactiveDisconnectTimeout, api.DERPMap(), *api.TailnetCoordinator.Load(), agent, db2sdk.Apps(apps, agent, workspace.OwnerUsername, workspace), convertScripts(scripts), convertLogSources(logSources), api.AgentInactiveDisconnectTimeout,
api.DeploymentValues.AgentFallbackTroubleshootingURL.String(), api.DeploymentValues.AgentFallbackTroubleshootingURL.String(),
) )
if err != nil { if err != nil {
@@ -958,8 +894,8 @@ func (api *API) convertWorkspaceBuild(
CreatedAt: build.CreatedAt, CreatedAt: build.CreatedAt,
UpdatedAt: build.UpdatedAt, UpdatedAt: build.UpdatedAt,
WorkspaceOwnerID: workspace.OwnerID, WorkspaceOwnerID: workspace.OwnerID,
WorkspaceOwnerName: username, WorkspaceOwnerName: workspace.OwnerUsername,
WorkspaceOwnerAvatarURL: avatarURL, WorkspaceOwnerAvatarURL: workspace.OwnerAvatarUrl,
WorkspaceID: build.WorkspaceID, WorkspaceID: build.WorkspaceID,
WorkspaceName: workspace.Name, WorkspaceName: workspace.Name,
TemplateVersionID: build.TemplateVersionID, TemplateVersionID: build.TemplateVersionID,
+1 -1
View File
@@ -1217,7 +1217,7 @@ func TestWorkspaceBuildTimings(t *testing.T) {
// Tests will run in parallel. To avoid conflicts and race conditions on the // Tests will run in parallel. To avoid conflicts and race conditions on the
// build number, each test will have its own workspace and build. // build number, each test will have its own workspace and build.
makeBuild := func() database.WorkspaceBuild { makeBuild := func() database.WorkspaceBuild {
ws := dbgen.Workspace(t, db, database.Workspace{ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: owner.UserID, OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
TemplateID: template.ID, TemplateID: template.ID,
+72 -114
View File
@@ -99,22 +99,12 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
httpapi.Forbidden(rw) httpapi.Forbidden(rw)
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: "unable to find workspace owner's username",
})
return
}
w, err := convertWorkspace( w, err := convertWorkspace(
apiKey.UserID, apiKey.UserID,
workspace, workspace,
data.builds[0], data.builds[0],
data.templates[0], data.templates[0],
owner.Username,
owner.AvatarURL,
api.Options.AllowWorkspaceRenames, api.Options.AllowWorkspaceRenames,
) )
if err != nil { if err != nil {
@@ -307,21 +297,12 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
httpapi.ResourceNotFound(rw) httpapi.ResourceNotFound(rw)
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: "unable to find workspace owner's username",
})
return
}
w, err := convertWorkspace( w, err := convertWorkspace(
apiKey.UserID, apiKey.UserID,
workspace, workspace,
data.builds[0], data.builds[0],
data.templates[0], data.templates[0],
owner.Username,
owner.AvatarURL,
api.Options.AllowWorkspaceRenames, api.Options.AllowWorkspaceRenames,
) )
if err != nil { if err != nil {
@@ -364,7 +345,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
} }
) )
aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -413,7 +394,7 @@ func (api *API) postUserWorkspaces(rw http.ResponseWriter, r *http.Request) {
user = httpmw.UserParam(r) user = httpmw.UserParam(r)
) )
aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -446,7 +427,7 @@ type workspaceOwner struct {
func createWorkspace( func createWorkspace(
ctx context.Context, ctx context.Context,
auditReq *audit.Request[database.Workspace], auditReq *audit.Request[database.WorkspaceTable],
initiatorID uuid.UUID, initiatorID uuid.UUID,
api *API, api *API,
owner workspaceOwner, owner workspaceOwner,
@@ -627,7 +608,7 @@ func createWorkspace(
err = api.Database.InTx(func(db database.Store) error { err = api.Database.InTx(func(db database.Store) error {
now := dbtime.Now() now := dbtime.Now()
// Workspaces are created without any versions. // Workspaces are created without any versions.
workspace, err = db.InsertWorkspace(ctx, database.InsertWorkspaceParams{ minimumWorkspace, err := db.InsertWorkspace(ctx, database.InsertWorkspaceParams{
ID: uuid.New(), ID: uuid.New(),
CreatedAt: now, CreatedAt: now,
UpdatedAt: now, UpdatedAt: now,
@@ -646,6 +627,14 @@ func createWorkspace(
return xerrors.Errorf("insert workspace: %w", err) return xerrors.Errorf("insert workspace: %w", err)
} }
// We have to refetch the workspace for the joined in fields.
// TODO: We can use WorkspaceTable for the builder to not require
// this extra fetch.
workspace, err = db.GetWorkspaceByID(ctx, minimumWorkspace.ID)
if err != nil {
return xerrors.Errorf("get workspace by ID: %w", err)
}
builder := wsbuilder.New(workspace, database.WorkspaceTransitionStart). builder := wsbuilder.New(workspace, database.WorkspaceTransitionStart).
Reason(database.BuildReasonInitiator). Reason(database.BuildReasonInitiator).
Initiator(initiatorID). Initiator(initiatorID).
@@ -685,7 +674,7 @@ func createWorkspace(
// Client probably doesn't care about this error, so just log it. // Client probably doesn't care about this error, so just log it.
api.Logger.Error(ctx, "failed to post provisioner job to pubsub", slog.Error(err)) api.Logger.Error(ctx, "failed to post provisioner job to pubsub", slog.Error(err))
} }
auditReq.New = workspace auditReq.New = workspace.WorkspaceTable()
api.Telemetry.Report(&telemetry.Snapshot{ api.Telemetry.Report(&telemetry.Snapshot{
Workspaces: []telemetry.Workspace{telemetry.ConvertWorkspace(workspace)}, Workspaces: []telemetry.Workspace{telemetry.ConvertWorkspace(workspace)},
@@ -699,8 +688,6 @@ func createWorkspace(
ProvisionerJob: *provisionerJob, ProvisionerJob: *provisionerJob,
QueuePosition: 0, QueuePosition: 0,
}, },
owner.Username,
owner.AvatarURL,
[]database.WorkspaceResource{}, []database.WorkspaceResource{},
[]database.WorkspaceResourceMetadatum{}, []database.WorkspaceResourceMetadatum{},
[]database.WorkspaceAgent{}, []database.WorkspaceAgent{},
@@ -722,8 +709,6 @@ func createWorkspace(
workspace, workspace,
apiBuild, apiBuild,
template, template,
owner.Username,
owner.AvatarURL,
api.Options.AllowWorkspaceRenames, api.Options.AllowWorkspaceRenames,
) )
if err != nil { if err != nil {
@@ -750,7 +735,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context() ctx = r.Context()
workspace = httpmw.WorkspaceParam(r) workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load() auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -759,7 +744,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
}) })
) )
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceRequest var req codersdk.UpdateWorkspaceRequest
if !httpapi.Read(ctx, rw, r, &req) { if !httpapi.Read(ctx, rw, r, &req) {
@@ -767,7 +752,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
} }
if req.Name == "" || req.Name == workspace.Name { if req.Name == "" || req.Name == workspace.Name {
aReq.New = workspace aReq.New = workspace.WorkspaceTable()
// Nothing changed, optionally this could be an error. // Nothing changed, optionally this could be an error.
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
return return
@@ -822,8 +807,8 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
} }
api.publishWorkspaceUpdate(ctx, workspace.ID) api.publishWorkspaceUpdate(ctx, workspace.ID)
aReq.New = newWorkspace aReq.New = newWorkspace
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
} }
@@ -841,7 +826,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context() ctx = r.Context()
workspace = httpmw.WorkspaceParam(r) workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load() auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -850,7 +835,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
}) })
) )
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceAutostartRequest var req codersdk.UpdateWorkspaceAutostartRequest
if !httpapi.Read(ctx, rw, r, &req) { if !httpapi.Read(ctx, rw, r, &req) {
@@ -897,7 +882,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
newWorkspace := workspace newWorkspace := workspace
newWorkspace.AutostartSchedule = dbSched newWorkspace.AutostartSchedule = dbSched
aReq.New = newWorkspace aReq.New = newWorkspace.WorkspaceTable()
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
} }
@@ -916,7 +901,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context() ctx = r.Context()
workspace = httpmw.WorkspaceParam(r) workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load() auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -925,7 +910,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
}) })
) )
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceTTLRequest var req codersdk.UpdateWorkspaceTTLRequest
if !httpapi.Read(ctx, rw, r, &req) { if !httpapi.Read(ctx, rw, r, &req) {
@@ -977,7 +962,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
newWorkspace := workspace newWorkspace := workspace
newWorkspace.Ttl = dbTTL newWorkspace.Ttl = dbTTL
aReq.New = newWorkspace aReq.New = newWorkspace.WorkspaceTable()
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
} }
@@ -995,19 +980,18 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) { func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
var ( var (
ctx = r.Context() ctx = r.Context()
workspace = httpmw.WorkspaceParam(r) oldWorkspace = httpmw.WorkspaceParam(r)
apiKey = httpmw.APIKey(r) apiKey = httpmw.APIKey(r)
oldWorkspace = workspace
auditor = api.Auditor.Load() auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
Action: database.AuditActionWrite, Action: database.AuditActionWrite,
OrganizationID: workspace.OrganizationID, OrganizationID: oldWorkspace.OrganizationID,
}) })
) )
aReq.Old = oldWorkspace aReq.Old = oldWorkspace.WorkspaceTable()
defer commitAudit() defer commitAudit()
var req codersdk.UpdateWorkspaceDormancy var req codersdk.UpdateWorkspaceDormancy
@@ -1016,7 +1000,7 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
} }
// If the workspace is already in the desired state do nothing! // If the workspace is already in the desired state do nothing!
if workspace.DormantAt.Valid == req.Dormant { if oldWorkspace.DormantAt.Valid == req.Dormant {
rw.WriteHeader(http.StatusNotModified) rw.WriteHeader(http.StatusNotModified)
return return
} }
@@ -1028,8 +1012,8 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
dormantAt.Time = dbtime.Now() dormantAt.Time = dbtime.Now()
} }
workspace, err := api.Database.UpdateWorkspaceDormantDeletingAt(ctx, database.UpdateWorkspaceDormantDeletingAtParams{ newWorkspace, err := api.Database.UpdateWorkspaceDormantDeletingAt(ctx, database.UpdateWorkspaceDormantDeletingAtParams{
ID: workspace.ID, ID: oldWorkspace.ID,
DormantAt: dormantAt, DormantAt: dormantAt,
}) })
if err != nil { if err != nil {
@@ -1041,26 +1025,26 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
} }
// We don't need to notify the owner if they are the one making the request. // We don't need to notify the owner if they are the one making the request.
if req.Dormant && apiKey.UserID != workspace.OwnerID { if req.Dormant && apiKey.UserID != newWorkspace.OwnerID {
initiator, initiatorErr := api.Database.GetUserByID(ctx, apiKey.UserID) initiator, initiatorErr := api.Database.GetUserByID(ctx, apiKey.UserID)
if initiatorErr != nil { if initiatorErr != nil {
api.Logger.Warn( api.Logger.Warn(
ctx, ctx,
"failed to fetch the user that marked the workspace as dormant", "failed to fetch the user that marked the workspace as dormant",
slog.Error(err), slog.Error(err),
slog.F("workspace_id", workspace.ID), slog.F("workspace_id", newWorkspace.ID),
slog.F("user_id", apiKey.UserID), slog.F("user_id", apiKey.UserID),
) )
} }
tmpl, tmplErr := api.Database.GetTemplateByID(ctx, workspace.TemplateID) tmpl, tmplErr := api.Database.GetTemplateByID(ctx, newWorkspace.TemplateID)
if tmplErr != nil { if tmplErr != nil {
api.Logger.Warn( api.Logger.Warn(
ctx, ctx,
"failed to fetch the template of the workspace marked as dormant", "failed to fetch the template of the workspace marked as dormant",
slog.Error(err), slog.Error(err),
slog.F("workspace_id", workspace.ID), slog.F("workspace_id", newWorkspace.ID),
slog.F("template_id", workspace.TemplateID), slog.F("template_id", newWorkspace.TemplateID),
) )
} }
@@ -1068,18 +1052,18 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
dormantTime := dbtime.Now().Add(time.Duration(tmpl.TimeTilDormant)) dormantTime := dbtime.Now().Add(time.Duration(tmpl.TimeTilDormant))
_, err = api.NotificationsEnqueuer.Enqueue( _, err = api.NotificationsEnqueuer.Enqueue(
ctx, ctx,
workspace.OwnerID, newWorkspace.OwnerID,
notifications.TemplateWorkspaceDormant, notifications.TemplateWorkspaceDormant,
map[string]string{ map[string]string{
"name": workspace.Name, "name": newWorkspace.Name,
"reason": "a " + initiator.Username + " request", "reason": "a " + initiator.Username + " request",
"timeTilDormant": humanize.Time(dormantTime), "timeTilDormant": humanize.Time(dormantTime),
}, },
"api", "api",
workspace.ID, newWorkspace.ID,
workspace.OwnerID, newWorkspace.OwnerID,
workspace.TemplateID, newWorkspace.TemplateID,
workspace.OrganizationID, newWorkspace.OrganizationID,
) )
if err != nil { if err != nil {
api.Logger.Warn(ctx, "failed to notify of workspace marked as dormant", slog.Error(err)) api.Logger.Warn(ctx, "failed to notify of workspace marked as dormant", slog.Error(err))
@@ -1087,6 +1071,16 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
} }
} }
// We have to refetch the workspace to get the joined in fields.
workspace, err := api.Database.GetWorkspaceByID(ctx, newWorkspace.ID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace.",
Detail: err.Error(),
})
return
}
data, err := api.workspaceData(ctx, []database.Workspace{workspace}) data, err := api.workspaceData(ctx, []database.Workspace{workspace})
if err != nil { if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -1095,29 +1089,22 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
}) })
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: "unable to find workspace owner's username",
})
return
}
// TODO: This is a strange error since it occurs after the mutatation.
// An example of why we should join in fields to prevent this forbidden error
// from being sent, when the action did succeed.
if len(data.templates) == 0 { if len(data.templates) == 0 {
httpapi.Forbidden(rw) httpapi.Forbidden(rw)
return return
} }
aReq.New = workspace aReq.New = newWorkspace
w, err := convertWorkspace( w, err := convertWorkspace(
apiKey.UserID, apiKey.UserID,
workspace, workspace,
data.builds[0], data.builds[0],
data.templates[0], data.templates[0],
owner.Username,
owner.AvatarURL,
api.Options.AllowWorkspaceRenames, api.Options.AllowWorkspaceRenames,
) )
if err != nil { if err != nil {
@@ -1371,7 +1358,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
return return
} }
aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -1379,7 +1366,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
OrganizationID: workspace.OrganizationID, OrganizationID: workspace.OrganizationID,
}) })
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
err := api.Database.FavoriteWorkspace(ctx, workspace.ID) err := api.Database.FavoriteWorkspace(ctx, workspace.ID)
if err != nil { if err != nil {
@@ -1390,7 +1377,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
return return
} }
aReq.New = workspace aReq.New = workspace.WorkspaceTable()
aReq.New.Favorite = true aReq.New.Favorite = true
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
@@ -1418,7 +1405,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
return return
} }
aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -1427,7 +1414,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
}) })
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
err := api.Database.UnfavoriteWorkspace(ctx, workspace.ID) err := api.Database.UnfavoriteWorkspace(ctx, workspace.ID)
if err != nil { if err != nil {
@@ -1437,7 +1424,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
}) })
return return
} }
aReq.New = workspace aReq.New = workspace.WorkspaceTable()
aReq.New.Favorite = false aReq.New.Favorite = false
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
@@ -1457,7 +1444,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
ctx = r.Context() ctx = r.Context()
workspace = httpmw.WorkspaceParam(r) workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load() auditor = api.Auditor.Load()
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor, Audit: *auditor,
Log: api.Logger, Log: api.Logger,
Request: r, Request: r,
@@ -1466,7 +1453,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
}) })
) )
defer commitAudit() defer commitAudit()
aReq.Old = workspace aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceAutomaticUpdatesRequest var req codersdk.UpdateWorkspaceAutomaticUpdatesRequest
if !httpapi.Read(ctx, rw, r, &req) { if !httpapi.Read(ctx, rw, r, &req) {
@@ -1499,7 +1486,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
newWorkspace := workspace newWorkspace := workspace
newWorkspace.AutomaticUpdates = database.AutomaticUpdates(req.AutomaticUpdates) newWorkspace.AutomaticUpdates = database.AutomaticUpdates(req.AutomaticUpdates)
aReq.New = newWorkspace aReq.New = newWorkspace.WorkspaceTable()
rw.WriteHeader(http.StatusNoContent) rw.WriteHeader(http.StatusNoContent)
} }
@@ -1658,25 +1645,11 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
return return
} }
owner, ok := userByID(workspace.OwnerID, data.users)
if !ok {
_ = sendEvent(ctx, codersdk.ServerSentEvent{
Type: codersdk.ServerSentEventTypeError,
Data: codersdk.Response{
Message: "Internal error fetching workspace resources.",
Detail: "unable to find workspace owner's username",
},
})
return
}
w, err := convertWorkspace( w, err := convertWorkspace(
apiKey.UserID, apiKey.UserID,
workspace, workspace,
data.builds[0], data.builds[0],
data.templates[0], data.templates[0],
owner.Username,
owner.AvatarURL,
api.Options.AllowWorkspaceRenames, api.Options.AllowWorkspaceRenames,
) )
if err != nil { if err != nil {
@@ -1778,7 +1751,6 @@ func (api *API) workspaceTimings(rw http.ResponseWriter, r *http.Request) {
type workspaceData struct { type workspaceData struct {
templates []database.Template templates []database.Template
builds []codersdk.WorkspaceBuild builds []codersdk.WorkspaceBuild
users []database.User
allowRenames bool allowRenames bool
} }
@@ -1808,7 +1780,7 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa
return workspaceData{}, xerrors.Errorf("get workspace builds: %w", err) return workspaceData{}, xerrors.Errorf("get workspace builds: %w", err)
} }
data, err := api.workspaceBuildsData(ctx, workspaces, builds) data, err := api.workspaceBuildsData(ctx, builds)
if err != nil { if err != nil {
return workspaceData{}, xerrors.Errorf("get workspace builds data: %w", err) return workspaceData{}, xerrors.Errorf("get workspace builds data: %w", err)
} }
@@ -1817,7 +1789,6 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa
builds, builds,
workspaces, workspaces,
data.jobs, data.jobs,
data.users,
data.resources, data.resources,
data.metadata, data.metadata,
data.agents, data.agents,
@@ -1833,7 +1804,6 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa
return workspaceData{ return workspaceData{
templates: templates, templates: templates,
builds: apiBuilds, builds: apiBuilds,
users: data.users,
allowRenames: api.Options.AllowWorkspaceRenames, allowRenames: api.Options.AllowWorkspaceRenames,
}, nil }, nil
} }
@@ -1847,10 +1817,6 @@ func convertWorkspaces(requesterID uuid.UUID, workspaces []database.Workspace, d
for _, template := range data.templates { for _, template := range data.templates {
templateByID[template.ID] = template templateByID[template.ID] = template
} }
userByID := map[uuid.UUID]database.User{}
for _, user := range data.users {
userByID[user.ID] = user
}
apiWorkspaces := make([]codersdk.Workspace, 0, len(workspaces)) apiWorkspaces := make([]codersdk.Workspace, 0, len(workspaces))
for _, workspace := range workspaces { for _, workspace := range workspaces {
@@ -1867,18 +1833,12 @@ func convertWorkspaces(requesterID uuid.UUID, workspaces []database.Workspace, d
if !exists { if !exists {
continue continue
} }
owner, exists := userByID[workspace.OwnerID]
if !exists {
continue
}
w, err := convertWorkspace( w, err := convertWorkspace(
requesterID, requesterID,
workspace, workspace,
build, build,
template, template,
owner.Username,
owner.AvatarURL,
data.allowRenames, data.allowRenames,
) )
if err != nil { if err != nil {
@@ -1895,8 +1855,6 @@ func convertWorkspace(
workspace database.Workspace, workspace database.Workspace,
workspaceBuild codersdk.WorkspaceBuild, workspaceBuild codersdk.WorkspaceBuild,
template database.Template, template database.Template,
username string,
avatarURL string,
allowRenames bool, allowRenames bool,
) (codersdk.Workspace, error) { ) (codersdk.Workspace, error) {
if requesterID == uuid.Nil { if requesterID == uuid.Nil {
@@ -1941,15 +1899,15 @@ func convertWorkspace(
CreatedAt: workspace.CreatedAt, CreatedAt: workspace.CreatedAt,
UpdatedAt: workspace.UpdatedAt, UpdatedAt: workspace.UpdatedAt,
OwnerID: workspace.OwnerID, OwnerID: workspace.OwnerID,
OwnerName: username, OwnerName: workspace.OwnerUsername,
OwnerAvatarURL: avatarURL, OwnerAvatarURL: workspace.OwnerAvatarUrl,
OrganizationID: workspace.OrganizationID, OrganizationID: workspace.OrganizationID,
OrganizationName: template.OrganizationName, OrganizationName: workspace.OrganizationName,
TemplateID: workspace.TemplateID, TemplateID: workspace.TemplateID,
LatestBuild: workspaceBuild, LatestBuild: workspaceBuild,
TemplateName: template.Name, TemplateName: workspace.TemplateName,
TemplateIcon: template.Icon, TemplateIcon: workspace.TemplateIcon,
TemplateDisplayName: template.DisplayName, TemplateDisplayName: workspace.TemplateDisplayName,
TemplateAllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, TemplateAllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs,
TemplateActiveVersionID: template.ActiveVersionID, TemplateActiveVersionID: template.ActiveVersionID,
TemplateRequireActiveVersion: template.RequireActiveVersion, TemplateRequireActiveVersion: template.RequireActiveVersion,
+26 -26
View File
@@ -392,7 +392,7 @@ func TestResolveAutostart(t *testing.T) {
defer cancel() defer cancel()
client, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) client, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
resp := dbfake.WorkspaceBuild(t, db, database.Workspace{ resp := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: member.ID, OwnerID: member.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
AutomaticUpdates: database.AutomaticUpdatesAlways, AutomaticUpdates: database.AutomaticUpdatesAlways,
@@ -456,22 +456,22 @@ func TestWorkspacesSortOrder(t *testing.T) {
}) })
// c-workspace should be running // c-workspace should be running
wsbC := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "c-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Do() wsbC := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "c-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Do()
// b-workspace should be stopped // b-workspace should be stopped
wsbB := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "b-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do() wsbB := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "b-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do()
// a-workspace should be running // a-workspace should be running
wsbA := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "a-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Do() wsbA := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "a-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Do()
// d-workspace should be stopped // d-workspace should be stopped
wsbD := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "d-workspace", OwnerID: secondUser.ID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do() wsbD := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "d-workspace", OwnerID: secondUser.ID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do()
// e-workspace should also be stopped // e-workspace should also be stopped
wsbE := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "e-workspace", OwnerID: secondUser.ID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do() wsbE := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "e-workspace", OwnerID: secondUser.ID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do()
// f-workspace is also stopped, but is marked as favorite // f-workspace is also stopped, but is marked as favorite
wsbF := dbfake.WorkspaceBuild(t, db, database.Workspace{Name: "f-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do() wsbF := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{Name: "f-workspace", OwnerID: firstUser.UserID, OrganizationID: firstUser.OrganizationID}).Seed(database.WorkspaceBuild{Transition: database.WorkspaceTransitionStop}).Do()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel() defer cancel()
@@ -905,7 +905,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
CreatedBy: owner.UserID, CreatedBy: owner.UserID,
}) })
makeWorkspace := func(workspace database.Workspace, job database.ProvisionerJob, transition database.WorkspaceTransition) (database.Workspace, database.WorkspaceBuild, database.ProvisionerJob) { makeWorkspace := func(workspace database.WorkspaceTable, job database.ProvisionerJob, transition database.WorkspaceTransition) (database.WorkspaceTable, database.WorkspaceBuild, database.ProvisionerJob) {
db := db db := db
workspace.OwnerID = owner.UserID workspace.OwnerID = owner.UserID
@@ -940,21 +940,21 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
} }
// pending // pending
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusPending), Name: string(database.WorkspaceStatusPending),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Valid: false}, StartedAt: sql.NullTime{Valid: false},
}, database.WorkspaceTransitionStart) }, database.WorkspaceTransitionStart)
// starting // starting
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStarting), Name: string(database.WorkspaceStatusStarting),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionStart) }, database.WorkspaceTransitionStart)
// running // running
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusRunning), Name: string(database.WorkspaceStatusRunning),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
CompletedAt: sql.NullTime{Time: time.Now(), Valid: true}, CompletedAt: sql.NullTime{Time: time.Now(), Valid: true},
@@ -962,14 +962,14 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart) }, database.WorkspaceTransitionStart)
// stopping // stopping
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStopping), Name: string(database.WorkspaceStatusStopping),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionStop) }, database.WorkspaceTransitionStop)
// stopped // stopped
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStopped), Name: string(database.WorkspaceStatusStopped),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -977,7 +977,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStop) }, database.WorkspaceTransitionStop)
// failed -- delete // failed -- delete
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusFailed) + "-deleted", Name: string(database.WorkspaceStatusFailed) + "-deleted",
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -986,7 +986,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionDelete) }, database.WorkspaceTransitionDelete)
// failed -- stop // failed -- stop
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusFailed) + "-stopped", Name: string(database.WorkspaceStatusFailed) + "-stopped",
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -995,7 +995,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStop) }, database.WorkspaceTransitionStop)
// canceling // canceling
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusCanceling), Name: string(database.WorkspaceStatusCanceling),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -1003,7 +1003,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart) }, database.WorkspaceTransitionStart)
// canceled // canceled
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusCanceled), Name: string(database.WorkspaceStatusCanceled),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -1012,14 +1012,14 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart) }, database.WorkspaceTransitionStart)
// deleting // deleting
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusDeleting), Name: string(database.WorkspaceStatusDeleting),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionDelete) }, database.WorkspaceTransitionDelete)
// deleted // deleted
makeWorkspace(database.Workspace{ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusDeleted), Name: string(database.WorkspaceStatusDeleted),
}, database.ProvisionerJob{ }, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true}, StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -1567,14 +1567,14 @@ func TestWorkspaceFilterManual(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel() defer cancel()
dormantWorkspace := dbfake.WorkspaceBuild(t, db, database.Workspace{ dormantWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user.UserID, OwnerID: user.UserID,
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
}).Do().Workspace }).Do().Workspace
// Create another workspace to validate that we do not return active workspaces. // Create another workspace to validate that we do not return active workspaces.
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
TemplateID: template.ID, TemplateID: template.ID,
OwnerID: user.UserID, OwnerID: user.UserID,
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
@@ -3246,8 +3246,8 @@ func TestWorkspaceFavoriteUnfavorite(t *testing.T) {
owner = coderdtest.CreateFirstUser(t, client) owner = coderdtest.CreateFirstUser(t, client)
memberClient, member = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) memberClient, member = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// This will be our 'favorite' workspace // This will be our 'favorite' workspace
wsb1 = dbfake.WorkspaceBuild(t, db, database.Workspace{OwnerID: member.ID, OrganizationID: owner.OrganizationID}).Do() wsb1 = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{OwnerID: member.ID, OrganizationID: owner.OrganizationID}).Do()
wsb2 = dbfake.WorkspaceBuild(t, db, database.Workspace{OwnerID: owner.UserID, OrganizationID: owner.OrganizationID}).Do() wsb2 = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{OwnerID: owner.UserID, OrganizationID: owner.OrganizationID}).Do()
) )
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
@@ -3324,7 +3324,7 @@ func TestWorkspaceUsageTracking(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil) client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
tmpDir := t.TempDir() tmpDir := t.TempDir()
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent { }).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -3371,7 +3371,7 @@ func TestWorkspaceUsageTracking(t *testing.T) {
ActivityBumpMillis: 8 * time.Hour.Milliseconds(), ActivityBumpMillis: 8 * time.Hour.Milliseconds(),
}) })
require.NoError(t, err) require.NoError(t, err)
r := dbfake.WorkspaceBuild(t, db, database.Workspace{ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -3598,7 +3598,7 @@ func TestWorkspaceTimings(t *testing.T) {
ActiveVersionID: version.ID, ActiveVersionID: version.ID,
CreatedBy: owner.UserID, CreatedBy: owner.UserID,
}) })
ws := dbgen.Workspace(t, db, database.Workspace{ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: owner.UserID, OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
TemplateID: template.ID, TemplateID: template.ID,
+1 -1
View File
@@ -191,7 +191,7 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
ActiveVersionID: templateVersion.ID, ActiveVersionID: templateVersion.ID,
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
ws = dbgen.Workspace(t, db, database.Workspace{ ws = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -162,7 +162,7 @@ type deps struct {
Agent database.WorkspaceAgent Agent database.WorkspaceAgent
Template database.Template Template database.Template
User database.User User database.User
Workspace database.Workspace Workspace database.WorkspaceTable
} }
// setupDeps sets up a set of test dependencies. // setupDeps sets up a set of test dependencies.
@@ -189,7 +189,7 @@ func setupDeps(t *testing.T, store database.Store, ps pubsub.Pubsub) deps {
OrganizationID: org.ID, OrganizationID: org.ID,
ActiveVersionID: tv.ID, ActiveVersionID: tv.ID,
}) })
ws := dbgen.Workspace(t, store, database.Workspace{ ws := dbgen.Workspace(t, store, database.WorkspaceTable{
TemplateID: tpl.ID, TemplateID: tpl.ID,
OwnerID: user.ID, OwnerID: user.ID,
OrganizationID: org.ID, OrganizationID: org.ID,
+1 -1
View File
@@ -149,7 +149,7 @@ func TestTracker_MultipleInstances(t *testing.T) {
numWorkspaces := 10 numWorkspaces := 10
w := make([]dbfake.WorkspaceResponse, numWorkspaces) w := make([]dbfake.WorkspaceResponse, numWorkspaces)
for i := 0; i < numWorkspaces; i++ { for i := 0; i < numWorkspaces; i++ {
wr := dbfake.WorkspaceBuild(t, db, database.Workspace{ wr := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: owner.UserID, OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
LastUsedAt: now, LastUsedAt: now,
+1 -1
View File
@@ -26,9 +26,9 @@ We track the following resources:
| Template<br><i>write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>active_version_id</td><td>true</td></tr><tr><td>activity_bump</td><td>true</td></tr><tr><td>allow_user_autostart</td><td>true</td></tr><tr><td>allow_user_autostop</td><td>true</td></tr><tr><td>allow_user_cancel_workspace_jobs</td><td>true</td></tr><tr><td>autostart_block_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_weeks</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>default_ttl</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deprecated</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>failure_ttl</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>max_port_sharing_level</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_display_name</td><td>false</td></tr><tr><td>organization_icon</td><td>false</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>organization_name</td><td>false</td></tr><tr><td>provisioner</td><td>true</td></tr><tr><td>require_active_version</td><td>true</td></tr><tr><td>time_til_dormant</td><td>true</td></tr><tr><td>time_til_dormant_autodelete</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table> | | Template<br><i>write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>active_version_id</td><td>true</td></tr><tr><td>activity_bump</td><td>true</td></tr><tr><td>allow_user_autostart</td><td>true</td></tr><tr><td>allow_user_autostop</td><td>true</td></tr><tr><td>allow_user_cancel_workspace_jobs</td><td>true</td></tr><tr><td>autostart_block_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_weeks</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>default_ttl</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deprecated</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>failure_ttl</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>max_port_sharing_level</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_display_name</td><td>false</td></tr><tr><td>organization_icon</td><td>false</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>organization_name</td><td>false</td></tr><tr><td>provisioner</td><td>true</td></tr><tr><td>require_active_version</td><td>true</td></tr><tr><td>time_til_dormant</td><td>true</td></tr><tr><td>time_til_dormant_autodelete</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table> |
| TemplateVersion<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> | | TemplateVersion<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
| User<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>avatar_url</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>github_com_user_id</td><td>false</td></tr><tr><td>hashed_one_time_passcode</td><td>false</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>must_reset_password</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>one_time_passcode_expires_at</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>theme_preference</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table> | | User<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>avatar_url</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>github_com_user_id</td><td>false</td></tr><tr><td>hashed_one_time_passcode</td><td>false</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>must_reset_password</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>one_time_passcode_expires_at</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>theme_preference</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table> |
| Workspace<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>automatic_updates</td><td>true</td></tr><tr><td>autostart_schedule</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deleting_at</td><td>true</td></tr><tr><td>dormant_at</td><td>true</td></tr><tr><td>favorite</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>ttl</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
| WorkspaceBuild<br><i>start, stop</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>provisioner_state</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table> | | WorkspaceBuild<br><i>start, stop</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>provisioner_state</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table> |
| WorkspaceProxy<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>version</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table> | | WorkspaceProxy<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>version</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table> |
| WorkspaceTable<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>automatic_updates</td><td>true</td></tr><tr><td>autostart_schedule</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deleting_at</td><td>true</td></tr><tr><td>dormant_at</td><td>true</td></tr><tr><td>favorite</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>ttl</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
<!-- End generated by 'make docs/admin/security/audit-logs.md'. --> <!-- End generated by 'make docs/admin/security/audit-logs.md'. -->
+4 -4
View File
@@ -370,8 +370,8 @@ func Test_diff(t *testing.T) {
runDiffTests(t, []diffTest{ runDiffTests(t, []diffTest{
{ {
name: "Create", name: "Create",
left: audit.Empty[database.Workspace](), left: audit.Empty[database.WorkspaceTable](),
right: database.Workspace{ right: database.WorkspaceTable{
ID: uuid.UUID{1}, ID: uuid.UUID{1},
CreatedAt: time.Now(), CreatedAt: time.Now(),
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
@@ -392,8 +392,8 @@ func Test_diff(t *testing.T) {
}, },
{ {
name: "NullSchedules", name: "NullSchedules",
left: audit.Empty[database.Workspace](), left: audit.Empty[database.WorkspaceTable](),
right: database.Workspace{ right: database.WorkspaceTable{
ID: uuid.UUID{1}, ID: uuid.UUID{1},
CreatedAt: time.Now(), CreatedAt: time.Now(),
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
+1 -1
View File
@@ -149,7 +149,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"one_time_passcode_expires_at": ActionTrack, "one_time_passcode_expires_at": ActionTrack,
"must_reset_password": ActionTrack, "must_reset_password": ActionTrack,
}, },
&database.Workspace{}: { &database.WorkspaceTable{}: {
"id": ActionTrack, "id": ActionTrack,
"created_at": ActionIgnore, // Never changes. "created_at": ActionIgnore, // Never changes.
"updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff. "updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
+1 -1
View File
@@ -148,7 +148,7 @@ func TestAnnouncementBanners(t *testing.T) {
err := client.UpdateAppearance(ctx, cfg) err := client.UpdateAppearance(ctx, cfg)
require.NoError(t, err) require.NoError(t, err)
r := dbfake.WorkspaceBuild(t, store, database.Workspace{ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
}).WithAgent().Do() }).WithAgent().Do()
+2 -2
View File
@@ -29,7 +29,7 @@ func TestJFrogXrayScan(t *testing.T) {
tac, ta := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin()) tac, ta := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin())
wsResp := dbfake.WorkspaceBuild(t, db, database.Workspace{ wsResp := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: ta.ID, OwnerID: ta.ID,
}).WithAgent().Do() }).WithAgent().Do()
@@ -85,7 +85,7 @@ func TestJFrogXrayScan(t *testing.T) {
memberClient, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) memberClient, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
wsResp := dbfake.WorkspaceBuild(t, db, database.Workspace{ wsResp := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
OwnerID: member.ID, OwnerID: member.ID,
}).WithAgent().Do() }).WithAgent().Do()
+2 -2
View File
@@ -136,7 +136,7 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S
var ( var (
template database.Template template database.Template
markedForDeletion []database.Workspace markedForDeletion []database.WorkspaceTable
) )
err = db.InTx(func(tx database.Store) error { err = db.InTx(func(tx database.Store) error {
ctx, span := tracing.StartSpanWithName(ctx, "(*schedule.EnterpriseTemplateScheduleStore).Set()-InTx()") ctx, span := tracing.StartSpanWithName(ctx, "(*schedule.EnterpriseTemplateScheduleStore).Set()-InTx()")
@@ -296,7 +296,7 @@ func (s *EnterpriseTemplateScheduleStore) updateWorkspaceBuild(ctx context.Conte
UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(), UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(),
// Use the job completion time as the time we calculate autostop from. // Use the job completion time as the time we calculate autostop from.
Now: job.CompletedAt.Time, Now: job.CompletedAt.Time,
Workspace: workspace, Workspace: workspace.WorkspaceTable(),
WorkspaceAutostart: workspace.AutostartSchedule.String, WorkspaceAutostart: workspace.AutostartSchedule.String,
}) })
if err != nil { if err != nil {
+7 -7
View File
@@ -211,7 +211,7 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) {
ActiveVersionID: templateVersion.ID, ActiveVersionID: templateVersion.ID,
CreatedBy: user.ID, CreatedBy: user.ID,
}) })
ws = dbgen.Workspace(t, db, database.Workspace{ ws = dbgen.Workspace(t, db, database.WorkspaceTable{
OrganizationID: organizationID, OrganizationID: organizationID,
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -357,7 +357,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) {
) )
// Create a workspace that will be shared by two builds. // Create a workspace that will be shared by two builds.
ws := dbgen.Workspace(t, db, database.Workspace{ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID, OrganizationID: templateJob.OrganizationID,
@@ -474,7 +474,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) {
for i, b := range builds { for i, b := range builds {
wsID := b.workspaceID wsID := b.workspaceID
if wsID == uuid.Nil { if wsID == uuid.Nil {
ws := dbgen.Workspace(t, db, database.Workspace{ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: b.templateID, TemplateID: b.templateID,
OrganizationID: templateJob.OrganizationID, OrganizationID: templateJob.OrganizationID,
@@ -642,21 +642,21 @@ func TestNotifications(t *testing.T) {
) )
// Add two dormant workspaces and one active workspace. // Add two dormant workspaces and one active workspace.
dormantWorkspaces := []database.Workspace{ dormantWorkspaces := []database.WorkspaceTable{
dbgen.Workspace(t, db, database.Workspace{ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID, OrganizationID: templateJob.OrganizationID,
LastUsedAt: time.Now().Add(-time.Hour), LastUsedAt: time.Now().Add(-time.Hour),
}), }),
dbgen.Workspace(t, db, database.Workspace{ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID, OrganizationID: templateJob.OrganizationID,
LastUsedAt: time.Now().Add(-time.Hour), LastUsedAt: time.Now().Add(-time.Hour),
}), }),
} }
dbgen.Workspace(t, db, database.Workspace{ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID, OwnerID: user.ID,
TemplateID: template.ID, TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID, OrganizationID: templateJob.OrganizationID,
+5 -5
View File
@@ -449,7 +449,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
TimeTilDormantMillis: inactiveTTL.Milliseconds(), TimeTilDormantMillis: inactiveTTL.Milliseconds(),
}) })
resp := dbfake.WorkspaceBuild(t, db, database.Workspace{ resp := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
TemplateID: template.ID, TemplateID: template.ID,
@@ -1260,18 +1260,18 @@ func TestWorkspacesFiltering(t *testing.T) {
CreatedBy: owner.UserID, CreatedBy: owner.UserID,
}).Do() }).Do()
dormantWS1 := dbfake.WorkspaceBuild(t, db, database.Workspace{ dormantWS1 := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID, OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
}).Do().Workspace }).Do().Workspace
dormantWS2 := dbfake.WorkspaceBuild(t, db, database.Workspace{ dormantWS2 := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID, OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
TemplateID: resp.Template.ID, TemplateID: resp.Template.ID,
}).Do().Workspace }).Do().Workspace
_ = dbfake.WorkspaceBuild(t, db, database.Workspace{ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID, OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
TemplateID: resp.Template.ID, TemplateID: resp.Template.ID,
@@ -1448,7 +1448,7 @@ func TestResolveAutostart(t *testing.T) {
client, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID) client, member := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
workspace := dbfake.WorkspaceBuild(t, db, database.Workspace{ workspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: member.ID, OwnerID: member.ID,
OrganizationID: owner.OrganizationID, OrganizationID: owner.OrganizationID,
TemplateID: version1.Template.ID, TemplateID: version1.Template.ID,
+1 -1
View File
@@ -199,7 +199,7 @@ func setupWorkspaceAndAgent(ctx context.Context, t *testing.T, client *codersdk.
CreatedBy: user.UserID, CreatedBy: user.UserID,
}). }).
Do() Do()
wbr := dbfake.WorkspaceBuild(t, db, database.Workspace{ wbr := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID, OrganizationID: user.OrganizationID,
OwnerID: user.UserID, OwnerID: user.UserID,
TemplateID: tv.Template.ID, TemplateID: tv.Template.ID,
+144
View File
@@ -0,0 +1,144 @@
package testutil
import (
"reflect"
"time"
"golang.org/x/xerrors"
)
type Random struct {
String func() string
Bool func() bool
Int func() int64
Uint func() uint64
Float func() float64
Complex func() complex128
Time func() time.Time
}
func NewRandom() *Random {
// Guaranteed to be random...
return &Random{
String: func() string { return "foo" },
Bool: func() bool { return true },
Int: func() int64 { return 500 },
Uint: func() uint64 { return 126 },
Float: func() float64 { return 3.14 },
Complex: func() complex128 { return 6.24 },
Time: func() time.Time { return time.Date(2020, 5, 2, 5, 19, 21, 30, time.UTC) },
}
}
// PopulateStruct does a best effort to populate a struct with random values.
func PopulateStruct(s interface{}, r *Random) error {
if r == nil {
r = NewRandom()
}
v := reflect.ValueOf(s)
if v.Kind() != reflect.Ptr || v.IsNil() {
return xerrors.Errorf("s must be a non-nil pointer")
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return xerrors.Errorf("s must be a pointer to a struct")
}
t := v.Type()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fieldName := field.Name
fieldValue := v.Field(i)
if !fieldValue.CanSet() {
continue // Skip if field is unexported
}
nv, err := populateValue(fieldValue, r)
if err != nil {
return xerrors.Errorf("%s : %w", fieldName, err)
}
v.Field(i).Set(nv)
}
return nil
}
func populateValue(v reflect.Value, r *Random) (reflect.Value, error) {
var err error
// Handle some special cases
switch v.Type() {
case reflect.TypeOf(time.Time{}):
v.Set(reflect.ValueOf(r.Time()))
return v, nil
default:
// Go to Kind instead
}
switch v.Kind() {
case reflect.Struct:
if err := PopulateStruct(v.Addr().Interface(), r); err != nil {
return v, err
}
case reflect.String:
v.SetString(r.String())
case reflect.Bool:
v.SetBool(true)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v.SetInt(r.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v.SetUint(r.Uint())
case reflect.Float32, reflect.Float64:
v.SetFloat(r.Float())
case reflect.Complex64, reflect.Complex128:
v.SetComplex(r.Complex())
case reflect.Array:
for i := 0; i < v.Len(); i++ {
nv, err := populateValue(v.Index(i), r)
if err != nil {
return v, xerrors.Errorf("array index %d : %w", i, err)
}
v.Index(i).Set(nv)
}
case reflect.Map:
m := reflect.MakeMap(v.Type())
// Set a value in the map
k := reflect.New(v.Type().Key())
kv := reflect.New(v.Type().Elem())
k, err = populateValue(k, r)
if err != nil {
return v, xerrors.Errorf("map key : %w", err)
}
kv, err = populateValue(kv, r)
if err != nil {
return v, xerrors.Errorf("map value : %w", err)
}
m.SetMapIndex(k, kv)
return m, nil
case reflect.Pointer:
return populateValue(v.Elem(), r)
case reflect.Slice:
s := reflect.MakeSlice(v.Type(), 2, 2)
sv, err := populateValue(reflect.New(v.Type().Elem()), r)
if err != nil {
return v, xerrors.Errorf("slice value : %w", err)
}
s.Index(0).Set(sv)
s.Index(1).Set(sv)
// reflect.AppendSlice(s, sv)
return s, nil
case reflect.Uintptr, reflect.UnsafePointer, reflect.Chan, reflect.Func, reflect.Interface:
// Unsupported
return v, xerrors.Errorf("%s is not supported", v.Kind())
default:
return v, xerrors.Errorf("unsupported kind %s", v.Kind())
}
return v, nil
}