Path: blob/main/components/gitpod-cli/cmd/tasks-attach.go
2498 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package cmd56import (7"fmt"8"os"910"github.com/gitpod-io/gitpod/gitpod-cli/pkg/supervisor"11"github.com/gitpod-io/gitpod/gitpod-cli/pkg/utils"12"github.com/gitpod-io/gitpod/supervisor/api"13"github.com/manifoldco/promptui"14"github.com/spf13/cobra"15"golang.org/x/xerrors"16"google.golang.org/grpc/codes"17"google.golang.org/grpc/status"18)1920var attachTaskCmdOpts struct {21Interactive bool22ForceResize bool23}2425// attachTaskCmd represents the attach task command26var attachTaskCmd = &cobra.Command{27Use: "attach <id>",28Short: "Attach to a workspace task",29Args: cobra.MaximumNArgs(1),30RunE: func(cmd *cobra.Command, args []string) error {31client, err := supervisor.New(cmd.Context())32if err != nil {33return err34}35defer client.Close()3637var terminalAlias string3839if len(args) > 0 {40terminalAlias = args[0]41} else {42tasks, err := client.GetTasksListByState(cmd.Context(), api.TaskState_running)43if err != nil {44return xerrors.Errorf("cannot get task list: %w", err)45}4647if len(tasks) == 0 {48fmt.Println("There are no running tasks")49return nil50}5152var taskNames []string53var taskIndex int5455if len(tasks) == 1 {56taskIndex = 057} else {5859for _, task := range tasks {60taskNames = append(taskNames, task.Presentation.Name)61}6263prompt := promptui.Select{64Label: "What task do you want attach to?",65Items: taskNames,66Templates: &promptui.SelectTemplates{67Selected: "Attaching to task: {{ . }}",68},69}7071selectedIndex, selectedValue, err := prompt.Run()7273if selectedValue == "" {74return nil75}7677if err != nil {78return err79}8081taskIndex = selectedIndex82}8384terminalAlias = tasks[taskIndex].Terminal85}8687terminal, err := client.Terminal.Get(cmd.Context(), &api.GetTerminalRequest{Alias: terminalAlias})88if err != nil {89if e, ok := status.FromError(err); ok {90switch e.Code() {91case codes.NotFound:92fmt.Println("Terminal is inactive:", terminalAlias)93default:94fmt.Println(e.Code(), e.Message())95}96return nil97} else {98return err99}100}101ppid := int64(os.Getppid())102103if ppid == terminal.Pid {104fmt.Println("You are already in terminal:", terminalAlias)105return GpError{OutCome: utils.UserErrorCode, ErrorCode: utils.UserErrorCode_AlreadyAttached}106}107108interactive, _ := cmd.Flags().GetBool("interactive")109forceResize, _ := cmd.Flags().GetBool("force-resize")110111exitCode, err := client.AttachToTerminal(cmd.Context(), terminalAlias, supervisor.AttachToTerminalOpts{112ForceResize: forceResize,113Interactive: interactive,114})115if err != nil {116return err117}118return GpError{ExitCode: &exitCode, OutCome: utils.Outcome_Success, Silence: true}119},120}121122func init() {123tasksCmd.AddCommand(attachTaskCmd)124125attachTaskCmd.Flags().BoolVarP(&attachTaskCmdOpts.Interactive, "interactive", "i", true, "assume control over the terminal")126attachTaskCmd.Flags().BoolVarP(&attachTaskCmdOpts.ForceResize, "force-resize", "r", true, "force this terminal's size irregardless of other clients")127}128129130