pi 0.1.23 → 0.1.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,37 +1,12 @@
1
- require "interact"
2
1
  module PI::Cli::Command
3
2
  class Services < Base
4
3
  include PI::Cli::ChooseHelper
5
- include Interactive
4
+ include PI::Cli::InteractHelper
6
5
 
7
- def usable_services(appname=nil)
8
- unless appname
9
- useproject = choose_project
10
- projectid = useproject[:id]
11
- useapp = choose_app(projectid)
12
- appname = useapp[:name]
13
- end
14
- services = client.usable_services(appname)
15
- return display JSON.pretty_generate(services) if @options[:json]
16
- return display "No Services" if services.nil? || services.empty?
17
- services.sort! {|a, b| a[:name] <=> b[:name] }
18
- services_table = table do |t|
19
- t.headings = 'Name', 'Version', 'Type'
20
- services.each do |s|
21
- t << [s[:name], s[:version] ,s[:service_type]]
22
- end
23
- end
24
- display services_table
25
- end
26
-
27
- def app_service(appname=nil)
28
- unless appname
29
- useproject = choose_project
30
- projectid = useproject[:id]
31
- useapp = choose_app(projectid)
32
- appname = useapp[:name]
33
- end
34
- services = client.app_service(appname)
6
+ def app_service(appid_or_appname=nil)
7
+ client.check_login_status
8
+ app = choose_app_help_target_not_all(appid_or_appname)
9
+ services = client.app_service(app[:id])
35
10
  return display JSON.pretty_generate(services) if @options[:json]
36
11
  return display "No Services" if services.nil? || services.empty?
37
12
  services.sort! {|a, b| a[:name] <=> b[:name] }
@@ -44,17 +19,10 @@ module PI::Cli::Command
44
19
  display services_table
45
20
  end
46
21
 
47
- def bind_service(appname=nil)
48
- unless appname
49
- useproject = choose_project
50
- projectid = useproject[:id]
51
- useapp = choose_app(projectid)
52
- appname = useapp[:name]
53
- end
54
- app = client.app_get_byname(appname)
55
- err "The application is not found! App name :#{appname}" unless (appname == app[:name] ? true : false)
56
-
57
- services = client.usable_services(appname)
22
+ def bind_service(appid_or_appname=nil)
23
+ client.check_login_status
24
+ app = choose_app_help_target_not_all(appid_or_appname)
25
+ services = client.usable_services(app[:id])
58
26
  err "No usable services!" if services.nil? || services.empty?
59
27
 
60
28
  choices = Array.new
@@ -62,10 +30,12 @@ module PI::Cli::Command
62
30
  choices << s[:name]
63
31
  end
64
32
 
65
- manifest = ask "Select services, indexed list?", :choices => choices, :indexed => true
66
- manifest = manifest.to_a
33
+ manifest = asks "Select services, indexed list?", :choices => choices, :indexed => true
67
34
  display "Selected services: ",false
68
- display "#{manifest}"
35
+ manifest.each do |m|
36
+ display "#{m} ",false
37
+ end
38
+ display "\n"
69
39
  display "Binding service: ",false
70
40
 
71
41
  t = Thread.new do
@@ -76,55 +46,60 @@ module PI::Cli::Command
76
46
  end
77
47
  end
78
48
 
79
- client.bind_service(appname,manifest)
80
- result = check_status(app[:name], "bindservice")
49
+ client.bind_service(app[:id],manifest)
50
+ result = check_status(app[:targetName], app[:name], "bindservice")
81
51
  Thread.kill(t)
82
- if result[:code] == 200
83
- display "OK".green
52
+ if result[:code] == 200
53
+ if not result[:text].empty?
54
+ display "OK".green
55
+ else
56
+ display "Please try again"
57
+ end
84
58
  else
85
59
  err result[:text]
86
60
  end
87
61
  end
88
62
 
89
- def unbind_service(appname=nil)
90
- unless appname
91
- useproject = choose_project
92
- projectid = useproject[:id]
93
- useapp = choose_app(projectid)
94
- appname = useapp[:name]
95
- end
96
- app = client.app_get_byname(appname)
97
- err "The application is not found! App name :#{appname}" unless (appname == app[:name] ? true : false)
98
- services = client.app_service(appname)
99
- err "No binded services!" if services.nil? || services.empty?
100
-
101
- useservice = nil
102
- choose do |menu|
103
- display "=============Services============"
104
- menu.prompt = "Select Service: "
105
- menu.select_by = :index_or_name
106
- services.each do |service|
107
- menu.choice("#{service[:name]}") { useservice = service }
108
- end
109
- end
110
- display "Selected Service: ",false
111
- display "#{useservice[:name]}"
112
- manifest = [useservice[:name]]
113
- display "Unbinding service: ",false
114
-
63
+ def unbind_service(appid_or_appname=nil)
64
+ client.check_login_status
65
+ app = choose_app_help_target_not_all(appid_or_appname)
66
+ services = client.app_service(app[:id])
67
+ err "No binded services!" if services.nil? || services.empty?
68
+ service_choices = Array.new
69
+ services.each do |s|
70
+ service_choices << s[:name]
71
+ end
72
+ services = asks "Select Service", :choices => service_choices, :indexed => true
73
+ display "Selected DNS: ",false
74
+ services.each do |m|
75
+ display "#{m} ",false
76
+ end
77
+ display "\n"
78
+ services.each do |service|
79
+ do_unbind_service(app, service)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def do_unbind_service(app, service)
86
+ display "Unbinding service '#{service}': ",false
115
87
  t = Thread.new do
116
88
  loop do
117
89
  display '.', false
118
90
  sleep (1)
119
91
  break unless t.alive?
120
92
  end
121
- end
122
-
123
- client.unbind_service(appname,manifest)
124
- result = check_status(app[:name], "unbindservice")
93
+ end
94
+ client.unbind_service(app[:id], service)
95
+ result = check_status(app[:targetName], app[:name], "unbindservice")
125
96
  Thread.kill(t)
126
- if result[:code] == 200
127
- display "OK".green
97
+ if result[:code] == 200
98
+ if not result[:text].empty?
99
+ display "OK".green
100
+ else
101
+ display "Please try again"
102
+ end
128
103
  else
129
104
  err result[:text]
130
105
  end
@@ -3,8 +3,12 @@ require 'set'
3
3
  module PI::Cli::Command
4
4
 
5
5
  class User < Base
6
-
6
+ YES_SET = Set.new(["y", "Y", "yes", "YES"])
7
+ NO_SET = Set.new(["n", "N", "no", "NO"])
8
+
7
9
  def login(url=nil)
10
+ user = @options[:user]
11
+ password = @options[:password]
8
12
  unless url
9
13
  url = ask "Attempting login to '#{target_url}'?", :default => true
10
14
  if url == true
@@ -14,12 +18,16 @@ module PI::Cli::Command
14
18
  end
15
19
  end
16
20
  url = "#{target_url}" if url.nil? || url.empty?
17
- eval("PI::Cli::Command::Misc").new().send("set_target", url)
21
+ eval("PI::Cli::Command::Misc").new().send("set_target", url)
22
+ unless client.target_valid?
23
+ display "Host is not available or is not valid: '#{target_url}'".red
24
+ display "\n<<<\n#{client.raw_info}\n>>>\n"
25
+ exit(false)
26
+ end
27
+
18
28
  tries ||= 0
19
- user = ask "User"
20
- password = ask "Password", :echo => '*'
21
- err "Need a valid user" unless user
22
- err "Need a password" unless password
29
+ user = ask "User" unless user
30
+ password = ask "Password", :echo => '*' unless password
23
31
  login_and_save_token(user, password)
24
32
  say "Successfully logged into [#{target_url}]".green
25
33
  rescue PI::Client::TargetError
@@ -27,7 +35,7 @@ module PI::Cli::Command
27
35
  retry if (tries += 1) < 3 && !@options[:passwd]
28
36
  exit 1
29
37
  rescue => e
30
- display "Problem with login, #{e}, try again or register for an account.".red
38
+ display "Problem with login, #{e}, try again.".red
31
39
  exit 1
32
40
  end
33
41
 
@@ -46,6 +54,7 @@ module PI::Cli::Command
46
54
  end
47
55
 
48
56
  def user
57
+ client.check_login_status
49
58
  user = client.user_info
50
59
  github_info = client.github_info
51
60
  github_info[:name] = "null" if github_info[:name].empty? || github_info[:name].nil?
@@ -62,6 +71,7 @@ module PI::Cli::Command
62
71
  end
63
72
 
64
73
  def targets
74
+ client.check_login_status
65
75
  targets = client.targets
66
76
  return display JSON.pretty_generate(targets) if @options[:json]
67
77
  return display 'No Targets' if targets.empty?
@@ -75,7 +85,8 @@ module PI::Cli::Command
75
85
  display targets_table
76
86
  end
77
87
 
78
- def password(newpassword=nil)
88
+ def password(newpassword=nil)
89
+ client.check_login_status
79
90
  unless newpassword
80
91
  loop{
81
92
  newpassword = ask "New Password", :echo => '*'
@@ -94,9 +105,12 @@ module PI::Cli::Command
94
105
  end
95
106
 
96
107
  def github(name=nil)
108
+ client.check_login_status
109
+ email = @options[:email]
110
+ password = @options[:password]
97
111
  name = ask "Please input your name" unless name
98
- email = ask "Please input your email"
99
- password = ask "Please input your password", :echo => '*'
112
+ email = ask "Please input your email" unless email
113
+ password = ask "Please input your password", :echo => '*' unless password
100
114
  manifest = {
101
115
  :name => "#{name}",
102
116
  :password => "#{password}",
@@ -108,6 +122,7 @@ module PI::Cli::Command
108
122
  end
109
123
 
110
124
  def runtimes
125
+ client.check_login_status
111
126
  runtimes_info = client.runtimes
112
127
  return display JSON.pretty_generate(runtimes_info) if @options[:json]
113
128
  return display "No Runtimes" if runtimes_info.empty?
@@ -120,6 +135,7 @@ module PI::Cli::Command
120
135
  end
121
136
 
122
137
  def frameworks
138
+ client.check_login_status
123
139
  runtimes = client.runtimes
124
140
  java_runtime = runtimes[0].downcase
125
141
  ruby_runtime = runtimes[1].downcase
@@ -0,0 +1,538 @@
1
+ module PI::Cli
2
+ module InteractHelper
3
+ EVENTS = {
4
+ "\b" => :backspace,
5
+ "\t" => :tab,
6
+ "\x01" => :home,
7
+ "\x03" => :interrupt,
8
+ "\x04" => :eof,
9
+ "\x05" => :end,
10
+ "\x17" => :kill_word,
11
+ "\x7f" => :backspace,
12
+ "\r" => :enter,
13
+ "\n" => :enter
14
+ }
15
+
16
+ ESCAPES = {
17
+ "[A" => :up, "H" => :up,
18
+ "[B" => :down, "P" => :down,
19
+ "[C" => :right, "M" => :right,
20
+ "[D" => :left, "K" => :left,
21
+ "[3~" => :delete, "S" => :delete,
22
+ "[H" => :home, "G" => :home,
23
+ "[F" => :end, "O" => :end,
24
+ "[Z" => :shift_tab
25
+ }
26
+
27
+ class InputState
28
+ attr_accessor :options, :answer, :position
29
+
30
+ def initialize(options = {}, answer = "", position = 0)
31
+ @options = options
32
+ @answer = answer
33
+ @position = position
34
+ @done = false
35
+ end
36
+
37
+ # Call to signal to the input reader that it can stop.
38
+ def done!
39
+ @done = true
40
+ end
41
+
42
+ # Is the input finished/complete?
43
+ def done?
44
+ @done
45
+ end
46
+
47
+ def censor(what)
48
+ if with = @options[:echo]
49
+ with * what.size
50
+ else
51
+ what
52
+ end
53
+ end
54
+
55
+ def display(what)
56
+ print(censor(what))
57
+ @position += what.size
58
+ end
59
+
60
+ def back(x)
61
+ return if x == 0
62
+
63
+ print("\b" * (x * char_size))
64
+
65
+ @position -= x
66
+ end
67
+
68
+ def clear(x)
69
+ return if x == 0
70
+
71
+ print(" " * (x * char_size))
72
+
73
+ @position += x
74
+
75
+ back(x)
76
+ end
77
+
78
+ def goto(pos)
79
+ return if pos == position
80
+
81
+ if pos > position
82
+ display(answer[position .. pos])
83
+ else
84
+ print("\b" * (position - pos) * char_size)
85
+ end
86
+
87
+ @position = pos
88
+ end
89
+
90
+ private
91
+
92
+ def char_size
93
+ @options[:echo] ? @options[:echo].size : 1
94
+ end
95
+ end
96
+
97
+ def read_char(options = {})
98
+ input = options[:input] || $stdin
99
+
100
+ with_char_io(input) do
101
+ get_character(input)
102
+ end
103
+ end
104
+
105
+ def read_event(options = {})
106
+ input = options[:input] || $stdin
107
+
108
+ with_char_io(input) do
109
+ get_event(input)
110
+ end
111
+ end
112
+
113
+ def read_line(options = {})
114
+ input = options[:input] || $stdin
115
+
116
+ state = input_state(options)
117
+ with_char_io(input) do
118
+ until state.done?
119
+ handler(get_event(input), state)
120
+ end
121
+ end
122
+
123
+ state.answer
124
+ end
125
+
126
+ def asks(question, options = {})
127
+ choices = options[:choices] && options[:choices].to_a
128
+
129
+ list_choices(choices, options) if choices
130
+
131
+ while true
132
+ prompt(question, options)
133
+ ok, res = new_answered(read_line(options), options)
134
+ return res if ok
135
+ end
136
+ end
137
+
138
+ private
139
+
140
+ def clear_input(state)
141
+ state.goto(0)
142
+ state.clear(state.answer.size)
143
+ state.answer = ""
144
+ end
145
+
146
+ def set_input(state, input)
147
+ clear_input(state)
148
+ state.display(input)
149
+ state.answer = input
150
+ end
151
+
152
+ def redraw_input(state)
153
+ pos = state.position
154
+ state.goto(0)
155
+ state.display(state.answer)
156
+ state.goto(pos)
157
+ end
158
+
159
+ def input_state(options)
160
+ InputState.new(options)
161
+ end
162
+
163
+ def get_event(input)
164
+ escaped = false
165
+ escape_seq = ""
166
+
167
+ while true
168
+ c = get_character(input)
169
+
170
+ if not c
171
+ return :eof
172
+ elsif c == "\e" || c == "\xE0"
173
+ escaped = true
174
+ elsif escaped
175
+ escape_seq << c
176
+
177
+ if cmd = ESCAPES[escape_seq]
178
+ return cmd
179
+ elsif ESCAPES.select { |k, v|
180
+ k.start_with? escape_seq
181
+ }.empty?
182
+ escaped, escape_seq = false, ""
183
+ end
184
+ elsif EVENTS.key? c
185
+ return EVENTS[c]
186
+ elsif c < " "
187
+ # ignore
188
+ else
189
+ return [:key, c]
190
+ end
191
+ end
192
+ end
193
+
194
+ def new_answered(ans, options)
195
+ print "\n"
196
+
197
+ if ans.empty?
198
+ if options.key?(:default)
199
+ [true, options[:default]]
200
+ end
201
+ elsif choices = options[:choices]
202
+ matches = choices.select { |x|
203
+ choice_completion(x, options).start_with? ans
204
+ }
205
+
206
+ if choices and ans =~ /^\s*\d+\s*$/ and \
207
+ ans.to_i - 1 >= 0 and res = choices.to_a[ans.to_i - 1]
208
+ res = Array.new
209
+ res = res.push(choices.to_a[ans.to_i - 1])
210
+ [true, res]
211
+ #add
212
+ elsif choices and ans =~ /^\s*(\d+,)*\d+\s*$/ and \
213
+ ans.to_i - 1 >= 0
214
+ ans = ans.split(",")
215
+ res = Array.new
216
+ ans.each do |a|
217
+ res.push(choices[a.to_i - 1])
218
+ end
219
+ # res = ["rails.samsungpaas.comrailstest.samsungpaas.com"]
220
+ [true, res]
221
+ #add
222
+ elsif matches.size == 1
223
+ [true, matches.first]
224
+ elsif matches.size > 1
225
+ matches_list = matches.collect { |m|
226
+ show_choice(m, options)
227
+ }.join " or "
228
+
229
+ puts "Please disambiguate: #{matches_list}?"
230
+
231
+ [false, nil]
232
+ else
233
+ puts "Unknown answer, please try again!"
234
+ [false, nil]
235
+ end
236
+ else
237
+ [true, match_type(ans, options[:default])]
238
+ end
239
+ end
240
+
241
+ def list_choices(choices, options = {})
242
+ return unless options[:indexed]
243
+
244
+ choices.each_with_index do |o, i|
245
+ puts "#{i + 1}: #{show_choice(o, options)}"
246
+ end
247
+ end
248
+
249
+ def show_choice(choice, options = {})
250
+ display = options[:display] || proc(&:to_s)
251
+ display.call(choice)
252
+ end
253
+
254
+ def choice_completion(choice, options = {})
255
+ complete = options[:complete] || options[:display] || proc(&:to_s)
256
+ complete.call(choice)
257
+ end
258
+
259
+ def common_prefix(*strs)
260
+ return strs.first.dup if strs.size == 1
261
+
262
+ longest = strs.sort_by(&:size).last
263
+ longest.size.times do |i|
264
+ sub = longest[0..(-1 - i)]
265
+ if strs.all? { |s| s.start_with?(sub) }
266
+ return sub
267
+ end
268
+ end
269
+
270
+ ""
271
+ end
272
+
273
+ def handler(which, state)
274
+ ans = state.answer
275
+ pos = state.position
276
+
277
+ case which
278
+ when :up
279
+ # nothing
280
+
281
+ when :down
282
+ # nothing
283
+
284
+ when :tab
285
+ matches =
286
+ if choices = state.options[:choices]
287
+ choices.collect { |c|
288
+ choice_completion(c, state.options)
289
+ }.select { |c|
290
+ c.start_with? ans
291
+ }
292
+ else
293
+ matching_paths(ans)
294
+ end
295
+
296
+ if matches.empty?
297
+ print("\a") # bell
298
+ else
299
+ old = ans
300
+ ans = state.answer = common_prefix(*matches)
301
+ state.display(ans[pos .. -1])
302
+ print("\a") if ans == old
303
+ end
304
+
305
+ when :right
306
+ unless pos == ans.size
307
+ state.display(ans[pos .. pos])
308
+ end
309
+
310
+ when :left
311
+ unless pos == 0
312
+ state.back(1)
313
+ end
314
+
315
+ when :delete
316
+ unless pos == ans.size
317
+ ans.slice!(pos, 1)
318
+ rest = ans[pos .. -1]
319
+ state.display(rest)
320
+ state.clear(1)
321
+ state.back(rest.size)
322
+ end
323
+
324
+ when :home
325
+ state.goto(0)
326
+
327
+ when :end
328
+ state.goto(ans.size)
329
+
330
+ when :backspace
331
+ if pos > 0
332
+ rest = ans[pos .. -1]
333
+
334
+ ans.slice!(pos - 1, 1)
335
+
336
+ state.back(1)
337
+ state.display(rest)
338
+ state.clear(1)
339
+ state.back(rest.size)
340
+ end
341
+
342
+ when :interrupt
343
+ raise Interrupt.new
344
+
345
+ when :eof
346
+ state.done! if ans.empty?
347
+
348
+ when :kill_word
349
+ if pos > 0
350
+ start = /[[:alnum:]]*\s*[^[:alnum:]]?$/ =~ ans[0 .. (pos - 1)]
351
+
352
+ if pos < ans.size
353
+ to_end = ans.size - pos
354
+ rest = ans[pos .. -1]
355
+ state.clear(to_end)
356
+ end
357
+
358
+ length = pos - start
359
+
360
+ ans.slice!(start, length)
361
+ state.back(length)
362
+ state.clear(length)
363
+
364
+ if to_end
365
+ state.display(rest)
366
+ state.back(to_end)
367
+ end
368
+ end
369
+
370
+ when :enter
371
+ state.done!
372
+
373
+ when Array
374
+ case which[0]
375
+ when :key
376
+ c = which[1]
377
+ rest = ans[pos .. -1]
378
+
379
+ ans.insert(pos, c)
380
+
381
+ state.display(c + rest)
382
+ state.back(rest.size)
383
+ end
384
+
385
+ else
386
+ return false
387
+ end
388
+
389
+ true
390
+ end
391
+
392
+ def matching_paths(input)
393
+ home = File.expand_path("~")
394
+
395
+ Dir.glob(input.sub("~", home) + "*").collect do |p|
396
+ p.sub(home, "~")
397
+ end
398
+ end
399
+
400
+ def prompt(question, options = {})
401
+ print question
402
+
403
+ if (choices = options[:choices]) && !options[:indexed]
404
+ print " (#{choices.collect(&:to_s).join ", "})"
405
+ end
406
+
407
+ case options[:default]
408
+ when true
409
+ print " [Yn]"
410
+ when false
411
+ print " [yN]"
412
+ when nil
413
+ else
414
+ print " [#{options[:default]}]"
415
+ end
416
+
417
+ print ": "
418
+ end
419
+
420
+ def match_type(str, x)
421
+ case x
422
+ when Integer
423
+ str.to_i
424
+ when true, false
425
+ str.upcase.start_with? "Y"
426
+ else
427
+ str
428
+ end
429
+ end
430
+
431
+ def with_char_io(input)
432
+ before = set_input_state(input)
433
+ yield
434
+ ensure
435
+ restore_input_state(input, before)
436
+ end
437
+
438
+ def chr(x)
439
+ x && x.chr
440
+ end
441
+
442
+ private :chr
443
+
444
+ # Definitions for reading character-by-character with no echoing.
445
+ begin
446
+ require "Win32API"
447
+
448
+ def set_input_state(input)
449
+ nil
450
+ end
451
+
452
+ def restore_input_state(input, state)
453
+ nil
454
+ end
455
+
456
+ def get_character(input)
457
+ if input == STDIN
458
+ begin
459
+ chr(Win32API.new("msvcrt", "_getch", [], "L").call)
460
+ rescue
461
+ chr(Win32API.new("crtdll", "_getch", [], "L").call)
462
+ end
463
+ else
464
+ chr(input.getc)
465
+ end
466
+ end
467
+ rescue LoadError
468
+ begin
469
+ require "termios"
470
+
471
+ def set_input_state(input)
472
+ return nil unless input.tty?
473
+ before = Termios.getattr(input)
474
+
475
+ new = before.dup
476
+ new.c_lflag &= ~(Termios::ECHO | Termios::ICANON)
477
+ new.c_cc[Termios::VMIN] = 1
478
+
479
+ Termios.setattr(input, Termios::TCSANOW, new)
480
+
481
+ before
482
+ end
483
+
484
+ def restore_input_state(input, before)
485
+ if before
486
+ Termios.setattr(input, Termios::TCSANOW, before)
487
+ end
488
+ end
489
+
490
+ def get_character(input)
491
+ chr(input.getc)
492
+ end
493
+ rescue LoadError
494
+ begin
495
+ require "ffi-ncurses"
496
+
497
+ def set_input_state(input)
498
+ return nil unless input.tty?
499
+
500
+ FFI::NCurses.initscr
501
+ FFI::NCurses.cbreak
502
+
503
+ true
504
+ end
505
+
506
+ def restore_input_state(input, before)
507
+ if before
508
+ FFI::NCurses.endwin
509
+ end
510
+ end
511
+
512
+ def get_character(input)
513
+ chr(input.getc)
514
+ end
515
+ rescue LoadError
516
+ def set_input_state(input)
517
+ return nil unless input.tty?
518
+
519
+ before = `stty -g`
520
+
521
+ Kernel.system("stty -echo -icanon isig")
522
+
523
+ before
524
+ end
525
+
526
+ def restore_input_state(input, before)
527
+ Kernel.system("stty #{before}") if before
528
+ end
529
+
530
+ def get_character(input)
531
+ chr(input.getc)
532
+ end
533
+ end
534
+ end
535
+ end
536
+
537
+ end
538
+ end