diff --git a/cli/agent_test.go b/cli/agent_test.go
index 5d37f2c54c9d4..0a948c0c84e9a 100644
--- a/cli/agent_test.go
+++ b/cli/agent_test.go
@@ -35,7 +35,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).
@@ -71,7 +71,7 @@ func TestWorkspaceAgent(t *testing.T) {
AzureCertificates: certificates,
})
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -110,7 +110,7 @@ func TestWorkspaceAgent(t *testing.T) {
AWSCertificates: certificates,
})
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -151,7 +151,7 @@ func TestWorkspaceAgent(t *testing.T) {
})
owner := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: memberUser.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -205,7 +205,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -279,7 +279,7 @@ func TestWorkspaceAgent(t *testing.T) {
}
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],
OwnerID: memberUser.ID,
}).WithAgent().Do()
diff --git a/cli/configssh_test.go b/cli/configssh_test.go
index feead1e279e96..5bedd18cb27dc 100644
--- a/cli/configssh_test.go
+++ b/cli/configssh_test.go
@@ -83,7 +83,7 @@ func TestConfigSSH(t *testing.T) {
})
owner := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: memberUser.ID,
}).WithAgent().Do()
@@ -647,7 +647,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
if tt.hasAgent {
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -767,7 +767,7 @@ func TestConfigSSH_Hostnames(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: memberUser.ID,
}).Resource(resources...).Do()
diff --git a/cli/favorite_test.go b/cli/favorite_test.go
index 5cdf5e765c6cf..0668f03361e2d 100644
--- a/cli/favorite_test.go
+++ b/cli/favorite_test.go
@@ -19,7 +19,7 @@ func TestFavoriteUnfavorite(t *testing.T) {
client, db = coderdtest.NewWithDatabase(t, nil)
owner = coderdtest.CreateFirstUser(t, client)
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)
diff --git a/cli/gitssh_test.go b/cli/gitssh_test.go
index 83b873dec914e..6d574ae651aec 100644
--- a/cli/gitssh_test.go
+++ b/cli/gitssh_test.go
@@ -48,7 +48,7 @@ func prepareTestGitSSH(ctx context.Context, t *testing.T) (*agentsdk.Client, str
require.NoError(t, err)
// setup template
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
diff --git a/cli/list_test.go b/cli/list_test.go
index 82d372bd350aa..37f2f36f79278 100644
--- a/cli/list_test.go
+++ b/cli/list_test.go
@@ -26,7 +26,7 @@ func TestList(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// setup template
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID,
}).WithAgent().Do()
@@ -54,7 +54,7 @@ func TestList(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
owner := coderdtest.CreateFirstUser(t, client)
member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: memberUser.ID,
}).WithAgent().Do()
diff --git a/cli/portforward_test.go b/cli/portforward_test.go
index edef520c23dc6..29fccafb20ac1 100644
--- a/cli/portforward_test.go
+++ b/cli/portforward_test.go
@@ -290,12 +290,12 @@ func TestPortForward(t *testing.T) {
// runAgent creates a fake workspace and starts an agent locally for that
// workspace. The agent will be cleaned up on test completion.
// 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)
require.NoError(t, err, "specified user does not exist")
require.Greater(t, len(user.OrganizationIDs), 0, "user has no organizations")
orgID := user.OrganizationIDs[0]
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: orgID,
OwnerID: owner,
}).WithAgent().Do()
diff --git a/cli/schedule_test.go b/cli/schedule_test.go
index 11e0171417c04..bf18155be293a 100644
--- a/cli/schedule_test.go
+++ b/cli/schedule_test.go
@@ -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) {
r.Username = "testuser2" // ensure deterministic ordering
})
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "a-owner",
OwnerID: owner.UserID,
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},
}).WithAgent().Do()
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "b-owner",
OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID,
AutostartSchedule: sql.NullString{String: sched.String(), Valid: true},
}).WithAgent().Do()
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "c-member",
OwnerID: memberUser.ID,
OrganizationID: owner.OrganizationID,
Ttl: sql.NullInt64{Int64: 8 * time.Hour.Nanoseconds(), Valid: true},
}).WithAgent().Do()
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
Name: "d-member",
OwnerID: memberUser.ID,
OrganizationID: owner.OrganizationID,
diff --git a/cli/ssh_test.go b/cli/ssh_test.go
index d000e090a44e4..c2a14c90e39e6 100644
--- a/cli/ssh_test.go
+++ b/cli/ssh_test.go
@@ -53,14 +53,14 @@ import (
"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()
client, store := coderdtest.NewWithDatabase(t, nil)
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: user.ID,
}).WithAgent(mutations...).Do()
@@ -260,7 +260,7 @@ func TestSSH(t *testing.T) {
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: user.ID,
}).WithAgent().Do()
@@ -763,7 +763,7 @@ func TestSSH(t *testing.T) {
client.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: user.ID,
}).WithAgent().Do()
@@ -1370,7 +1370,7 @@ func TestSSH(t *testing.T) {
admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, admin)
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,
OwnerID: user.ID,
}).WithAgent().Do()
diff --git a/cli/start_test.go b/cli/start_test.go
index e9809ff4bc4ff..da5fb74cacf72 100644
--- a/cli/start_test.go
+++ b/cli/start_test.go
@@ -390,7 +390,7 @@ func TestStart_AlreadyRunning(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
owner := coderdtest.CreateFirstUser(t, client)
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,
OrganizationID: owner.OrganizationID,
}).Do()
@@ -417,7 +417,7 @@ func TestStart_Starting(t *testing.T) {
client := coderdtest.New(t, &coderdtest.Options{Pubsub: ps, Database: store})
owner := coderdtest.CreateFirstUser(t, client)
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,
OrganizationID: owner.OrganizationID,
}).
diff --git a/cli/state_test.go b/cli/state_test.go
index 08f2c96d14f7b..44b92b2c7960d 100644
--- a/cli/state_test.go
+++ b/cli/state_test.go
@@ -28,7 +28,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state")
- r := dbfake.WorkspaceBuild(t, store, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID,
}).
@@ -49,7 +49,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
templateAdmin, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state")
- r := dbfake.WorkspaceBuild(t, store, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID,
}).
@@ -69,7 +69,7 @@ func TestStatePull(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
_, taUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
wantState := []byte("some state")
- r := dbfake.WorkspaceBuild(t, store, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: taUser.ID,
}).
diff --git a/cli/support_test.go b/cli/support_test.go
index 6fe8f015c3f2b..274454acb7a48 100644
--- a/cli/support_test.go
+++ b/cli/support_test.go
@@ -53,7 +53,7 @@ func TestSupportBundle(t *testing.T) {
DeploymentValues: dc.Values,
})
owner := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: owner.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -132,7 +132,7 @@ func TestSupportBundle(t *testing.T) {
DeploymentValues: dc.Values,
})
admin := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: admin.OrganizationID,
OwnerID: admin.UserID,
}).Do() // without agent!
@@ -151,7 +151,7 @@ func TestSupportBundle(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
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,
OwnerID: member.ID,
}).WithAgent().Do()
diff --git a/cli/vscodessh_test.go b/cli/vscodessh_test.go
index f80b6b0b6029e..9ef2ab912a206 100644
--- a/cli/vscodessh_test.go
+++ b/cli/vscodessh_test.go
@@ -41,7 +41,7 @@ func TestVSCodeSSH(t *testing.T) {
admin.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
first := coderdtest.CreateFirstUser(t, admin)
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,
OwnerID: user.ID,
}).WithAgent().Do()
diff --git a/coderd/agentapi/api.go b/coderd/agentapi/api.go
index bea1fa5d881a3..f69f366b43d4e 100644
--- a/coderd/agentapi/api.go
+++ b/coderd/agentapi/api.go
@@ -106,7 +106,7 @@ func New(opts Options) *API {
if err != nil {
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.cachedWorkspaceID = getWorkspaceAgentByIDRow.Workspace.ID
+ a.cachedWorkspaceID = getWorkspaceAgentByIDRow.ID
a.mu.Unlock()
- return getWorkspaceAgentByIDRow.Workspace.ID, nil
+ return getWorkspaceAgentByIDRow.ID, nil
}
func (a *API) publishWorkspaceUpdate(ctx context.Context, agent *database.WorkspaceAgent) error {
diff --git a/coderd/agentapi/stats.go b/coderd/agentapi/stats.go
index 226f06732d4ee..3108d17f75b14 100644
--- a/coderd/agentapi/stats.go
+++ b/coderd/agentapi/stats.go
@@ -50,7 +50,7 @@ func (a *StatsAPI) UpdateStats(ctx context.Context, req *agentproto.UpdateStatsR
if err != nil {
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",
slog.F("interval", a.AgentStatsRefreshInterval),
slog.F("workspace_id", workspace.ID),
diff --git a/coderd/agentapi/stats_test.go b/coderd/agentapi/stats_test.go
index 57534208be110..d2c8e4f163df5 100644
--- a/coderd/agentapi/stats_test.go
+++ b/coderd/agentapi/stats_test.go
@@ -40,10 +40,11 @@ func TestUpdateStates(t *testing.T) {
Name: "tpl",
}
workspace = database.Workspace{
- ID: uuid.New(),
- OwnerID: user.ID,
- TemplateID: template.ID,
- Name: "xyz",
+ ID: uuid.New(),
+ OwnerID: user.ID,
+ TemplateID: template.ID,
+ Name: "xyz",
+ TemplateName: template.Name,
}
agent = database.WorkspaceAgent{
ID: uuid.New(),
@@ -127,10 +128,7 @@ func TestUpdateStates(t *testing.T) {
}
// Workspace gets fetched.
- dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{
- Workspace: workspace,
- TemplateName: template.Name,
- }, nil)
+ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
// We expect an activity bump because ConnectionCount > 0.
dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{
@@ -225,10 +223,7 @@ func TestUpdateStates(t *testing.T) {
}
// Workspace gets fetched.
- dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{
- Workspace: workspace,
- TemplateName: template.Name,
- }, nil)
+ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
// Workspace last used at gets bumped.
dbM.EXPECT().UpdateWorkspaceLastUsedAt(gomock.Any(), database.UpdateWorkspaceLastUsedAtParams{
@@ -350,10 +345,7 @@ func TestUpdateStates(t *testing.T) {
}
// Workspace gets fetched.
- dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{
- Workspace: workspace,
- TemplateName: template.Name,
- }, nil)
+ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
// We expect an activity bump because ConnectionCount > 0. However, the
// next autostart time will be set on the bump.
@@ -461,10 +453,7 @@ func TestUpdateStates(t *testing.T) {
}
// Workspace gets fetched.
- dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(database.GetWorkspaceByAgentIDRow{
- Workspace: workspace,
- TemplateName: template.Name,
- }, nil)
+ dbM.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agent.ID).Return(workspace, nil)
// We expect an activity bump because ConnectionCount > 0.
dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{
diff --git a/coderd/audit/diff.go b/coderd/audit/diff.go
index 04943c760a55e..8d5923d575054 100644
--- a/coderd/audit/diff.go
+++ b/coderd/audit/diff.go
@@ -12,7 +12,7 @@ type Auditable interface {
database.Template |
database.TemplateVersion |
database.User |
- database.Workspace |
+ database.WorkspaceTable |
database.GitSSHKey |
database.WorkspaceBuild |
database.AuditableGroup |
diff --git a/coderd/audit/request.go b/coderd/audit/request.go
index adaf3ce1f573c..88b637384eeda 100644
--- a/coderd/audit/request.go
+++ b/coderd/audit/request.go
@@ -82,7 +82,7 @@ func ResourceTarget[T Auditable](tgt T) string {
return typed.Name
case database.User:
return typed.Username
- case database.Workspace:
+ case database.WorkspaceTable:
return typed.Name
case database.WorkspaceBuild:
// this isn't used
@@ -133,7 +133,7 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
return typed.ID
case database.User:
return typed.ID
- case database.Workspace:
+ case database.WorkspaceTable:
return typed.ID
case database.WorkspaceBuild:
return typed.ID
@@ -181,7 +181,7 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeTemplateVersion
case database.User:
return database.ResourceTypeUser
- case database.Workspace:
+ case database.WorkspaceTable:
return database.ResourceTypeWorkspace
case database.WorkspaceBuild:
return database.ResourceTypeWorkspaceBuild
@@ -225,7 +225,7 @@ func ResourceRequiresOrgID[T Auditable]() bool {
switch any(tgt).(type) {
case database.Template, database.TemplateVersion:
return true
- case database.Workspace, database.WorkspaceBuild:
+ case database.WorkspaceTable, database.WorkspaceBuild:
return true
case database.AuditableGroup:
return true
diff --git a/coderd/autobuild/lifecycle_executor.go b/coderd/autobuild/lifecycle_executor.go
index 5bd8efe2b9fcf..400f0406aee0e 100644
--- a/coderd/autobuild/lifecycle_executor.go
+++ b/coderd/autobuild/lifecycle_executor.go
@@ -234,22 +234,24 @@ func (e *Executor) runOnce(t time.Time) Stats {
// threshold for inactivity.
if reason == database.BuildReasonDormancy {
wsOld := ws
- ws, err = tx.UpdateWorkspaceDormantDeletingAt(e.ctx, database.UpdateWorkspaceDormantDeletingAtParams{
+ wsNew, err := tx.UpdateWorkspaceDormantDeletingAt(e.ctx, database.UpdateWorkspaceDormantDeletingAtParams{
ID: ws.ID,
DormantAt: sql.NullTime{
Time: dbtime.Now(),
Valid: true,
},
})
-
- auditLog = &auditParams{
- Old: wsOld,
- New: ws,
- }
if err != nil {
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
log.Info(e.ctx, "dormant workspace",
@@ -510,8 +512,8 @@ func isEligibleForFailedStop(build database.WorkspaceBuild, job database.Provisi
}
type auditParams struct {
- Old database.Workspace
- New database.Workspace
+ Old database.WorkspaceTable
+ New database.WorkspaceTable
Success bool
}
@@ -521,7 +523,7 @@ func auditBuild(ctx context.Context, log slog.Logger, auditor audit.Auditor, par
status = http.StatusOK
}
- audit.BackgroundAudit(ctx, &audit.BackgroundAuditParams[database.Workspace]{
+ audit.BackgroundAudit(ctx, &audit.BackgroundAuditParams[database.WorkspaceTable]{
Audit: auditor,
Log: log,
UserID: params.New.OwnerID,
diff --git a/coderd/coderd_test.go b/coderd/coderd_test.go
index f19c8d4c533dd..9e1d9154a07bc 100644
--- a/coderd/coderd_test.go
+++ b/coderd/coderd_test.go
@@ -355,7 +355,7 @@ func TestCSRFExempt(t *testing.T) {
// Create a workspace.
const agentSlug = "james"
const appSlug = "web"
- wrk := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{
+ wrk := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{
OwnerID: owner.ID,
OrganizationID: first.OrganizationID,
}).
diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go
index a587788791c35..052f25450e6a5 100644
--- a/coderd/database/dbauthz/dbauthz.go
+++ b/coderd/database/dbauthz/dbauthz.go
@@ -2574,7 +2574,7 @@ func (q *querier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, 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)
}
@@ -2719,7 +2719,7 @@ func (q *querier) GetWorkspaces(ctx context.Context, arg database.GetWorkspacesP
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)
}
@@ -3009,7 +3009,7 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin
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)
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)
}
-func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) {
- fetch := func(ctx context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) {
- return q.db.GetWorkspaceByID(ctx, arg.ID)
+func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
+ fetch := func(ctx context.Context, arg database.UpdateWorkspaceParams) (database.WorkspaceTable, error) {
+ 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)
}
@@ -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)
}
-func (q *querier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) {
- fetch := func(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.Workspace, error) {
- return q.db.GetWorkspaceByID(ctx, arg.ID)
+func (q *querier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
+ fetch := func(ctx context.Context, arg database.UpdateWorkspaceDormantDeletingAtParams) (database.WorkspaceTable, error) {
+ 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)
}
@@ -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)
}
-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)
if err != nil {
return nil, xerrors.Errorf("get template by id: %w", err)
diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go
index f554d709ad4d0..6a34e88104ce1 100644
--- a/coderd/database/dbauthz/dbauthz_test.go
+++ b/coderd/database/dbauthz/dbauthz_test.go
@@ -90,7 +90,7 @@ func TestInTX(t *testing.T) {
Scope: rbac.ScopeAll,
}
- w := dbgen.Workspace(t, db, database.Workspace{})
+ w := dbgen.Workspace(t, db, database.WorkspaceTable{})
ctx := dbauthz.As(context.Background(), actor)
err := q.InTx(func(tx database.Store) error {
// The inner tx should use the parent's authz
@@ -108,7 +108,7 @@ func TestNew(t *testing.T) {
var (
db = dbmem.New()
- exp = dbgen.Workspace(t, db, database.Workspace{})
+ exp = dbgen.Workspace(t, db, database.WorkspaceTable{})
rec = &coderdtest.RecordingAuthorizer{
Wrapped: &coderdtest.FakeAuthorizer{},
}
@@ -123,7 +123,7 @@ func TestNew(t *testing.T) {
w, err := az.GetWorkspaceByID(ctx, exp.ID)
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))
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)
}))
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{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
@@ -498,7 +498,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
}))
s.Run("Build/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) {
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{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
@@ -507,7 +507,7 @@ func (s *MethodTestSuite) TestProvisionerJob() {
}))
s.Run("BuildFalseCancel/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) {
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{
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))
}))
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{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
@@ -1455,29 +1455,29 @@ func (s *MethodTestSuite) TestUser() {
func (s *MethodTestSuite) TestWorkspace() {
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)
}))
s.Run("GetWorkspaces", s.Subtest(func(db database.Store, check *expects) {
- _ = dbgen.Workspace(s.T(), db, database.Workspace{})
- _ = dbgen.Workspace(s.T(), db, database.Workspace{})
+ _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
+ _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
// No asserts here because SQLFilter.
check.Args(database.GetWorkspacesParams{}).Asserts()
}))
s.Run("GetAuthorizedWorkspaces", s.Subtest(func(db database.Store, check *expects) {
- _ = dbgen.Workspace(s.T(), db, database.Workspace{})
- _ = dbgen.Workspace(s.T(), db, database.Workspace{})
+ _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
+ _ = dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
// No asserts here because SQLFilter.
check.Args(database.GetWorkspacesParams{}, emptyPreparedAuthorized{}).Asserts()
}))
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})
check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns(b)
}))
s.Run("GetWorkspaceAgentByID", s.Subtest(func(db database.Store, check *expects) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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) {
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,
})
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))
}))
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})
check.Args(build.ID).Asserts(ws, policy.ActionRead).Returns(build)
}))
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})
check.Args(build.JobID).Asserts(ws, policy.ActionRead).Returns(build)
}))
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})
check.Args(database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{
WorkspaceID: ws.ID,
@@ -1635,13 +1635,13 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionRead).Returns(build)
}))
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})
check.Args(build.ID).Asserts(ws, policy.ActionRead).
Returns([]database.WorkspaceBuildParameter{})
}))
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: 2})
_ = 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) {
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,
})
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})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
- check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(database.GetWorkspaceByAgentIDRow{
- Workspace: ws,
- TemplateName: tpl.Name,
- })
+ check.Args(agt.ID).Asserts(ws, policy.ActionRead)
}))
s.Run("GetWorkspaceAgentsInLatestBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) {
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,
})
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)
}))
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{
OwnerID: ws.OwnerID,
Deleted: ws.Deleted,
Name: ws.Name,
- }).Asserts(ws, policy.ActionRead).Returns(ws)
+ }).Asserts(ws, policy.ActionRead)
}))
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()})
_ = 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})
check.Args(res.ID).Asserts(ws, policy.ActionRead).Returns(res)
}))
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()})
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{})
@@ -1709,7 +1706,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}))
s.Run("Start/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
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,
})
check.Args(database.InsertWorkspaceBuildParams{
@@ -1720,7 +1717,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}))
s.Run("Stop/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
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,
})
check.Args(database.InsertWorkspaceBuildParams{
@@ -1740,7 +1737,7 @@ func (s *MethodTestSuite) TestWorkspace() {
v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
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,
})
check.Args(database.InsertWorkspaceBuildParams{
@@ -1766,7 +1763,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})
require.NoError(s.T(), err)
- w := dbgen.Workspace(s.T(), db, database.Workspace{
+ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
TemplateID: t.ID,
})
// 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) {
- w := dbgen.Workspace(s.T(), db, database.Workspace{})
+ w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.InsertWorkspaceBuildParams{
WorkspaceID: w.ID,
Transition: database.WorkspaceTransitionDelete,
@@ -1789,7 +1786,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionDelete)
}))
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})
check.Args(database.InsertWorkspaceBuildParametersParams{
WorkspaceBuildID: b.ID,
@@ -1798,7 +1795,7 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionUpdate)
}))
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.Name = ""
check.Args(database.UpdateWorkspaceParams{
@@ -1806,20 +1803,20 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(w, policy.ActionUpdate).Returns(expected)
}))
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{
ID: w.ID,
}).Asserts(w, policy.ActionUpdate)
}))
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{
ID: w.ID,
AutomaticUpdates: database.AutomaticUpdatesAlways,
}).Asserts(w, policy.ActionUpdate)
}))
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()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
@@ -1830,13 +1827,13 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionUpdate).Returns()
}))
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{
ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns()
}))
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()})
check.Args(database.UpdateWorkspaceBuildDeadlineByIDParams{
ID: build.ID,
@@ -1845,46 +1842,46 @@ func (s *MethodTestSuite) TestWorkspace() {
}).Asserts(ws, policy.ActionUpdate)
}))
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
check.Args(ws.ID).Asserts(ws, policy.ActionDelete).Returns()
}))
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{
ID: ws.ID,
Deleted: true,
}).Asserts(ws, policy.ActionDelete).Returns()
}))
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{
ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns()
}))
s.Run("BatchUpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) {
- ws1 := dbgen.Workspace(s.T(), db, database.Workspace{})
- ws2 := dbgen.Workspace(s.T(), db, database.Workspace{})
+ ws1 := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
+ ws2 := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
check.Args(database.BatchUpdateWorkspaceLastUsedAtParams{
IDs: []uuid.UUID{ws1.ID, ws2.ID},
}).Asserts(rbac.ResourceWorkspace.All(), policy.ActionUpdate).Returns()
}))
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{
ID: ws.ID,
}).Asserts(ws, policy.ActionUpdate).Returns()
}))
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()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.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) {
- 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()})
dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
check.Args(database.ActivityBumpWorkspaceParams{
@@ -1893,12 +1890,12 @@ func (s *MethodTestSuite) TestWorkspace() {
}))
s.Run("FavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) {
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()
}))
s.Run("UnfavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) {
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()
}))
}
@@ -1906,7 +1903,7 @@ func (s *MethodTestSuite) TestWorkspace() {
func (s *MethodTestSuite) TestWorkspacePortSharing() {
s.Run("UpsertWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
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})
//nolint:gosimple // casting is not a simplification
check.Args(database.UpsertWorkspaceAgentPortShareParams{
@@ -1919,7 +1916,7 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
}))
s.Run("GetWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
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})
check.Args(database.GetWorkspaceAgentPortShareParams{
WorkspaceID: ps.WorkspaceID,
@@ -1929,13 +1926,13 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
}))
s.Run("ListWorkspaceAgentPortShares", s.Subtest(func(db database.Store, check *expects) {
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})
check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceAgentPortShare{ps})
}))
s.Run("DeleteWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) {
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})
check.Args(database.DeleteWorkspaceAgentPortShareParams{
WorkspaceID: ps.WorkspaceID,
@@ -1946,14 +1943,14 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
s.Run("DeleteWorkspaceAgentPortSharesByTemplate", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{})
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})
check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns()
}))
s.Run("ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{})
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})
check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns()
}))
@@ -2305,7 +2302,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns(l)
}))
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})
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)
}))
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()})
check.Args(database.UpdateWorkspaceBuildProvisionerStateByIDParams{
ID: build.ID,
@@ -2457,13 +2454,13 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Asserts(tpl, policy.ActionRead).Errors(sql.ErrNoRows)
}))
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()})
aRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: aBuild.JobID})
aAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: aRes.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()})
bRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: bBuild.JobID})
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()})
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()})
wJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild})
check.Args([]uuid.UUID{tJob.ID, wJob.ID}).
@@ -2486,7 +2483,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Returns([]database.WorkspaceResource{})
}))
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()})
_ = 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})
@@ -2495,7 +2492,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
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()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
@@ -2529,7 +2526,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
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()})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID})
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)
}))
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{})
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) {
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,
})
check.Args(database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{
@@ -2848,7 +2845,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
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{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
@@ -2857,7 +2854,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
check.Args(j.ID).Asserts(w, policy.ActionRead).Returns(t)
}))
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{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go
index 4f9d6ddc5b28c..616dd2afac619 100644
--- a/coderd/database/dbfake/dbfake.go
+++ b/coderd/database/dbfake/dbfake.go
@@ -32,7 +32,7 @@ var ownerCtx = dbauthz.As(context.Background(), rbac.Subject{
})
type WorkspaceResponse struct {
- Workspace database.Workspace
+ Workspace database.WorkspaceTable
Build database.WorkspaceBuild
AgentToken string
TemplateVersionResponse
@@ -44,7 +44,7 @@ type WorkspaceBuildBuilder struct {
t testing.TB
db database.Store
ps pubsub.Pubsub
- ws database.Workspace
+ ws database.WorkspaceTable
seed database.WorkspaceBuild
resources []*sdkproto.Resource
params []database.WorkspaceBuildParameter
@@ -60,7 +60,7 @@ type workspaceBuildDisposition struct {
// 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
// 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}
}
diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go
index a8ecabe752011..255c62f82aef2 100644
--- a/coderd/database/dbgen/dbgen.go
+++ b/coderd/database/dbgen/dbgen.go
@@ -232,7 +232,7 @@ func WorkspaceAgentScriptTiming(t testing.TB, db database.Store, orig database.W
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()
workspace, err := db.InsertWorkspace(genCtx, database.InsertWorkspaceParams{
diff --git a/coderd/database/dbgen/dbgen_test.go b/coderd/database/dbgen/dbgen_test.go
index 04f6d38d70d00..eec6e90d5904a 100644
--- a/coderd/database/dbgen/dbgen_test.go
+++ b/coderd/database/dbgen/dbgen_test.go
@@ -128,8 +128,8 @@ func TestGenerator(t *testing.T) {
t.Run("Workspace", func(t *testing.T) {
t.Parallel()
db := dbmem.New()
- exp := dbgen.Workspace(t, db, database.Workspace{})
- require.Equal(t, exp, must(db.GetWorkspaceByID(context.Background(), exp.ID)))
+ exp := dbgen.Workspace(t, db, database.WorkspaceTable{})
+ require.Equal(t, exp, must(db.GetWorkspaceByID(context.Background(), exp.ID)).WorkspaceTable())
})
t.Run("WorkspaceAgent", func(t *testing.T) {
diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go
index ef7a2e63f0b5f..24498d88c9dbc 100644
--- a/coderd/database/dbmem/dbmem.go
+++ b/coderd/database/dbmem/dbmem.go
@@ -81,7 +81,7 @@ func New() database.Store {
workspaceAgentLogs: make([]database.WorkspaceAgentLog, 0),
workspaceBuilds: make([]database.WorkspaceBuild, 0),
workspaceApps: make([]database.WorkspaceApp, 0),
- workspaces: make([]database.Workspace, 0),
+ workspaces: make([]database.WorkspaceTable, 0),
licenses: make([]database.License, 0),
workspaceProxies: make([]database.WorkspaceProxy, 0),
customRoles: make([]database.CustomRole, 0),
@@ -232,7 +232,7 @@ type data struct {
workspaceBuildParameters []database.WorkspaceBuildParameter
workspaceResourceMetadata []database.WorkspaceResourceMetadatum
workspaceResources []database.WorkspaceResource
- workspaces []database.Workspace
+ workspaces []database.WorkspaceTable
workspaceProxies []database.WorkspaceProxy
customRoles []database.CustomRole
provisionerJobTimings []database.ProvisionerJobTiming
@@ -445,9 +445,11 @@ func mapAgentStatus(dbAgent database.WorkspaceAgent, agentInactiveDisconnectTime
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))
for _, w := range workspaces {
+ extended := q.extendWorkspace(w)
+
wr := database.GetWorkspacesRow{
ID: w.ID,
CreatedAt: w.CreatedAt,
@@ -462,16 +464,33 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
LastUsedAt: w.LastUsedAt,
DormantAt: w.DormantAt,
DeletingAt: w.DeletingAt,
- Count: count,
AutomaticUpdates: w.AutomaticUpdates,
Favorite: w.Favorite,
- }
- for _, t := range q.templates {
- if t.ID == w.TemplateID {
- wr.TemplateName = t.Name
- break
- }
+ OwnerAvatarUrl: extended.OwnerAvatarUrl,
+ OwnerUsername: extended.OwnerUsername,
+
+ 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 {
@@ -488,15 +507,14 @@ func (q *FakeQuerier) convertToWorkspaceRowsNoLock(ctx context.Context, workspac
if pj, err := q.getProvisionerJobByIDNoLock(ctx, build.JobID); err == nil {
wr.LatestBuildStatus = pj.JobStatus
+ wr.LatestBuildCanceledAt = pj.CanceledAt
+ wr.LatestBuildCompletedAt = pj.CompletedAt
+ wr.LatestBuildError = pj.Error
}
wr.LatestBuildTransition = build.Transition
}
- if u, err := q.getUserByIDNoLock(w.OwnerID); err == nil {
- wr.Username = u.Username
- }
-
rows = append(rows, wr)
}
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) {
- for _, workspace := range q.workspaces {
- if workspace.ID == id {
- return workspace, nil
- }
+ return q.getWorkspaceNoLock(func(w database.WorkspaceTable) bool {
+ return w.ID == id
+ })
+}
+
+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
}
+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) {
var agent database.WorkspaceAgent
for _, _agent := range q.workspaceAgents {
@@ -551,13 +605,9 @@ func (q *FakeQuerier) getWorkspaceByAgentIDNoLock(_ context.Context, agentID uui
return database.Workspace{}, sql.ErrNoRows
}
- for _, workspace := range q.workspaces {
- if workspace.ID == build.WorkspaceID {
- return workspace, nil
- }
- }
-
- return database.Workspace{}, sql.ErrNoRows
+ return q.getWorkspaceNoLock(func(w database.WorkspaceTable) bool {
+ return w.ID == build.WorkspaceID
+ })
}
func (q *FakeQuerier) getWorkspaceBuildByIDNoLock(_ context.Context, id uuid.UUID) (database.WorkspaceBuild, error) {
@@ -986,14 +1036,14 @@ func (q *FakeQuerier) getLatestWorkspaceAppByTemplateIDUserIDSlugNoLock(ctx cont
LIMIT 1
*/
- var workspaces []database.Workspace
+ var workspaces []database.WorkspaceTable
for _, w := range q.workspaces {
if w.TemplateID != templateID || w.OwnerID != userID {
continue
}
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) {
return 1
} else if a.CreatedAt.Equal(b.CreatedAt) {
@@ -5644,7 +5694,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
continue
}
row := database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{
- Workspace: database.Workspace{
+ WorkspaceTable: database.WorkspaceTable{
ID: ws.ID,
TemplateID: ws.TemplateID,
},
@@ -5655,7 +5705,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
if err != nil {
return database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{}, sql.ErrNoRows
}
- row.Workspace.OwnerID = usr.ID
+ row.WorkspaceTable.OwnerID = usr.ID
// Keep track of the latest build number
rows = append(rows, row)
@@ -5672,7 +5722,7 @@ func (q *FakeQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(_ context.Conte
continue
}
- if rows[i].WorkspaceBuild.BuildNumber != latestBuildNumber[rows[i].Workspace.ID] {
+ if rows[i].WorkspaceBuild.BuildNumber != latestBuildNumber[rows[i].WorkspaceTable.ID] {
continue
}
@@ -6514,24 +6564,16 @@ func (q *FakeQuerier) GetWorkspaceBuildsCreatedAfter(_ context.Context, after ti
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()
defer q.mutex.RUnlock()
w, err := q.getWorkspaceByAgentIDNoLock(ctx, agentID)
if err != nil {
- return database.GetWorkspaceByAgentIDRow{}, err
- }
-
- tpl, err := q.getTemplateByIDNoLock(ctx, w.TemplateID)
- if err != nil {
- return database.GetWorkspaceByAgentIDRow{}, err
+ return database.Workspace{}, err
}
- return database.GetWorkspaceByAgentIDRow{
- Workspace: w,
- TemplateName: tpl.Name,
- }, nil
+ return w, nil
}
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()
defer q.mutex.RUnlock()
- var found *database.Workspace
+ var found *database.WorkspaceTable
for _, workspace := range q.workspaces {
workspace := workspace
if workspace.OwnerID != arg.OwnerID {
@@ -6568,7 +6610,7 @@ func (q *FakeQuerier) GetWorkspaceByOwnerIDAndName(_ context.Context, arg databa
}
}
if found != nil {
- return *found, nil
+ return q.extendWorkspace(*found), nil
}
return database.Workspace{}, sql.ErrNoRows
}
@@ -6794,11 +6836,11 @@ func (q *FakeQuerier) GetWorkspaces(ctx context.Context, arg database.GetWorkspa
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()
defer q.mutex.RUnlock()
- workspaces := []database.Workspace{}
+ workspaces := []database.WorkspaceTable{}
for _, workspace := range q.workspaces {
build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, workspace.ID)
if err != nil {
@@ -7759,16 +7801,16 @@ func (q *FakeQuerier) InsertUserLink(_ context.Context, args database.InsertUser
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 {
- return database.Workspace{}, err
+ return database.WorkspaceTable{}, err
}
q.mutex.Lock()
defer q.mutex.Unlock()
//nolint:gosimple
- workspace := database.Workspace{
+ workspace := database.WorkspaceTable{
ID: arg.ID,
CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt,
@@ -9408,9 +9450,9 @@ func (q *FakeQuerier) UpdateUserStatus(_ context.Context, arg database.UpdateUse
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 {
- return database.Workspace{}, err
+ return database.WorkspaceTable{}, err
}
q.mutex.Lock()
@@ -9425,7 +9467,7 @@ func (q *FakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWork
continue
}
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 database.Workspace{}, sql.ErrNoRows
+ return database.WorkspaceTable{}, sql.ErrNoRows
}
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
}
-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 {
- return database.Workspace{}, err
+ return database.WorkspaceTable{}, err
}
q.mutex.Lock()
defer q.mutex.Unlock()
@@ -9724,7 +9766,7 @@ func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg da
}
}
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 {
workspace.DeletingAt = sql.NullTime{
@@ -9736,7 +9778,7 @@ func (q *FakeQuerier) UpdateWorkspaceDormantDeletingAt(_ context.Context, arg da
q.workspaces[index] = workspace
return workspace, nil
}
- return database.Workspace{}, sql.ErrNoRows
+ return database.WorkspaceTable{}, sql.ErrNoRows
}
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
}
-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()
defer q.mutex.Unlock()
@@ -9828,7 +9870,7 @@ func (q *FakeQuerier) UpdateWorkspacesDormantDeletingAtByTemplateID(_ context.Co
return nil, err
}
- affectedRows := []database.Workspace{}
+ affectedRows := []database.WorkspaceTable{}
for i, ws := range q.workspaces {
if ws.TemplateID != arg.TemplateID {
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 {
if arg.OwnerID != uuid.Nil && workspace.OwnerID != arg.OwnerID {
continue
@@ -11159,7 +11201,7 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
if arg.Offset > 0 {
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:]
}
diff --git a/coderd/database/dbmetrics/dbmetrics.go b/coderd/database/dbmetrics/dbmetrics.go
index b543d27c5f833..c3e9de22fb0d8 100644
--- a/coderd/database/dbmetrics/dbmetrics.go
+++ b/coderd/database/dbmetrics/dbmetrics.go
@@ -1544,7 +1544,7 @@ func (m metricsStore) GetWorkspaceBuildsCreatedAfter(ctx context.Context, create
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()
workspace, err := m.s.GetWorkspaceByAgentID(ctx, agentID)
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
}
-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()
workspaces, err := m.s.GetWorkspacesEligibleForTransition(ctx, now)
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
}
-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()
workspace, err := m.s.InsertWorkspace(ctx, arg)
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
}
-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()
workspace, err := m.s.UpdateWorkspace(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspace").Observe(time.Since(start).Seconds())
@@ -2482,7 +2482,7 @@ func (m metricsStore) UpdateWorkspaceDeletedByID(ctx context.Context, arg databa
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()
ws, r0 := m.s.UpdateWorkspaceDormantDeletingAt(ctx, arg)
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
}
-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()
r0, r1 := m.s.UpdateWorkspacesDormantDeletingAtByTemplateID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspacesDormantDeletingAtByTemplateID").Observe(time.Since(start).Seconds())
diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go
index fb8bb1a55e00d..b3c7b9e7615d3 100644
--- a/coderd/database/dbmock/dbmock.go
+++ b/coderd/database/dbmock/dbmock.go
@@ -3234,10 +3234,10 @@ func (mr *MockStoreMockRecorder) GetWorkspaceBuildsCreatedAfter(arg0, arg1 any)
}
// 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()
ret := m.ctrl.Call(m, "GetWorkspaceByAgentID", arg0, arg1)
- ret0, _ := ret[0].(database.GetWorkspaceByAgentIDRow)
+ ret0, _ := ret[0].(database.Workspace)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -3474,10 +3474,10 @@ func (mr *MockStoreMockRecorder) GetWorkspaces(arg0, arg1 any) *gomock.Call {
}
// 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()
ret := m.ctrl.Call(m, "GetWorkspacesEligibleForTransition", arg0, arg1)
- ret0, _ := ret[0].([]database.Workspace)
+ ret0, _ := ret[0].([]database.WorkspaceTable)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -4021,10 +4021,10 @@ func (mr *MockStoreMockRecorder) InsertUserLink(arg0, arg1 any) *gomock.Call {
}
// 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()
ret := m.ctrl.Call(m, "InsertWorkspace", arg0, arg1)
- ret0, _ := ret[0].(database.Workspace)
+ ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5041,10 +5041,10 @@ func (mr *MockStoreMockRecorder) UpdateUserStatus(arg0, arg1 any) *gomock.Call {
}
// 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()
ret := m.ctrl.Call(m, "UpdateWorkspace", arg0, arg1)
- ret0, _ := ret[0].(database.Workspace)
+ ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5224,10 +5224,10 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceDeletedByID(arg0, arg1 any) *gom
}
// 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()
ret := m.ctrl.Call(m, "UpdateWorkspaceDormantDeletingAt", arg0, arg1)
- ret0, _ := ret[0].(database.Workspace)
+ ret0, _ := ret[0].(database.WorkspaceTable)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -5296,10 +5296,10 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceTTL(arg0, arg1 any) *gomock.Call
}
// 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()
ret := m.ctrl.Call(m, "UpdateWorkspacesDormantDeletingAtByTemplateID", arg0, arg1)
- ret0, _ := ret[0].([]database.Workspace)
+ ret0, _ := ret[0].([]database.WorkspaceTable)
ret1, _ := ret[1].(error)
return ret0, ret1
}
diff --git a/coderd/database/dbpurge/dbpurge_test.go b/coderd/database/dbpurge/dbpurge_test.go
index 8353a1cbdcd1b..75c73700d1e4f 100644
--- a/coderd/database/dbpurge/dbpurge_test.go
+++ b/coderd/database/dbpurge/dbpurge_test.go
@@ -195,7 +195,7 @@ func TestDeleteOldWorkspaceAgentLogs(t *testing.T) {
// Workspace A was built twice before the threshold, and never connected on
// 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)
wbA2 := mustCreateWorkspaceBuild(t, db, org, tv, wsA.ID, beforeThreshold, 2)
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")
// 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)
wbB2 := mustCreateWorkspaceBuild(t, db, org, tv, wsB.ID, beforeThreshold, 2)
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")
// 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)
wbC2 := mustCreateWorkspaceBuild(t, db, org, tv, wsC.ID, afterThreshold, 2)
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")
// 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)
wbD2 := mustCreateWorkspaceBuild(t, db, org, tv, wsD.ID, afterThreshold, 2)
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")
// 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)
agentE1 := mustCreateAgent(t, db, wbE1)
mustCreateAgentLogs(ctx, t, db, agentE1, nil, "agent e1 logs should be retained")
diff --git a/coderd/database/dbrollup/dbrollup_test.go b/coderd/database/dbrollup/dbrollup_test.go
index 6c8e96b847b80..0c32ddc9a9c9a 100644
--- a/coderd/database/dbrollup/dbrollup_test.go
+++ b/coderd/database/dbrollup/dbrollup_test.go
@@ -64,7 +64,7 @@ func TestRollup_TwoInstancesUseLocking(t *testing.T) {
user = dbgen.User(t, db, database.User{Name: "user1"})
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})
- 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})
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})
@@ -151,7 +151,7 @@ func TestRollupTemplateUsageStats(t *testing.T) {
user = dbgen.User(t, db, database.User{Name: "user1"})
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})
- 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})
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})
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 382cab743fb39..3a9a5a7a2d8f6 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -1701,6 +1701,39 @@ CREATE TABLE workspaces (
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 provisioner_job_logs ALTER COLUMN id SET DEFAULT nextval('provisioner_job_logs_id_seq'::regclass);
diff --git a/coderd/database/gentest/models_test.go b/coderd/database/gentest/models_test.go
index c1d2ea4999668..7cd54224cfaf2 100644
--- a/coderd/database/gentest/models_test.go
+++ b/coderd/database/gentest/models_test.go
@@ -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 {
names := make([]string, len(fields))
for i, field := range fields {
diff --git a/coderd/database/migrations/000269_workspace_with_names.down.sql b/coderd/database/migrations/000269_workspace_with_names.down.sql
new file mode 100644
index 0000000000000..dd9c23c2f36c5
--- /dev/null
+++ b/coderd/database/migrations/000269_workspace_with_names.down.sql
@@ -0,0 +1 @@
+DROP VIEW workspaces_expanded;
diff --git a/coderd/database/migrations/000269_workspace_with_names.up.sql b/coderd/database/migrations/000269_workspace_with_names.up.sql
new file mode 100644
index 0000000000000..8264b17d8bbc1
--- /dev/null
+++ b/coderd/database/migrations/000269_workspace_with_names.up.sql
@@ -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.';
diff --git a/coderd/database/modelmethods.go b/coderd/database/modelmethods.go
index 846de6e36aa47..a74ddf29bfcf9 100644
--- a/coderd/database/modelmethods.go
+++ b/coderd/database/modelmethods.go
@@ -192,12 +192,36 @@ func (gm GroupMember) RBACObject() rbac.Object {
return rbac.ResourceGroupMember.WithID(gm.UserID).InOrg(gm.OrganizationID).WithOwner(gm.UserID.String())
}
-func (w GetWorkspaceByAgentIDRow) RBACObject() rbac.Object {
- return w.Workspace.RBACObject()
+// WorkspaceTable converts a Workspace to it's reduced version.
+// 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 {
- // If a workspace is locked it cannot be accessed.
+ return w.WorkspaceTable().RBACObject()
+}
+
+func (w WorkspaceTable) RBACObject() rbac.Object {
if w.DormantAt.Valid {
return w.DormantRBAC()
}
@@ -207,7 +231,7 @@ func (w Workspace) RBACObject() rbac.Object {
WithOwner(w.OwnerID.String())
}
-func (w Workspace) DormantRBAC() rbac.Object {
+func (w WorkspaceTable) DormantRBAC() rbac.Object {
return rbac.ResourceWorkspaceDormant.
WithID(w.ID).
InOrg(w.OrganizationID).
@@ -389,21 +413,31 @@ func ConvertWorkspaceRows(rows []GetWorkspacesRow) []Workspace {
workspaces := make([]Workspace, len(rows))
for i, r := range rows {
workspaces[i] = Workspace{
- ID: r.ID,
- CreatedAt: r.CreatedAt,
- UpdatedAt: r.UpdatedAt,
- OwnerID: r.OwnerID,
- OrganizationID: r.OrganizationID,
- TemplateID: r.TemplateID,
- Deleted: r.Deleted,
- Name: r.Name,
- AutostartSchedule: r.AutostartSchedule,
- Ttl: r.Ttl,
- LastUsedAt: r.LastUsedAt,
- DormantAt: r.DormantAt,
- DeletingAt: r.DeletingAt,
- AutomaticUpdates: r.AutomaticUpdates,
- Favorite: r.Favorite,
+ ID: r.ID,
+ CreatedAt: r.CreatedAt,
+ UpdatedAt: r.UpdatedAt,
+ OwnerID: r.OwnerID,
+ OrganizationID: r.OrganizationID,
+ TemplateID: r.TemplateID,
+ Deleted: r.Deleted,
+ Name: r.Name,
+ AutostartSchedule: r.AutostartSchedule,
+ Ttl: r.Ttl,
+ LastUsedAt: r.LastUsedAt,
+ DormantAt: r.DormantAt,
+ DeletingAt: r.DeletingAt,
+ AutomaticUpdates: r.AutomaticUpdates,
+ 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,
}
}
diff --git a/coderd/database/modelqueries.go b/coderd/database/modelqueries.go
index 1274608a7d276..9888027e01559 100644
--- a/coderd/database/modelqueries.go
+++ b/coderd/database/modelqueries.go
@@ -288,10 +288,18 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
+ &i.OwnerAvatarUrl,
+ &i.OwnerUsername,
+ &i.OrganizationName,
+ &i.OrganizationDisplayName,
+ &i.OrganizationIcon,
+ &i.OrganizationDescription,
&i.TemplateName,
+ &i.TemplateDisplayName,
+ &i.TemplateIcon,
+ &i.TemplateDescription,
&i.TemplateVersionID,
&i.TemplateVersionName,
- &i.Username,
&i.LatestBuildCompletedAt,
&i.LatestBuildCanceledAt,
&i.LatestBuildError,
diff --git a/coderd/database/modelqueries_internal_test.go b/coderd/database/modelqueries_internal_test.go
index 4977120e88135..992eb269ddc14 100644
--- a/coderd/database/modelqueries_internal_test.go
+++ b/coderd/database/modelqueries_internal_test.go
@@ -2,8 +2,11 @@ package database
import (
"testing"
+ "time"
"github.com/stretchr/testify/require"
+
+ "github.com/coder/coder/v2/testutil"
)
func TestIsAuthorizedQuery(t *testing.T) {
@@ -13,3 +16,41 @@ func TestIsAuthorizedQuery(t *testing.T) {
_, err := insertAuthorizedFilter(query, "")
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.")
+}
diff --git a/coderd/database/models.go b/coderd/database/models.go
index c44aa6011bc22..1207587d46529 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -2902,23 +2902,33 @@ type VisibleUser struct {
AvatarURL string `db:"avatar_url" json:"avatar_url"`
}
+// Joins in the display name information such as username, avatar, and organization name.
type Workspace 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"`
+ 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 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 {
@@ -3184,3 +3194,22 @@ type WorkspaceResourceMetadatum struct {
Sensitive bool `db:"sensitive" json:"sensitive"`
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"`
+}
diff --git a/coderd/database/querier.go b/coderd/database/querier.go
index cb126f83af32f..fcb58a7d6e305 100644
--- a/coderd/database/querier.go
+++ b/coderd/database/querier.go
@@ -319,7 +319,7 @@ type sqlcQuerier interface {
GetWorkspaceBuildStatsByTemplates(ctx context.Context, since time.Time) ([]GetWorkspaceBuildStatsByTemplatesRow, error)
GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg GetWorkspaceBuildsByWorkspaceIDParams) ([]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)
GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWorkspaceByOwnerIDAndNameParams) (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
// be used in a WHERE clause.
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)
// We use the organization_id as the id
// 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(ctx context.Context, arg InsertUserGroupsByNameParams) 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)
InsertWorkspaceAgentLogSources(ctx context.Context, arg InsertWorkspaceAgentLogSourcesParams) ([]WorkspaceAgentLogSource, error)
InsertWorkspaceAgentLogs(ctx context.Context, arg InsertWorkspaceAgentLogsParams) ([]WorkspaceAgentLog, error)
@@ -469,7 +469,7 @@ type sqlcQuerier interface {
UpdateUserQuietHoursSchedule(ctx context.Context, arg UpdateUserQuietHoursScheduleParams) (User, error)
UpdateUserRoles(ctx context.Context, arg UpdateUserRolesParams) (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
UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context, arg UpdateWorkspaceAgentLifecycleStateByIDParams) error
UpdateWorkspaceAgentLogOverflowByID(ctx context.Context, arg UpdateWorkspaceAgentLogOverflowByIDParams) error
@@ -482,13 +482,13 @@ type sqlcQuerier interface {
UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg UpdateWorkspaceBuildDeadlineByIDParams) error
UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg UpdateWorkspaceBuildProvisionerStateByIDParams) 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
// This allows editing the properties of a workspace proxy.
UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error)
UpdateWorkspaceProxyDeleted(ctx context.Context, arg UpdateWorkspaceProxyDeletedParams) 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
UpsertAppSecurityKey(ctx context.Context, value string) error
UpsertApplicationName(ctx context.Context, value string) error
diff --git a/coderd/database/querier_test.go b/coderd/database/querier_test.go
index dfa024464de9b..58c9626f2c9bf 100644
--- a/coderd/database/querier_test.go
+++ b/coderd/database/querier_test.go
@@ -416,7 +416,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
OrganizationID: org.ID,
CreatedBy: user1.ID,
})
- workspace1 := dbgen.Workspace(t, db, database.Workspace{
+ workspace1 := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user1.ID,
OrganizationID: org.ID,
TemplateID: template1.ID,
@@ -435,7 +435,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
CreatedBy: user1.ID,
OrganizationID: org.ID,
})
- workspace2 := dbgen.Workspace(t, db, database.Workspace{
+ workspace2 := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user2.ID,
OrganizationID: org.ID,
TemplateID: template2.ID,
@@ -577,7 +577,7 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
OrganizationID: org.ID,
CreatedBy: user.ID,
})
- workspace := dbgen.Workspace(t, db, database.Workspace{
+ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.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)
if args.CreateWorkspace {
- wrk := dbgen.Workspace(t, db, database.Workspace{
+ wrk := dbgen.Workspace(t, db, database.WorkspaceTable{
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
OwnerID: tpl.CreatedBy,
diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go
index 913d3a040e8b8..45cbef3f5e1d8 100644
--- a/coderd/database/queries.sql.go
+++ b/coderd/database/queries.sql.go
@@ -11117,7 +11117,7 @@ WHERE
`
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"`
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)
var i GetWorkspaceAgentAndLatestBuildByAuthTokenRow
err := row.Scan(
- &i.Workspace.ID,
- &i.Workspace.CreatedAt,
- &i.Workspace.UpdatedAt,
- &i.Workspace.OwnerID,
- &i.Workspace.OrganizationID,
- &i.Workspace.TemplateID,
- &i.Workspace.Deleted,
- &i.Workspace.Name,
- &i.Workspace.AutostartSchedule,
- &i.Workspace.Ttl,
- &i.Workspace.LastUsedAt,
- &i.Workspace.DormantAt,
- &i.Workspace.DeletingAt,
- &i.Workspace.AutomaticUpdates,
- &i.Workspace.Favorite,
+ &i.WorkspaceTable.ID,
+ &i.WorkspaceTable.CreatedAt,
+ &i.WorkspaceTable.UpdatedAt,
+ &i.WorkspaceTable.OwnerID,
+ &i.WorkspaceTable.OrganizationID,
+ &i.WorkspaceTable.TemplateID,
+ &i.WorkspaceTable.Deleted,
+ &i.WorkspaceTable.Name,
+ &i.WorkspaceTable.AutostartSchedule,
+ &i.WorkspaceTable.Ttl,
+ &i.WorkspaceTable.LastUsedAt,
+ &i.WorkspaceTable.DormantAt,
+ &i.WorkspaceTable.DeletingAt,
+ &i.WorkspaceTable.AutomaticUpdates,
+ &i.WorkspaceTable.Favorite,
&i.WorkspaceAgent.ID,
&i.WorkspaceAgent.CreatedAt,
&i.WorkspaceAgent.UpdatedAt,
@@ -14539,12 +14539,9 @@ func (q *sqlQuerier) GetDeploymentWorkspaceStats(ctx context.Context) (GetDeploy
const getWorkspaceByAgentID = `-- name: GetWorkspaceByAgentID :one
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,
- templates.name as template_name
+ 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
- workspaces
-INNER JOIN
- templates ON workspaces.template_id = templates.id
+ workspaces_expanded as workspaces
WHERE
workspaces.id = (
SELECT
@@ -14570,40 +14567,44 @@ WHERE
)
`
-type GetWorkspaceByAgentIDRow struct {
- 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) {
+func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUID) (Workspace, error) {
row := q.db.QueryRowContext(ctx, getWorkspaceByAgentID, agentID)
- var i GetWorkspaceByAgentIDRow
+ var i Workspace
err := row.Scan(
- &i.Workspace.ID,
- &i.Workspace.CreatedAt,
- &i.Workspace.UpdatedAt,
- &i.Workspace.OwnerID,
- &i.Workspace.OrganizationID,
- &i.Workspace.TemplateID,
- &i.Workspace.Deleted,
- &i.Workspace.Name,
- &i.Workspace.AutostartSchedule,
- &i.Workspace.Ttl,
- &i.Workspace.LastUsedAt,
- &i.Workspace.DormantAt,
- &i.Workspace.DeletingAt,
- &i.Workspace.AutomaticUpdates,
- &i.Workspace.Favorite,
+ &i.ID,
+ &i.CreatedAt,
+ &i.UpdatedAt,
+ &i.OwnerID,
+ &i.OrganizationID,
+ &i.TemplateID,
+ &i.Deleted,
+ &i.Name,
+ &i.AutostartSchedule,
+ &i.Ttl,
+ &i.LastUsedAt,
+ &i.DormantAt,
+ &i.DeletingAt,
+ &i.AutomaticUpdates,
+ &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
}
const getWorkspaceByID = `-- name: GetWorkspaceByID :one
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
- workspaces
+ workspaces_expanded
WHERE
id = $1
LIMIT
@@ -14629,15 +14630,25 @@ func (q *sqlQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Worksp
&i.DeletingAt,
&i.AutomaticUpdates,
&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
}
const getWorkspaceByOwnerIDAndName = `-- name: GetWorkspaceByOwnerIDAndName :one
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
- workspaces
+ workspaces_expanded as workspaces
WHERE
owner_id = $1
AND deleted = $2
@@ -14670,15 +14681,25 @@ func (q *sqlQuerier) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWo
&i.DeletingAt,
&i.AutomaticUpdates,
&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
}
const getWorkspaceByWorkspaceAppID = `-- name: GetWorkspaceByWorkspaceAppID :one
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
- workspaces
+ workspaces_expanded as workspaces
WHERE
workspaces.id = (
SELECT
@@ -14730,6 +14751,16 @@ func (q *sqlQuerier) GetWorkspaceByWorkspaceAppID(ctx context.Context, workspace
&i.DeletingAt,
&i.AutomaticUpdates,
&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
}
@@ -14781,18 +14812,16 @@ SELECT
),
filtered_workspaces 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,
- COALESCE(template.name, 'unknown') as template_name,
+ 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,
latest_build.template_version_id,
latest_build.template_version_name,
- users.username as username,
latest_build.completed_at as latest_build_completed_at,
latest_build.canceled_at as latest_build_canceled_at,
latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status
FROM
- workspaces
+ workspaces_expanded as workspaces
JOIN
users
ON
@@ -14931,7 +14960,7 @@ WHERE
-- Filter by owner_name
AND CASE
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
END
-- Filter by template_name
@@ -15023,7 +15052,7 @@ WHERE
-- @authorize_filter
), filtered_workspaces_order AS (
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
filtered_workspaces fw
ORDER BY
@@ -15033,7 +15062,7 @@ WHERE
latest_build_canceled_at IS NULL AND
latest_build_error IS NULL AND
latest_build_transition = 'start'::workspace_transition) DESC,
- LOWER(username) ASC,
+ LOWER(owner_username) ASC,
LOWER(name) ASC
LIMIT
CASE
@@ -15044,7 +15073,7 @@ WHERE
$20
), filtered_workspaces_order_with_summary AS (
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
filtered_workspaces_order fwo
-- 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
'never'::automatic_updates, -- automatic_updates
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_display_name
+ '', -- template_icon
+ '', -- template_description
+ -- Extra columns added to ` + "`" + `filtered_workspaces` + "`" + `
'00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id
'', -- 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_canceled_at,
'', -- latest_build_error
@@ -15085,7 +15122,7 @@ WHERE
filtered_workspaces
)
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
FROM
filtered_workspaces_order_with_summary fwos
@@ -15119,31 +15156,39 @@ type GetWorkspacesParams struct {
}
type GetWorkspacesRow 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 bool `db:"favorite" json:"favorite"`
- TemplateName string `db:"template_name" json:"template_name"`
- TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
- TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"`
- Username string `db:"username" json:"username"`
- 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"`
+ 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 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"`
+ 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.
@@ -15197,10 +15242,18 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
+ &i.OwnerAvatarUrl,
+ &i.OwnerUsername,
+ &i.OrganizationName,
+ &i.OrganizationDisplayName,
+ &i.OrganizationIcon,
+ &i.OrganizationDescription,
&i.TemplateName,
+ &i.TemplateDisplayName,
+ &i.TemplateIcon,
+ &i.TemplateDescription,
&i.TemplateVersionID,
&i.TemplateVersionName,
- &i.Username,
&i.LatestBuildCompletedAt,
&i.LatestBuildCanceledAt,
&i.LatestBuildError,
@@ -15295,15 +15348,15 @@ WHERE
) 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)
if err != nil {
return nil, err
}
defer rows.Close()
- var items []Workspace
+ var items []WorkspaceTable
for rows.Next() {
- var i Workspace
+ var i WorkspaceTable
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
@@ -15367,7 +15420,7 @@ type InsertWorkspaceParams struct {
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,
arg.ID,
arg.CreatedAt,
@@ -15381,7 +15434,7 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar
arg.LastUsedAt,
arg.AutomaticUpdates,
)
- var i Workspace
+ var i WorkspaceTable
err := row.Scan(
&i.ID,
&i.CreatedAt,
@@ -15445,9 +15498,9 @@ type UpdateWorkspaceParams struct {
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)
- var i Workspace
+ var i WorkspaceTable
err := row.Scan(
&i.ID,
&i.CreatedAt,
@@ -15558,9 +15611,9 @@ type UpdateWorkspaceDormantDeletingAtParams struct {
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)
- var i Workspace
+ var i WorkspaceTable
err := row.Scan(
&i.ID,
&i.CreatedAt,
@@ -15641,15 +15694,15 @@ type UpdateWorkspacesDormantDeletingAtByTemplateIDParams struct {
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)
if err != nil {
return nil, err
}
defer rows.Close()
- var items []Workspace
+ var items []WorkspaceTable
for rows.Next() {
- var i Workspace
+ var i WorkspaceTable
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
diff --git a/coderd/database/queries/workspaces.sql b/coderd/database/queries/workspaces.sql
index 42d7a5247f1b5..08e795d7a2402 100644
--- a/coderd/database/queries/workspaces.sql
+++ b/coderd/database/queries/workspaces.sql
@@ -2,7 +2,7 @@
SELECT
*
FROM
- workspaces
+ workspaces_expanded
WHERE
id = $1
LIMIT
@@ -12,7 +12,7 @@ LIMIT
SELECT
*
FROM
- workspaces
+ workspaces_expanded as workspaces
WHERE
workspaces.id = (
SELECT
@@ -46,12 +46,9 @@ WHERE
-- name: GetWorkspaceByAgentID :one
SELECT
- sqlc.embed(workspaces),
- templates.name as template_name
+ *
FROM
- workspaces
-INNER JOIN
- templates ON workspaces.template_id = templates.id
+ workspaces_expanded as workspaces
WHERE
workspaces.id = (
SELECT
@@ -89,17 +86,15 @@ SELECT
filtered_workspaces AS (
SELECT
workspaces.*,
- COALESCE(template.name, 'unknown') as template_name,
latest_build.template_version_id,
latest_build.template_version_name,
- users.username as username,
latest_build.completed_at as latest_build_completed_at,
latest_build.canceled_at as latest_build_canceled_at,
latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status
FROM
- workspaces
+ workspaces_expanded as workspaces
JOIN
users
ON
@@ -238,7 +233,7 @@ WHERE
-- Filter by owner_name
AND CASE
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
END
-- Filter by template_name
@@ -340,7 +335,7 @@ WHERE
latest_build_canceled_at IS NULL AND
latest_build_error IS NULL AND
latest_build_transition = 'start'::workspace_transition) DESC,
- LOWER(username) ASC,
+ LOWER(owner_username) ASC,
LOWER(name) ASC
LIMIT
CASE
@@ -373,11 +368,19 @@ WHERE
'0001-01-01 00:00:00+00'::timestamptz, -- deleting_at
'never'::automatic_updates, -- automatic_updates
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_display_name
+ '', -- template_icon
+ '', -- template_description
+ -- Extra columns added to `filtered_workspaces`
'00000000-0000-0000-0000-000000000000'::uuid, -- template_version_id
'', -- 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_canceled_at,
'', -- latest_build_error
@@ -403,7 +406,7 @@ CROSS JOIN
SELECT
*
FROM
- workspaces
+ workspaces_expanded as workspaces
WHERE
owner_id = @owner_id
AND deleted = @deleted
diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml
index 7ef860e0b36ce..a70e45a522989 100644
--- a/coderd/database/sqlc.yaml
+++ b/coderd/database/sqlc.yaml
@@ -83,6 +83,8 @@ sql:
template_with_name: Template
workspace_build: WorkspaceBuildTable
workspace_build_with_user: WorkspaceBuild
+ workspace: WorkspaceTable
+ workspaces_expanded: Workspace
template_version: TemplateVersionTable
template_version_with_user: TemplateVersion
api_key: APIKey
diff --git a/coderd/httpmw/workspaceagent.go b/coderd/httpmw/workspaceagent.go
index 99889c0bae5fc..b27af7d0093a0 100644
--- a/coderd/httpmw/workspaceagent.go
+++ b/coderd/httpmw/workspaceagent.go
@@ -110,7 +110,7 @@ func ExtractWorkspaceAgentAndLatestBuild(opts ExtractWorkspaceAgentAndLatestBuil
}
//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 {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error checking workspace agent authorization.",
@@ -129,13 +129,13 @@ func ExtractWorkspaceAgentAndLatestBuild(opts ExtractWorkspaceAgentAndLatestBuil
}
subject := rbac.Subject{
- ID: row.Workspace.OwnerID.String(),
+ ID: row.WorkspaceTable.OwnerID.String(),
Roles: rbac.RoleIdentifiers(roleNames),
Groups: roles.Groups,
Scope: rbac.WorkspaceAgentScope(rbac.WorkspaceAgentScopeParams{
- WorkspaceID: row.Workspace.ID,
- OwnerID: row.Workspace.OwnerID,
- TemplateID: row.Workspace.TemplateID,
+ WorkspaceID: row.WorkspaceTable.ID,
+ OwnerID: row.WorkspaceTable.OwnerID,
+ TemplateID: row.WorkspaceTable.TemplateID,
VersionID: row.WorkspaceBuild.TemplateVersionID,
}),
}.WithCachedASTValue()
diff --git a/coderd/httpmw/workspaceagent_test.go b/coderd/httpmw/workspaceagent_test.go
index 0bc4b04a3589d..8d79b6ddbdbb9 100644
--- a/coderd/httpmw/workspaceagent_test.go
+++ b/coderd/httpmw/workspaceagent_test.go
@@ -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()
org := dbgen.Organization(t, db, database.Organization{})
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,
CreatedBy: user.ID,
})
- workspace := dbgen.Workspace(t, db, database.Workspace{
+ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.ID,
TemplateID: template.ID,
diff --git a/coderd/httpmw/workspaceagentparam_test.go b/coderd/httpmw/workspaceagentparam_test.go
index b27c80ba94710..51e55b81e20a7 100644
--- a/coderd/httpmw/workspaceagentparam_test.go
+++ b/coderd/httpmw/workspaceagentparam_test.go
@@ -31,7 +31,7 @@ func TestWorkspaceAgentParam(t *testing.T) {
UserID: user.ID,
})
tpl = dbgen.Template(t, db, database.Template{})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
TemplateID: tpl.ID,
})
diff --git a/coderd/httpmw/workspacebuildparam_test.go b/coderd/httpmw/workspacebuildparam_test.go
index fb2d2f044f77f..e4bd4d10dafb2 100644
--- a/coderd/httpmw/workspacebuildparam_test.go
+++ b/coderd/httpmw/workspacebuildparam_test.go
@@ -20,13 +20,13 @@ import (
func TestWorkspaceBuildParam(t *testing.T) {
t.Parallel()
- setupAuthentication := func(db database.Store) (*http.Request, database.Workspace) {
+ setupAuthentication := func(db database.Store) (*http.Request, database.WorkspaceTable) {
var (
user = dbgen.User(t, db, database.User{})
_, token = dbgen.APIKey(t, db, database.APIKey{
UserID: user.ID,
})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
})
)
diff --git a/coderd/httpmw/workspaceparam_test.go b/coderd/httpmw/workspaceparam_test.go
index 54daf661c39c8..81f47d135f6ee 100644
--- a/coderd/httpmw/workspaceparam_test.go
+++ b/coderd/httpmw/workspaceparam_test.go
@@ -355,7 +355,7 @@ func setupWorkspaceWithAgents(t testing.TB, cfg setupConfig) (database.Store, *h
_, token = dbgen.APIKey(t, db, database.APIKey{
UserID: user.ID,
})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
Name: cfg.WorkspaceName,
})
diff --git a/coderd/metricscache/metricscache_test.go b/coderd/metricscache/metricscache_test.go
index 891a66738c803..f854d21e777b0 100644
--- a/coderd/metricscache/metricscache_test.go
+++ b/coderd/metricscache/metricscache_test.go
@@ -49,7 +49,7 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
"TemplateWorkspaceOwners never populated 0 owners",
)
- dbgen.Workspace(t, db, database.Workspace{
+ dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID,
OwnerID: user1.ID,
})
@@ -61,7 +61,7 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
"TemplateWorkspaceOwners never populated 1 owner",
)
- workspace2 := dbgen.Workspace(t, db, database.Workspace{
+ workspace2 := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.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.
- dbgen.Workspace(t, db, database.Workspace{
+ dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID,
OwnerID: user1.ID,
})
diff --git a/coderd/notifications/reports/generator_internal_test.go b/coderd/notifications/reports/generator_internal_test.go
index a6a7f66f725cf..fcf22d80d80f9 100644
--- a/coderd/notifications/reports/generator_internal_test.go
+++ b/coderd/notifications/reports/generator_internal_test.go
@@ -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()})
// 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}})
_ = 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()})
// Workspaces
- w1 := dbgen.Workspace(t, db, database.Workspace{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})
- w3 := dbgen.Workspace(t, db, database.Workspace{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})
+ w1 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.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.WorkspaceTable{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
+ w4 := dbgen.Workspace(t, db, database.WorkspaceTable{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID})
// When: first run
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()})
// 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
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()})
// 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
notifEnq.Clear()
diff --git a/coderd/prometheusmetrics/insights/metricscollector_test.go b/coderd/prometheusmetrics/insights/metricscollector_test.go
index 9179c9896235d..9382fa5013525 100644
--- a/coderd/prometheusmetrics/insights/metricscollector_test.go
+++ b/coderd/prometheusmetrics/insights/metricscollector_test.go
@@ -63,8 +63,8 @@ func TestCollectInsights(t *testing.T) {
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"})
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})
- workspace2 = 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.WorkspaceTable{OrganizationID: orgID, TemplateID: tpl.ID, OwnerID: user.ID})
job1 = 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})
diff --git a/coderd/prometheusmetrics/prometheusmetrics.go b/coderd/prometheusmetrics/prometheusmetrics.go
index a6aec430a6b08..ebd50ff0f42ce 100644
--- a/coderd/prometheusmetrics/prometheusmetrics.go
+++ b/coderd/prometheusmetrics/prometheusmetrics.go
@@ -166,7 +166,7 @@ func Workspaces(ctx context.Context, logger slog.Logger, registerer prometheus.R
workspaceLatestBuildStatuses.Reset()
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)
}
}
diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go
index e81aa02f0c264..0a4198423e403 100644
--- a/coderd/provisionerdserver/provisionerdserver.go
+++ b/coderd/provisionerdserver/provisionerdserver.go
@@ -1406,7 +1406,7 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
TemplateScheduleStore: *s.TemplateScheduleStore.Load(),
UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(),
Now: now,
- Workspace: workspace,
+ Workspace: workspace.WorkspaceTable(),
// Allowed to be the empty string.
WorkspaceAutostart: workspace.AutostartSchedule.String,
})
diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go
index c6c5613f97a35..baa53b92d74e2 100644
--- a/coderd/provisionerdserver/provisionerdserver_test.go
+++ b/coderd/provisionerdserver/provisionerdserver_test.go
@@ -267,7 +267,7 @@ func TestAcquireJob(t *testing.T) {
Required: true,
Sensitive: false,
})
- workspace := dbgen.Workspace(t, db, database.Workspace{
+ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID,
OwnerID: user.ID,
OrganizationID: pd.OrganizationID,
@@ -1263,7 +1263,7 @@ func TestCompleteJob(t *testing.T) {
Valid: true,
}
}
- workspace := dbgen.Workspace(t, db, database.Workspace{
+ workspaceTable := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID,
Ttl: workspaceTTL,
OwnerID: user.ID,
@@ -1278,7 +1278,7 @@ func TestCompleteJob(t *testing.T) {
JobID: uuid.New(),
})
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
- WorkspaceID: workspace.ID,
+ WorkspaceID: workspaceTable.ID,
TemplateVersionID: version.ID,
Transition: c.transition,
Reason: database.BuildReasonInitiator,
@@ -1331,7 +1331,7 @@ func TestCompleteJob(t *testing.T) {
<-publishedWorkspace
<-publishedLogs
- workspace, err = db.GetWorkspaceByID(ctx, workspace.ID)
+ workspace, err := db.GetWorkspaceByID(ctx, workspaceTable.ID)
require.NoError(t, err)
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)
require.NoError(t, err)
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,
OwnerID: user.ID,
OrganizationID: pd.OrganizationID,
@@ -1636,7 +1636,7 @@ func TestNotifications(t *testing.T) {
JobID: uuid.New(),
})
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
- WorkspaceID: workspace.ID,
+ WorkspaceID: workspaceTable.ID,
TemplateVersionID: version.ID,
InitiatorID: initiator.ID,
Transition: database.WorkspaceTransitionDelete,
@@ -1674,7 +1674,7 @@ func TestNotifications(t *testing.T) {
})
require.NoError(t, err)
- workspace, err = db.GetWorkspaceByID(ctx, workspace.ID)
+ workspace, err := db.GetWorkspaceByID(ctx, workspaceTable.ID)
require.NoError(t, err)
require.True(t, workspace.Deleted)
@@ -1740,7 +1740,7 @@ func TestNotifications(t *testing.T) {
OrganizationID: pd.OrganizationID,
})
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,
OwnerID: user.ID,
OrganizationID: pd.OrganizationID,
@@ -1822,7 +1822,7 @@ func TestNotifications(t *testing.T) {
template := dbgen.Template(t, db, database.Template{
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,
})
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
diff --git a/coderd/schedule/autostop.go b/coderd/schedule/autostop.go
index 1651b3f64aa9c..88529d26b3b78 100644
--- a/coderd/schedule/autostop.go
+++ b/coderd/schedule/autostop.go
@@ -51,7 +51,7 @@ type CalculateAutostopParams struct {
WorkspaceAutostart string
Now time.Time
- Workspace database.Workspace
+ Workspace database.WorkspaceTable
}
type AutostopTime struct {
diff --git a/coderd/schedule/autostop_test.go b/coderd/schedule/autostop_test.go
index 0c4c072438537..e28ce3579cd4c 100644
--- a/coderd/schedule/autostop_test.go
+++ b/coderd/schedule/autostop_test.go
@@ -561,7 +561,7 @@ func TestCalculateAutoStop(t *testing.T) {
Valid: true,
}
}
- workspace := dbgen.Workspace(t, db, database.Workspace{
+ workspace := dbgen.Workspace(t, db, database.WorkspaceTable{
TemplateID: template.ID,
OrganizationID: org.ID,
OwnerID: user.ID,
diff --git a/coderd/telemetry/telemetry_test.go b/coderd/telemetry/telemetry_test.go
index fd9f4752bff51..908bcd657ee4f 100644
--- a/coderd/telemetry/telemetry_test.go
+++ b/coderd/telemetry/telemetry_test.go
@@ -50,7 +50,7 @@ func TestTelemetry(t *testing.T) {
})
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{})
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{
SharingLevel: database.AppSharingLevelOwner,
Health: database.WorkspaceAppHealthDisabled,
diff --git a/coderd/unhanger/detector_test.go b/coderd/unhanger/detector_test.go
index 28bb2575b9ee7..b1bf374881d37 100644
--- a/coderd/unhanger/detector_test.go
+++ b/coderd/unhanger/detector_test.go
@@ -133,7 +133,7 @@ func TestDetectorHungWorkspaceBuild(t *testing.T) {
},
CreatedBy: user.ID,
})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.ID,
TemplateID: template.ID,
@@ -255,7 +255,7 @@ func TestDetectorHungWorkspaceBuildNoOverrideState(t *testing.T) {
},
CreatedBy: user.ID,
})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.ID,
TemplateID: template.ID,
@@ -377,7 +377,7 @@ func TestDetectorHungWorkspaceBuildNoOverrideStateIfNoExistingBuild(t *testing.T
},
CreatedBy: user.ID,
})
- workspace = dbgen.Workspace(t, db, database.Workspace{
+ workspace = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.ID,
TemplateID: template.ID,
diff --git a/coderd/users.go b/coderd/users.go
index 78b88ba892426..73ac5c4212a42 100644
--- a/coderd/users.go
+++ b/coderd/users.go
@@ -1461,15 +1461,6 @@ func userOrganizationIDs(ctx context.Context, api *API, user database.User) ([]u
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 {
return codersdk.APIKey{
ID: k.ID,
diff --git a/coderd/users_test.go b/coderd/users_test.go
index ff7c63e63bebc..bd66bdb1d9a09 100644
--- a/coderd/users_test.go
+++ b/coderd/users_test.go
@@ -1936,7 +1936,7 @@ func TestUserAutofillParameters(t *testing.T) {
},
).Do()
- dbfake.WorkspaceBuild(t, db, database.Workspace{
+ dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: u2.ID,
TemplateID: version.Template.ID,
OrganizationID: u1.OrganizationID,
@@ -1969,7 +1969,7 @@ func TestUserAutofillParameters(t *testing.T) {
require.Equal(t, "foo", params[0].Value)
// Verify that latest parameter value is returned.
- dbfake.WorkspaceBuild(t, db, database.Workspace{
+ dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: u1.OrganizationID,
OwnerID: u2.ID,
TemplateID: version.Template.ID,
diff --git a/coderd/util/slice/slice.go b/coderd/util/slice/slice.go
index 78d5e7fe61928..7317a801a089f 100644
--- a/coderd/util/slice/slice.go
+++ b/coderd/util/slice/slice.go
@@ -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)
func Overlap[T comparable](a []T, b []T) bool {
return OverlapCompare(a, b, func(a, b T) bool {
diff --git a/coderd/workspaceagentportshare_test.go b/coderd/workspaceagentportshare_test.go
index f767aed933562..201ba68f3d6c5 100644
--- a/coderd/workspaceagentportshare_test.go
+++ b/coderd/workspaceagentportshare_test.go
@@ -24,7 +24,7 @@ func TestPostWorkspaceAgentPortShare(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir()
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -141,7 +141,7 @@ func TestGetWorkspaceAgentPortShares(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir()
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -177,7 +177,7 @@ func TestDeleteWorkspaceAgentPortShare(t *testing.T) {
client, user := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID)
tmpDir := t.TempDir()
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go
index 4b1af869cc007..6ea631f2e7d0c 100644
--- a/coderd/workspaceagents.go
+++ b/coderd/workspaceagents.go
@@ -366,7 +366,7 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
return
}
- row, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
+ workspace, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace by agent id.",
@@ -374,7 +374,6 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
})
return
}
- workspace := row.Workspace
api.WebsocketWaitMutex.Lock()
api.WebsocketWaitGroup.Add(1)
diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go
index 906333456ae70..8c0801a914d61 100644
--- a/coderd/workspaceagents_test.go
+++ b/coderd/workspaceagents_test.go
@@ -57,7 +57,7 @@ func TestWorkspaceAgent(t *testing.T) {
tmpDir := t.TempDir()
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,
OwnerID: anotherUser.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -79,7 +79,7 @@ func TestWorkspaceAgent(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
tmpDir := t.TempDir()
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -107,7 +107,7 @@ func TestWorkspaceAgent(t *testing.T) {
wantTroubleshootingURL := "https://example.com/troubleshoot"
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -148,7 +148,7 @@ func TestWorkspaceAgent(t *testing.T) {
PortForwardingHelper: true,
SshHelper: true,
}
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -181,7 +181,7 @@ func TestWorkspaceAgent(t *testing.T) {
apps.WebTerminal = false
// Creating another workspace is easier
- r = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -205,7 +205,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -247,7 +247,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -289,7 +289,7 @@ func TestWorkspaceAgentLogs(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -332,7 +332,7 @@ func TestWorkspaceAgentConnectRPC(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -420,7 +420,7 @@ func TestWorkspaceAgentConnectRPC(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
// 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()
// When: the workspace is marked as soft-deleted
// nolint:gocritic // this is a test
@@ -446,7 +446,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -486,7 +486,7 @@ func TestWorkspaceAgentClientCoordinate_BadVersion(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).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
// 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,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -679,7 +679,7 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) {
DeploymentValues: dv,
})
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -750,7 +750,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
require.NoError(t, err)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).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,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1088,7 +1088,7 @@ func TestWorkspaceAgentPostLogSource(t *testing.T) {
user := coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitShort)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -1130,7 +1130,7 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -1203,7 +1203,7 @@ func TestWorkspaceAgent_Metadata(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1368,7 +1368,7 @@ func TestWorkspaceAgent_Metadata_DisplayOrder(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1475,7 +1475,7 @@ func TestWorkspaceAgent_Metadata_CatchMemoryLeak(t *testing.T) {
Logger: &logger,
})
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -1607,7 +1607,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -1653,7 +1653,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -1698,7 +1698,7 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) {
api.DERPMapper.Store(&derpMapFn)
// Start workspace a workspace agent.
- r := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -1815,7 +1815,7 @@ func TestWorkspaceAgentExternalAuthListen(t *testing.T) {
tmpDir := t.TempDir()
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,
OwnerID: user.ID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
diff --git a/coderd/workspaceagentsrpc_test.go b/coderd/workspaceagentsrpc_test.go
index ca8f334d4e766..817aa11c4c292 100644
--- a/coderd/workspaceagentsrpc_test.go
+++ b/coderd/workspaceagentsrpc_test.go
@@ -22,7 +22,7 @@ func TestWorkspaceAgentReportStats(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
@@ -72,7 +72,7 @@ func TestAgentAPI_LargeManifest(t *testing.T) {
for i := range longScript {
longScript[i] = 'q'
}
- r := dbfake.WorkspaceBuild(t, store, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: adminUser.OrganizationID,
OwnerID: adminUser.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
diff --git a/coderd/workspacebuilds.go b/coderd/workspacebuilds.go
index 92e21b78e0756..3515bc4a944b5 100644
--- a/coderd/workspacebuilds.go
+++ b/coderd/workspacebuilds.go
@@ -46,7 +46,7 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
workspaceBuild := httpmw.WorkspaceBuildParam(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 {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.",
@@ -72,21 +72,11 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
})
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(
workspaceBuild,
workspace,
data.jobs[0],
- owner.Username,
- owner.AvatarURL,
data.resources,
data.metadata,
data.agents,
@@ -189,7 +179,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
return
}
- data, err := api.workspaceBuildsData(ctx, []database.Workspace{workspace}, workspaceBuilds)
+ data, err := api.workspaceBuildsData(ctx, workspaceBuilds)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.",
@@ -202,7 +192,6 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
workspaceBuilds,
[]database.Workspace{workspace},
data.jobs,
- data.users,
data.resources,
data.metadata,
data.agents,
@@ -279,7 +268,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
return
}
- data, err := api.workspaceBuildsData(ctx, []database.Workspace{workspace}, []database.WorkspaceBuild{workspaceBuild})
+ data, err := api.workspaceBuildsData(ctx, []database.WorkspaceBuild{workspaceBuild})
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting workspace build data.",
@@ -287,21 +276,11 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
})
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(
workspaceBuild,
workspace,
data.jobs[0],
- owner.Username,
- owner.AvatarURL,
data.resources,
data.metadata,
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))
}
- 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(
*workspaceBuild,
workspace,
@@ -437,8 +396,6 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
ProvisionerJob: *provisionerJob,
QueuePosition: 0,
},
- owner.Username,
- owner.AvatarURL,
[]database.WorkspaceResource{},
[]database.WorkspaceResourceMetadatum{},
[]database.WorkspaceAgent{},
@@ -674,7 +631,6 @@ func (api *API) workspaceBuildTimings(rw http.ResponseWriter, r *http.Request) {
}
type workspaceBuildsData struct {
- users []database.User
jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow
templateVersions []database.TemplateVersion
resources []database.WorkspaceResource
@@ -685,16 +641,7 @@ type workspaceBuildsData struct {
logSources []database.WorkspaceAgentLogSource
}
-func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.Workspace, 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)
- }
-
+func (api *API) workspaceBuildsData(ctx context.Context, workspaceBuilds []database.WorkspaceBuild) (workspaceBuildsData, error) {
jobIDs := make([]uuid.UUID, 0, len(workspaceBuilds))
for _, build := range workspaceBuilds {
jobIDs = append(jobIDs, build.JobID)
@@ -723,7 +670,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
if len(resources) == 0 {
return workspaceBuildsData{
- users: users,
jobs: jobs,
templateVersions: templateVersions,
}, nil
@@ -748,7 +694,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
if len(resources) == 0 {
return workspaceBuildsData{
- users: users,
jobs: jobs,
templateVersions: templateVersions,
resources: resources,
@@ -789,7 +734,6 @@ func (api *API) workspaceBuildsData(ctx context.Context, workspaces []database.W
}
return workspaceBuildsData{
- users: users,
jobs: jobs,
templateVersions: templateVersions,
resources: resources,
@@ -805,7 +749,6 @@ func (api *API) convertWorkspaceBuilds(
workspaceBuilds []database.WorkspaceBuild,
workspaces []database.Workspace,
jobs []database.GetProvisionerJobsByIDsWithQueuePositionRow,
- users []database.User,
workspaceResources []database.WorkspaceResource,
resourceMetadata []database.WorkspaceResourceMetadatum,
resourceAgents []database.WorkspaceAgent,
@@ -842,17 +785,11 @@ func (api *API) convertWorkspaceBuilds(
if !exists {
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(
build,
workspace,
job,
- owner.Username,
- owner.AvatarURL,
workspaceResources,
resourceMetadata,
resourceAgents,
@@ -875,7 +812,6 @@ func (api *API) convertWorkspaceBuild(
build database.WorkspaceBuild,
workspace database.Workspace,
job database.GetProvisionerJobsByIDsWithQueuePositionRow,
- username, avatarURL string,
workspaceResources []database.WorkspaceResource,
resourceMetadata []database.WorkspaceResourceMetadatum,
resourceAgents []database.WorkspaceAgent,
@@ -931,7 +867,7 @@ func (api *API) convertWorkspaceBuild(
scripts := scriptsByAgentID[agent.ID]
logSources := logSourcesByAgentID[agent.ID]
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(),
)
if err != nil {
@@ -958,8 +894,8 @@ func (api *API) convertWorkspaceBuild(
CreatedAt: build.CreatedAt,
UpdatedAt: build.UpdatedAt,
WorkspaceOwnerID: workspace.OwnerID,
- WorkspaceOwnerName: username,
- WorkspaceOwnerAvatarURL: avatarURL,
+ WorkspaceOwnerName: workspace.OwnerUsername,
+ WorkspaceOwnerAvatarURL: workspace.OwnerAvatarUrl,
WorkspaceID: build.WorkspaceID,
WorkspaceName: workspace.Name,
TemplateVersionID: build.TemplateVersionID,
diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go
index ec20556a7b2ed..e8eeca0f49d66 100644
--- a/coderd/workspacebuilds_test.go
+++ b/coderd/workspacebuilds_test.go
@@ -1217,7 +1217,7 @@ func TestWorkspaceBuildTimings(t *testing.T) {
// Tests will run in parallel. To avoid conflicts and race conditions on the
// build number, each test will have its own workspace and build.
makeBuild := func() database.WorkspaceBuild {
- ws := dbgen.Workspace(t, db, database.Workspace{
+ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID,
TemplateID: template.ID,
diff --git a/coderd/workspaces.go b/coderd/workspaces.go
index 2407130ea38e4..394a728472b0d 100644
--- a/coderd/workspaces.go
+++ b/coderd/workspaces.go
@@ -99,22 +99,12 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
httpapi.Forbidden(rw)
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(
apiKey.UserID,
workspace,
data.builds[0],
data.templates[0],
- owner.Username,
- owner.AvatarURL,
api.Options.AllowWorkspaceRenames,
)
if err != nil {
@@ -307,21 +297,12 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
httpapi.ResourceNotFound(rw)
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(
apiKey.UserID,
workspace,
data.builds[0],
data.templates[0],
- owner.Username,
- owner.AvatarURL,
api.Options.AllowWorkspaceRenames,
)
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,
Log: api.Logger,
Request: r,
@@ -413,7 +394,7 @@ func (api *API) postUserWorkspaces(rw http.ResponseWriter, r *http.Request) {
user = httpmw.UserParam(r)
)
- aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -446,7 +427,7 @@ type workspaceOwner struct {
func createWorkspace(
ctx context.Context,
- auditReq *audit.Request[database.Workspace],
+ auditReq *audit.Request[database.WorkspaceTable],
initiatorID uuid.UUID,
api *API,
owner workspaceOwner,
@@ -627,7 +608,7 @@ func createWorkspace(
err = api.Database.InTx(func(db database.Store) error {
now := dbtime.Now()
// Workspaces are created without any versions.
- workspace, err = db.InsertWorkspace(ctx, database.InsertWorkspaceParams{
+ minimumWorkspace, err := db.InsertWorkspace(ctx, database.InsertWorkspaceParams{
ID: uuid.New(),
CreatedAt: now,
UpdatedAt: now,
@@ -646,6 +627,14 @@ func createWorkspace(
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).
Reason(database.BuildReasonInitiator).
Initiator(initiatorID).
@@ -685,7 +674,7 @@ func createWorkspace(
// 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))
}
- auditReq.New = workspace
+ auditReq.New = workspace.WorkspaceTable()
api.Telemetry.Report(&telemetry.Snapshot{
Workspaces: []telemetry.Workspace{telemetry.ConvertWorkspace(workspace)},
@@ -699,8 +688,6 @@ func createWorkspace(
ProvisionerJob: *provisionerJob,
QueuePosition: 0,
},
- owner.Username,
- owner.AvatarURL,
[]database.WorkspaceResource{},
[]database.WorkspaceResourceMetadatum{},
[]database.WorkspaceAgent{},
@@ -722,8 +709,6 @@ func createWorkspace(
workspace,
apiBuild,
template,
- owner.Username,
- owner.AvatarURL,
api.Options.AllowWorkspaceRenames,
)
if err != nil {
@@ -750,7 +735,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
- aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -759,7 +744,7 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
})
)
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceRequest
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 {
- aReq.New = workspace
+ aReq.New = workspace.WorkspaceTable()
// Nothing changed, optionally this could be an error.
rw.WriteHeader(http.StatusNoContent)
return
@@ -822,8 +807,8 @@ func (api *API) patchWorkspace(rw http.ResponseWriter, r *http.Request) {
}
api.publishWorkspaceUpdate(ctx, workspace.ID)
-
aReq.New = newWorkspace
+
rw.WriteHeader(http.StatusNoContent)
}
@@ -841,7 +826,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
- aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -850,7 +835,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
})
)
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceAutostartRequest
if !httpapi.Read(ctx, rw, r, &req) {
@@ -897,7 +882,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
newWorkspace := workspace
newWorkspace.AutostartSchedule = dbSched
- aReq.New = newWorkspace
+ aReq.New = newWorkspace.WorkspaceTable()
rw.WriteHeader(http.StatusNoContent)
}
@@ -916,7 +901,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
- aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -925,7 +910,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
})
)
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceTTLRequest
if !httpapi.Read(ctx, rw, r, &req) {
@@ -977,7 +962,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
newWorkspace := workspace
newWorkspace.Ttl = dbTTL
- aReq.New = newWorkspace
+ aReq.New = newWorkspace.WorkspaceTable()
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) {
var (
ctx = r.Context()
- workspace = httpmw.WorkspaceParam(r)
+ oldWorkspace = httpmw.WorkspaceParam(r)
apiKey = httpmw.APIKey(r)
- oldWorkspace = workspace
auditor = api.Auditor.Load()
- aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
Action: database.AuditActionWrite,
- OrganizationID: workspace.OrganizationID,
+ OrganizationID: oldWorkspace.OrganizationID,
})
)
- aReq.Old = oldWorkspace
+ aReq.Old = oldWorkspace.WorkspaceTable()
defer commitAudit()
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 workspace.DormantAt.Valid == req.Dormant {
+ if oldWorkspace.DormantAt.Valid == req.Dormant {
rw.WriteHeader(http.StatusNotModified)
return
}
@@ -1028,8 +1012,8 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
dormantAt.Time = dbtime.Now()
}
- workspace, err := api.Database.UpdateWorkspaceDormantDeletingAt(ctx, database.UpdateWorkspaceDormantDeletingAtParams{
- ID: workspace.ID,
+ newWorkspace, err := api.Database.UpdateWorkspaceDormantDeletingAt(ctx, database.UpdateWorkspaceDormantDeletingAtParams{
+ ID: oldWorkspace.ID,
DormantAt: dormantAt,
})
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.
- if req.Dormant && apiKey.UserID != workspace.OwnerID {
+ if req.Dormant && apiKey.UserID != newWorkspace.OwnerID {
initiator, initiatorErr := api.Database.GetUserByID(ctx, apiKey.UserID)
if initiatorErr != nil {
api.Logger.Warn(
ctx,
"failed to fetch the user that marked the workspace as dormant",
slog.Error(err),
- slog.F("workspace_id", workspace.ID),
+ slog.F("workspace_id", newWorkspace.ID),
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 {
api.Logger.Warn(
ctx,
"failed to fetch the template of the workspace marked as dormant",
slog.Error(err),
- slog.F("workspace_id", workspace.ID),
- slog.F("template_id", workspace.TemplateID),
+ slog.F("workspace_id", newWorkspace.ID),
+ 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))
_, err = api.NotificationsEnqueuer.Enqueue(
ctx,
- workspace.OwnerID,
+ newWorkspace.OwnerID,
notifications.TemplateWorkspaceDormant,
map[string]string{
- "name": workspace.Name,
+ "name": newWorkspace.Name,
"reason": "a " + initiator.Username + " request",
"timeTilDormant": humanize.Time(dormantTime),
},
"api",
- workspace.ID,
- workspace.OwnerID,
- workspace.TemplateID,
- workspace.OrganizationID,
+ newWorkspace.ID,
+ newWorkspace.OwnerID,
+ newWorkspace.TemplateID,
+ newWorkspace.OrganizationID,
)
if err != nil {
api.Logger.Warn(ctx, "failed to notify of workspace marked as dormant", slog.Error(err))
@@ -1087,37 +1071,40 @@ func (api *API) putWorkspaceDormant(rw http.ResponseWriter, r *http.Request) {
}
}
- data, err := api.workspaceData(ctx, []database.Workspace{workspace})
+ // 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 resources.",
+ Message: "Internal error fetching workspace.",
Detail: err.Error(),
})
return
}
- owner, ok := userByID(workspace.OwnerID, data.users)
- if !ok {
+
+ data, err := api.workspaceData(ctx, []database.Workspace{workspace})
+ if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.",
- Detail: "unable to find workspace owner's username",
+ Detail: err.Error(),
})
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 {
httpapi.Forbidden(rw)
return
}
- aReq.New = workspace
+ aReq.New = newWorkspace
w, err := convertWorkspace(
apiKey.UserID,
workspace,
data.builds[0],
data.templates[0],
- owner.Username,
- owner.AvatarURL,
api.Options.AllowWorkspaceRenames,
)
if err != nil {
@@ -1371,7 +1358,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
return
}
- aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -1379,7 +1366,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
OrganizationID: workspace.OrganizationID,
})
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
err := api.Database.FavoriteWorkspace(ctx, workspace.ID)
if err != nil {
@@ -1390,7 +1377,7 @@ func (api *API) putFavoriteWorkspace(rw http.ResponseWriter, r *http.Request) {
return
}
- aReq.New = workspace
+ aReq.New = workspace.WorkspaceTable()
aReq.New.Favorite = true
rw.WriteHeader(http.StatusNoContent)
@@ -1418,7 +1405,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
return
}
- aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit := audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -1427,7 +1414,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
})
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
err := api.Database.UnfavoriteWorkspace(ctx, workspace.ID)
if err != nil {
@@ -1437,7 +1424,7 @@ func (api *API) deleteFavoriteWorkspace(rw http.ResponseWriter, r *http.Request)
})
return
}
- aReq.New = workspace
+ aReq.New = workspace.WorkspaceTable()
aReq.New.Favorite = false
rw.WriteHeader(http.StatusNoContent)
@@ -1457,7 +1444,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
ctx = r.Context()
workspace = httpmw.WorkspaceParam(r)
auditor = api.Auditor.Load()
- aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
+ aReq, commitAudit = audit.InitRequest[database.WorkspaceTable](rw, &audit.RequestParams{
Audit: *auditor,
Log: api.Logger,
Request: r,
@@ -1466,7 +1453,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
})
)
defer commitAudit()
- aReq.Old = workspace
+ aReq.Old = workspace.WorkspaceTable()
var req codersdk.UpdateWorkspaceAutomaticUpdatesRequest
if !httpapi.Read(ctx, rw, r, &req) {
@@ -1499,7 +1486,7 @@ func (api *API) putWorkspaceAutoupdates(rw http.ResponseWriter, r *http.Request)
newWorkspace := workspace
newWorkspace.AutomaticUpdates = database.AutomaticUpdates(req.AutomaticUpdates)
- aReq.New = newWorkspace
+ aReq.New = newWorkspace.WorkspaceTable()
rw.WriteHeader(http.StatusNoContent)
}
@@ -1658,25 +1645,11 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
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(
apiKey.UserID,
workspace,
data.builds[0],
data.templates[0],
- owner.Username,
- owner.AvatarURL,
api.Options.AllowWorkspaceRenames,
)
if err != nil {
@@ -1778,7 +1751,6 @@ func (api *API) workspaceTimings(rw http.ResponseWriter, r *http.Request) {
type workspaceData struct {
templates []database.Template
builds []codersdk.WorkspaceBuild
- users []database.User
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)
}
- data, err := api.workspaceBuildsData(ctx, workspaces, builds)
+ data, err := api.workspaceBuildsData(ctx, builds)
if err != nil {
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,
workspaces,
data.jobs,
- data.users,
data.resources,
data.metadata,
data.agents,
@@ -1833,7 +1804,6 @@ func (api *API) workspaceData(ctx context.Context, workspaces []database.Workspa
return workspaceData{
templates: templates,
builds: apiBuilds,
- users: data.users,
allowRenames: api.Options.AllowWorkspaceRenames,
}, nil
}
@@ -1847,10 +1817,6 @@ func convertWorkspaces(requesterID uuid.UUID, workspaces []database.Workspace, d
for _, template := range data.templates {
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))
for _, workspace := range workspaces {
@@ -1867,18 +1833,12 @@ func convertWorkspaces(requesterID uuid.UUID, workspaces []database.Workspace, d
if !exists {
continue
}
- owner, exists := userByID[workspace.OwnerID]
- if !exists {
- continue
- }
w, err := convertWorkspace(
requesterID,
workspace,
build,
template,
- owner.Username,
- owner.AvatarURL,
data.allowRenames,
)
if err != nil {
@@ -1895,8 +1855,6 @@ func convertWorkspace(
workspace database.Workspace,
workspaceBuild codersdk.WorkspaceBuild,
template database.Template,
- username string,
- avatarURL string,
allowRenames bool,
) (codersdk.Workspace, error) {
if requesterID == uuid.Nil {
@@ -1941,15 +1899,15 @@ func convertWorkspace(
CreatedAt: workspace.CreatedAt,
UpdatedAt: workspace.UpdatedAt,
OwnerID: workspace.OwnerID,
- OwnerName: username,
- OwnerAvatarURL: avatarURL,
+ OwnerName: workspace.OwnerUsername,
+ OwnerAvatarURL: workspace.OwnerAvatarUrl,
OrganizationID: workspace.OrganizationID,
- OrganizationName: template.OrganizationName,
+ OrganizationName: workspace.OrganizationName,
TemplateID: workspace.TemplateID,
LatestBuild: workspaceBuild,
- TemplateName: template.Name,
- TemplateIcon: template.Icon,
- TemplateDisplayName: template.DisplayName,
+ TemplateName: workspace.TemplateName,
+ TemplateIcon: workspace.TemplateIcon,
+ TemplateDisplayName: workspace.TemplateDisplayName,
TemplateAllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs,
TemplateActiveVersionID: template.ActiveVersionID,
TemplateRequireActiveVersion: template.RequireActiveVersion,
diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go
index dc83289340059..c24afc67de8ba 100644
--- a/coderd/workspaces_test.go
+++ b/coderd/workspaces_test.go
@@ -392,7 +392,7 @@ func TestResolveAutostart(t *testing.T) {
defer cancel()
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,
OrganizationID: owner.OrganizationID,
AutomaticUpdates: database.AutomaticUpdatesAlways,
@@ -456,22 +456,22 @@ func TestWorkspacesSortOrder(t *testing.T) {
})
// 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
- 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
- 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
- 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
- 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
- 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)
defer cancel()
@@ -905,7 +905,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
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
workspace.OwnerID = owner.UserID
@@ -940,21 +940,21 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}
// pending
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusPending),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Valid: false},
}, database.WorkspaceTransitionStart)
// starting
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStarting),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionStart)
// running
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusRunning),
}, database.ProvisionerJob{
CompletedAt: sql.NullTime{Time: time.Now(), Valid: true},
@@ -962,14 +962,14 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart)
// stopping
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStopping),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionStop)
// stopped
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusStopped),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -977,7 +977,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStop)
// failed -- delete
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusFailed) + "-deleted",
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -986,7 +986,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionDelete)
// failed -- stop
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusFailed) + "-stopped",
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -995,7 +995,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStop)
// canceling
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusCanceling),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -1003,7 +1003,7 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart)
// canceled
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusCanceled),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
@@ -1012,14 +1012,14 @@ func TestWorkspaceFilterAllStatus(t *testing.T) {
}, database.WorkspaceTransitionStart)
// deleting
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusDeleting),
}, database.ProvisionerJob{
StartedAt: sql.NullTime{Time: time.Now().Add(time.Second * -2), Valid: true},
}, database.WorkspaceTransitionDelete)
// deleted
- makeWorkspace(database.Workspace{
+ makeWorkspace(database.WorkspaceTable{
Name: string(database.WorkspaceStatusDeleted),
}, database.ProvisionerJob{
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)
defer cancel()
- dormantWorkspace := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ dormantWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
TemplateID: template.ID,
OwnerID: user.UserID,
OrganizationID: user.OrganizationID,
}).Do().Workspace
// 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,
OwnerID: user.UserID,
OrganizationID: user.OrganizationID,
@@ -3246,8 +3246,8 @@ func TestWorkspaceFavoriteUnfavorite(t *testing.T) {
owner = coderdtest.CreateFirstUser(t, client)
memberClient, member = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// This will be our 'favorite' workspace
- wsb1 = dbfake.WorkspaceBuild(t, db, database.Workspace{OwnerID: member.ID, OrganizationID: owner.OrganizationID}).Do()
- wsb2 = dbfake.WorkspaceBuild(t, db, database.Workspace{OwnerID: owner.UserID, OrganizationID: owner.OrganizationID}).Do()
+ wsb1 = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{OwnerID: member.ID, 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)
@@ -3324,7 +3324,7 @@ func TestWorkspaceUsageTracking(t *testing.T) {
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
tmpDir := t.TempDir()
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
@@ -3371,7 +3371,7 @@ func TestWorkspaceUsageTracking(t *testing.T) {
ActivityBumpMillis: 8 * time.Hour.Milliseconds(),
})
require.NoError(t, err)
- r := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
TemplateID: template.ID,
@@ -3598,7 +3598,7 @@ func TestWorkspaceTimings(t *testing.T) {
ActiveVersionID: version.ID,
CreatedBy: owner.UserID,
})
- ws := dbgen.Workspace(t, db, database.Workspace{
+ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID,
TemplateID: template.ID,
diff --git a/coderd/workspacestats/activitybump_test.go b/coderd/workspacestats/activitybump_test.go
index 3abb46b7ab343..50c22042d6491 100644
--- a/coderd/workspacestats/activitybump_test.go
+++ b/coderd/workspacestats/activitybump_test.go
@@ -191,7 +191,7 @@ func Test_ActivityBumpWorkspace(t *testing.T) {
ActiveVersionID: templateVersion.ID,
CreatedBy: user.ID,
})
- ws = dbgen.Workspace(t, db, database.Workspace{
+ ws = dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
OrganizationID: org.ID,
TemplateID: template.ID,
diff --git a/coderd/workspacestats/batcher_internal_test.go b/coderd/workspacestats/batcher_internal_test.go
index 2f7a25b152127..3e106f07e4e2f 100644
--- a/coderd/workspacestats/batcher_internal_test.go
+++ b/coderd/workspacestats/batcher_internal_test.go
@@ -162,7 +162,7 @@ type deps struct {
Agent database.WorkspaceAgent
Template database.Template
User database.User
- Workspace database.Workspace
+ Workspace database.WorkspaceTable
}
// 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,
ActiveVersionID: tv.ID,
})
- ws := dbgen.Workspace(t, store, database.Workspace{
+ ws := dbgen.Workspace(t, store, database.WorkspaceTable{
TemplateID: tpl.ID,
OwnerID: user.ID,
OrganizationID: org.ID,
diff --git a/coderd/workspacestats/tracker_test.go b/coderd/workspacestats/tracker_test.go
index 99e9f9503b645..4b5115fd143e9 100644
--- a/coderd/workspacestats/tracker_test.go
+++ b/coderd/workspacestats/tracker_test.go
@@ -149,7 +149,7 @@ func TestTracker_MultipleInstances(t *testing.T) {
numWorkspaces := 10
w := make([]dbfake.WorkspaceResponse, numWorkspaces)
for i := 0; i < numWorkspaces; i++ {
- wr := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ wr := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: owner.UserID,
OrganizationID: owner.OrganizationID,
LastUsedAt: now,
diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md
index b22055ff18b5a..602710289261f 100644
--- a/docs/admin/security/audit-logs.md
+++ b/docs/admin/security/audit-logs.md
@@ -26,9 +26,9 @@ We track the following resources:
| Template
write, delete |
Field | Tracked |
---|
active_version_id | true |
activity_bump | true |
allow_user_autostart | true |
allow_user_autostop | true |
allow_user_cancel_workspace_jobs | true |
autostart_block_days_of_week | true |
autostop_requirement_days_of_week | true |
autostop_requirement_weeks | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
default_ttl | true |
deleted | false |
deprecated | true |
description | true |
display_name | true |
failure_ttl | true |
group_acl | true |
icon | true |
id | true |
max_port_sharing_level | true |
name | true |
organization_display_name | false |
organization_icon | false |
organization_id | false |
organization_name | false |
provisioner | true |
require_active_version | true |
time_til_dormant | true |
time_til_dormant_autodelete | true |
updated_at | false |
user_acl | true |
|
| TemplateVersion
create, write | Field | Tracked |
---|
archived | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
external_auth_providers | false |
id | true |
job_id | false |
message | false |
name | true |
organization_id | false |
readme | true |
template_id | true |
updated_at | false |
|
| User
create, write, delete | Field | Tracked |
---|
avatar_url | false |
created_at | false |
deleted | true |
email | true |
github_com_user_id | false |
hashed_one_time_passcode | false |
hashed_password | true |
id | true |
last_seen_at | false |
login_type | true |
must_reset_password | true |
name | true |
one_time_passcode_expires_at | true |
quiet_hours_schedule | true |
rbac_roles | true |
status | true |
theme_preference | false |
updated_at | false |
username | true |
|
-| Workspace
create, write, delete | Field | Tracked |
---|
automatic_updates | true |
autostart_schedule | true |
created_at | false |
deleted | false |
deleting_at | true |
dormant_at | true |
favorite | true |
id | true |
last_used_at | false |
name | true |
organization_id | false |
owner_id | true |
template_id | true |
ttl | true |
updated_at | false |
|
| WorkspaceBuild
start, stop | Field | Tracked |
---|
build_number | false |
created_at | false |
daily_cost | false |
deadline | false |
id | false |
initiator_by_avatar_url | false |
initiator_by_username | false |
initiator_id | false |
job_id | false |
max_deadline | false |
provisioner_state | false |
reason | false |
template_version_id | true |
transition | false |
updated_at | false |
workspace_id | false |
|
| WorkspaceProxy
| Field | Tracked |
---|
created_at | true |
deleted | false |
derp_enabled | true |
derp_only | true |
display_name | true |
icon | true |
id | true |
name | true |
region_id | true |
token_hashed_secret | true |
updated_at | false |
url | true |
version | true |
wildcard_hostname | true |
|
+| WorkspaceTable
| Field | Tracked |
---|
automatic_updates | true |
autostart_schedule | true |
created_at | false |
deleted | false |
deleting_at | true |
dormant_at | true |
favorite | true |
id | true |
last_used_at | false |
name | true |
organization_id | false |
owner_id | true |
template_id | true |
ttl | true |
updated_at | false |
|
diff --git a/enterprise/audit/diff_internal_test.go b/enterprise/audit/diff_internal_test.go
index f98d16138cf1f..d5c191c8907fa 100644
--- a/enterprise/audit/diff_internal_test.go
+++ b/enterprise/audit/diff_internal_test.go
@@ -370,8 +370,8 @@ func Test_diff(t *testing.T) {
runDiffTests(t, []diffTest{
{
name: "Create",
- left: audit.Empty[database.Workspace](),
- right: database.Workspace{
+ left: audit.Empty[database.WorkspaceTable](),
+ right: database.WorkspaceTable{
ID: uuid.UUID{1},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -392,8 +392,8 @@ func Test_diff(t *testing.T) {
},
{
name: "NullSchedules",
- left: audit.Empty[database.Workspace](),
- right: database.Workspace{
+ left: audit.Empty[database.WorkspaceTable](),
+ right: database.WorkspaceTable{
ID: uuid.UUID{1},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index baa9f33b18786..2de2d918dc0aa 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -149,7 +149,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"one_time_passcode_expires_at": ActionTrack,
"must_reset_password": ActionTrack,
},
- &database.Workspace{}: {
+ &database.WorkspaceTable{}: {
"id": ActionTrack,
"created_at": ActionIgnore, // Never changes.
"updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
diff --git a/enterprise/coderd/appearance_test.go b/enterprise/coderd/appearance_test.go
index e3563aa882e5a..8550f13904e2d 100644
--- a/enterprise/coderd/appearance_test.go
+++ b/enterprise/coderd/appearance_test.go
@@ -148,7 +148,7 @@ func TestAnnouncementBanners(t *testing.T) {
err := client.UpdateAppearance(ctx, cfg)
require.NoError(t, err)
- r := dbfake.WorkspaceBuild(t, store, database.Workspace{
+ r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
diff --git a/enterprise/coderd/jfrog_test.go b/enterprise/coderd/jfrog_test.go
index fd47f80b3ee92..a9841a6d92067 100644
--- a/enterprise/coderd/jfrog_test.go
+++ b/enterprise/coderd/jfrog_test.go
@@ -29,7 +29,7 @@ func TestJFrogXrayScan(t *testing.T) {
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,
OwnerID: ta.ID,
}).WithAgent().Do()
@@ -85,7 +85,7 @@ func TestJFrogXrayScan(t *testing.T) {
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,
OwnerID: member.ID,
}).WithAgent().Do()
diff --git a/enterprise/coderd/schedule/template.go b/enterprise/coderd/schedule/template.go
index 6b148e8ef4708..626e296d6a3e8 100644
--- a/enterprise/coderd/schedule/template.go
+++ b/enterprise/coderd/schedule/template.go
@@ -136,7 +136,7 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S
var (
template database.Template
- markedForDeletion []database.Workspace
+ markedForDeletion []database.WorkspaceTable
)
err = db.InTx(func(tx database.Store) error {
ctx, span := tracing.StartSpanWithName(ctx, "(*schedule.EnterpriseTemplateScheduleStore).Set()-InTx()")
@@ -296,7 +296,7 @@ func (s *EnterpriseTemplateScheduleStore) updateWorkspaceBuild(ctx context.Conte
UserQuietHoursScheduleStore: *s.UserQuietHoursScheduleStore.Load(),
// Use the job completion time as the time we calculate autostop from.
Now: job.CompletedAt.Time,
- Workspace: workspace,
+ Workspace: workspace.WorkspaceTable(),
WorkspaceAutostart: workspace.AutostartSchedule.String,
})
if err != nil {
diff --git a/enterprise/coderd/schedule/template_test.go b/enterprise/coderd/schedule/template_test.go
index bce5ffbec930e..c85c2c6ea1b0e 100644
--- a/enterprise/coderd/schedule/template_test.go
+++ b/enterprise/coderd/schedule/template_test.go
@@ -211,7 +211,7 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) {
ActiveVersionID: templateVersion.ID,
CreatedBy: user.ID,
})
- ws = dbgen.Workspace(t, db, database.Workspace{
+ ws = dbgen.Workspace(t, db, database.WorkspaceTable{
OrganizationID: organizationID,
OwnerID: user.ID,
TemplateID: template.ID,
@@ -357,7 +357,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) {
)
// 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,
TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID,
@@ -474,7 +474,7 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) {
for i, b := range builds {
wsID := b.workspaceID
if wsID == uuid.Nil {
- ws := dbgen.Workspace(t, db, database.Workspace{
+ ws := dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
TemplateID: b.templateID,
OrganizationID: templateJob.OrganizationID,
@@ -642,21 +642,21 @@ func TestNotifications(t *testing.T) {
)
// Add two dormant workspaces and one active workspace.
- dormantWorkspaces := []database.Workspace{
- dbgen.Workspace(t, db, database.Workspace{
+ dormantWorkspaces := []database.WorkspaceTable{
+ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID,
LastUsedAt: time.Now().Add(-time.Hour),
}),
- dbgen.Workspace(t, db, database.Workspace{
+ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID,
LastUsedAt: time.Now().Add(-time.Hour),
}),
}
- dbgen.Workspace(t, db, database.Workspace{
+ dbgen.Workspace(t, db, database.WorkspaceTable{
OwnerID: user.ID,
TemplateID: template.ID,
OrganizationID: templateJob.OrganizationID,
diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go
index dc685c46cec41..239c7ae377102 100644
--- a/enterprise/coderd/workspaces_test.go
+++ b/enterprise/coderd/workspaces_test.go
@@ -449,7 +449,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
TimeTilDormantMillis: inactiveTTL.Milliseconds(),
})
- resp := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ resp := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
TemplateID: template.ID,
@@ -1260,18 +1260,18 @@ func TestWorkspacesFiltering(t *testing.T) {
CreatedBy: owner.UserID,
}).Do()
- dormantWS1 := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ dormantWS1 := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID,
}).Do().Workspace
- dormantWS2 := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ dormantWS2 := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID,
TemplateID: resp.Template.ID,
}).Do().Workspace
- _ = dbfake.WorkspaceBuild(t, db, database.Workspace{
+ _ = dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: templateAdmin.ID,
OrganizationID: owner.OrganizationID,
TemplateID: resp.Template.ID,
@@ -1448,7 +1448,7 @@ func TestResolveAutostart(t *testing.T) {
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,
OrganizationID: owner.OrganizationID,
TemplateID: version1.Template.ID,
diff --git a/support/support_test.go b/support/support_test.go
index cdd62ceeb8f9b..1a088eb734185 100644
--- a/support/support_test.go
+++ b/support/support_test.go
@@ -199,7 +199,7 @@ func setupWorkspaceAndAgent(ctx context.Context, t *testing.T, client *codersdk.
CreatedBy: user.UserID,
}).
Do()
- wbr := dbfake.WorkspaceBuild(t, db, database.Workspace{
+ wbr := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
TemplateID: tv.Template.ID,
diff --git a/testutil/reflect.go b/testutil/reflect.go
new file mode 100644
index 0000000000000..a776ac98e20a0
--- /dev/null
+++ b/testutil/reflect.go
@@ -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
+}