vmc 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/parse.rb ADDED
@@ -0,0 +1,719 @@
1
+ # Copyright 2010, VMware, Inc. Licensed under the
2
+ # MIT license, please see the LICENSE file. All rights reserved
3
+
4
+ require File.join(File.dirname(__FILE__),'vmc')
5
+
6
+ require 'yaml'
7
+
8
+ def display(msg, nl=true)
9
+ if nl
10
+ puts(msg)
11
+ else
12
+ print(msg)
13
+ STDOUT.flush
14
+ end
15
+ end
16
+
17
+ def display_usage(msg, nl=true)
18
+ display("\nUsage: vmc #{msg}\n\n", nl)
19
+ end
20
+
21
+ def show_help
22
+ help = %Q{
23
+
24
+ version # version
25
+ help, -h # show usage
26
+
27
+ aliases # lists current aliases
28
+ alias <alias>[=]<command> # create an alias for a command
29
+
30
+ target [host[:port]] # reports current target or sets the target site
31
+ info # information
32
+ register [--email, --passwd] # register and create an account
33
+ login [email] [--email, --passwd] # login
34
+ logout # logout
35
+ passwd # change password for current user
36
+ user # display current user
37
+
38
+ services # list of services available
39
+
40
+ create-service <service> [--name, --bind] # create a service instance. we will
41
+ # auto-generate a name if you leave off
42
+ # the --name flag, if you add the --bind
43
+ # flag with an app name we will also bind
44
+ # the service to that app
45
+
46
+ delete-service [service] # delete the service
47
+
48
+ bind-service <service> <appname> # bind service to appname
49
+ unbind-service <service> <appname> # unbind service from appname
50
+
51
+ apps # list your apps
52
+ push <appname> [--instances --exec
53
+ --noframework --url
54
+ --mem --path
55
+ --no-start] # push and start the application
56
+ push <appname> # push and start the application
57
+ start <appname> # start the application
58
+ stop <appname> # stop the application
59
+ restart <appname> # restart the application
60
+ delete <appname || --all> [--force] # delete the application
61
+ update <appname> [--canary] # update the application
62
+ instances <appname> [num] # list instances, scale up or down
63
+ # the number of instances
64
+
65
+ mem <appname> [memsize] # update the memory reservation for this application
66
+
67
+ crashes <appname> # list recent application crashes
68
+ crashlogs <appname> [--instance] # dump all the logs for the crashed instance
69
+ logs <appname> [--instance] # dump all the logs for the instance
70
+ files <appname> [path] [--instance] # directory listing or file download
71
+ stats <appname> # report resource usage for the application
72
+
73
+ map <appname> <url> # register the application with the url
74
+ unmap <appname> <url> # unregister the application from the url
75
+
76
+ }
77
+
78
+ display(help)
79
+ end
80
+
81
+ def setup(verb)
82
+ trap("TERM") { print "\nInterupted\n\n"; exit}
83
+ trap("INT") { print "\nInterupted\n\n"; exit}
84
+ cli = VMC::Client.new
85
+ cli.set_puser($puser)
86
+ cli.setup_target_uris
87
+ # Check to make sure the server is there..
88
+ cli.check_target unless verb =~ /target/i
89
+ cli
90
+ end
91
+
92
+ def get_option(options, default=true)
93
+ test = [options]
94
+ args = ARGV
95
+ return unless opt_index = ARGV.select { |a| test.include? a }.first
96
+ opt_position = args.index(opt_index) + 1
97
+ if ARGV.size > opt_position && opt_value = ARGV[opt_position]
98
+ if opt_value.include?('--')
99
+ opt_value = nil
100
+ else
101
+ ARGV.delete_at(opt_position)
102
+ end
103
+ end
104
+ ARGV.delete(opt_index)
105
+ opt_value ||= default
106
+ end
107
+
108
+ $puser = get_option('-u')
109
+
110
+ # parse command line aliases from '~/.vmc-aliases'
111
+ alias_file = File.expand_path('~/.vmc-aliases')
112
+ if File.exist?(alias_file)
113
+ aliases = YAML.load_file(alias_file)
114
+ if key = aliases.values.grep(ARGV[0]).first
115
+ #display "[#{ARGV[0]} aliased to #{aliases.invert[key]}]"
116
+ ARGV[0] = aliases.invert[key]
117
+ end
118
+ end
119
+
120
+ require 'main'
121
+
122
+
123
+ # hack, allows support negative deltas for instances, like vmc instances foo -2
124
+ if ARGV[0] =~ /instances/i && ARGV[2] =~ /(-\d+)/
125
+ ARGV[2] = '--n'
126
+ ARGV[3] = $1
127
+ end
128
+
129
+ Main {
130
+
131
+ description "VMware Cloud Command Line Tool"
132
+
133
+ mode(:version) {
134
+ description "Show version of this CLI"
135
+ def run
136
+ cli = setup(:version)
137
+ cli.version
138
+ end
139
+ }
140
+
141
+ mode(:delete) {
142
+ description "delete the application"
143
+ option 'delete-option'
144
+ argument(:appname){
145
+ optional
146
+
147
+ }
148
+ option('all'){
149
+ cast :boolean
150
+ }
151
+
152
+ option('force'){
153
+ cast :boolean
154
+ }
155
+ def run
156
+ if (! params['all'].given?) && (! params['appname'].given? )
157
+ display_usage "delete <appname || --all>"
158
+ exit 1
159
+ end
160
+ cli = setup('delete')
161
+ cli.delete(params['all'].given? ? '--all' : params['appname'].value, params['force'].given?)
162
+ end
163
+ }
164
+
165
+ # vmc alias restart bounce
166
+ mode(:alias) {
167
+ description "create an alias for a command in our CLI namespace"
168
+ argument(:_alias){
169
+ required
170
+ error { display_usage "alias <alias>[=]<command>" }
171
+ }
172
+ argument(:real){ optional }
173
+ argument(:real2){ optional }
174
+
175
+ def run
176
+ alias_file = File.expand_path('~/.vmc-aliases')
177
+ aliases = YAML.load_file(alias_file) rescue {}
178
+
179
+ _alias = params['_alias'].value
180
+ real = params['real'].value
181
+ real2 = params['real2'].value
182
+
183
+ k = v = nil
184
+
185
+ if (_alias and real and not real2)
186
+ k,v = _alias, real
187
+ elsif (_alias and not real and not real2)
188
+ k,v = _alias.split('=')
189
+ elsif (_alias and real and real2 and real == '=')
190
+ k,v = _alias, real2
191
+ else
192
+ display_usage "alias <alias>[=]<command>"
193
+ exit(1)
194
+ end
195
+
196
+ aliases[v] = k
197
+ File.open(alias_file, 'wb') {|f| f.write(aliases.to_yaml)}
198
+ display("Successfully aliased #{k} to #{v}")
199
+ rescue => e
200
+ error("There was a problem writing to the '~/.vmc-aliases' file: #{e}")
201
+ end
202
+ }
203
+
204
+ mode(:aliases) {
205
+ description "List aliases"
206
+
207
+ def run
208
+ alias_file = File.expand_path('~/.vmc-aliases')
209
+ aliases = YAML.load_file(alias_file) rescue {}
210
+ aliases.each do |k,v|
211
+ display "#{v} = #{k}"
212
+ end
213
+ end
214
+ }
215
+
216
+ mode('remove-alias') {
217
+ description "Remove alias"
218
+ argument(:_alias){
219
+ required
220
+ error { display_usage "remove-alias <alias>" }
221
+ }
222
+
223
+ def run
224
+ alias_file = File.expand_path('~/.vmc-aliases')
225
+ aliases = YAML.load_file(alias_file) rescue {}
226
+ aliases.each do |k,v|
227
+ aliases.delete(k) if v == params['_alias'].value
228
+ end
229
+ File.open(alias_file, 'wb') {|f| f.write(aliases.to_yaml)}
230
+ display "Successfully removed alias: #{params['_alias'].value}\nRemaining aliases:\n"
231
+ aliases.each do |k,v|
232
+ display "#{v} = #{k}"
233
+ end
234
+
235
+ end
236
+ }
237
+
238
+ mode(:target) {
239
+ description "Set the target Cloud for this CLI session"
240
+ argument(:host){ optional }
241
+ def run
242
+ cli = setup('target')
243
+ cli.target(params['host'].value)
244
+ end
245
+ }
246
+
247
+ mode(:info) {
248
+ description "information (optionally about services)"
249
+ def run
250
+ cli = setup('info')
251
+ cli.info
252
+ end
253
+ }
254
+
255
+ mode(:register) {
256
+ description "register and create an account"
257
+
258
+ option('email=[email]'){
259
+ arity 1
260
+ }
261
+
262
+ option('passwd=[passwd]'){
263
+ arity 1
264
+ }
265
+
266
+ def run
267
+ cli = setup('register')
268
+ cli.register(params['email'].value, params['passwd'].value)
269
+ end
270
+ }
271
+
272
+ mode(:login) {
273
+ description "login to the cloud"
274
+
275
+ argument(:email_arg) { optional }
276
+ argument(:passwd_arg) { optional }
277
+
278
+
279
+ option('email=[email]'){
280
+ arity 1
281
+ }
282
+
283
+ option('passwd=[passwd]'){
284
+ arity 1
285
+ }
286
+
287
+ def run
288
+ cli = setup('login')
289
+
290
+ email = params['email_arg'].given? ? params['email_arg'].value : params['email'].value
291
+ pass = params['passwd_arg'].given? ? params['passwd_arg'].value : params['passwd'].value
292
+ cli.login(email, pass)
293
+ end
294
+ }
295
+
296
+ mode(:logout) {
297
+ description "logout"
298
+ def run
299
+ cli = setup('logout')
300
+ cli.logout
301
+ end
302
+ }
303
+
304
+ mode(:passwd) {
305
+ description "change password for current user"
306
+
307
+ option('passwd=[passwd]'){
308
+ arity 1
309
+ }
310
+
311
+ def run
312
+ cli = setup('passwd')
313
+ cli.passwd(params['passwd'].value)
314
+ end
315
+ }
316
+
317
+ mode(:user) {
318
+ description "display current user"
319
+ def run
320
+ cli = setup('user')
321
+ cli.user
322
+ end
323
+ }
324
+
325
+ mode(:services) {
326
+ description "list of services available"
327
+ def run
328
+ cli = setup('services')
329
+ cli.services
330
+ end
331
+ }
332
+
333
+
334
+ # vmc create-service redis --name my-redis
335
+ mode('create-service') {
336
+ description "provision a service"
337
+ option 'add-option'
338
+
339
+ argument(:servicename) {
340
+ required
341
+ error { display_usage "create-service <service> [--name, --bind]" }
342
+ }
343
+
344
+ argument(:pname) { optional }
345
+ argument(:pbind) { optional }
346
+
347
+ option('name=[name]'){
348
+ arity 1
349
+ }
350
+
351
+ option('bind=[bind]'){
352
+ arity 1
353
+ }
354
+
355
+ def run
356
+ cli = setup('create_service')
357
+ opts = {
358
+ :bind => params['bind'].value || params['pbind'].value,
359
+ :name => params['name'].value || params['pname'].value,
360
+ }
361
+ cli.create_service(params['servicename'].value, opts)
362
+ end
363
+ }
364
+
365
+ mode('delete-service') {
366
+ description "Delete a provisioned service"
367
+ argument(:servicename) { optional }
368
+
369
+ def run
370
+ cli = setup('delete_service')
371
+ cli.delete_service(params['servicename'].value)
372
+ end
373
+ }
374
+
375
+ mode('bind-service') {
376
+ description "Bind a provisioned service"
377
+
378
+ argument(:servicename){
379
+ required
380
+ error { display_usage "bind-service <service> <appname>" }
381
+ }
382
+ argument(:appname){
383
+ required
384
+ error { display_usage "bind-service <service> <appname>" }
385
+ }
386
+
387
+ def run
388
+ cli = setup('bind_service')
389
+ cli.bind_service(params['servicename'].value, params['appname'].value)
390
+ end
391
+ }
392
+
393
+ mode('unbind-service') {
394
+ description "Bind a provisioned service"
395
+
396
+ argument(:servicename){
397
+ required
398
+ error { display_usage "unbind-service <service> <appname>" }
399
+ }
400
+ argument(:appname){
401
+ required
402
+ error { display_usage "unbind-service <service> <appname>" }
403
+ }
404
+
405
+ def run
406
+ cli = setup('unbind_service')
407
+ cli.unbind_service(params['servicename'].value, params['appname'].value)
408
+ end
409
+ }
410
+
411
+ mode(:apps) {
412
+ description "list your apps"
413
+ option 'apps-option'
414
+
415
+ def run
416
+ cli = setup('apps')
417
+ cli.apps(nil)
418
+ end
419
+ }
420
+
421
+ mode(:mem) {
422
+ argument(:appname){
423
+ required
424
+ error { display_usage "mem <appname> [memsize]"}
425
+ }
426
+ argument(:memsize){ optional }
427
+ def run
428
+ if params['memsize'].given?
429
+ unless %w(64M 128M 256M 512M 1G 2G).include?(params['memsize'].value)
430
+ display_usage "mem <appname> <memsize>"
431
+ display "<memsize> must be one of: (64M 128M 256M 512M)"
432
+ display "you provided #{params['memsize'].value}"
433
+ exit 1
434
+ end
435
+ end
436
+
437
+ cli = setup('mem')
438
+ cli.mem(params['appname'].value, params['memsize'].value)
439
+ end
440
+
441
+ }
442
+
443
+ mode(:push) {
444
+ description "push and start the application"
445
+ option 'push-option'
446
+ argument(:appname){ optional }
447
+
448
+ option('instances=[instances]'){
449
+ arity 1
450
+ }
451
+
452
+ option('exec=[exec]'){
453
+ arity 1
454
+ }
455
+
456
+ option('path=[path]'){
457
+ arity 1
458
+ }
459
+
460
+ option('noframework'){
461
+ default false
462
+ }
463
+
464
+ option('url=[url]'){
465
+ arity 1
466
+ }
467
+
468
+ option('mem=[mem]'){
469
+ arity 1
470
+ }
471
+
472
+ option('no-start'){
473
+
474
+ }
475
+
476
+ def run
477
+ cli = setup('push')
478
+
479
+ if params['mem'].given?
480
+ unless %w(64M 128M 256M 512M 1G 2G).include?(params['mem'].value)
481
+ display_usage "push --mem <memsize>"
482
+ display "<memsize> must be one of: (64M 128M 256M 512M)"
483
+ display "you provided #{params['mem'].value}"
484
+ exit 1
485
+ end
486
+ end
487
+
488
+ opts = {:instances => params['instances'].value,
489
+ :exec => params['exec'].value,
490
+ :noframework => params['noframework'].value,
491
+ :appname => params['appname'].value,
492
+ :url => params['url'].value,
493
+ :mem => params['mem'].value,
494
+ :path => params['path'].value,
495
+ :no_start => params['no-start'].given?
496
+ }
497
+ cli.push(opts)
498
+ end
499
+ }
500
+
501
+ mode(:start) {
502
+ description "start the application"
503
+ option 'start-option'
504
+ argument(:appname){
505
+ required
506
+ error { display_usage "start <appname>" }
507
+ }
508
+ def run
509
+ cli = setup('start')
510
+ cli.start(params['appname'].value)
511
+ end
512
+ }
513
+
514
+ mode(:stop) {
515
+ description "stop the application"
516
+ option 'stop-option'
517
+ argument(:appname){
518
+ required
519
+ error { display_usage "stop <appname>" }
520
+ }
521
+ def run
522
+ cli = setup('stop')
523
+ cli.stop(params['appname'].value)
524
+ end
525
+ }
526
+
527
+ mode(:restart) {
528
+ description "restart the application"
529
+ option 'restart-option'
530
+ argument(:appname){
531
+ required
532
+ error { display_usage "restart <appname>" }
533
+ }
534
+ def run
535
+ cli = setup('restart')
536
+ cli.restart(params['appname'].value)
537
+ end
538
+ }
539
+
540
+ mode(:update) {
541
+ description "update the application"
542
+ option 'update-option'
543
+ argument(:appname){
544
+ required
545
+ error { display_usage "update <appname> [--canary]" }
546
+ }
547
+ option('canary'){
548
+ cast :bool
549
+ default true
550
+ optional
551
+ }
552
+ def run
553
+ cli = setup('update')
554
+ cli.update(params['appname'].value, params['canary'].given?)
555
+ end
556
+ }
557
+
558
+ mode(:instances) {
559
+ description "list instances, scale up or down the number of instances"
560
+ option 'instances-option'
561
+
562
+ argument(:appname){
563
+ required
564
+ error { display_usage "instances <appname> [num]" }
565
+ }
566
+ argument(:num){
567
+ optional
568
+ }
569
+ option(:n) {
570
+ argument_required
571
+ }
572
+
573
+ def run
574
+ cli = setup('instances')
575
+ chg = params['n'].given? ? params['n'].value : params['num'].value
576
+ cli.instances(params['appname'].value, chg)
577
+ end
578
+ }
579
+
580
+ mode(:map) {
581
+ description "register the application with the url"
582
+ option 'map-option'
583
+ argument(:appname){
584
+ required
585
+ error { display_usage "map <appname> <url>"}
586
+ }
587
+ argument(:url){
588
+ required
589
+ error { display_usage "map <appname> <url>"}
590
+ }
591
+
592
+ def run
593
+ cli = setup('map')
594
+ cli.map(params['appname'].value, params['url'].value)
595
+ end
596
+ }
597
+
598
+ mode(:unmap) {
599
+ description "unregister the application from the url"
600
+ option 'unmap-option'
601
+ argument(:appname){
602
+ required
603
+ error { display_usage "unmap <appname> <url>"}
604
+ }
605
+ argument(:url){
606
+ required
607
+ error { display_usage "unmap <appname> <url>"}
608
+ }
609
+ def run
610
+ cli = setup('unmap')
611
+ cli.unmap(params['appname'].value, params['url'].value)
612
+ end
613
+ }
614
+
615
+ mode(:crashes) {
616
+ description "list recent application crashes"
617
+ option 'crashes-option'
618
+ argument(:appname){
619
+ required
620
+ error { display_usage "crashes <appname>" }
621
+ }
622
+ def run
623
+ cli = setup('crashes')
624
+ cli.crashes(params['appname'].value)
625
+ end
626
+ }
627
+
628
+ mode(:files) {
629
+ description "directory listing or file download"
630
+ option 'files-option'
631
+ argument(:appname){
632
+ required
633
+ error { display_usage "files <appname> [path]" }
634
+ }
635
+ argument(:dir_or_file){ optional }
636
+ option('instance', 'i'){
637
+ default '0'
638
+ optional
639
+ arity 1
640
+ argument_required
641
+ }
642
+ def run
643
+ cli = setup('files')
644
+ cli.files(params['appname'].value, params['dir_or_file'].value, params['instance'].value)
645
+ end
646
+ }
647
+
648
+ mode(:crashlogs) {
649
+ description "Dump all logs from first crashed instance"
650
+ argument(:appname){
651
+ required
652
+ error { display_usage "crashlogs <appname> [--instance]" }
653
+ }
654
+ option('instance', 'i'){
655
+ default '0'
656
+ arity 1
657
+ optional
658
+ argument_required
659
+ }
660
+
661
+ def run
662
+ cli = setup('crashlogs')
663
+ cli.grab_crash_logs(params['appname'].value, params['instance'].value)
664
+ end
665
+ }
666
+
667
+ mode(:logs) {
668
+ description "Dump all logs"
669
+ argument(:appname){
670
+ required
671
+ error { display_usage "logs <appname> [--instance]" }
672
+ }
673
+ option('instance', 'i'){
674
+ default '0'
675
+ arity 1
676
+ optional
677
+ argument_required
678
+ }
679
+
680
+ def run
681
+ cli = setup('logs')
682
+ cli.grab_logs(params['appname'].value, params['instance'].value)
683
+ end
684
+ }
685
+
686
+ mode(:stats) {
687
+ description "report resource usage for the application"
688
+ option 'stats-option'
689
+ argument(:appname){
690
+ required
691
+ error { display_usage "stats <appname>" }
692
+ }
693
+ def run
694
+ cli = setup('stats')
695
+ cli.stats(params['appname'].value)
696
+ end
697
+ }
698
+
699
+ mode(:help) {
700
+ show_help
701
+ }
702
+
703
+ mode('-h') {
704
+ show_help
705
+ }
706
+
707
+ mode('-v') {
708
+ description "Show version of this CLI"
709
+ def run
710
+ cli = setup(:version)
711
+ cli.version
712
+ end
713
+ }
714
+
715
+ def run
716
+ display "\nUsage: vmc COMMAND [OPTIONS] 'vmc -h' for more information.\n\n"
717
+ end
718
+
719
+ }