feat: Add support for renaming workspaces (#3409)

* feat: Implement workspace renaming

* feat: Add hidden rename command (and data loss warning)

* feat: Implement database.IsUniqueViolation
This commit is contained in:
Mathias Fredriksson
2022-08-26 12:28:38 +03:00
committed by GitHub
parent 623fc5baac
commit c8f8c95f6a
13 changed files with 343 additions and 13 deletions

View File

@ -9,6 +9,7 @@ import (
"time"
"github.com/google/uuid"
"github.com/lib/pq"
"golang.org/x/exp/slices"
"github.com/coder/coder/coderd/database"
@ -2086,6 +2087,32 @@ func (q *fakeQuerier) UpdateProvisionerJobWithCompleteByID(_ context.Context, ar
return sql.ErrNoRows
}
func (q *fakeQuerier) UpdateWorkspace(_ context.Context, arg database.UpdateWorkspaceParams) (database.Workspace, error) {
q.mutex.Lock()
defer q.mutex.Unlock()
for i, workspace := range q.workspaces {
if workspace.Deleted || workspace.ID != arg.ID {
continue
}
for _, other := range q.workspaces {
if other.Deleted || other.ID == workspace.ID || workspace.OwnerID != other.OwnerID {
continue
}
if other.Name == arg.Name {
return database.Workspace{}, &pq.Error{Code: "23505", Message: "duplicate key value violates unique constraint"}
}
}
workspace.Name = arg.Name
q.workspaces[i] = workspace
return workspace, nil
}
return database.Workspace{}, sql.ErrNoRows
}
func (q *fakeQuerier) UpdateWorkspaceAutostart(_ context.Context, arg database.UpdateWorkspaceAutostartParams) error {
q.mutex.Lock()
defer q.mutex.Unlock()

38
coderd/database/errors.go Normal file
View File

@ -0,0 +1,38 @@
package database
import (
"errors"
"github.com/lib/pq"
)
// UniqueConstraint represents a named unique constraint on a table.
type UniqueConstraint string
// UniqueConstraint enums.
// TODO(mafredri): Generate these from the database schema.
const (
UniqueWorkspacesOwnerIDLowerIdx UniqueConstraint = "workspaces_owner_id_lower_idx"
)
// IsUniqueViolation checks if the error is due to a unique violation.
// If one or more specific unique constraints are given as arguments,
// the error must be caused by one of them. If no constraints are given,
// this function returns true for any unique violation.
func IsUniqueViolation(err error, uniqueConstraints ...UniqueConstraint) bool {
var pqErr *pq.Error
if errors.As(err, &pqErr) {
if pqErr.Code.Name() == "unique_violation" {
if len(uniqueConstraints) == 0 {
return true
}
for _, uc := range uniqueConstraints {
if pqErr.Constraint == string(uc) {
return true
}
}
}
}
return false
}

View File

@ -139,6 +139,7 @@ type querier interface {
UpdateUserProfile(ctx context.Context, arg UpdateUserProfileParams) (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)
UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg UpdateWorkspaceAgentConnectionByIDParams) error
UpdateWorkspaceAgentKeysByID(ctx context.Context, arg UpdateWorkspaceAgentKeysByIDParams) error
UpdateWorkspaceAutostart(ctx context.Context, arg UpdateWorkspaceAutostartParams) error

View File

@ -4732,6 +4732,40 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar
return i, err
}
const updateWorkspace = `-- name: UpdateWorkspace :one
UPDATE
workspaces
SET
name = $2
WHERE
id = $1
AND deleted = false
RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl
`
type UpdateWorkspaceParams struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
}
func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (Workspace, error) {
row := q.db.QueryRowContext(ctx, updateWorkspace, arg.ID, arg.Name)
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,
)
return i, err
}
const updateWorkspaceAutostart = `-- name: UpdateWorkspaceAutostart :exec
UPDATE
workspaces

View File

@ -112,6 +112,16 @@ SET
WHERE
id = $1;
-- name: UpdateWorkspace :one
UPDATE
workspaces
SET
name = $2
WHERE
id = $1
AND deleted = false
RETURNING *;
-- name: UpdateWorkspaceAutostart :exec
UPDATE
workspaces