-
Notifications
You must be signed in to change notification settings - Fork 1
/
console.go
170 lines (142 loc) · 3.94 KB
/
console.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package cmd
import (
"fmt"
"io"
"os"
"strings"
"github.com/chzyer/readline"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
rcli "github.com/gomeet-examples/svc-profile/cmd/remotecli"
)
// consoleCmd represents the console command
var (
consoleAddress string
consoleCmd = &cobra.Command{
Use: "console",
Short: "Interactive console on svc-profile service",
Long: `Use this command for prompt a interactive console
`,
Run: console,
}
)
func init() {
RootCmd.AddCommand(consoleCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// Port flag
consoleCmd.PersistentFlags().StringVar(&consoleAddress, "address", "localhost:13000", "Address to server")
// CA certificate
consoleCmd.PersistentFlags().StringVar(&caCertificate, "ca", "", "X.509 certificate of the Certificate Authority (required for gRPC TLS support)")
// gRPC client certificate
consoleCmd.PersistentFlags().StringVar(&clientCertificate, "cert", "", "X.509 certificate of the gRPC client (required for gRPC TLS support)")
// gRPC client private key
consoleCmd.PersistentFlags().StringVar(&clientPrivateKey, "key", "", "RSA private key of the gRPC client (required for gRPC TLS support)")
// gRPC timeout
consoleCmd.PersistentFlags().IntVar(&timeoutSeconds, "timeout", 5, "gRPC timeout in seconds")
// JSON Web Token
consoleCmd.PersistentFlags().StringVar(&jwtToken, "jwt", "", "JSON Web Token")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// consoleCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
func console(cmd *cobra.Command, args []string) {
log.WithFields(log.Fields{
"Name": svc.Name,
"Version": svc.Version,
"FullName": svcName,
}).Info("console version")
// Initialize remote cli
c, err := rcli.NewRemoteCli(
svc.Name,
svc.Version,
rcli.ConsoleCall,
consoleAddress,
timeoutSeconds,
caCertificate,
clientCertificate,
clientPrivateKey,
jwtToken,
)
if err != nil {
log.Fatalf("Remote cli init fail - %v", err)
}
// Defer remote cli closing
defer c.Close()
// Get remote version for use in prompt
var prompt string
rVersion, err := c.RemoteVersion()
if err != nil {
log.Warnf("Get remote version fail : %v", err)
prompt = svc.Name
} else {
log.WithFields(log.Fields{
"Name": rVersion.Name,
"Version": rVersion.Version,
}).Info("remote version")
prompt = fmt.Sprintf("%s-%s@%s", rVersion.Name, rVersion.Version, consoleAddress)
}
var pfxCompl []readline.PrefixCompleterInterface
for k, _ := range c.GetActionsMap() {
pfxCompl = append(pfxCompl, readline.PcItem(k))
}
for _, v := range []string{"exit"} {
pfxCompl = append(pfxCompl, readline.PcItem(v))
}
completer := readline.NewPrefixCompleter(pfxCompl...)
// Set up interactive console
cfg := &readline.Config{
// Prompt definition
Prompt: fmt.Sprintf("└─┤%s├─$ ", prompt),
HistoryFile: fmt.Sprintf("/tmp/%s-%d.tmp", svc.Name, os.Getpid()),
AutoComplete: completer,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
}
l, err := readline.NewEx(cfg)
if err != nil {
log.Fatal(err)
}
defer l.Close()
log.WithFields(log.Fields{
"HistoryFile": cfg.HistoryFile,
"Interrupt": cfg.InterruptPrompt,
"Exit": cfg.EOFPrompt,
}).Info("load console")
// REPL
log.SetOutput(l.Stderr())
for {
// read interaction
line, err := l.Readline()
if err == readline.ErrInterrupt {
if len(line) == 0 {
break
} else {
continue
}
} else if err == io.EOF {
break
}
line = strings.TrimSpace(line)
if len(line) == 0 {
log.Info("")
continue
}
// Eval/Print
switch {
case line == "exit":
goto exit
default:
// Evaluate arguments string
ok, err := c.Eval(line)
if err != nil {
log.Warn(err)
break
}
log.Info(ok)
} // loop
}
exit:
}