mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add frontend for locked workspaces (#8655)
- Fix workspaces query for locked workspaces.
This commit is contained in:
@@ -2587,11 +2587,11 @@ func (q *querier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg database.Up
|
||||
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLastUsedAt)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
|
||||
func (q *querier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
|
||||
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
|
||||
return q.db.GetWorkspaceByID(ctx, arg.ID)
|
||||
}
|
||||
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedDeletingAt)(ctx, arg)
|
||||
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedDeletingAt)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
|
||||
@@ -5250,9 +5250,9 @@ func (q *FakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
|
||||
func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
|
||||
if err := validateDatabaseType(arg); err != nil {
|
||||
return err
|
||||
return database.Workspace{}, err
|
||||
}
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
@@ -5274,7 +5274,7 @@ func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg dat
|
||||
}
|
||||
}
|
||||
if template.ID == uuid.Nil {
|
||||
return xerrors.Errorf("unable to find workspace template")
|
||||
return database.Workspace{}, xerrors.Errorf("unable to find workspace template")
|
||||
}
|
||||
if template.LockedTTL > 0 {
|
||||
workspace.DeletingAt = sql.NullTime{
|
||||
@@ -5284,9 +5284,9 @@ func (q *FakeQuerier) UpdateWorkspaceLockedDeletingAt(_ context.Context, arg dat
|
||||
}
|
||||
}
|
||||
q.workspaces[index] = workspace
|
||||
return nil
|
||||
return workspace, nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
return database.Workspace{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) UpdateWorkspaceProxy(_ context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
@@ -5730,6 +5730,16 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
|
||||
}
|
||||
}
|
||||
|
||||
// We omit locked workspaces by default.
|
||||
if arg.LockedAt.IsZero() && workspace.LockedAt.Valid {
|
||||
continue
|
||||
}
|
||||
|
||||
// Filter out workspaces that are locked after the timestamp.
|
||||
if !arg.LockedAt.IsZero() && workspace.LockedAt.Time.Before(arg.LockedAt) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(arg.TemplateIDs) > 0 {
|
||||
match := false
|
||||
for _, id := range arg.TemplateIDs {
|
||||
|
||||
@@ -1572,11 +1572,11 @@ func (m metricsStore) UpdateWorkspaceLastUsedAt(ctx context.Context, arg databas
|
||||
return err
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) error {
|
||||
func (m metricsStore) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpdateWorkspaceLockedDeletingAt(ctx, arg)
|
||||
ws, r0 := m.s.UpdateWorkspaceLockedDeletingAt(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpdateWorkspaceLockedDeletingAt").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
return ws, r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
|
||||
@@ -3307,11 +3307,12 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceLastUsedAt(arg0, arg1 interface{
|
||||
}
|
||||
|
||||
// UpdateWorkspaceLockedDeletingAt mocks base method.
|
||||
func (m *MockStore) UpdateWorkspaceLockedDeletingAt(arg0 context.Context, arg1 database.UpdateWorkspaceLockedDeletingAtParams) error {
|
||||
func (m *MockStore) UpdateWorkspaceLockedDeletingAt(arg0 context.Context, arg1 database.UpdateWorkspaceLockedDeletingAtParams) (database.Workspace, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateWorkspaceLockedDeletingAt", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
ret0, _ := ret[0].(database.Workspace)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateWorkspaceLockedDeletingAt indicates an expected call of UpdateWorkspaceLockedDeletingAt.
|
||||
|
||||
@@ -217,6 +217,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
|
||||
arg.Name,
|
||||
arg.HasAgent,
|
||||
arg.AgentInactiveDisconnectTimeoutSeconds,
|
||||
arg.LockedAt,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
|
||||
@@ -277,7 +277,7 @@ type sqlcQuerier interface {
|
||||
UpdateWorkspaceBuildCostByID(ctx context.Context, arg UpdateWorkspaceBuildCostByIDParams) error
|
||||
UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error
|
||||
UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error
|
||||
UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg UpdateWorkspaceLockedDeletingAtParams) error
|
||||
UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg UpdateWorkspaceLockedDeletingAtParams) (Workspace, 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
|
||||
|
||||
@@ -9001,6 +9001,14 @@ WHERE
|
||||
) > 0
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by locked workspaces. By default we do not return locked
|
||||
-- workspaces since they are considered soft-deleted.
|
||||
AND CASE
|
||||
WHEN $10 :: timestamptz > '0001-01-01 00:00:00+00'::timestamptz THEN
|
||||
locked_at IS NOT NULL AND locked_at >= $10
|
||||
ELSE
|
||||
locked_at IS NULL
|
||||
END
|
||||
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
|
||||
-- @authorize_filter
|
||||
ORDER BY
|
||||
@@ -9012,11 +9020,11 @@ ORDER BY
|
||||
LOWER(workspaces.name) ASC
|
||||
LIMIT
|
||||
CASE
|
||||
WHEN $11 :: integer > 0 THEN
|
||||
$11
|
||||
WHEN $12 :: integer > 0 THEN
|
||||
$12
|
||||
END
|
||||
OFFSET
|
||||
$10
|
||||
$11
|
||||
`
|
||||
|
||||
type GetWorkspacesParams struct {
|
||||
@@ -9029,6 +9037,7 @@ type GetWorkspacesParams struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
HasAgent string `db:"has_agent" json:"has_agent"`
|
||||
AgentInactiveDisconnectTimeoutSeconds int64 `db:"agent_inactive_disconnect_timeout_seconds" json:"agent_inactive_disconnect_timeout_seconds"`
|
||||
LockedAt time.Time `db:"locked_at" json:"locked_at"`
|
||||
Offset int32 `db:"offset_" json:"offset_"`
|
||||
Limit int32 `db:"limit_" json:"limit_"`
|
||||
}
|
||||
@@ -9064,6 +9073,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
|
||||
arg.Name,
|
||||
arg.HasAgent,
|
||||
arg.AgentInactiveDisconnectTimeoutSeconds,
|
||||
arg.LockedAt,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
@@ -9366,7 +9376,7 @@ func (q *sqlQuerier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWo
|
||||
return err
|
||||
}
|
||||
|
||||
const updateWorkspaceLockedDeletingAt = `-- name: UpdateWorkspaceLockedDeletingAt :exec
|
||||
const updateWorkspaceLockedDeletingAt = `-- name: UpdateWorkspaceLockedDeletingAt :one
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
@@ -9383,6 +9393,7 @@ WHERE
|
||||
workspaces.template_id = templates.id
|
||||
AND
|
||||
workspaces.id = $1
|
||||
RETURNING 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.locked_at, workspaces.deleting_at
|
||||
`
|
||||
|
||||
type UpdateWorkspaceLockedDeletingAtParams struct {
|
||||
@@ -9390,9 +9401,25 @@ type UpdateWorkspaceLockedDeletingAtParams struct {
|
||||
LockedAt sql.NullTime `db:"locked_at" json:"locked_at"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg UpdateWorkspaceLockedDeletingAtParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateWorkspaceLockedDeletingAt, arg.ID, arg.LockedAt)
|
||||
return err
|
||||
func (q *sqlQuerier) UpdateWorkspaceLockedDeletingAt(ctx context.Context, arg UpdateWorkspaceLockedDeletingAtParams) (Workspace, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateWorkspaceLockedDeletingAt, arg.ID, arg.LockedAt)
|
||||
var i Workspace
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OwnerID,
|
||||
&i.OrganizationID,
|
||||
&i.TemplateID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
&i.DeletingAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateWorkspaceTTL = `-- name: UpdateWorkspaceTTL :exec
|
||||
|
||||
@@ -259,6 +259,14 @@ WHERE
|
||||
) > 0
|
||||
ELSE true
|
||||
END
|
||||
-- Filter by locked workspaces. By default we do not return locked
|
||||
-- workspaces since they are considered soft-deleted.
|
||||
AND CASE
|
||||
WHEN @locked_at :: timestamptz > '0001-01-01 00:00:00+00'::timestamptz THEN
|
||||
locked_at IS NOT NULL AND locked_at >= @locked_at
|
||||
ELSE
|
||||
locked_at IS NULL
|
||||
END
|
||||
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
|
||||
-- @authorize_filter
|
||||
ORDER BY
|
||||
@@ -474,7 +482,7 @@ WHERE
|
||||
)
|
||||
) AND workspaces.deleted = 'false';
|
||||
|
||||
-- name: UpdateWorkspaceLockedDeletingAt :exec
|
||||
-- name: UpdateWorkspaceLockedDeletingAt :one
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
@@ -490,7 +498,8 @@ FROM
|
||||
WHERE
|
||||
workspaces.template_id = templates.id
|
||||
AND
|
||||
workspaces.id = $1;
|
||||
workspaces.id = $1
|
||||
RETURNING workspaces.*;
|
||||
|
||||
-- name: UpdateWorkspacesDeletingAtByTemplateID :exec
|
||||
UPDATE
|
||||
|
||||
Reference in New Issue
Block a user