mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: provide endpoint to lock/unlock workspace (#8239)
This commit is contained in:
@@ -143,13 +143,14 @@ var (
|
||||
DisplayName: "Provisioner Daemon",
|
||||
Site: rbac.Permissions(map[string][]rbac.Action{
|
||||
// TODO: Add ProvisionerJob resource type.
|
||||
rbac.ResourceFile.Type: {rbac.ActionRead},
|
||||
rbac.ResourceSystem.Type: {rbac.WildcardSymbol},
|
||||
rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceUser.Type: {rbac.ActionRead},
|
||||
rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
rbac.ResourceUserData.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceAPIKey.Type: {rbac.WildcardSymbol},
|
||||
rbac.ResourceFile.Type: {rbac.ActionRead},
|
||||
rbac.ResourceSystem.Type: {rbac.WildcardSymbol},
|
||||
rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceUser.Type: {rbac.ActionRead},
|
||||
rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
rbac.ResourceWorkspaceBuild.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
rbac.ResourceUserData.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceAPIKey.Type: {rbac.WildcardSymbol},
|
||||
}),
|
||||
Org: map[string][]rbac.Permission{},
|
||||
User: []rbac.Permission{},
|
||||
@@ -165,9 +166,10 @@ var (
|
||||
Name: "autostart",
|
||||
DisplayName: "Autostart Daemon",
|
||||
Site: rbac.Permissions(map[string][]rbac.Action{
|
||||
rbac.ResourceSystem.Type: {rbac.WildcardSymbol},
|
||||
rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceSystem.Type: {rbac.WildcardSymbol},
|
||||
rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspaceBuild.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
}),
|
||||
Org: map[string][]rbac.Permission{},
|
||||
User: []rbac.Permission{},
|
||||
@@ -213,6 +215,7 @@ var (
|
||||
rbac.ResourceUser.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
rbac.ResourceUserData.Type: {rbac.ActionCreate, rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspace.Type: {rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspaceBuild.Type: {rbac.ActionUpdate},
|
||||
rbac.ResourceWorkspaceExecution.Type: {rbac.ActionCreate},
|
||||
rbac.ResourceWorkspaceProxy.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete},
|
||||
}),
|
||||
@@ -1998,7 +2001,7 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
|
||||
action = rbac.ActionDelete
|
||||
}
|
||||
|
||||
if err = q.authorizeContext(ctx, action, w); err != nil {
|
||||
if err = q.authorizeContext(ctx, action, w.WorkspaceBuildRBAC(arg.Transition)); err != nil {
|
||||
return database.WorkspaceBuild{}, err
|
||||
}
|
||||
|
||||
@@ -2530,6 +2533,13 @@ 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) UpdateWorkspaceLockedAt(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
|
||||
fetch := func(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) (database.Workspace, error) {
|
||||
return q.db.GetWorkspaceByID(ctx, arg.ID)
|
||||
}
|
||||
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceLockedAt)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
fetch := func(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
return q.db.GetWorkspaceProxyByID(ctx, arg.ID)
|
||||
|
||||
@@ -1196,7 +1196,7 @@ func (s *MethodTestSuite) TestWorkspace() {
|
||||
WorkspaceID: w.ID,
|
||||
Transition: database.WorkspaceTransitionStart,
|
||||
Reason: database.BuildReasonInitiator,
|
||||
}).Asserts(w, rbac.ActionUpdate)
|
||||
}).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), rbac.ActionUpdate)
|
||||
}))
|
||||
s.Run("Delete/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) {
|
||||
w := dbgen.Workspace(s.T(), db, database.Workspace{})
|
||||
@@ -1204,7 +1204,7 @@ func (s *MethodTestSuite) TestWorkspace() {
|
||||
WorkspaceID: w.ID,
|
||||
Transition: database.WorkspaceTransitionDelete,
|
||||
Reason: database.BuildReasonInitiator,
|
||||
}).Asserts(w, rbac.ActionDelete)
|
||||
}).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionDelete), rbac.ActionDelete)
|
||||
}))
|
||||
s.Run("InsertWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) {
|
||||
w := dbgen.Workspace(s.T(), db, database.Workspace{})
|
||||
|
||||
@@ -5197,6 +5197,26 @@ func (q *fakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateWorkspaceLockedAt(_ context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
|
||||
if err := validateDatabaseType(arg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
for index, workspace := range q.workspaces {
|
||||
if workspace.ID != arg.ID {
|
||||
continue
|
||||
}
|
||||
workspace.LockedAt = arg.LockedAt
|
||||
q.workspaces[index] = workspace
|
||||
return nil
|
||||
}
|
||||
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateWorkspaceProxy(_ context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
@@ -1531,6 +1531,13 @@ func (m metricsStore) UpdateWorkspaceLastUsedAt(ctx context.Context, arg databas
|
||||
return err
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateWorkspaceLockedAt(ctx context.Context, arg database.UpdateWorkspaceLockedAtParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.UpdateWorkspaceLockedAt(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("UpdateWorkspaceLockedAt").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m metricsStore) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
start := time.Now()
|
||||
proxy, err := m.s.UpdateWorkspaceProxy(ctx, arg)
|
||||
|
||||
@@ -3165,6 +3165,20 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceLastUsedAt(arg0, arg1 interface{
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceLastUsedAt", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceLastUsedAt), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateWorkspaceLockedAt mocks base method.
|
||||
func (m *MockStore) UpdateWorkspaceLockedAt(arg0 context.Context, arg1 database.UpdateWorkspaceLockedAtParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateWorkspaceLockedAt", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateWorkspaceLockedAt indicates an expected call of UpdateWorkspaceLockedAt.
|
||||
func (mr *MockStoreMockRecorder) UpdateWorkspaceLockedAt(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceLockedAt", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceLockedAt), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateWorkspaceProxy mocks base method.
|
||||
func (m *MockStore) UpdateWorkspaceProxy(arg0 context.Context, arg1 database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
Generated
+2
-1
@@ -816,7 +816,8 @@ CREATE TABLE workspaces (
|
||||
name character varying(64) NOT NULL,
|
||||
autostart_schedule text,
|
||||
ttl bigint,
|
||||
last_used_at timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL
|
||||
last_used_at timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
|
||||
locked_at timestamp with time zone
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('licenses_id_seq'::regclass);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
BEGIN;
|
||||
ALTER TABLE workspaces DROP COLUMN locked_at;
|
||||
COMMIT;
|
||||
@@ -0,0 +1,3 @@
|
||||
BEGIN;
|
||||
ALTER TABLE workspaces ADD COLUMN locked_at timestamptz NULL;
|
||||
COMMIT;
|
||||
@@ -145,6 +145,11 @@ func (w Workspace) RBACObject() rbac.Object {
|
||||
}
|
||||
|
||||
func (w Workspace) ExecutionRBAC() rbac.Object {
|
||||
// If a workspace is locked it cannot be accessed.
|
||||
if w.LockedAt.Valid {
|
||||
return w.LockedRBAC()
|
||||
}
|
||||
|
||||
return rbac.ResourceWorkspaceExecution.
|
||||
WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
@@ -152,12 +157,40 @@ func (w Workspace) ExecutionRBAC() rbac.Object {
|
||||
}
|
||||
|
||||
func (w Workspace) ApplicationConnectRBAC() rbac.Object {
|
||||
// If a workspace is locked it cannot be accessed.
|
||||
if w.LockedAt.Valid {
|
||||
return w.LockedRBAC()
|
||||
}
|
||||
|
||||
return rbac.ResourceWorkspaceApplicationConnect.
|
||||
WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
|
||||
func (w Workspace) WorkspaceBuildRBAC(transition WorkspaceTransition) rbac.Object {
|
||||
// If a workspace is locked it cannot be built.
|
||||
// However we need to allow stopping a workspace by a caller once a workspace
|
||||
// is locked (e.g. for autobuild). Additionally, if a user wants to delete
|
||||
// a locked workspace, they shouldn't have to have it unlocked first.
|
||||
if w.LockedAt.Valid && transition != WorkspaceTransitionStop &&
|
||||
transition != WorkspaceTransitionDelete {
|
||||
return w.LockedRBAC()
|
||||
}
|
||||
|
||||
return rbac.ResourceWorkspaceBuild.
|
||||
WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
|
||||
func (w Workspace) LockedRBAC() rbac.Object {
|
||||
return rbac.ResourceWorkspaceLocked.
|
||||
WithID(w.ID).
|
||||
InOrg(w.OrganizationID).
|
||||
WithOwner(w.OwnerID.String())
|
||||
}
|
||||
|
||||
func (m OrganizationMember) RBACObject() rbac.Object {
|
||||
return rbac.ResourceOrganizationMember.
|
||||
WithID(m.UserID).
|
||||
|
||||
@@ -235,6 +235,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
&i.Count,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1687,6 +1687,7 @@ type Workspace struct {
|
||||
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"`
|
||||
LockedAt sql.NullTime `db:"locked_at" json:"locked_at"`
|
||||
}
|
||||
|
||||
type WorkspaceAgent struct {
|
||||
|
||||
@@ -254,6 +254,7 @@ type sqlcQuerier interface {
|
||||
UpdateWorkspaceBuildCostByID(ctx context.Context, arg UpdateWorkspaceBuildCostByIDParams) (WorkspaceBuild, error)
|
||||
UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error
|
||||
UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error
|
||||
UpdateWorkspaceLockedAt(ctx context.Context, arg UpdateWorkspaceLockedAtParams) 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
|
||||
|
||||
@@ -8147,7 +8147,7 @@ func (q *sqlQuerier) GetDeploymentWorkspaceStats(ctx context.Context) (GetDeploy
|
||||
|
||||
const getWorkspaceByAgentID = `-- name: GetWorkspaceByAgentID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
@@ -8190,13 +8190,14 @@ func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUI
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
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
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
@@ -8220,13 +8221,14 @@ func (q *sqlQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Worksp
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
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
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
@@ -8257,13 +8259,14 @@ func (q *sqlQuerier) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWo
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
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
|
||||
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
FROM
|
||||
workspaces
|
||||
WHERE
|
||||
@@ -8313,13 +8316,14 @@ func (q *sqlQuerier) GetWorkspaceByWorkspaceAppID(ctx context.Context, workspace
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaces = `-- name: GetWorkspaces :many
|
||||
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, COUNT(*) OVER () as count
|
||||
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, COUNT(*) OVER () as count
|
||||
FROM
|
||||
workspaces
|
||||
JOIN
|
||||
@@ -8529,6 +8533,7 @@ type GetWorkspacesRow struct {
|
||||
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"`
|
||||
LockedAt sql.NullTime `db:"locked_at" json:"locked_at"`
|
||||
Count int64 `db:"count" json:"count"`
|
||||
}
|
||||
|
||||
@@ -8565,6 +8570,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
&i.Count,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -8582,7 +8588,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
|
||||
|
||||
const getWorkspacesEligibleForTransition = `-- name: GetWorkspacesEligibleForTransition :many
|
||||
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.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
|
||||
FROM
|
||||
workspaces
|
||||
LEFT JOIN
|
||||
@@ -8651,6 +8657,7 @@ func (q *sqlQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -8680,7 +8687,7 @@ INSERT INTO
|
||||
last_used_at
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
`
|
||||
|
||||
type InsertWorkspaceParams struct {
|
||||
@@ -8722,6 +8729,7 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -8734,7 +8742,7 @@ SET
|
||||
WHERE
|
||||
id = $1
|
||||
AND deleted = false
|
||||
RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at
|
||||
RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, locked_at
|
||||
`
|
||||
|
||||
type UpdateWorkspaceParams struct {
|
||||
@@ -8757,6 +8765,7 @@ func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspacePar
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
&i.LockedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -8818,6 +8827,25 @@ func (q *sqlQuerier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWo
|
||||
return err
|
||||
}
|
||||
|
||||
const updateWorkspaceLockedAt = `-- name: UpdateWorkspaceLockedAt :exec
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
locked_at = $2
|
||||
WHERE
|
||||
id = $1
|
||||
`
|
||||
|
||||
type UpdateWorkspaceLockedAtParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
LockedAt sql.NullTime `db:"locked_at" json:"locked_at"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateWorkspaceLockedAt(ctx context.Context, arg UpdateWorkspaceLockedAtParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateWorkspaceLockedAt, arg.ID, arg.LockedAt)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateWorkspaceTTL = `-- name: UpdateWorkspaceTTL :exec
|
||||
UPDATE
|
||||
workspaces
|
||||
|
||||
@@ -453,3 +453,11 @@ WHERE
|
||||
workspace_builds.transition = 'start'::workspace_transition
|
||||
)
|
||||
) AND workspaces.deleted = 'false';
|
||||
|
||||
-- name: UpdateWorkspaceLockedAt :exec
|
||||
UPDATE
|
||||
workspaces
|
||||
SET
|
||||
locked_at = $2
|
||||
WHERE
|
||||
id = $1;
|
||||
|
||||
Reference in New Issue
Block a user