vmc 0.5.0.beta.6 → 0.5.0.beta.7

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/vmc/cli.rb CHANGED
@@ -158,6 +158,17 @@ module VMC
158
158
  f.puts msg
159
159
  f.puts ""
160
160
 
161
+ if e.respond_to?(:request_trace)
162
+ f.puts "<<<"
163
+ f.puts e.request_trace
164
+ end
165
+
166
+ if e.respond_to?(:response_trace)
167
+ f.puts e.response_trace
168
+ f.puts ">>>"
169
+ f.puts ""
170
+ end
171
+
161
172
  vmc_dir = File.expand_path("../../../..", __FILE__) + "/"
162
173
  e.backtrace.each do |loc|
163
174
  if loc =~ /\/gems\//
@@ -52,10 +52,10 @@ module VMC
52
52
  end
53
53
 
54
54
  def human_size(num, precision = 1)
55
- sizes = ["G", "M", "K"]
55
+ sizes = %w(G M K)
56
56
  sizes.each.with_index do |suf, i|
57
57
  pow = sizes.size - i
58
- unit = 1024 ** pow
58
+ unit = 1024.0 ** pow
59
59
  if num >= unit
60
60
  return format("%.#{precision}f%s", num / unit, suf)
61
61
  end
@@ -19,7 +19,7 @@ module VMC::App
19
19
 
20
20
  line unless quiet?
21
21
 
22
- spaced(instances) do |i|
22
+ spaced(instances.sort { |a, b| a.id.to_i <=> b.id.to_i }) do |i|
23
23
  if quiet?
24
24
  line i.id
25
25
  else
@@ -29,9 +29,11 @@ module VMC::App
29
29
  end
30
30
  end
31
31
 
32
+ private
33
+
32
34
  def display_instance(i)
33
35
  start_line "instance #{c("\##{i.id}", :instance)}: "
34
- puts "#{b(c(i.state.downcase, state_color(i.state)))} "
36
+ puts "#{b(c(i.state.downcase, state_color(i.state)))}"
35
37
 
36
38
  indented do
37
39
  if s = i.since
@@ -17,7 +17,7 @@ module VMC::App
17
17
  input :instances, :desc => "Number of instances to run", :type => :integer
18
18
  input :framework, :desc => "Framework to use", :from_given => by_name(:framework)
19
19
  input :runtime, :desc => "Runtime to use", :from_given => by_name(:runtime)
20
- input :command, :desc => "Startup command for standalone app"
20
+ input :command, :desc => "Startup command"
21
21
  input :plan, :desc => "Application plan", :default => "D100"
22
22
  input :start, :desc => "Start app after pushing?", :default => true
23
23
  input :restart, :desc => "Restart app after updating?", :default => true
@@ -26,6 +26,7 @@ module VMC::App
26
26
  input :bind_services, :desc => "Interactively bind services?",
27
27
  :type => :boolean, :default => proc { force? ? false : interact }
28
28
  interactions PushInteractions
29
+
29
30
  def push
30
31
  name = input[:name]
31
32
  path = File.expand_path(input[:path])
@@ -12,7 +12,7 @@ module VMC::App
12
12
  inputs[:space] = client.current_space if client.current_space
13
13
  inputs[:production] = !!(input[:plan] =~ /^p/i) if v2?
14
14
  inputs[:framework] = framework = determine_framework
15
- inputs[:command] = input[:command] if framework.name == "standalone"
15
+ inputs[:command] = input[:command] if can_have_custom_start_command?(framework)
16
16
  inputs[:runtime] = determine_runtime(framework)
17
17
 
18
18
  human_mb = human_mb(detector.suggested_memory(framework) || 64)
@@ -114,6 +114,10 @@ module VMC::App
114
114
 
115
115
  private
116
116
 
117
+ def can_have_custom_start_command?(framework)
118
+ %w(standalone buildpack).include?(framework.name)
119
+ end
120
+
117
121
  def all_instances
118
122
  @all_instances ||= client.service_instances
119
123
  end
@@ -37,7 +37,9 @@ module VMC::App
37
37
  end
38
38
 
39
39
  def ask_command
40
- ask("Startup command")
40
+ if ask("Use custom startup command?", :default => false)
41
+ ask("Startup command")
42
+ end
41
43
  end
42
44
 
43
45
  def ask_create_services
@@ -37,7 +37,7 @@ module VMC::App
37
37
  if usage
38
38
  [ idx,
39
39
  "#{percentage(usage[:cpu])} of #{b(stats[:cores])} cores",
40
- "#{usage(usage[:mem] * 1024, stats[:mem_quota])}",
40
+ "#{usage(usage[:mem], stats[:mem_quota])}",
41
41
  "#{usage(usage[:disk], stats[:disk_quota])}"
42
42
  ]
43
43
  else
@@ -36,11 +36,11 @@ module VMC::Start
36
36
  end
37
37
  end
38
38
 
39
- info = client.info
40
-
41
39
  showing_any = runtimes || services || frameworks
42
40
 
43
41
  unless !all && showing_any
42
+ info = client.info
43
+
44
44
  line if showing_any
45
45
  line info[:description]
46
46
  line
data/lib/vmc/plugin.rb CHANGED
@@ -21,8 +21,9 @@ module VMC
21
21
 
22
22
  enabled = Set.new(matching.collect(&:name))
23
23
 
24
- Gem.loaded_specs["vmc"].dependencies.each do |dep|
25
- if dep.name =~ /vmc-plugin/ && dep.type == :runtime
24
+ vmc_gems = Gem.loaded_specs["vmc"]
25
+ ((vmc_gems && vmc_gems.dependencies) || Gem.loaded_specs.values).each do |dep|
26
+ if dep.name =~ /vmc-plugin/
26
27
  require "#{dep.name}/plugin"
27
28
  enabled.delete dep.name
28
29
  end
data/lib/vmc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module VMC
2
- VERSION = "0.5.0.beta.6".freeze
2
+ VERSION = "0.5.0.beta.7".freeze
3
3
  end
@@ -1,5 +1,6 @@
1
1
  def vmc_ok(argv)
2
2
  with_output_to do |out|
3
+ Mothership.new.exit_status 0
3
4
  code = VMC::CLI.start(argv + ["--no-script"])
4
5
  yield out.string.strip_progress_dots if block_given?
5
6
  expect(code).to eq 0
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require "vmc/cli/app/base"
3
+
4
+ describe VMC::App::Base do
5
+ describe '#human_size' do
6
+ let(:base) { VMC::App::Base.new }
7
+
8
+ it { base.human_size(1_023).should == "1023.0B" }
9
+ it { base.human_size(1_024).should == "1.0K" }
10
+ it { base.human_size(1_024 * 1_024).should == "1.0M" }
11
+ it { base.human_size(1_024 * 1_024 * 1.5).should == "1.5M" }
12
+ it { base.human_size(1_024 * 1_024 * 1_024).should == "1.0G" }
13
+ it { base.human_size(1_024 * 1_024 * 1_024 * 1.5).should == "1.5G" }
14
+ it { base.human_size(1_024 * 1_024 * 1_024 * 1.234, 3).should == "1.234G" }
15
+ it { base.human_size(31395840).should == "29.9M" } # tests against floating point errors
16
+ end
17
+ end
@@ -5,7 +5,7 @@ describe VMC::App::Delete do
5
5
  let(:global) { { :color => false, :quiet => true } }
6
6
  let(:inputs) { {} }
7
7
  let(:given) { {} }
8
- let(:client) { FactoryGirl.build(:client) }
8
+ let(:client) { fake_client }
9
9
  let(:app) {}
10
10
  let(:new_name) { "some-new-name" }
11
11
 
@@ -49,28 +49,25 @@ describe VMC::App::Delete do
49
49
  end
50
50
 
51
51
  context 'when there are apps' do
52
- let(:client) { FactoryGirl.build(:client, :apps => apps) }
52
+ let(:client) { fake_client(:apps => apps) }
53
53
  let(:apps) { [basic_app, app_with_orphans, app_without_orphans] }
54
- let(:service_1) { FactoryGirl.build(:service_instance) }
55
- let(:service_2) { FactoryGirl.build(:service_instance) }
56
- let(:basic_app) { FactoryGirl.build(:app, :name => "basic_app") }
54
+ let(:service_1) { fake :service_instance }
55
+ let(:service_2) { fake :service_instance }
56
+ let(:basic_app) { fake(:app, :name => "basic_app") }
57
57
  let(:app_with_orphans) {
58
- FactoryGirl.build(:app,
58
+ fake :app,
59
59
  :name => "app_with_orphans",
60
60
  :service_bindings => [
61
- FactoryGirl.build(:service_binding,
62
- :service_instance => service_1),
63
- FactoryGirl.build(:service_binding,
64
- :service_instance => service_2)
65
- ])
61
+ fake(:service_binding, :service_instance => service_1),
62
+ fake(:service_binding, :service_instance => service_2)
63
+ ]
66
64
  }
67
65
  let(:app_without_orphans) {
68
- FactoryGirl.build(:app,
66
+ fake :app,
69
67
  :name => "app_without_orphans",
70
68
  :service_bindings => [
71
- FactoryGirl.build(:service_binding,
72
- :service_instance => service_1)
73
- ])
69
+ fake(:service_binding, :service_instance => service_1)
70
+ ]
74
71
  }
75
72
 
76
73
  context 'and no app is given' do
@@ -125,6 +122,8 @@ describe VMC::App::Delete do
125
122
  stub_ask("Really delete #{deleted_app.name}?", anything) { true }
126
123
  stub(deleted_app).delete!
127
124
 
125
+ stub(service_2).invalidate!
126
+
128
127
  mock_ask("Delete orphaned service #{service_2.name}?", anything) { true }
129
128
 
130
129
  any_instance_of(VMC::App::Delete) do |del|
@@ -141,6 +140,8 @@ describe VMC::App::Delete do
141
140
  stub_ask("Really delete #{deleted_app.name}?", anything) { false }
142
141
  dont_allow(deleted_app).delete!
143
142
 
143
+ stub(service_2).invalidate!
144
+
144
145
  dont_allow_ask("Delete orphaned service #{service_2.name}?")
145
146
 
146
147
  any_instance_of(VMC::App::Delete) do |del|
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe VMC::App::Stats do
5
+ let(:global) { { :color => false } }
6
+ let(:inputs) { {:app => apps[0]} }
7
+ let(:given) { {} }
8
+ let(:output) { StringIO.new }
9
+ let(:client) { fake_client(:apps => apps) }
10
+ let(:apps) { [fake(:app, :name => "basic_app")] }
11
+ let(:time) { Time.local(2012,11,1,2,30)}
12
+
13
+ before do
14
+ any_instance_of(VMC::CLI) do |cli|
15
+ stub(cli).client { client }
16
+ stub(cli).precondition { nil }
17
+ end
18
+ stub(client).base.stub!.instances(anything) do
19
+ {
20
+ "12" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
21
+ "1" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
22
+ "2" => {:state => "STARTED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"}
23
+ }
24
+ end
25
+ end
26
+
27
+ subject do
28
+ with_output_to output do
29
+ Mothership.new.invoke(:instances, inputs, given, global)
30
+ end
31
+ end
32
+
33
+ describe 'metadata' do
34
+ let(:command) { Mothership.commands[:instances] }
35
+
36
+ describe 'command' do
37
+ subject { command }
38
+ its(:description) { should eq "List an app's instances" }
39
+ it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
40
+ end
41
+
42
+ include_examples 'inputs must have descriptions'
43
+
44
+ describe 'arguments' do
45
+ subject { command.arguments }
46
+ it 'has no arguments' do
47
+ should eq([{:type=>:splat, :value=>nil, :name=>:apps}])
48
+ end
49
+ end
50
+ end
51
+
52
+ it 'prints out the instances in the correct order' do
53
+ subject
54
+
55
+ output.rewind
56
+ expect(output.string).to match /.*instance \#1.*instance \#2.*instance \#12.*/m
57
+ end
58
+
59
+ it 'prints out one of the instances correctly' do
60
+ subject
61
+
62
+ output.rewind
63
+ expect(output.string).to include <<-OUT.strip_heredoc
64
+ instance #2: started
65
+ started: #{time.strftime("%F %r")}
66
+ debugger: port bar at foo
67
+ console: port qux at baz
68
+ OUT
69
+ end
70
+ end
@@ -5,19 +5,20 @@ describe VMC::App::Create do
5
5
  let(:given) { {} }
6
6
  let(:global) { { :color => false, :quiet => true } }
7
7
 
8
- let(:frameworks) { FactoryGirl.build_list(:framework, 3) }
9
- let(:framework) { frameworks.first }
10
- let(:standalone) { FactoryGirl.build(:framework, :name => "standalone") }
8
+ let(:frameworks) { fake_list(:framework, 3) }
9
+ let(:framework) { buildpack }
10
+ let(:buildpack) { fake(:framework, :name => "buildpack") }
11
+ let(:standalone) { fake(:framework, :name => "standalone") }
11
12
 
12
- let(:runtimes) { FactoryGirl.build_list(:runtime, 3) }
13
+ let(:runtimes) { fake_list(:runtime, 3) }
13
14
  let(:runtime) { runtimes.first }
14
15
 
15
- let(:service_instances) { FactoryGirl.build_list(:service_instance, 5) }
16
+ let(:service_instances) { fake_list(:service_instance, 5) }
16
17
 
17
18
  let(:client) do
18
- FactoryGirl.build(
19
- :client,
20
- :frameworks => frameworks, :runtimes => runtimes,
19
+ fake_client(
20
+ :frameworks => frameworks,
21
+ :runtimes => runtimes,
21
22
  :service_instances => service_instances)
22
23
  end
23
24
 
@@ -44,7 +45,8 @@ describe VMC::App::Create do
44
45
  :plan => "p100",
45
46
  :framework => framework,
46
47
  :runtime => runtime,
47
- :memory => "1G"
48
+ :memory => "1G",
49
+ :command => "ruby main.rb"
48
50
  }
49
51
  end
50
52
 
@@ -54,7 +56,7 @@ describe VMC::App::Create do
54
56
  its([:space]) { should eq client.current_space }
55
57
  its([:production]) { should eq true }
56
58
  its([:framework]) { should eq framework }
57
- its([:command]) { should eq nil }
59
+ its([:command]) { should eq "ruby main.rb" }
58
60
  its([:runtime]) { should eq runtime }
59
61
  its([:memory]) { should eq 1024 }
60
62
  end
@@ -81,10 +83,54 @@ describe VMC::App::Create do
81
83
  subject
82
84
  end
83
85
 
84
- it 'should ask for the command if the framework is standalone' do
85
- inputs[:framework] = standalone
86
- mock_ask("Startup command") { "ruby main.rb" }
87
- subject
86
+ context 'when the command is not given' do
87
+ before { inputs.delete(:command) }
88
+
89
+ shared_examples 'an app that can have a custom start command' do
90
+ it 'should ask if there is a custom start command' do
91
+ mock_ask("Use custom startup command?", :default => false) { false }
92
+ subject
93
+ end
94
+
95
+ context 'when the user answers "yes" to the custom start command' do
96
+ before { stub_ask("Use custom startup command?", :default => false) { true } }
97
+
98
+ it 'should ask for the startup command' do
99
+ mock_ask("Startup command") { "foo bar.com" }
100
+ subject[:command].should eq "foo bar.com"
101
+ end
102
+ end
103
+
104
+ context 'when the user answers "no" to the custom start command' do
105
+ before { stub_ask("Use custom startup command?", :default => false) { false } }
106
+
107
+ it 'should not ask for the startup command' do
108
+ dont_allow_ask("Startup command")
109
+ subject
110
+ end
111
+ end
112
+ end
113
+
114
+ context 'when the framework is "buildpack"' do
115
+ let(:framework) { buildpack }
116
+
117
+ include_examples 'an app that can have a custom start command'
118
+ end
119
+
120
+ context 'when the framework is "standalone"' do
121
+ let(:framework) { standalone }
122
+
123
+ include_examples 'an app that can have a custom start command'
124
+ end
125
+
126
+ context 'when the framework is neither "buildpack" nor "standalone"' do
127
+ let(:framework) { fake(:framework, :name => "java") }
128
+
129
+ it 'does not ask if there is a custom start command' do
130
+ dont_allow_ask("Startup command")
131
+ subject
132
+ end
133
+ end
88
134
  end
89
135
 
90
136
  it 'should ask for the runtime' do
@@ -225,7 +271,7 @@ describe VMC::App::Create do
225
271
  describe '#create_app' do
226
272
  before { dont_allow_ask }
227
273
 
228
- let(:app) { FactoryGirl.build(:app, :guid => nil) }
274
+ let(:app) { fake(:app, :guid => nil) }
229
275
 
230
276
  let(:attributes) do
231
277
  { :name => "some-app",
@@ -255,7 +301,7 @@ describe VMC::App::Create do
255
301
  end
256
302
 
257
303
  describe '#map_url' do
258
- let(:app) { FactoryGirl.build(:app) }
304
+ let(:app) { fake(:app) }
259
305
  let(:url_choices) { %W(#{app.name}.foo-cloud.com) }
260
306
 
261
307
  before do
@@ -291,7 +337,7 @@ describe VMC::App::Create do
291
337
  mock_ask('URL', anything) { url_choices.first }
292
338
 
293
339
  mock(create).invoke(:map, :app => app, :url => url_choices.first) do
294
- raise CFoundry::RouteHostTaken.new(1234, "foo")
340
+ raise CFoundry::RouteHostTaken.new(nil, nil, "foo", 1234)
295
341
  end
296
342
  end
297
343
 
@@ -319,7 +365,7 @@ describe VMC::App::Create do
319
365
  end
320
366
 
321
367
  describe '#create_services' do
322
- let(:app) { FactoryGirl.build(:app) }
368
+ let(:app) { fake(:app) }
323
369
  subject { create.create_services(app) }
324
370
 
325
371
  context 'when forcing' do
@@ -365,7 +411,7 @@ describe VMC::App::Create do
365
411
  end
366
412
 
367
413
  describe '#bind_services' do
368
- let(:app) { FactoryGirl.build(:app) }
414
+ let(:app) { fake(:app) }
369
415
 
370
416
  subject { create.bind_services(app) }
371
417
 
@@ -437,7 +483,7 @@ describe VMC::App::Create do
437
483
  end
438
484
 
439
485
  describe '#start_app' do
440
- let(:app) { FactoryGirl.build(:app) }
486
+ let(:app) { fake(:app) }
441
487
  subject { create.start_app(app) }
442
488
 
443
489
  context 'when the start flag is provided' do