@@ -6,7 +6,7 @@ package main
6
6
import (
7
7
"encoding/json"
8
8
"flag"
9
- "log "
9
+ "fmt "
10
10
"net"
11
11
"os"
12
12
"strings"
20
20
)
21
21
22
22
func main () {
23
- log .SetOutput (os .Stdout )
24
- log .SetFlags (0 )
25
-
26
23
verbose := flag .Bool ("v" , false , "Verbose output" )
27
24
flag .Usage = usage
28
25
flag .Parse ()
@@ -33,16 +30,16 @@ func main() {
33
30
os .Exit (2 )
34
31
}
35
32
36
- log .Println ("psmcli" , Version )
37
- log .Println ("^D to quit" )
33
+ fmt .Println ("psmcli" , Version )
34
+ fmt .Println ("^D to quit" )
38
35
39
36
// Add default port 3994 if it's missing in the dst string
40
37
41
38
host , port , err := net .SplitHostPort (dst )
42
39
if err != nil && strings .Contains (err .Error (), "missing port" ) {
43
40
dst = net .JoinHostPort (dst , "3994" )
44
41
} else if err != nil {
45
- log .Println (err )
42
+ fmt .Println (err )
46
43
return
47
44
} else if port == "" {
48
45
dst = net .JoinHostPort (host , "3994" )
@@ -52,18 +49,18 @@ func main() {
52
49
53
50
conn , err := newConnection (dst )
54
51
if err != nil {
55
- log .Println (err )
52
+ fmt .Println (err )
56
53
return
57
54
}
58
- log .Println ("Connected to" , conn .conn .RemoteAddr ())
59
- log .Println ("" )
55
+ fmt .Println ("Connected to" , conn .conn .RemoteAddr ())
56
+ fmt .Println ("" )
60
57
61
58
// Use system.version as dummy call to check if we can proceed without
62
59
// authentication.
63
60
64
61
res , err := conn .run (command {Method : "system.version" })
65
62
if err != nil {
66
- log .Println (err )
63
+ fmt .Println (err )
67
64
return
68
65
}
69
66
@@ -76,19 +73,19 @@ func main() {
76
73
77
74
oldState , err := terminal .MakeRaw (0 )
78
75
if err != nil {
79
- log .Println (err )
76
+ fmt .Println (err )
80
77
return
81
78
}
82
79
defer func () {
83
80
terminal .Restore (0 , oldState )
84
- log .Println ("" )
81
+ fmt .Println ("" )
85
82
}()
86
83
87
84
term := terminal .NewTerminal (os .NewFile (0 , "terminal" ), initialPrompt )
88
85
89
86
h , w , err := terminal .GetSize (0 )
90
87
if err != nil {
91
- log .Println (err )
88
+ fmt .Println (err )
92
89
return
93
90
}
94
91
term .SetSize (h , w )
@@ -98,26 +95,26 @@ func main() {
98
95
term .SetPrompt ("Username: " )
99
96
user , err = term .ReadLine ()
100
97
if err != nil {
101
- log .Println (err )
98
+ fmt .Println (err )
102
99
return
103
100
}
104
101
pass , err := term .ReadPassword ("Password: " )
105
102
if err != nil {
106
- log .Println (err )
103
+ fmt .Println (err )
107
104
return
108
105
}
109
106
res , err = conn .run (command {Method : "system.login" , Params : []interface {}{user , pass }})
110
107
if err != nil {
111
- log .Println (err )
108
+ fmt .Println (err )
112
109
return
113
110
}
114
111
if res .Error .Code != 0 {
115
- log .Println (res .Error .Message )
116
- log .Println ()
112
+ fmt .Println (res .Error .Message )
113
+ fmt .Println ()
117
114
} else {
118
115
res , err = conn .run (command {Method : "system.version" })
119
116
if err != nil {
120
- log .Println (err )
117
+ fmt .Println (err )
121
118
return
122
119
}
123
120
}
@@ -132,19 +129,19 @@ func main() {
132
129
133
130
res , err = conn .run (command {Method : "system.hostname" })
134
131
if err != nil {
135
- log .Println (err )
132
+ fmt .Println (err )
136
133
return
137
134
}
138
135
hostname , ok := res .Result .(string )
139
136
if ! ok {
140
137
hostname = "(unknown)"
141
138
}
142
139
143
- log .Println ("PSM version" , version , "at" , hostname )
140
+ fmt .Println ("PSM version" , version , "at" , hostname )
144
141
145
142
res , err = conn .run (command {Method : "model.isReadOnly" })
146
143
if err != nil {
147
- log .Println (err )
144
+ fmt .Println (err )
148
145
return
149
146
}
150
147
@@ -160,13 +157,14 @@ func main() {
160
157
hostname = hostnameParts [0 ]
161
158
term .SetPrompt (user + "@" + hostname + roRw )
162
159
163
- log .Println ()
160
+ fmt .Println ()
164
161
165
162
// Set up tab completion based on announced commands and parameters
166
163
167
164
smd , err := conn .smd ()
168
165
if err != nil {
169
- log .Fatal (err )
166
+ fmt .Println (err )
167
+ os .Exit (1 )
170
168
}
171
169
172
170
matchers := importSMD (smd .Result .Services )
@@ -175,6 +173,7 @@ func main() {
175
173
176
174
// Start the REPL
177
175
176
+ id := 0
178
177
for {
179
178
line , err := term .ReadLine ()
180
179
if err != nil {
@@ -187,33 +186,34 @@ func main() {
187
186
}
188
187
189
188
if line == "help" || line == "?" {
190
- completer . PrintHelp (term .Escape )
189
+ printHelp (term .Escape )
191
190
continue
192
191
}
193
-
194
- fields := strings .Fields (line )
195
- if len (fields ) < 2 {
196
- log .Println ("incomplete command" )
192
+ if line == "commands" {
193
+ completer .PrintHelp (term .Escape )
197
194
continue
198
195
}
199
196
200
- cmd , err := parseCommand (fields )
197
+ cmd , err := parseCommand (line )
201
198
if err != nil {
202
- log .Println (err )
199
+ fmt .Println (err )
203
200
continue
204
201
}
205
202
203
+ cmd .ID = id
204
+ id ++
205
+
206
206
if * verbose {
207
207
// Print the command locally
208
208
bs , _ := json .Marshal (cmd )
209
- log .Printf ("> %s" , bs )
209
+ fmt .Printf ("> %s" , bs )
210
210
}
211
211
212
212
// Execute command on PSM
213
213
214
214
res , err := conn .run (cmd )
215
215
if err != nil {
216
- log .Println (err )
216
+ fmt .Println (err )
217
217
return
218
218
}
219
219
@@ -222,75 +222,65 @@ func main() {
222
222
}
223
223
224
224
func usage () {
225
- log .Println ("psmcli" , Version )
226
- log .Println ()
227
- log .Println ("Usage:" )
228
- log .Println (" psmcli [-v] <host:port>" )
229
- }
230
-
231
- var nextID int
232
-
233
- func parseCommand (fields []string ) (command , error ) {
234
- // The command is the first two parts joined with a dot.
235
-
236
- cmd := command {
237
- ID : nextID ,
238
- Method : fields [0 ] + "." + fields [1 ],
239
- }
240
- nextID ++
241
-
242
- // Look for key=val,key=val sequences among params and make them objects.
243
- // Not stuff that starts with "(" though, because that might be an LDAP
244
- // query expression.
245
-
246
- for _ , param := range fields [2 :] {
247
- if strings .HasPrefix (param , "{" ) {
248
- var obj map [string ]interface {}
249
- err := json .Unmarshal ([]byte (param ), & obj )
250
- if err != nil {
251
- return command {}, err
252
- }
253
- cmd .Params = append (cmd .Params , obj )
254
- } else if strings .Contains (param , "=" ) && ! strings .HasPrefix (param , "(" ) {
255
- parts := strings .Split (param , "," )
256
- obj := map [string ]string {}
257
- for _ , part := range parts {
258
- kv := strings .SplitN (part , "=" , 2 )
259
- obj [kv [0 ]] = kv [1 ]
260
- }
261
- cmd .Params = append (cmd .Params , obj )
262
- } else {
263
- cmd .Params = append (cmd .Params , param )
264
- }
265
- }
266
-
267
- return cmd , nil
225
+ fmt .Println ("psmcli" , Version )
226
+ fmt .Println ()
227
+ fmt .Println ("Usage:" )
228
+ fmt .Println (" psmcli [-v] <host:port>" )
268
229
}
269
230
270
231
func printResponse (res response ) {
271
232
if res .Error .Code != 0 {
272
- log .Printf ("Error %d: %s" , res .Error .Code , res .Error .Message )
233
+ fmt .Printf ("Error %d: %s" , res .Error .Code , res .Error .Message )
273
234
} else if res .Result != nil {
274
235
switch result := res .Result .(type ) {
275
236
case []interface {}:
276
237
for _ , res := range result {
277
238
switch res := res .(type ) {
278
239
case string , int , json.Number :
279
- log .Println (res )
240
+ fmt .Println (res )
280
241
default :
281
242
bs , _ := json .MarshalIndent (res , "" , " " )
282
- log .Printf ("%s\n \n " , bs )
243
+ fmt .Printf ("%s\n \n " , bs )
283
244
}
284
245
}
285
246
286
247
case map [string ]interface {}:
287
248
bs , _ := json .MarshalIndent (result , "" , " " )
288
- log .Printf ("%s\n \n " , bs )
249
+ fmt .Printf ("%s\n \n " , bs )
289
250
290
251
default :
291
- log .Println (result )
252
+ fmt .Println (result )
292
253
}
293
- } else {
294
- log .Println ("OK" )
295
254
}
296
255
}
256
+
257
+ func printHelp (esc * terminal.EscapeCodes ) {
258
+ fmt .Println (`Usage:
259
+
260
+ help, ?:
261
+ Print this help
262
+
263
+ commands:
264
+ Print available PSM commands. Commands have tab completion available.
265
+
266
+ Examples:
267
+
268
+ Simple command without parameter:
269
+ $ system hostname
270
+
271
+ Command with parameters:
272
+ $ object deleteByAid subscriber 1234
273
+
274
+ Command with object parameters:
275
+ $ object updateByAid subscriber 1234 attr=value
276
+ $ object updateByAid subscriber 1234 attr1=value1,attr2=value2
277
+
278
+ (No spaces in the object parameter!)
279
+
280
+ Command with arbitrary JSON object parameter:
281
+ $ object updateByAid subscriber 1234
282
+ {"attr1": "value1 with space", "attr2": "value2"}
283
+
284
+ (Line break for display purposes only)
285
+ ` )
286
+ }
0 commit comments