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
+62
View File
@@ -0,0 +1,62 @@
package cli
import (
"fmt"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/codersdk"
)
func rename() *cobra.Command {
cmd := &cobra.Command{
Annotations: workspaceCommand,
Use: "rename <workspace> <new name>",
Short: "Rename a workspace",
Args: cobra.ExactArgs(2),
// Keep hidden until renaming is safe, see:
// * https://github.com/coder/coder/issues/3000
// * https://github.com/coder/coder/issues/3386
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
client, err := CreateClient(cmd)
if err != nil {
return err
}
workspace, err := namedWorkspace(cmd, client, args[0])
if err != nil {
return xerrors.Errorf("get workspace: %w", err)
}
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n",
cliui.Styles.Wrap.Render("WARNING: A rename can result in data loss if a resource references the workspace name in the template (e.g volumes)."),
)
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
Text: fmt.Sprintf("Type %q to confirm rename:", workspace.Name),
Validate: func(s string) error {
if s == workspace.Name {
return nil
}
return xerrors.Errorf("Input %q does not match %q", s, workspace.Name)
},
})
if err != nil {
return err
}
err = client.UpdateWorkspace(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceRequest{
Name: args[1],
})
if err != nil {
return xerrors.Errorf("rename workspace: %w", err)
}
return nil
},
}
cliui.AllowSkipPrompt(cmd)
return cmd
}
+52
View File
@@ -0,0 +1,52 @@
package cli_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/testutil"
)
func TestRename(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
want := workspace.Name + "-test"
cmd, root := clitest.New(t, "rename", workspace.Name, want, "--yes")
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t)
cmd.SetIn(pty.Input())
cmd.SetOut(pty.Output())
errC := make(chan error, 1)
go func() {
errC <- cmd.ExecuteContext(ctx)
}()
pty.ExpectMatch("confirm rename:")
pty.WriteLine(workspace.Name)
require.NoError(t, <-errC)
ws, err := client.Workspace(ctx, workspace.ID)
assert.NoError(t, err)
got := ws.Name
assert.Equal(t, want, got, "workspace name did not change")
}
+1
View File
@@ -79,6 +79,7 @@ func Core() []*cobra.Command {
start(),
state(),
stop(),
rename(),
templates(),
update(),
users(),