vmc 0.4.0.beta.6 → 0.4.0.beta.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/bin/vmc +11 -10
  2. data/{LICENSE → vmc-ng/LICENSE} +0 -0
  3. data/{Rakefile → vmc-ng/Rakefile} +0 -0
  4. data/vmc-ng/bin/vmc +14 -0
  5. data/{lib → vmc-ng/lib}/vmc.rb +0 -0
  6. data/{lib → vmc-ng/lib}/vmc/cli.rb +0 -0
  7. data/{lib → vmc-ng/lib}/vmc/cli/app.rb +2 -2
  8. data/{lib → vmc-ng/lib}/vmc/cli/better_help.rb +0 -0
  9. data/{lib → vmc-ng/lib}/vmc/cli/command.rb +2 -2
  10. data/{lib → vmc-ng/lib}/vmc/cli/dots.rb +3 -1
  11. data/{lib → vmc-ng/lib}/vmc/cli/service.rb +0 -0
  12. data/{lib → vmc-ng/lib}/vmc/cli/user.rb +0 -0
  13. data/{lib → vmc-ng/lib}/vmc/constants.rb +0 -0
  14. data/{lib → vmc-ng/lib}/vmc/detect.rb +0 -0
  15. data/{lib → vmc-ng/lib}/vmc/errors.rb +0 -0
  16. data/{lib → vmc-ng/lib}/vmc/plugin.rb +0 -0
  17. data/vmc-ng/lib/vmc/version.rb +3 -0
  18. data/vmc/LICENSE +24 -0
  19. data/vmc/README.md +102 -0
  20. data/vmc/Rakefile +101 -0
  21. data/vmc/bin/vmc +6 -0
  22. data/vmc/caldecott_helper/Gemfile +10 -0
  23. data/vmc/caldecott_helper/Gemfile.lock +48 -0
  24. data/vmc/caldecott_helper/server.rb +43 -0
  25. data/vmc/config/clients.yml +17 -0
  26. data/vmc/config/micro/offline.conf +2 -0
  27. data/vmc/config/micro/paths.yml +22 -0
  28. data/vmc/config/micro/refresh_ip.rb +20 -0
  29. data/vmc/lib/cli.rb +47 -0
  30. data/vmc/lib/cli/commands/admin.rb +80 -0
  31. data/vmc/lib/cli/commands/apps.rb +1126 -0
  32. data/vmc/lib/cli/commands/base.rb +227 -0
  33. data/vmc/lib/cli/commands/manifest.rb +56 -0
  34. data/vmc/lib/cli/commands/micro.rb +115 -0
  35. data/vmc/lib/cli/commands/misc.rb +129 -0
  36. data/vmc/lib/cli/commands/services.rb +180 -0
  37. data/vmc/lib/cli/commands/user.rb +65 -0
  38. data/vmc/lib/cli/config.rb +173 -0
  39. data/vmc/lib/cli/console_helper.rb +160 -0
  40. data/vmc/lib/cli/core_ext.rb +122 -0
  41. data/vmc/lib/cli/errors.rb +19 -0
  42. data/vmc/lib/cli/frameworks.rb +265 -0
  43. data/vmc/lib/cli/manifest_helper.rb +302 -0
  44. data/vmc/lib/cli/runner.rb +531 -0
  45. data/vmc/lib/cli/services_helper.rb +84 -0
  46. data/vmc/lib/cli/tunnel_helper.rb +332 -0
  47. data/vmc/lib/cli/usage.rb +115 -0
  48. data/vmc/lib/cli/version.rb +7 -0
  49. data/vmc/lib/cli/zip_util.rb +77 -0
  50. data/vmc/lib/vmc.rb +3 -0
  51. data/vmc/lib/vmc/client.rb +471 -0
  52. data/vmc/lib/vmc/const.rb +22 -0
  53. data/vmc/lib/vmc/micro.rb +56 -0
  54. data/vmc/lib/vmc/micro/switcher/base.rb +97 -0
  55. data/vmc/lib/vmc/micro/switcher/darwin.rb +19 -0
  56. data/vmc/lib/vmc/micro/switcher/dummy.rb +15 -0
  57. data/vmc/lib/vmc/micro/switcher/linux.rb +16 -0
  58. data/vmc/lib/vmc/micro/switcher/windows.rb +31 -0
  59. data/vmc/lib/vmc/micro/vmrun.rb +158 -0
  60. metadata +266 -34
  61. data/lib/vmc/version.rb +0 -3
@@ -0,0 +1,531 @@
1
+
2
+ require 'optparse'
3
+
4
+ require File.dirname(__FILE__) + '/usage'
5
+
6
+ class VMC::Cli::Runner
7
+
8
+ attr_reader :namespace
9
+ attr_reader :action
10
+ attr_reader :args
11
+ attr_reader :options
12
+
13
+ def self.run(args)
14
+ new(args).run
15
+ end
16
+
17
+ def initialize(args=[])
18
+ @args = args
19
+ @options = { :colorize => true }
20
+ @exit_status = true
21
+ end
22
+
23
+ # Collect all the available options for all commands
24
+ # Some duplicates exists to capture all scenarios
25
+ def parse_options!
26
+ opts_parser = OptionParser.new do |opts|
27
+ opts.banner = "\nAvailable options:\n\n"
28
+
29
+ opts.on('--email EMAIL') { |email| @options[:email] = email }
30
+ opts.on('--user EMAIL') { |email| @options[:email] = email }
31
+ opts.on('--passwd PASS') { |pass| @options[:password] = pass }
32
+ opts.on('--pass PASS') { |pass| @options[:password] = pass }
33
+ opts.on('--password PASS') { |pass| @options[:password] = pass }
34
+ opts.on('--token-file TOKEN_FILE') { |token_file| @options[:token_file] = token_file }
35
+ opts.on('--app NAME') { |name| @options[:name] = name }
36
+ opts.on('--name NAME') { |name| @options[:name] = name }
37
+ opts.on('--bind BIND') { |bind| @options[:bind] = bind }
38
+ opts.on('--instance INST') { |inst| @options[:instance] = inst }
39
+ opts.on('--instances INST') { |inst| @options[:instances] = inst }
40
+ opts.on('--url URL') { |url| @options[:url] = url }
41
+ opts.on('--mem MEM') { |mem| @options[:mem] = mem }
42
+ opts.on('--path PATH') { |path| @options[:path] = path }
43
+ opts.on('--no-start') { @options[:nostart] = true }
44
+ opts.on('--nostart') { @options[:nostart] = true }
45
+ opts.on('--force') { @options[:force] = true }
46
+ opts.on('--all') { @options[:all] = true }
47
+
48
+ # generic tracing and debugging
49
+ opts.on('-t [TKEY]') { |tkey| @options[:trace] = tkey || true }
50
+ opts.on('--trace [TKEY]') { |tkey| @options[:trace] = tkey || true }
51
+
52
+ # start application in debug mode
53
+ opts.on('-d [MODE]') { |mode| @options[:debug] = mode || "run" }
54
+ opts.on('--debug [MODE]') { |mode| @options[:debug] = mode || "run" }
55
+
56
+ # override manifest file
57
+ opts.on('-m FILE') { |file| @options[:manifest] = file }
58
+ opts.on('--manifest FILE') { |file| @options[:manifest] = file }
59
+
60
+ opts.on('-q', '--quiet') { @options[:quiet] = true }
61
+
62
+ # micro cloud options
63
+ opts.on('--vmx FILE') { |file| @options[:vmx] = file }
64
+ opts.on('--vmrun FILE') { |file| @options[:vmrun] = file }
65
+ opts.on('--save') { @options[:save] = true }
66
+
67
+ # Don't use builtin zip
68
+ opts.on('--no-zip') { @options[:nozip] = true }
69
+ opts.on('--nozip') { @options[:nozip] = true }
70
+
71
+ opts.on('--no-resources') { @options[:noresources] = true }
72
+ opts.on('--noresources') { @options[:noresources] = true }
73
+
74
+ opts.on('--no-color') { @options[:colorize] = false }
75
+ opts.on('--verbose') { @options[:verbose] = true }
76
+
77
+ opts.on('-n','--no-prompt') { @options[:noprompts] = true }
78
+ opts.on('--noprompt') { @options[:noprompts] = true }
79
+ opts.on('--non-interactive') { @options[:noprompts] = true }
80
+
81
+ opts.on('--prefix') { @options[:prefixlogs] = true }
82
+ opts.on('--prefix-logs') { @options[:prefixlogs] = true }
83
+ opts.on('--prefixlogs') { @options[:prefixlogs] = true }
84
+
85
+ opts.on('--json') { @options[:json] = true }
86
+
87
+ opts.on('-v', '--version') { set_cmd(:misc, :version) }
88
+ opts.on('-h', '--help') { puts "#{command_usage}\n"; exit }
89
+
90
+ opts.on('--port PORT') { |port| @options[:port] = port }
91
+
92
+ opts.on('--runtime RUNTIME') { |rt| @options[:runtime] = rt }
93
+
94
+ # deprecated
95
+ opts.on('--exec EXEC') { |exec| @options[:exec] = exec }
96
+ opts.on('--noframework') { @options[:noframework] = true }
97
+ opts.on('--canary') { @options[:canary] = true }
98
+
99
+ # Proxying for another user, requires admin privileges
100
+ opts.on('-u PROXY') { |proxy| @options[:proxy] = proxy }
101
+
102
+ opts.on_tail('--options') { puts "#{opts}\n"; exit }
103
+ end
104
+ instances_delta_arg = check_instances_delta!
105
+ @args = opts_parser.parse!(@args)
106
+ @args.concat instances_delta_arg
107
+ convert_options!
108
+ self
109
+ end
110
+
111
+ def check_instances_delta!
112
+ return unless @args
113
+ instance_args = @args.select { |arg| /^[-]\d+$/ =~ arg } || []
114
+ @args.delete_if { |arg| instance_args.include? arg}
115
+ instance_args
116
+ end
117
+
118
+ def display_help
119
+ puts command_usage
120
+ exit
121
+ end
122
+
123
+ def convert_options!
124
+ # make sure certain options are valid and in correct form.
125
+ @options[:instances] = Integer(@options[:instances]) if @options[:instances]
126
+ end
127
+
128
+ def set_cmd(namespace, action, args_range=0)
129
+ return if @help_only
130
+ unless args_range == "*" || args_range.is_a?(Range)
131
+ args_range = (args_range.to_i..args_range.to_i)
132
+ end
133
+
134
+ if args_range == "*" || args_range.include?(@args.size)
135
+ @namespace = namespace
136
+ @action = action
137
+ else
138
+ @exit_status = false
139
+ if @args.size > args_range.last
140
+ usage_error("Too many arguments for [#{action}]: %s" % [ @args[args_range.last..-1].map{|a| "'#{a}'"}.join(', ') ])
141
+ else
142
+ usage_error("Not enough arguments for [#{action}]")
143
+ end
144
+ end
145
+ end
146
+
147
+ def parse_command!
148
+ # just return if already set, happends with -v, -h
149
+ return if @namespace && @action
150
+
151
+ verb = @args.shift
152
+ case verb
153
+
154
+ when 'version'
155
+ usage('vmc version')
156
+ set_cmd(:misc, :version)
157
+
158
+ when 'target'
159
+ usage('vmc target [url] [--url]')
160
+ if @args.size == 1
161
+ set_cmd(:misc, :set_target, 1)
162
+ else
163
+ set_cmd(:misc, :target)
164
+ end
165
+
166
+ when 'targets'
167
+ usage('vmc targets')
168
+ set_cmd(:misc, :targets)
169
+
170
+ when 'tokens'
171
+ usage('vmc tokens')
172
+ set_cmd(:misc, :tokens)
173
+
174
+ when 'info'
175
+ usage('vmc info')
176
+ set_cmd(:misc, :info)
177
+
178
+ when 'runtimes'
179
+ usage('vmc runtimes')
180
+ set_cmd(:misc, :runtimes)
181
+
182
+ when 'frameworks'
183
+ usage('vmc frameworks')
184
+ set_cmd(:misc, :frameworks)
185
+
186
+ when 'user'
187
+ usage('vmc user')
188
+ set_cmd(:user, :info)
189
+
190
+ when 'login'
191
+ usage('vmc login [email] [--email EMAIL] [--passwd PASS]')
192
+ if @args.size == 1
193
+ set_cmd(:user, :login, 1)
194
+ else
195
+ set_cmd(:user, :login)
196
+ end
197
+
198
+ when 'logout'
199
+ usage('vmc logout')
200
+ set_cmd(:user, :logout)
201
+
202
+ when 'passwd'
203
+ usage('vmc passwd')
204
+ if @args.size == 1
205
+ set_cmd(:user, :change_password, 1)
206
+ else
207
+ set_cmd(:user, :change_password)
208
+ end
209
+
210
+ when 'add-user', 'add_user', 'create_user', 'create-user', 'register'
211
+ usage('vmc add-user [user] [--email EMAIL] [--passwd PASS]')
212
+ if @args.size == 1
213
+ set_cmd(:admin, :add_user, 1)
214
+ else
215
+ set_cmd(:admin, :add_user)
216
+ end
217
+
218
+ when 'delete-user', 'delete_user', 'unregister'
219
+ usage('vmc delete-user <user>')
220
+ set_cmd(:admin, :delete_user, 1)
221
+
222
+ when 'users'
223
+ usage('vmc users')
224
+ set_cmd(:admin, :users)
225
+
226
+ when 'apps'
227
+ usage('vmc apps')
228
+ set_cmd(:apps, :apps)
229
+
230
+ when 'list'
231
+ usage('vmc list')
232
+ set_cmd(:apps, :list)
233
+
234
+ when 'start'
235
+ usage('vmc start <appname>')
236
+ set_cmd(:apps, :start, @args.size == 1 ? 1 : 0)
237
+
238
+ when 'stop'
239
+ usage('vmc stop <appname>')
240
+ set_cmd(:apps, :stop, @args.size == 1 ? 1 : 0)
241
+
242
+ when 'restart'
243
+ usage('vmc restart <appname>')
244
+ set_cmd(:apps, :restart, @args.size == 1 ? 1 : 0)
245
+
246
+ when 'mem'
247
+ usage('vmc mem <appname> [memsize]')
248
+ if @args.size == 2
249
+ set_cmd(:apps, :mem, 2)
250
+ else
251
+ set_cmd(:apps, :mem, 1)
252
+ end
253
+
254
+ when 'stats'
255
+ usage('vmc stats <appname>')
256
+ set_cmd(:apps, :stats, @args.size == 1 ? 1 : 0)
257
+
258
+ when 'map'
259
+ usage('vmc map <appname> <url>')
260
+ set_cmd(:apps, :map, 2)
261
+
262
+ when 'unmap'
263
+ usage('vmc unmap <appname> <url>')
264
+ set_cmd(:apps, :unmap, 2)
265
+
266
+ when 'delete'
267
+ usage('vmc delete <appname>')
268
+ if @options[:all] && @args.size == 0
269
+ set_cmd(:apps, :delete)
270
+ else
271
+ set_cmd(:apps, :delete, 1)
272
+ end
273
+
274
+ when 'files'
275
+ usage('vmc files <appname> [path] [--instance N] [--all] [--prefix]')
276
+ if @args.size == 1
277
+ set_cmd(:apps, :files, 1)
278
+ else
279
+ set_cmd(:apps, :files, 2)
280
+ end
281
+
282
+ when 'logs'
283
+ usage('vmc logs <appname> [--instance N] [--all] [--prefix]')
284
+ set_cmd(:apps, :logs, 1)
285
+
286
+ when 'instances', 'scale'
287
+ if @args.size > 1
288
+ usage('vmc instances <appname> <num|delta>')
289
+ set_cmd(:apps, :instances, 2)
290
+ else
291
+ usage('vmc instances <appname>')
292
+ set_cmd(:apps, :instances, 1)
293
+ end
294
+
295
+ when 'crashes'
296
+ usage('vmc crashes <appname>')
297
+ set_cmd(:apps, :crashes, 1)
298
+
299
+ when 'crashlogs'
300
+ usage('vmc crashlogs <appname>')
301
+ set_cmd(:apps, :crashlogs, 1)
302
+
303
+ when 'push'
304
+ usage('vmc push [appname] [--path PATH] [--url URL] [--instances N] [--mem] [--runtime RUNTIME] [--no-start]')
305
+ if @args.size == 1
306
+ set_cmd(:apps, :push, 1)
307
+ else
308
+ set_cmd(:apps, :push, 0)
309
+ end
310
+
311
+ when 'update'
312
+ usage('vmc update <appname> [--path PATH]')
313
+ set_cmd(:apps, :update, @args.size == 1 ? 1 : 0)
314
+
315
+ when 'services'
316
+ usage('vmc services')
317
+ set_cmd(:services, :services)
318
+
319
+ when 'env'
320
+ usage('vmc env <appname>')
321
+ set_cmd(:apps, :environment, 1)
322
+
323
+ when 'env-add'
324
+ usage('vmc env-add <appname> <variable[=]value>')
325
+ if @args.size == 2
326
+ set_cmd(:apps, :environment_add, 2)
327
+ elsif @args.size == 3
328
+ set_cmd(:apps, :environment_add, 3)
329
+ end
330
+
331
+ when 'env-del'
332
+ usage('vmc env-del <appname> <variable>')
333
+ set_cmd(:apps, :environment_del, 2)
334
+
335
+ when 'create-service', 'create_service'
336
+ usage('vmc create-service [service] [servicename] [appname] [--name servicename] [--bind appname]')
337
+ set_cmd(:services, :create_service) if @args.size == 0
338
+ set_cmd(:services, :create_service, 1) if @args.size == 1
339
+ set_cmd(:services, :create_service, 2) if @args.size == 2
340
+ set_cmd(:services, :create_service, 3) if @args.size == 3
341
+
342
+ when 'delete-service', 'delete_service'
343
+ usage('vmc delete-service <service>')
344
+ if @args.size == 1
345
+ set_cmd(:services, :delete_service, 1)
346
+ else
347
+ set_cmd(:services, :delete_service)
348
+ end
349
+
350
+ when 'bind-service', 'bind_service'
351
+ usage('vmc bind-service <servicename> <appname>')
352
+ set_cmd(:services, :bind_service, 2)
353
+
354
+ when 'unbind-service', 'unbind_service'
355
+ usage('vmc unbind-service <servicename> <appname>')
356
+ set_cmd(:services, :unbind_service, 2)
357
+
358
+ when 'clone-services'
359
+ usage('vmc clone-services <src-app> <dest-app>')
360
+ set_cmd(:services, :clone_services, 2)
361
+
362
+ when 'aliases'
363
+ usage('vmc aliases')
364
+ set_cmd(:misc, :aliases)
365
+
366
+ when 'alias'
367
+ usage('vmc alias <alias[=]command>')
368
+ if @args.size == 1
369
+ set_cmd(:misc, :alias, 1)
370
+ elsif @args.size == 2
371
+ set_cmd(:misc, :alias, 2)
372
+ end
373
+
374
+ when 'unalias'
375
+ usage('vmc unalias <alias>')
376
+ set_cmd(:misc, :unalias, 1)
377
+
378
+ when 'tunnel'
379
+ usage('vmc tunnel [servicename] [clientcmd] [--port port]')
380
+ set_cmd(:services, :tunnel, 0) if @args.size == 0
381
+ set_cmd(:services, :tunnel, 1) if @args.size == 1
382
+ set_cmd(:services, :tunnel, 2) if @args.size == 2
383
+
384
+ when 'rails-console'
385
+ usage('vmc rails-console <appname>')
386
+ set_cmd(:apps, :console, 1)
387
+
388
+ when 'micro'
389
+ usage('vmc micro <online|offline|status> [--password password] [--save] [--vmx file] [--vmrun executable]')
390
+ if %w[online offline status].include?(@args[0])
391
+ set_cmd(:micro, @args[0].to_sym, 1)
392
+ end
393
+
394
+ when 'help'
395
+ display_help if @args.size == 0
396
+ @help_only = true
397
+ parse_command!
398
+
399
+ when 'usage'
400
+ display basic_usage
401
+ exit(true)
402
+
403
+ when 'options'
404
+ # Simulate --options
405
+ @args = @args.unshift('--options')
406
+ parse_options!
407
+
408
+ when 'manifest'
409
+ usage('vmc manifest')
410
+ set_cmd(:manifest, :edit)
411
+
412
+ when 'extend-manifest'
413
+ usage('vmc extend-manifest')
414
+ set_cmd(:manifest, :extend, 1)
415
+
416
+ else
417
+ if verb
418
+ display "vmc: Unknown command [#{verb}]"
419
+ display basic_usage
420
+ exit(false)
421
+ end
422
+ end
423
+ end
424
+
425
+ def process_aliases!
426
+ return if @args.empty?
427
+ aliases = VMC::Cli::Config.aliases
428
+ aliases.each_pair do |k,v|
429
+ if @args[0] == k
430
+ display "[#{@args[0]} aliased to #{aliases.invert[key]}]" if @options[:verbose]
431
+ @args[0] = v
432
+ break;
433
+ end
434
+ end
435
+ end
436
+
437
+ def usage(msg = nil)
438
+ @usage = msg if msg
439
+ @usage
440
+ end
441
+
442
+ def usage_error(msg = nil)
443
+ @usage_error = msg if msg
444
+ @usage_error
445
+ end
446
+
447
+ def run
448
+
449
+ trap('TERM') { print "\nTerminated\n"; exit(false)}
450
+
451
+ parse_options!
452
+
453
+ @options[:colorize] = false unless STDOUT.tty?
454
+
455
+ VMC::Cli::Config.colorize = @options.delete(:colorize)
456
+ VMC::Cli::Config.nozip = @options.delete(:nozip)
457
+ VMC::Cli::Config.trace = @options.delete(:trace)
458
+ VMC::Cli::Config.output ||= STDOUT unless @options[:quiet]
459
+
460
+ process_aliases!
461
+ parse_command!
462
+
463
+ if @namespace && @action
464
+ cmd = VMC::Cli::Command.const_get(@namespace.to_s.capitalize)
465
+ cmd.new(@options).send(@action, *@args.collect(&:dup))
466
+ elsif @help_only || @usage
467
+ display_usage
468
+ else
469
+ display basic_usage
470
+ exit(false)
471
+ end
472
+
473
+ rescue OptionParser::InvalidOption => e
474
+ puts(e.message.red)
475
+ puts("\n")
476
+ puts(basic_usage)
477
+ @exit_status = false
478
+ rescue OptionParser::AmbiguousOption => e
479
+ puts(e.message.red)
480
+ puts("\n")
481
+ puts(basic_usage)
482
+ @exit_status = false
483
+ rescue VMC::Client::AuthError => e
484
+ if VMC::Cli::Config.auth_token.nil?
485
+ puts "Login Required".red
486
+ else
487
+ puts "Not Authorized".red
488
+ end
489
+ @exit_status = false
490
+ rescue VMC::Client::TargetError, VMC::Client::NotFound, VMC::Client::BadTarget => e
491
+ puts e.message.red
492
+ @exit_status = false
493
+ rescue VMC::Client::HTTPException => e
494
+ puts e.message.red
495
+ @exit_status = false
496
+ rescue VMC::Cli::GracefulExit => e
497
+ # Redirected commands end up generating this exception (kind of goto)
498
+ rescue VMC::Cli::CliExit => e
499
+ puts e.message.red
500
+ @exit_status = false
501
+ rescue VMC::Cli::CliError => e
502
+ say("Error #{e.error_code}: #{e.message}".red)
503
+ @exit_status = false
504
+ rescue SystemExit => e
505
+ @exit_status = e.success?
506
+ rescue SyntaxError => e
507
+ puts e.message.red
508
+ puts e.backtrace
509
+ @exit_status = false
510
+ rescue Interrupt => e
511
+ say("\nInterrupted".red)
512
+ @exit_status = false
513
+ rescue Exception => e
514
+ puts e.message.red
515
+ puts e.backtrace
516
+ @exit_status = false
517
+ ensure
518
+ say("\n")
519
+ @exit_status == true if @exit_status.nil?
520
+ if @options[:verbose]
521
+ if @exit_status
522
+ puts "[#{@namespace}:#{@action}] SUCCEEDED".green
523
+ else
524
+ puts "[#{@namespace}:#{@action}] FAILED".red
525
+ end
526
+ say("\n")
527
+ end
528
+ exit(@exit_status)
529
+ end
530
+
531
+ end