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

Sign up to get free protection for your applications and to get access to all the features.
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