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
+}
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy