vmc 0.4.0.beta.21 → 0.4.0.beta.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,14 +40,18 @@ module VMC
40
40
  }
41
41
  end
42
42
 
43
+ def self.by_name(what)
44
+ proc { |name|
45
+ client.send(:"#{what}_by_name", name) ||
46
+ fail("Unknown #{what} '#{name}'")
47
+ }
48
+ end
49
+
43
50
 
44
51
  desc "List your applications"
45
52
  group :apps
46
53
  input :space, :desc => "Show apps in given space",
47
- :from_given => proc { |name|
48
- client.space_by_name(name) || \
49
- fail("Unknown space '#{name}'")
50
- }
54
+ :from_given => by_name("space")
51
55
  input :name, :desc => "Filter by name regexp"
52
56
  input :runtime, :desc => "Filter by runtime regexp"
53
57
  input :framework, :desc => "Filter by framework regexp"
@@ -56,7 +60,8 @@ module VMC
56
60
  if space = input[:space] || client.current_space
57
61
  apps =
58
62
  with_progress("Getting applications in #{c(space.name, :name)}") do
59
- space.apps
63
+ # depth of 2 for service binding instance names
64
+ space.apps(2)
60
65
  end
61
66
  else
62
67
  apps =
@@ -82,7 +87,8 @@ module VMC
82
87
  input(:name, :argument => true, :desc => "Application name") {
83
88
  ask("Name")
84
89
  }
85
- input :path, :desc => "Path containing the application"
90
+ input :path, :default => ".",
91
+ :desc => "Path containing the application"
86
92
  input(:url, :desc => "URL bound to app") { |default|
87
93
  ask("URL", :default => default)
88
94
  }
@@ -98,8 +104,8 @@ module VMC
98
104
  :desc => "Number of instances to run") {
99
105
  ask("Instances", :default => 1)
100
106
  }
101
- input(:framework, :desc => "Framework to use",
102
- :from_given => find_by_name("framework")) { |choices, default, other|
107
+ input(:framework, :from_given => find_by_name("framework"),
108
+ :desc => "Framework to use") { |choices, default, other|
103
109
  choices = choices.sort_by(&:name)
104
110
  choices << other if other
105
111
 
@@ -138,13 +144,13 @@ module VMC
138
144
  ask "Bind other services to application?", :default => false
139
145
  }
140
146
  def push(input)
141
- path = File.expand_path(input[:path] || ".")
147
+ path = File.expand_path(input[:path])
142
148
 
143
- name = input[:name] if input[:name]
149
+ name = input[:name]
144
150
 
145
151
  if exists = client.app_by_name(name)
146
152
  upload_app(exists, path)
147
- invoke :restart, :name => exists.name if input[:restart]
153
+ invoke :restart, :app => exists if input[:restart]
148
154
  return
149
155
  end
150
156
 
@@ -193,43 +199,35 @@ module VMC
193
199
 
194
200
  app.memory = megabytes(input[:memory, framework, runtime])
195
201
 
196
- bindings = []
197
- if !v2? && input[:create_services] && !force?
198
- services = client.services
202
+ app = filter(:create_app, app)
199
203
 
200
- while true
201
- instance = invoke :create_service
204
+ with_progress("Creating #{c(app.name, :name)}") do
205
+ app.create!
206
+ end
202
207
 
203
- bindings << instance.name
208
+ bindings = []
204
209
 
210
+ if input[:create_services] && !force?
211
+ while true
212
+ invoke :create_service, :app => app
205
213
  break unless ask "Create another service?", :default => false
206
214
  end
207
215
  end
208
216
 
209
- if !v2? && input[:bind_services] && !force?
210
- services = client.service_instances.collect(&:name)
217
+ if input[:bind_services] && !force?
218
+ instances = client.service_instances
211
219
 
212
220
  while true
213
- choices = services - bindings
214
- break if choices.empty?
221
+ invoke :bind_service, :app => app
215
222
 
216
- bindings << ask("Bind which service?", :choices => choices.sort)
223
+ break if (instances - app.services).empty?
217
224
 
218
- unless bindings.size < services.size &&
219
- ask("Bind another service?", :default => false)
220
- break
221
- end
225
+ break unless ask("Bind another service?", :default => false)
222
226
  end
223
227
  end
224
228
 
225
- app.services = bindings
226
-
227
229
  app = filter(:push_app, app)
228
230
 
229
- with_progress("Creating #{c(name, :name)}") do
230
- app.create!
231
- end
232
-
233
231
  begin
234
232
  upload_app(app, path)
235
233
  rescue
@@ -237,32 +235,27 @@ module VMC
237
235
  raise
238
236
  end
239
237
 
240
- invoke :start, :name => app.name if input[:start]
238
+ invoke :start, :app => app if input[:start]
241
239
  end
242
240
 
243
241
 
244
242
  desc "Start an application"
245
243
  group :apps, :manage
246
- input :names, :argument => :splat, :singular => :name,
247
- :desc => "Applications to start"
244
+ input :apps, :argument => :splat, :singular => :app,
245
+ :desc => "Applications to start",
246
+ :from_given => find_by_name("app")
248
247
  input :debug_mode, :aliases => "-d",
249
248
  :desc => "Debug mode to start in"
250
249
  def start(input)
251
- names = input[:names]
252
- fail "No applications given." if names.empty?
253
-
254
- apps = client.apps
255
-
256
- names.each do |name|
257
- app = apps.find { |a| a.name == name }
258
-
259
- fail "Unknown application '#{name}'" unless app
250
+ apps = input[:apps, client.apps]
251
+ fail "No applications given." if apps.empty?
260
252
 
253
+ apps.each do |app|
261
254
  app = filter(:start_app, app)
262
255
 
263
256
  switch_mode(app, input[:debug_mode])
264
257
 
265
- with_progress("Starting #{c(name, :name)}") do |s|
258
+ with_progress("Starting #{c(app.name, :name)}") do |s|
266
259
  if app.started?
267
260
  s.skip do
268
261
  err "Already started."
@@ -279,7 +272,7 @@ module VMC
279
272
 
280
273
  if app.debug_mode && !quiet?
281
274
  puts ""
282
- instances(name)
275
+ invoke :instances, :app => app
283
276
  end
284
277
  end
285
278
  end
@@ -287,20 +280,15 @@ module VMC
287
280
 
288
281
  desc "Stop an application"
289
282
  group :apps, :manage
290
- input :names, :argument => :splat, :singular => :name,
291
- :desc => "Applications to stop"
283
+ input :apps, :argument => :splat, :singular => :app,
284
+ :desc => "Applications to start",
285
+ :from_given => find_by_name("app")
292
286
  def stop(input)
293
- names = input[:names]
294
- fail "No applications given." if names.empty?
295
-
296
- apps = client.apps
297
-
298
- names.each do |name|
299
- app = apps.find { |a| a.name == name }
287
+ apps = input[:apps, client.apps]
288
+ fail "No applications given." if apps.empty?
300
289
 
301
- fail "Unknown application '#{name}'" unless app
302
-
303
- with_progress("Stopping #{c(name, :name)}") do |s|
290
+ apps.each do |app|
291
+ with_progress("Stopping #{c(app.name, :name)}") do |s|
304
292
  if app.stopped?
305
293
  s.skip do
306
294
  err "Application is not running."
@@ -315,28 +303,31 @@ module VMC
315
303
 
316
304
  desc "Stop and start an application"
317
305
  group :apps, :manage
318
- input :names, :argument => :splat, :singular => :name,
319
- :desc => "Applications to stop"
306
+ input :apps, :argument => :splat, :singular => :app,
307
+ :desc => "Applications to start",
308
+ :from_given => find_by_name("app")
320
309
  input :debug_mode, :aliases => "-d",
321
310
  :desc => "Debug mode to start in"
322
311
  def restart(input)
323
- invoke :stop, :names => input[:names]
324
- invoke :start, :names => input[:names],
312
+ apps = client.apps
313
+
314
+ invoke :stop, :apps => input[:apps, apps]
315
+ invoke :start, :apps => input[:apps, apps],
325
316
  :debug_mode => input[:debug_mode]
326
317
  end
327
318
 
328
319
 
329
320
  desc "Delete an application"
330
321
  group :apps, :manage
331
- input(:really, :type => :boolean, :forget => true) { |name, color|
332
- force? || ask("Really delete #{c(name, color)}?", :default => false)
333
- }
334
322
  input(:apps, :argument => :splat, :singular => :app,
335
323
  :desc => "Applications to delete",
336
- :from_given => find_by_name("application")) { |apps|
324
+ :from_given => find_by_name("app")) { |apps|
337
325
  [ask("Delete which application?", :choices => apps.sort_by(&:name),
338
326
  :display => proc(&:name))]
339
327
  }
328
+ input(:really, :type => :boolean, :forget => true) { |name, color|
329
+ force? || ask("Really delete #{c(name, color)}?", :default => false)
330
+ }
340
331
  input :orphaned, :aliases => "-o", :type => :boolean,
341
332
  :desc => "Delete orphaned instances"
342
333
  input :all, :default => false,
@@ -387,18 +378,19 @@ module VMC
387
378
 
388
379
  desc "List an app's instances"
389
380
  group :apps, :info, :hidden => true
390
- input :names, :argument => :splat, :singular => :name,
391
- :desc => "Applications to list instances of"
381
+ input :apps, :argument => :splat, :singular => :app,
382
+ :desc => "Applications to start",
383
+ :from_given => find_by_name("app")
392
384
  def instances(input)
393
385
  no_v2
394
386
 
395
- names = input[:names]
396
- fail "No applications given." if names.empty?
387
+ apps = input[:apps, client.apps]
388
+ fail "No applications given." if apps.empty?
397
389
 
398
- names.each do |name|
390
+ apps.each do |app|
399
391
  instances =
400
- with_progress("Getting instances for #{c(name, :name)}") do
401
- client.app_by_name(name).instances
392
+ with_progress("Getting instances for #{c(app.name, :name)}") do
393
+ app.instances
402
394
  end
403
395
 
404
396
  instances.each do |i|
@@ -415,7 +407,8 @@ module VMC
415
407
 
416
408
  desc "Update the instances/memory limit for an application"
417
409
  group :apps, :info, :hidden => true
418
- input :name, :argument => true, :desc => "Application to update"
410
+ input :app, :argument => true, :desc => "Application to update",
411
+ :from_given => by_name("app")
419
412
  input(:instances, :type => :numeric,
420
413
  :desc => "Number of instances to run") { |default|
421
414
  ask("Instances", :default => default)
@@ -427,8 +420,7 @@ module VMC
427
420
  input :restart, :type => :boolean, :default => true,
428
421
  :desc => "Restart app after updating?"
429
422
  def scale(input)
430
- name = input[:name]
431
- app = client.app_by_name(name)
423
+ app = input[:app]
432
424
 
433
425
  instances = input.given(:instances)
434
426
  memory = input.given(:memory)
@@ -445,22 +437,23 @@ module VMC
445
437
 
446
438
  return unless memory_changed || instances_changed
447
439
 
448
- with_progress("Scaling #{c(name, :name)}") do
440
+ with_progress("Scaling #{c(app.name, :name)}") do
449
441
  app.total_instances = instances.to_i if instances
450
442
  app.memory = megs if memory
451
443
  app.update!
452
444
  end
453
445
 
454
446
  if memory_changed && app.started? && input[:restart]
455
- invoke :restart, :name => name
447
+ invoke :restart, :app => app
456
448
  end
457
449
  end
458
450
 
459
451
 
460
452
  desc "Print out an app's logs"
461
453
  group :apps, :info, :hidden => true
462
- input :name, :argument => true,
463
- :desc => "Application to get the logs of"
454
+ input :app, :argument => true,
455
+ :desc => "Application to get the logs of",
456
+ :from_given => by_name("app")
464
457
  input :instance, :type => :numeric, :default => 0,
465
458
  :desc => "Instance of application to get the logs of"
466
459
  input :all, :default => false,
@@ -468,10 +461,7 @@ module VMC
468
461
  def logs(input)
469
462
  no_v2
470
463
 
471
- name = input[:name]
472
-
473
- app = client.app_by_name(name)
474
- fail "Unknown application '#{name}'" unless app.exists?
464
+ app = input[:app]
475
465
 
476
466
  instances =
477
467
  if input[:all]
@@ -484,16 +474,15 @@ module VMC
484
474
  if input[:all]
485
475
  fail "No instances found."
486
476
  else
487
- fail "Instance #{name} \##{input[:instance]} not found."
477
+ fail "Instance #{app.name} \##{input[:instance]} not found."
488
478
  end
489
479
  end
490
480
 
491
481
  instances.each do |i|
492
482
  logs =
493
483
  with_progress(
494
- "Getting logs for " +
495
- c(name, :name) + " " +
496
- c("\##{i.index}", :instance)) do
484
+ "Getting logs for #{c(app.name, :name)}" +
485
+ c("\##{i.index}", :instance)) do
497
486
  i.files("logs")
498
487
  end
499
488
 
@@ -514,16 +503,19 @@ module VMC
514
503
 
515
504
  desc "Print out an app's file contents"
516
505
  group :apps, :info, :hidden => true
517
- input :name, :argument => true,
518
- :desc => "Application to inspect the files of"
506
+ input :app, :argument => true,
507
+ :desc => "Application to inspect the files of",
508
+ :from_given => by_name("app")
519
509
  input :path, :argument => true, :default => "/",
520
510
  :desc => "Path of file to read"
521
511
  def file(input)
522
512
  no_v2
523
513
 
514
+ app = input[:app]
515
+
524
516
  file =
525
517
  with_progress("Getting file contents") do
526
- client.app(input[:name]).file(*input[:path].split("/"))
518
+ app.file(*input[:path].split("/"))
527
519
  end
528
520
 
529
521
  puts "" unless quiet?
@@ -533,16 +525,19 @@ module VMC
533
525
 
534
526
  desc "Examine an app's files"
535
527
  group :apps, :info, :hidden => true
536
- input :name, :argument => true,
537
- :desc => "Application to inspect the files of"
528
+ input :app, :argument => true,
529
+ :desc => "Application to inspect the files of",
530
+ :from_given => by_name("app")
538
531
  input :path, :argument => true, :default => "/",
539
532
  :desc => "Path of directory to list"
540
533
  def files(input)
541
534
  no_v2
542
535
 
536
+ app = input[:app]
537
+
543
538
  files =
544
539
  with_progress("Getting file listing") do
545
- client.app(input[:name]).files(*input[:path].split("/"))
540
+ app.files(*input[:path].split("/"))
546
541
  end
547
542
 
548
543
  puts "" unless quiet?
@@ -554,22 +549,22 @@ module VMC
554
549
 
555
550
  desc "Get application health"
556
551
  group :apps, :info, :hidden => true
557
- input :names, :argument => :splat, :singular => :name,
558
- :desc => "Application to check the status of"
552
+ input :apps, :argument => :splat, :singular => :app,
553
+ :desc => "Applications to start",
554
+ :from_given => find_by_name("application")
559
555
  def health(input)
560
- # TODO: get all apps and filter
556
+ apps = input[:apps, client.apps]
557
+ fail "No applications given." if apps.empty?
561
558
 
562
- apps =
563
- with_progress("Getting application health") do
564
- input[:names].collect do |n|
565
- [n, app_status(client.app_by_name(n))]
566
- end
559
+ health =
560
+ with_progress("Getting health status") do
561
+ apps.collect { |a| [a, app_status(a)] }
567
562
  end
568
563
 
569
- apps.each do |name, status|
564
+ health.each do |app, status|
570
565
  unless quiet?
571
566
  puts ""
572
- print "#{c(name, :name)}: "
567
+ print "#{c(app.name, :name)}: "
573
568
  end
574
569
 
575
570
  puts status
@@ -579,49 +574,53 @@ module VMC
579
574
 
580
575
  desc "Display application instance status"
581
576
  group :apps, :info, :hidden => true
582
- input :name, :argument => true,
583
- :desc => "Application to get the stats for"
577
+ input :app, :argument => true,
578
+ :desc => "Application to get the stats for",
579
+ :from_given => by_name("app")
584
580
  def stats(input)
585
581
  no_v2
586
582
 
583
+ app = input[:app]
584
+
587
585
  stats =
588
- with_progress("Getting stats for #{c(input[:name], :name)}") do
589
- client.app_by_name(input[:name]).stats
586
+ with_progress("Getting stats for #{c(app.name, :name)}") do
587
+ app.stats
590
588
  end
591
589
 
592
- stats.sort_by { |k, _| k }.each do |idx, info|
590
+ stats.sort_by(&:first).each do |idx, info|
593
591
  puts ""
594
592
 
595
- if info["state"] == "DOWN"
593
+ if info[:state] == "DOWN"
596
594
  puts "Instance #{c("\##{idx}", :instance)} is down."
597
595
  next
598
596
  end
599
597
 
600
- stats = info["stats"]
601
- usage = stats["usage"]
598
+ stats = info[:stats]
599
+ usage = stats[:usage]
602
600
  puts "instance #{c("\##{idx}", :instance)}:"
603
- print " cpu: #{percentage(usage["cpu"])} of"
604
- puts " #{b(stats["cores"])} cores"
605
- puts " memory: #{usage(usage["mem"] * 1024, stats["mem_quota"])}"
606
- puts " disk: #{usage(usage["disk"], stats["disk_quota"])}"
601
+ print " cpu: #{percentage(usage[:cpu])} of"
602
+ puts " #{b(stats[:cores])} cores"
603
+ puts " memory: #{usage(usage[:mem] * 1024, stats[:mem_quota])}"
604
+ puts " disk: #{usage(usage[:disk], stats[:disk_quota])}"
607
605
  end
608
606
  end
609
607
 
610
608
 
611
609
  desc "Add a URL mapping for an app"
612
610
  group :apps, :info, :hidden => true
613
- input :name, :argument => true,
614
- :desc => "Application to add the URL to"
611
+ input :app, :argument => true,
612
+ :desc => "Application to add the URL to",
613
+ :from_given => by_name("app")
615
614
  input :url, :argument => true,
616
615
  :desc => "URL to route"
617
616
  def map(input)
618
617
  no_v2
619
618
 
620
- name = input[:name]
619
+ app = input[:app]
620
+
621
621
  simple = input[:url].sub(/^https?:\/\/(.*)\/?/i, '\1')
622
622
 
623
- with_progress("Updating #{c(name, :name)}") do
624
- app = client.app_by_name(name)
623
+ with_progress("Updating #{c(app.name, :name)}") do
625
624
  app.urls << simple
626
625
  app.update!
627
626
  end
@@ -630,24 +629,21 @@ module VMC
630
629
 
631
630
  desc "Remove a URL mapping from an app"
632
631
  group :apps, :info, :hidden => true
633
- input :name, :argument => true,
634
- :desc => "Application to remove the URL from"
632
+ input :app, :argument => true,
633
+ :desc => "Application to remove the URL from",
634
+ :from_given => by_name("app")
635
635
  input(:url, :argument => true, :desc => "URL to unmap") { |choices|
636
636
  ask("Which URL?", :choices => choices)
637
637
  }
638
638
  def unmap(input)
639
639
  no_v2
640
640
 
641
- name = input[:name]
642
- app = client.app_by_name(name)
643
-
641
+ app = input[:app]
644
642
  url = input[:url, app.urls]
645
643
 
646
644
  simple = url.sub(/^https?:\/\/(.*)\/?/i, '\1')
647
645
 
648
- fail "Unknown application '#{name}'" unless app.exists?
649
-
650
- with_progress("Updating #{c(name, :name)}") do |s|
646
+ with_progress("Updating #{c(app.name, :name)}") do |s|
651
647
  unless app.urls.delete(simple)
652
648
  s.fail do
653
649
  err "URL #{url} is not mapped to this application."
@@ -662,22 +658,14 @@ module VMC
662
658
 
663
659
  desc "Show all environment variables set for an app"
664
660
  group :apps, :info, :hidden => true
665
- input :name, :argument => true,
666
- :desc => "Application to inspect the environment of"
661
+ input :app, :argument => true,
662
+ :desc => "Application to inspect the environment of",
663
+ :from_given => by_name("app")
667
664
  def env(input)
668
- appname = input[:name]
665
+ app = input[:app]
669
666
 
670
667
  vars =
671
- with_progress("Getting env for #{c(input[:name], :name)}") do |s|
672
- app = client.app_by_name(appname)
673
-
674
- unless app.exists?
675
- s.fail do
676
- err "Unknown application '#{appname}'"
677
- return
678
- end
679
- end
680
-
668
+ with_progress("Getting env for #{c(app.name, :name)}") do |s|
681
669
  app.env
682
670
  end
683
671
 
@@ -693,20 +681,21 @@ module VMC
693
681
 
694
682
  desc "Set an environment variable"
695
683
  group :apps, :info, :hidden => true
684
+ input :app, :argument => true,
685
+ :desc => "Application to set the variable for",
686
+ :from_given => by_name("app")
696
687
  input :name, :argument => true,
697
- :desc => "Application to set the variable for"
698
- input :var, :argument => true,
699
688
  :desc => "Environment variable name"
700
689
  input :value, :argument => :optional,
701
690
  :desc => "Environment variable value"
702
691
  input :restart, :type => :boolean, :default => true,
703
692
  :desc => "Restart app after updating?"
704
693
  def set_env(input)
705
- appname = input[:name]
706
- name = input[:var]
694
+ app = input[:app]
695
+ name = input[:name]
707
696
 
708
697
  if value = input[:value]
709
- name = input[:var]
698
+ name = input[:name]
710
699
  elsif name["="]
711
700
  name, value = name.split("=")
712
701
  end
@@ -715,16 +704,13 @@ module VMC
715
704
  fail "Invalid variable name; must match #{VALID_ENV_VAR.inspect}"
716
705
  end
717
706
 
718
- app = client.app_by_name(appname)
719
- fail "Unknown application '#{appname}'" unless app.exists?
720
-
721
707
  with_progress("Updating #{c(app.name, :name)}") do
722
708
  app.env[name] = value
723
709
  app.update!
724
710
  end
725
711
 
726
712
  if app.started? && input[:restart]
727
- invoke :restart, :name => app.name
713
+ invoke :restart, :app => app
728
714
  end
729
715
  end
730
716
 
@@ -735,18 +721,16 @@ module VMC
735
721
 
736
722
  desc "Remove an environment variable"
737
723
  group :apps, :info, :hidden => true
724
+ input :app, :argument => true,
725
+ :desc => "Application to set the variable for",
726
+ :from_given => by_name("app")
738
727
  input :name, :argument => true,
739
- :desc => "Application to remove the variable from"
740
- input :var, :argument => true,
741
728
  :desc => "Environment variable name"
742
729
  input :restart, :type => :boolean, :default => true,
743
730
  :desc => "Restart app after updating?"
744
731
  def delete_env(input)
745
- appname = input[:name]
746
- name = input[:var]
747
-
748
- app = client.app_by_name(appname)
749
- fail "Unknown application '#{appname}'" unless app.exists?
732
+ app = input[:app]
733
+ name = input[:name]
750
734
 
751
735
  with_progress("Updating #{c(app.name, :name)}") do
752
736
  app.env.delete(name)
@@ -754,7 +738,7 @@ module VMC
754
738
  end
755
739
 
756
740
  if app.started? && input[:restart]
757
- invoke :restart, :name => app.name
741
+ invoke :restart, :app => app
758
742
  end
759
743
  end
760
744
 
@@ -814,7 +798,8 @@ module VMC
814
798
  end
815
799
 
816
800
  unless a.services.empty?
817
- puts " services: #{a.services.collect { |s| b(s) }.join(", ")}"
801
+ print " services: "
802
+ puts a.services.collect { |s| b(s.name) }.join(", ")
818
803
  end
819
804
  end
820
805
 
@@ -929,9 +914,9 @@ module VMC
929
914
  orphaned = []
930
915
 
931
916
  apps.each do |a|
932
- a.services.each do |s|
933
- if apps.none? { |x| x != a && x.services.include?(s) }
934
- orphaned << s
917
+ a.services.each do |i|
918
+ if apps.none? { |x| x != a && x.services.include?(i) }
919
+ orphaned << i
935
920
  end
936
921
  end
937
922
  end
@@ -939,17 +924,18 @@ module VMC
939
924
  orphaned
940
925
  end
941
926
 
942
- def delete_orphaned_services(names, orphaned)
943
- return if names.empty?
927
+ def delete_orphaned_services(instances, orphaned)
928
+ return if instances.empty?
944
929
 
945
930
  puts "" unless quiet?
946
931
 
947
- names.select { |s|
932
+ instances.select { |i|
948
933
  orphaned ||
949
- ask("Delete orphaned service #{c(s, :name)}?", :default => false)
950
- }.each do |name|
934
+ ask("Delete orphaned service instance #{c(i.name, :name)}?",
935
+ :default => false)
936
+ }.each do |instance|
951
937
  # TODO: splat
952
- invoke :delete_service, :name => name, :really => true
938
+ invoke :delete_service, :instance => instance, :really => true
953
939
  end
954
940
  end
955
941
 
@@ -2,7 +2,21 @@ require "vmc/cli"
2
2
 
3
3
  module VMC
4
4
  class Service < CLI
5
- desc "List your services"
5
+ def self.find_by_name(what)
6
+ proc { |name, choices|
7
+ choices.find { |c| c.name == name } ||
8
+ fail("Unknown #{what} '#{name}'")
9
+ }
10
+ end
11
+
12
+ def self.by_name(what, obj = what)
13
+ proc { |name, *_|
14
+ client.send(:"#{obj}_by_name", name) ||
15
+ fail("Unknown #{what} '#{name}'")
16
+ }
17
+ end
18
+
19
+ desc "List your service instances"
6
20
  group :services
7
21
  input :name, :desc => "Filter by name regexp"
8
22
  input :app, :desc => "Filter by bound application regexp"
@@ -30,10 +44,6 @@ module VMC
30
44
  services.select { |s| s.label == label }
31
45
  }
32
46
 
33
- plan_from_name = proc { |name, plans|
34
- plans.find { |p| p.name == name }
35
- }
36
-
37
47
  desc "Create a service"
38
48
  group :services, :manage
39
49
  input(:service, :argument => true,
@@ -55,7 +65,7 @@ module VMC
55
65
  ask "Name?", :default => "#{service.label}-#{random}"
56
66
  }
57
67
  input(:plan, :desc => "Service plan",
58
- :from_given => plan_from_name) { |plans|
68
+ :from_given => find_by_name("plan")) { |plans|
59
69
  if d100 = plans.find { |p| p.name == "D100" }
60
70
  d100
61
71
  else
@@ -65,7 +75,8 @@ module VMC
65
75
  end
66
76
  }
67
77
  input :provider, :desc => "Service provider"
68
- input :bind, :alias => "--app",
78
+ input :version, :desc => "Service version"
79
+ input :app, :alias => "--bind", :from_given => by_name("app"),
69
80
  :desc => "Application to immediately bind to"
70
81
  def create_service(input)
71
82
  services = client.services
@@ -74,8 +85,13 @@ module VMC
74
85
  services.reject! { |s| s.provider != input[:provider] }
75
86
  end
76
87
 
88
+ if input[:version]
89
+ services.reject! { |s| s.version != input[:version] }
90
+ end
91
+
77
92
  until services.size < 2
78
- services = input[:service, services]
93
+ # cast to Array since it might be given as a Service with #invoke
94
+ services = Array(input[:service, services])
79
95
  input.forget(:service)
80
96
  end
81
97
 
@@ -103,61 +119,75 @@ module VMC
103
119
  instance.create!
104
120
  end
105
121
 
106
- if app = input[:bind]
107
- invoke :bind_service, :name => instance.name, :app => app
122
+ if app = input[:app]
123
+ invoke :bind_service, :instance => instance, :app => app
108
124
  end
109
125
 
110
126
  instance
111
127
  end
112
128
 
113
129
 
114
- desc "Bind a service to an application"
130
+ desc "Bind a service instance to an application"
115
131
  group :services, :manage
116
- input(:name, :argument => true,
117
- :desc => "Service to bind") { |choices|
118
- ask "Which service?", :choices => choices
132
+ input(:instance, :argument => true,
133
+ :from_given => by_name("instance", :service_instance),
134
+ :desc => "Service to bind") { |app|
135
+ instances = client.service_instances
136
+ fail "No service instances." if instances.empty?
137
+
138
+ ask "Which service instance?",
139
+ :choices => instances - app.services,
140
+ :display => proc(&:name)
119
141
  }
120
142
  input(:app, :argument => true,
121
- :desc => "Application to bind to") { |choices|
122
- ask "Which application?", :choices => choices
143
+ :from_given => by_name("app"),
144
+ :desc => "Application to bind to") {
145
+ ask "Which application?", :choices => client.apps(2),
146
+ :display => proc(&:name)
123
147
  }
124
148
  def bind_service(input)
125
- name = input[:name, client.service_instances.collect(&:name)]
126
- appname = input[:app, client.apps.collect(&:name)]
149
+ app = input[:app]
150
+ instance = input[:instance, app]
127
151
 
128
- with_progress("Binding #{c(name, :name)} to #{c(appname, :name)}") do
129
- client.app_by_name(appname).bind(name)
152
+ with_progress(
153
+ "Binding #{c(instance.name, :name)} to #{c(app.name, :name)}") do
154
+ app.bind(instance)
130
155
  end
131
156
  end
132
157
 
133
158
 
134
159
  desc "Unbind a service from an application"
135
160
  group :services, :manage
136
- input(:name, :argument => true,
137
- :desc => "Service to unbind") { |choices|
138
- ask "Which service?", :choices => choices
161
+ input(:instance, :argument => true,
162
+ :from_given => find_by_name("instance"),
163
+ :desc => "Service to bind") { |instances|
164
+ ask "Which service instance?", :choices => instances,
165
+ :display => proc(&:name)
139
166
  }
140
167
  input(:app, :argument => true,
141
- :desc => "Application to unbind from") { |choices|
142
- ask "Which application?", :choices => choices
168
+ :from_given => find_by_name("app"),
169
+ :desc => "Application to bind to") { |apps|
170
+ ask "Which application?", :choices => apps,
171
+ :display => proc(&:name)
143
172
  }
144
173
  def unbind_service(input)
145
- appname = input[:app, client.apps.collect(&:name)]
146
-
147
- app = client.app_by_name(appname)
148
- name = input[:name, app.services]
174
+ app = input[:app, client.apps(2)]
175
+ instance = input[:instance, app.services]
149
176
 
150
- with_progress("Unbinding #{c(name, :name)} from #{c(appname, :name)}") do
151
- app.unbind(name)
177
+ with_progress(
178
+ "Unbinding #{c(instance.name, :name)} from #{c(app.name, :name)}") do
179
+ app.unbind(instance)
152
180
  end
153
181
  end
154
182
 
155
183
 
156
184
  desc "Delete a service"
157
185
  group :services, :manage
158
- input(:name, :argument => true,
159
- :desc => "Service to delete") { |choices|
160
- ask "Delete which service?", :choices => choices
186
+ input(:instance, :argument => true,
187
+ :from_given => find_by_name("instance"),
188
+ :desc => "Service to bind") { |instances|
189
+ ask "Which service instance?", :choices => instances,
190
+ :display => proc(&:name)
161
191
  }
162
192
  input(:really, :type => :boolean, :forget => true) { |name, color|
163
193
  force? || ask("Really delete #{c(name, color)}?", :default => false)
@@ -167,8 +197,8 @@ module VMC
167
197
  if input[:all]
168
198
  return unless input[:really, "ALL SERVICES", :bad]
169
199
 
170
- with_progress("Deleting all services") do
171
- client.service_instances.collect(&:delete!)
200
+ client.service_instances.each do |i|
201
+ invoke :delete_service, :instance => i, :really => true
172
202
  end
173
203
 
174
204
  return
@@ -177,13 +207,21 @@ module VMC
177
207
  instances = client.service_instances
178
208
  fail "No services." if instances.empty?
179
209
 
180
- name = input[:name, instances.collect(&:name)]
181
- service = instances.find { |i| i.name == name }
210
+ instance = input[:instance, instances]
211
+
212
+ return unless input[:really, instance.name, :name]
182
213
 
183
- return unless input[:really, name, :name]
214
+ with_progress("Deleting #{c(instance.name, :name)}") do |s|
215
+ bindings = instance.service_bindings
184
216
 
185
- with_progress("Deleting #{c(name, :name)}") do
186
- service.delete!
217
+ if bindings.empty?
218
+ instance.delete!
219
+ else
220
+ s.skip do
221
+ apps = bindings.collect(&:app).collect { |a| b(a.name) }
222
+ err "Service instance is bound to #{human_list(apps)}."
223
+ end
224
+ end
187
225
  end
188
226
  end
189
227
 
@@ -229,5 +267,16 @@ module VMC
229
267
  puts " description: #{plan.description}"
230
268
  end
231
269
  end
270
+
271
+ def human_list(xs)
272
+ if xs.size == 1
273
+ xs.first
274
+ elsif xs.size == 2
275
+ "#{xs.first} and #{xs.last}"
276
+ else
277
+ last = xs.pop
278
+ xs.join(", ") + ", and #{last}"
279
+ end
280
+ end
232
281
  end
233
282
  end
@@ -146,11 +146,6 @@ module VMC
146
146
  with_progress("Setting target to #{display}") do
147
147
  set_target(target)
148
148
  end
149
-
150
- unless quiet?
151
- puts ""
152
- display_org_and_space
153
- end
154
149
  end
155
150
 
156
151
  return unless v2? && client.logged_in?
@@ -428,7 +423,7 @@ module VMC
428
423
  if !input[:interactive] && spaces.size == 1 && !input.given?(:space)
429
424
  space = spaces.first
430
425
  else
431
- puts "" if changed_org
426
+ puts "" if input[:interactive] && changed_org
432
427
  space = input[:space, spaces.sort_by(&:name)]
433
428
  end
434
429
 
@@ -92,6 +92,7 @@ module VMC
92
92
  rescue Mothership::Error
93
93
  raise
94
94
  rescue UserError => e
95
+ log_error(e)
95
96
  err e.message
96
97
  rescue CFoundry::Denied => e
97
98
  if !$vmc_asked_auth && e.error_code == 200
@@ -290,13 +291,17 @@ module VMC
290
291
  @@client.proxy = option(:proxy)
291
292
  @@client.trace = option(:trace)
292
293
 
293
- info[:version] ||=
294
- case @@client
295
- when CFoundry::V2::Client
296
- 2
297
- else
298
- 1
299
- end
294
+ unless info.key? :version
295
+ info[:version] =
296
+ case @@client
297
+ when CFoundry::V2::Client
298
+ 2
299
+ else
300
+ 1
301
+ end
302
+
303
+ save_target_info(info)
304
+ end
300
305
 
301
306
  if org = info[:organization]
302
307
  @@client.current_organization = @@client.organization(org)
@@ -306,8 +311,6 @@ module VMC
306
311
  @@client.current_space = @@client.space(space)
307
312
  end
308
313
 
309
- save_target_info(info)
310
-
311
314
  @@client
312
315
  end
313
316
 
@@ -1,3 +1,3 @@
1
1
  module VMC
2
- VERSION = "0.4.0.beta.21"
2
+ VERSION = "0.4.0.beta.22"
3
3
  end
@@ -6,6 +6,16 @@ describe "Start#target" do
6
6
  end
7
7
 
8
8
  describe "switching target url" do
9
+ before(:all) do
10
+ @old_target = File.read(File.expand_path(VMC::TARGET_FILE))
11
+ end
12
+
13
+ after(:all) do
14
+ File.open(File.expand_path(VMC::TARGET_FILE), "w") do |io|
15
+ io.print @old_target
16
+ end
17
+ end
18
+
9
19
  before(:each) do
10
20
  @old_client = client
11
21
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmc
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196425
4
+ hash: 62196431
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
9
  - 0
10
10
  - beta
11
- - 21
12
- version: 0.4.0.beta.21
11
+ - 22
12
+ version: 0.4.0.beta.22
13
13
  platform: ruby
14
14
  authors:
15
15
  - VMware
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2012-07-19 00:00:00 Z
20
+ date: 2012-07-23 00:00:00 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: json_pure
@@ -249,12 +249,12 @@ dependencies:
249
249
  requirements:
250
250
  - - ~>
251
251
  - !ruby/object:Gem::Version
252
- hash: 3
252
+ hash: 1
253
253
  segments:
254
254
  - 0
255
255
  - 3
256
- - 8
257
- version: 0.3.8
256
+ - 9
257
+ version: 0.3.9
258
258
  type: :runtime
259
259
  version_requirements: *id014
260
260
  - !ruby/object:Gem::Dependency
@@ -265,12 +265,12 @@ dependencies:
265
265
  requirements:
266
266
  - - ~>
267
267
  - !ruby/object:Gem::Version
268
- hash: 15
268
+ hash: 11
269
269
  segments:
270
270
  - 0
271
271
  - 0
272
- - 8
273
- version: 0.0.8
272
+ - 10
273
+ version: 0.0.10
274
274
  type: :runtime
275
275
  version_requirements: *id015
276
276
  - !ruby/object:Gem::Dependency
@@ -281,12 +281,12 @@ dependencies:
281
281
  requirements:
282
282
  - - ~>
283
283
  - !ruby/object:Gem::Version
284
- hash: 17
284
+ hash: 15
285
285
  segments:
286
286
  - 0
287
- - 3
288
- - 1
289
- version: 0.3.1
287
+ - 4
288
+ - 0
289
+ version: 0.4.0
290
290
  type: :runtime
291
291
  version_requirements: *id016
292
292
  - !ruby/object:Gem::Dependency