vmc-stic 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/LICENSE +24 -0
  2. data/README.md +102 -0
  3. data/Rakefile +99 -0
  4. data/bin/vmc +6 -0
  5. data/caldecott_helper/Gemfile +10 -0
  6. data/caldecott_helper/Gemfile.lock +48 -0
  7. data/caldecott_helper/server.rb +43 -0
  8. data/config/clients.yml +17 -0
  9. data/config/micro/offline.conf +2 -0
  10. data/config/micro/paths.yml +22 -0
  11. data/config/micro/refresh_ip.rb +20 -0
  12. data/lib/cli.rb +46 -0
  13. data/lib/cli/commands/admin.rb +80 -0
  14. data/lib/cli/commands/apps.rb +1103 -0
  15. data/lib/cli/commands/base.rb +227 -0
  16. data/lib/cli/commands/manifest.rb +56 -0
  17. data/lib/cli/commands/micro.rb +115 -0
  18. data/lib/cli/commands/misc.rb +129 -0
  19. data/lib/cli/commands/services.rb +180 -0
  20. data/lib/cli/commands/user.rb +65 -0
  21. data/lib/cli/config.rb +173 -0
  22. data/lib/cli/console_helper.rb +157 -0
  23. data/lib/cli/core_ext.rb +122 -0
  24. data/lib/cli/errors.rb +19 -0
  25. data/lib/cli/frameworks.rb +142 -0
  26. data/lib/cli/manifest_helper.rb +262 -0
  27. data/lib/cli/runner.rb +532 -0
  28. data/lib/cli/services_helper.rb +84 -0
  29. data/lib/cli/tunnel_helper.rb +332 -0
  30. data/lib/cli/usage.rb +115 -0
  31. data/lib/cli/version.rb +7 -0
  32. data/lib/cli/zip_util.rb +77 -0
  33. data/lib/vmc.rb +3 -0
  34. data/lib/vmc/client.rb +471 -0
  35. data/lib/vmc/const.rb +22 -0
  36. data/lib/vmc/micro.rb +56 -0
  37. data/lib/vmc/micro/switcher/base.rb +97 -0
  38. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  39. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  40. data/lib/vmc/micro/switcher/linux.rb +16 -0
  41. data/lib/vmc/micro/switcher/windows.rb +31 -0
  42. data/lib/vmc/micro/vmrun.rb +158 -0
  43. metadata +207 -0
data/lib/cli/runner.rb ADDED
@@ -0,0 +1,532 @@
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, @args.size == 1 ? 1 : 0)
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
+ puts e.backtrace
493
+ @exit_status = false
494
+ rescue VMC::Client::HTTPException => e
495
+ puts e.message.red
496
+ @exit_status = false
497
+ rescue VMC::Cli::GracefulExit => e
498
+ # Redirected commands end up generating this exception (kind of goto)
499
+ rescue VMC::Cli::CliExit => e
500
+ puts e.message.red
501
+ @exit_status = false
502
+ rescue VMC::Cli::CliError => e
503
+ say("Error #{e.error_code}: #{e.message}".red)
504
+ @exit_status = false
505
+ rescue SystemExit => e
506
+ @exit_status = e.success?
507
+ rescue SyntaxError => e
508
+ puts e.message.red
509
+ puts e.backtrace
510
+ @exit_status = false
511
+ rescue Interrupt => e
512
+ say("\nInterrupted".red)
513
+ @exit_status = false
514
+ rescue Exception => e
515
+ puts e.message.red
516
+ puts e.backtrace
517
+ @exit_status = false
518
+ ensure
519
+ say("\n")
520
+ @exit_status == true if @exit_status.nil?
521
+ if @options[:verbose]
522
+ if @exit_status
523
+ puts "[#{@namespace}:#{@action}] SUCCEEDED".green
524
+ else
525
+ puts "[#{@namespace}:#{@action}] FAILED".red
526
+ end
527
+ say("\n")
528
+ end
529
+ exit(@exit_status)
530
+ end
531
+
532
+ end