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

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.
@@ -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