vmc 0.0.4 → 0.0.5

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.
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
+ }