...
1 package emulator
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "os/exec"
8 "strings"
9
10 "github.com/c-bata/go-prompt"
11
12 "edge-infra.dev/pkg/sds/lib/colors"
13 )
14
15 func (em *Emulator) startShell(connectionDetails connectionData) error {
16
17
18
19
20
21 err := em.cls.Connect(em.runCtx, connectionDetails.projectID, connectionDetails.bannerID, connectionDetails.storeID, connectionDetails.terminalID)
22 if err != nil {
23 return err
24 }
25
26 err = em.cls.End()
27 if err != nil {
28 em.log.Error(err, "ending session")
29 }
30
31 fmt.Println(colors.Text("Shell prompt. 'Ctrl-D', 'end', 'exit' or 'q' to exit.", colors.BgGreen))
32 em.connectData = connectionDetails
33 em.shellPrompt().Run()
34
35 return nil
36 }
37
38 func (em *Emulator) shellPrompt() *prompt.Prompt {
39 opts := []prompt.Option{
40 prompt.OptionSetExitCheckerOnInput(em.handleBreakLineExit),
41
42
43 prompt.OptionHistory(em.shellHistory.history),
44
45
46 prompt.OptionAddKeyBind(commonKeyBindings...),
47
48
49 prompt.OptionPreviewSuggestionTextColor(prompt.Blue),
50 prompt.OptionSelectedSuggestionBGColor(prompt.LightGray),
51 prompt.OptionSuggestionBGColor(prompt.DarkGray),
52
53 prompt.OptionPrefixTextColor(prompt.Yellow),
54 prompt.OptionPrefix("<> "),
55 }
56
57 return prompt.New(em.shellPromptExecutor,
58 shellPromptCompleter,
59 opts...,
60 )
61 }
62
63 func (em *Emulator) shellPromptExecutor(in string) {
64 if em.handleBreakLineExit(in, true) {
65 return
66 }
67 in = strings.TrimRight(in, "\r")
68
69 err := em.shellHistory.updateHistory(in, historyFileLimit)
70 if err != nil {
71 em.log.Error(err, "Error updating shell history file")
72 }
73
74 env := append(os.Environ(),
75 em.cls.Env()...,
76 )
77 env = append(env,
78 envVar("RCLI_BANNER", em.connectData.bannerID),
79 envVar("RCLI_STORE", em.connectData.storeID),
80 envVar("RCLI_TERMINAL", em.connectData.terminalID),
81 )
82
83 c := exec.Command("bash", "-c", in)
84 if c.Err != nil {
85 fmt.Printf("invalid command: %s\n", c.Err.Error())
86 return
87 }
88
89 c.Env = env
90
91 out, rErr := c.CombinedOutput()
92
93 var exitError *exec.ExitError
94 if rErr != nil && !errors.As(rErr, &exitError) {
95
96
97
98 fmt.Println("Error occurred while executing command. See logs for details")
99 em.log.Error(rErr, "error executing shell command")
100 }
101
102 fmt.Print(string(out))
103
104 exitCode := c.ProcessState.ExitCode()
105 if exitCode == 0 {
106 fmt.Println(colors.BufferedText("Exit code: %d", colors.BgGreen, exitCode))
107 } else {
108 fmt.Println(colors.BufferedText("Exit code: %d", colors.BgRed, exitCode))
109 }
110 }
111
112
113
114 func envVar(name, value string) string {
115 return name + "=" + value
116 }
117
118 func shellPromptCompleter(_ prompt.Document) []prompt.Suggest {
119 return []prompt.Suggest{}
120 }
121
View as plain text