Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-cli/cmd/tasks-attach.go
2498 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cmd
6
7
import (
8
"fmt"
9
"os"
10
11
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/supervisor"
12
"github.com/gitpod-io/gitpod/gitpod-cli/pkg/utils"
13
"github.com/gitpod-io/gitpod/supervisor/api"
14
"github.com/manifoldco/promptui"
15
"github.com/spf13/cobra"
16
"golang.org/x/xerrors"
17
"google.golang.org/grpc/codes"
18
"google.golang.org/grpc/status"
19
)
20
21
var attachTaskCmdOpts struct {
22
Interactive bool
23
ForceResize bool
24
}
25
26
// attachTaskCmd represents the attach task command
27
var attachTaskCmd = &cobra.Command{
28
Use: "attach <id>",
29
Short: "Attach to a workspace task",
30
Args: cobra.MaximumNArgs(1),
31
RunE: func(cmd *cobra.Command, args []string) error {
32
client, err := supervisor.New(cmd.Context())
33
if err != nil {
34
return err
35
}
36
defer client.Close()
37
38
var terminalAlias string
39
40
if len(args) > 0 {
41
terminalAlias = args[0]
42
} else {
43
tasks, err := client.GetTasksListByState(cmd.Context(), api.TaskState_running)
44
if err != nil {
45
return xerrors.Errorf("cannot get task list: %w", err)
46
}
47
48
if len(tasks) == 0 {
49
fmt.Println("There are no running tasks")
50
return nil
51
}
52
53
var taskNames []string
54
var taskIndex int
55
56
if len(tasks) == 1 {
57
taskIndex = 0
58
} else {
59
60
for _, task := range tasks {
61
taskNames = append(taskNames, task.Presentation.Name)
62
}
63
64
prompt := promptui.Select{
65
Label: "What task do you want attach to?",
66
Items: taskNames,
67
Templates: &promptui.SelectTemplates{
68
Selected: "Attaching to task: {{ . }}",
69
},
70
}
71
72
selectedIndex, selectedValue, err := prompt.Run()
73
74
if selectedValue == "" {
75
return nil
76
}
77
78
if err != nil {
79
return err
80
}
81
82
taskIndex = selectedIndex
83
}
84
85
terminalAlias = tasks[taskIndex].Terminal
86
}
87
88
terminal, err := client.Terminal.Get(cmd.Context(), &api.GetTerminalRequest{Alias: terminalAlias})
89
if err != nil {
90
if e, ok := status.FromError(err); ok {
91
switch e.Code() {
92
case codes.NotFound:
93
fmt.Println("Terminal is inactive:", terminalAlias)
94
default:
95
fmt.Println(e.Code(), e.Message())
96
}
97
return nil
98
} else {
99
return err
100
}
101
}
102
ppid := int64(os.Getppid())
103
104
if ppid == terminal.Pid {
105
fmt.Println("You are already in terminal:", terminalAlias)
106
return GpError{OutCome: utils.UserErrorCode, ErrorCode: utils.UserErrorCode_AlreadyAttached}
107
}
108
109
interactive, _ := cmd.Flags().GetBool("interactive")
110
forceResize, _ := cmd.Flags().GetBool("force-resize")
111
112
exitCode, err := client.AttachToTerminal(cmd.Context(), terminalAlias, supervisor.AttachToTerminalOpts{
113
ForceResize: forceResize,
114
Interactive: interactive,
115
})
116
if err != nil {
117
return err
118
}
119
return GpError{ExitCode: &exitCode, OutCome: utils.Outcome_Success, Silence: true}
120
},
121
}
122
123
func init() {
124
tasksCmd.AddCommand(attachTaskCmd)
125
126
attachTaskCmd.Flags().BoolVarP(&attachTaskCmdOpts.Interactive, "interactive", "i", true, "assume control over the terminal")
127
attachTaskCmd.Flags().BoolVarP(&attachTaskCmdOpts.ForceResize, "force-resize", "r", true, "force this terminal's size irregardless of other clients")
128
}
129
130