diff --git a/cli/restart.go b/cli/restart.go new file mode 100644 index 0000000000000..687297d371f5f --- /dev/null +++ b/cli/restart.go @@ -0,0 +1,68 @@ +package cli + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" + + "github.com/coder/coder/cli/cliui" + "github.com/coder/coder/codersdk" +) + +func restart() *cobra.Command { + cmd := &cobra.Command{ + Annotations: workspaceCommand, + Use: "restart ", + Short: "Restart a workspace", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + out := cmd.OutOrStdout() + + _, err := cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm restart workspace?", + IsConfirm: true, + }) + if err != nil { + return err + } + + client, err := CreateClient(cmd) + if err != nil { + return err + } + workspace, err := namedWorkspace(cmd, client, args[0]) + if err != nil { + return err + } + + build, err := client.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{ + Transition: codersdk.WorkspaceTransitionStop, + }) + if err != nil { + return err + } + err = cliui.WorkspaceBuild(ctx, out, client, build.ID) + if err != nil { + return err + } + + build, err = client.CreateWorkspaceBuild(ctx, workspace.ID, codersdk.CreateWorkspaceBuildRequest{ + Transition: codersdk.WorkspaceTransitionStart, + }) + if err != nil { + return err + } + err = cliui.WorkspaceBuild(ctx, out, client, build.ID) + if err != nil { + return err + } + + _, _ = fmt.Fprintf(out, "\nThe %s workspace has been restarted at %s!\n", cliui.Styles.Keyword.Render(workspace.Name), cliui.Styles.DateTimeStamp.Render(time.Now().Format(time.Stamp))) + return nil + }, + } + cliui.AllowSkipPrompt(cmd) + return cmd +} diff --git a/cli/restart_test.go b/cli/restart_test.go new file mode 100644 index 0000000000000..9ad55a05137da --- /dev/null +++ b/cli/restart_test.go @@ -0,0 +1,48 @@ +package cli_test + +import ( + "testing" + + "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 TestRestart(t *testing.T) { + t.Parallel() + + t.Run("OK", func(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: 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, _ := testutil.Context(t) + + cmd, root := clitest.New(t, "restart", workspace.Name, "--yes") + clitest.SetupConfig(t, client, root) + + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + + done := make(chan error, 1) + go func() { + done <- cmd.ExecuteContext(ctx) + }() + pty.ExpectMatch("Stopping workspace") + pty.ExpectMatch("Starting workspace") + pty.ExpectMatch("workspace has been restarted") + + err := <-done + require.NoError(t, err, "execute failed") + }) +} diff --git a/cli/root.go b/cli/root.go index 3d0b237e89bb2..867b77e69d446 100644 --- a/cli/root.go +++ b/cli/root.go @@ -95,6 +95,7 @@ func Core() []*cobra.Command { start(), state(), stop(), + restart(), templates(), tokens(), update(), diff --git a/cli/testdata/coder_--help.golden b/cli/testdata/coder_--help.golden index 8ceef13ee0444..aa6f82b6cba35 100644 --- a/cli/testdata/coder_--help.golden +++ b/cli/testdata/coder_--help.golden @@ -37,6 +37,7 @@ Workspace Commands: delete Delete a workspace list List workspaces rename Rename a workspace + restart Restart a workspace schedule Schedule automated start and stop times for workspaces show Display details of a workspace's resources and agents speedtest Run upload and download tests from your machine to a workspace diff --git a/cli/testdata/coder_restart_--help.golden b/cli/testdata/coder_restart_--help.golden new file mode 100644 index 0000000000000..3c3f77766889b --- /dev/null +++ b/cli/testdata/coder_restart_--help.golden @@ -0,0 +1,25 @@ +Restart a workspace + +Usage: + coder restart [flags] + +Flags: + -h, --help help for restart + -y, --yes Bypass prompts + +Global Flags: + --global-config coder Path to the global coder config directory. + Consumes $CODER_CONFIG_DIR (default "/tmp/coder-cli-test-config") + --header stringArray HTTP headers added to all requests. Provide as "Key=Value". + Consumes $CODER_HEADER + --no-feature-warning Suppress warnings about unlicensed features. + Consumes $CODER_NO_FEATURE_WARNING + --no-version-warning Suppress warning when client and server versions do not match. + Consumes $CODER_NO_VERSION_WARNING + --token string Specify an authentication token. For security reasons setting + CODER_SESSION_TOKEN is preferred. + Consumes $CODER_SESSION_TOKEN + --url string URL to a deployment. + Consumes $CODER_URL + -v, --verbose Enable verbose output. + Consumes $CODER_VERBOSE