cf 5.2.1.rc4 → 5.2.1.rc5

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.
@@ -6,7 +6,7 @@ module CF
6
6
  let(:global) { {:color => false, :quiet => true} }
7
7
  let(:inputs) { {} }
8
8
  let(:given) { {} }
9
- let(:path) { "somepath" }
9
+ let(:path) { "/somepath" }
10
10
  let(:client) { build(:client) }
11
11
  let(:push) { CF::App::Push.new(Mothership.commands[:push]) }
12
12
 
@@ -18,37 +18,28 @@ module CF
18
18
  describe "metadata" do
19
19
  let(:command) { Mothership.commands[:push] }
20
20
 
21
- describe "command" do
21
+ describe "has the correct information" do
22
22
  subject { command }
23
23
  its(:description) { should eq "Push an application, syncing changes if it exists" }
24
24
  it { expect(Mothership::Help.group(:apps, :manage)).to include(subject) }
25
25
  end
26
26
 
27
- include_examples "inputs must have descriptions"
28
-
29
- describe "arguments" do
30
- subject { command.arguments }
31
- it "has the correct argument order" do
32
- should eq([{:type => :optional, :value => nil, :name => :name}])
33
- end
34
- end
27
+ it_behaves_like "inputs must have descriptions"
35
28
  end
36
29
 
37
- describe "#sync_app" do
30
+ describe "#push" do
38
31
  let(:app) { build(:app, :client => client, :name => "app-name-1") }
39
32
 
40
33
  before do
41
34
  app.stub(:upload)
42
35
  app.changes = {}
43
36
  push.stub(:warn)
37
+ client.stub(:app_by_name).and_return(app)
44
38
  end
45
39
 
46
- subject do
47
- push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
48
- push.sync_app(app, path)
49
- end
40
+ let(:inputs) { {} }
50
41
 
51
- shared_examples "common tests for inputs" do |*args|
42
+ shared_examples_for "an input" do |*args|
52
43
  context "when the new input is the same as the old" do
53
44
  type, input = args
54
45
  input ||= type
@@ -58,19 +49,36 @@ module CF
58
49
  it "does not update the app's #{type}" do
59
50
  push.should_not_receive(:line)
60
51
  app.should_not_receive(:update!)
61
- expect { subject }.not_to change { app.send(type) }
52
+ expect do
53
+ push.input = Mothership::Inputs.new(Mothership.commands[:push], push, inputs, {}, global)
54
+ push.push
55
+ end.not_to change { app.send(type) }
62
56
  end
63
57
  end
64
58
  end
65
59
 
66
60
  it "triggers the :push_app filter" do
67
61
  push.should_receive(:filter).with(:push_app, app) { app }
68
- subject
62
+ push.input = Mothership::Inputs.new(Mothership.commands[:push], push, inputs, {}, global)
63
+ push.push
69
64
  end
70
65
 
71
- it "uploads the app" do
72
- app.should_receive(:upload).with(path)
73
- subject
66
+ describe 'uploading the app from the correct path' do
67
+ context 'when the user does not specify a path' do
68
+ it 'uploads the app' do
69
+ app.should_receive(:upload).with(File.expand_path('.'))
70
+ push.input = Mothership::Inputs.new(Mothership.commands[:push], push, {}, {}, global)
71
+ push.push
72
+ end
73
+ end
74
+
75
+ context 'when the user specifies a path' do
76
+ it 'uploads the app' do
77
+ app.should_receive(:upload).with(path)
78
+ push.input = Mothership::Inputs.new(Mothership.commands[:push], push, {:path => path}, {}, global)
79
+ push.push
80
+ end
81
+ end
74
82
  end
75
83
 
76
84
  context "when the app is stopped" do
@@ -80,21 +88,24 @@ module CF
80
88
 
81
89
  it "warns the user" do
82
90
  push.should_receive(:warn).with("\n#{app.name} is currently stopped, start it with 'cf start'")
83
- subject
91
+ push.input = Mothership::Inputs.new(nil, push, {:path => path}, {}, global)
92
+ push.push
84
93
  end
85
94
  end
86
95
 
87
- context "when no inputs are given" do
88
- let(:inputs) { {} }
96
+ context "when no inputs other than path are given" do
97
+ let(:inputs) { {:path => ""} }
89
98
 
90
99
  it "should not update the app" do
91
100
  app.should_not_receive(:update!)
92
- subject
101
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
102
+ push.push
93
103
  end
94
104
 
95
105
  it "should not set memory on the app" do
96
106
  app.should_not_receive(:memory=)
97
- subject
107
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
108
+ push.push
98
109
  end
99
110
  end
100
111
 
@@ -102,93 +113,116 @@ module CF
102
113
  let(:old) { 1024 }
103
114
  let(:new) { "2G" }
104
115
  let(:app) { build(:app, :memory => old) }
105
- let(:inputs) { {:memory => new} }
116
+ let(:inputs) { {:path => path, :memory => new} }
106
117
 
107
118
  it "updates the app memory, converting to megabytes" do
108
119
  push.stub(:line)
109
120
  app.should_receive(:update!)
110
- expect { subject }.to change { app.memory }.from(old).to(2048)
121
+ expect { push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
122
+ push.push }.to change { app.memory }.from(old).to(2048)
111
123
  end
112
124
 
113
125
  it "outputs the changed memory in human readable sizes" do
114
126
  push.should_receive(:line).with("Changes:")
115
127
  push.should_receive(:line).with("memory: 1G -> 2G")
116
128
  app.stub(:update!)
117
- subject
129
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
130
+ push.push
118
131
  end
119
132
 
120
- include_examples "common tests for inputs", :memory
133
+ it_behaves_like "an input", :memory
121
134
  end
122
135
 
123
136
  context "when instances is given" do
124
137
  let(:old) { 1 }
125
138
  let(:new) { 2 }
126
139
  let(:app) { build(:app, :total_instances => old) }
127
- let(:inputs) { {:instances => new} }
140
+ let(:inputs) { {:path => path, :instances => new} }
128
141
 
129
142
  it "updates the app instances" do
130
143
  push.stub(:line)
131
144
  app.stub(:update!)
132
- expect { subject }.to change { app.total_instances }.from(old).to(new)
145
+ expect do
146
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
147
+ push.push
148
+ end.to change { app.total_instances }.from(old).to(new)
133
149
  end
134
150
 
135
151
  it "outputs the changed instances" do
136
152
  push.should_receive(:line).with("Changes:")
137
153
  push.should_receive(:line).with("total_instances: 1 -> 2")
138
154
  app.stub(:update!)
139
- subject
155
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
156
+ push.push
140
157
  end
141
158
 
142
- include_examples "common tests for inputs", :total_instances, :instances
159
+ it_behaves_like "an input", :total_instances, :instances
143
160
  end
144
161
 
145
162
  context "when command is given" do
146
163
  let(:old) { "./start" }
147
164
  let(:new) { "./start foo " }
148
165
  let(:app) { build(:app, :command => old) }
149
- let(:inputs) { {:command => new} }
166
+ let(:inputs) { {:path => path, :command => new} }
150
167
 
151
168
  it "updates the app command" do
152
169
  push.stub(:line)
153
170
  app.should_receive(:update!)
154
- expect { subject }.to change { app.command }.from("./start").to("./start foo ")
171
+ expect do
172
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
173
+ push.push
174
+ end.to change { app.command }.from("./start").to("./start foo ")
155
175
  end
156
176
 
157
177
  it "outputs the changed command in single quotes" do
158
178
  push.should_receive(:line).with("Changes:")
159
179
  push.should_receive(:line).with("command: './start' -> './start foo '")
160
180
  app.stub(:update!)
161
- subject
181
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
182
+ push.push
162
183
  end
163
184
 
164
- include_examples "common tests for inputs", :command
185
+ it_behaves_like "an input", :command
165
186
  end
166
187
 
167
188
  context "when restart is given" do
168
- let(:inputs) { {:restart => true, :memory => 4096} }
189
+ let(:inputs) { {:path => path, :restart => true, :memory => 4096} }
190
+
191
+ let(:mock_restart_command) do
192
+ MockRestartCommand.new
193
+ end
169
194
 
170
195
  before do
171
196
  CF::App::Base.any_instance.stub(:human_mb).and_return(0)
197
+ Restart.stub(:new).and_return(mock_restart_command)
172
198
  end
173
199
 
174
200
  context "when the app is already started" do
175
201
  let(:app) { build(:app, :state => "STARTED") }
176
202
 
177
- it "invokes the restart command" do
203
+ it "restarts the app after updating" do
178
204
  push.stub(:line)
179
- app.should_receive(:update!)
180
- push.should_receive(:invoke).with(:restart, :app => app)
181
- subject
205
+ app.should_receive(:update!) do
206
+ expect(mock_restart_command.restarted_apps).to be_empty
207
+ end
208
+
209
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
210
+ push.push
211
+
212
+ expect(mock_restart_command.restarted_apps).to eq [app]
182
213
  end
183
214
 
184
215
  context "but there are no changes" do
185
- let(:inputs) { {:restart => true} }
216
+ let(:inputs) { {:path => path, :restart => true} }
186
217
 
187
- it "invokes the restart command" do
218
+ it "restarts the app without updating" do
188
219
  push.stub(:line)
189
220
  app.should_not_receive(:update!)
190
- push.should_receive(:invoke).with(:restart, :app => app)
191
- subject
221
+
222
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
223
+ push.push
224
+
225
+ mock_restart_command.restarted_apps.should == [app]
192
226
  end
193
227
  end
194
228
  end
@@ -196,11 +230,14 @@ module CF
196
230
  context "when the app is not already started" do
197
231
  let(:app) { build(:app, :state => "STOPPED") }
198
232
 
199
- it "does not invoke the restart command" do
233
+ it "updates the app without restarting" do
200
234
  push.stub(:line)
201
235
  app.should_receive(:update!)
202
- push.should_not_receive(:invoke).with(:restart, :app => app)
203
- subject
236
+
237
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
238
+ push.push
239
+
240
+ expect(mock_restart_command.restarted_apps).to be_empty
204
241
  end
205
242
  end
206
243
  end
@@ -208,7 +245,7 @@ module CF
208
245
  context "when buildpack is given" do
209
246
  let(:old) { nil }
210
247
  let(:app) { build(:app, :buildpack => old) }
211
- let(:inputs) { {:buildpack => new} }
248
+ let(:inputs) { {:path => path, :buildpack => new} }
212
249
 
213
250
  context "and it's an invalid URL" do
214
251
  let(:new) { "git@github.com:foo/bar.git" }
@@ -216,15 +253,18 @@ module CF
216
253
  before do
217
254
  app.stub(:update!) do
218
255
  raise CFoundry::MessageParseError.new(
219
- "Request invalid due to parse error: Field: buildpack, Error: Value git@github.com:cloudfoundry/heroku-buildpack-ruby.git doesn't match regexp String /GIT_URL_REGEX/",
220
- 1001)
256
+ "Request invalid due to parse error: Field: buildpack, Error: Value git@github.com:cloudfoundry/heroku-buildpack-ruby.git doesn't match regexp String /GIT_URL_REGEX/",
257
+ 1001)
221
258
  end
222
259
  end
223
260
 
224
261
  it "fails and prints a pretty message" do
225
262
  push.stub(:line)
226
- expect { subject }.to raise_error(
227
- CF::UserError, "Buildpack must be a public git repository URI.")
263
+ expect do
264
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
265
+ push.push
266
+ end.to raise_error(
267
+ CF::UserError, "Buildpack must be a public git repository URI.")
228
268
  end
229
269
  end
230
270
 
@@ -234,17 +274,21 @@ module CF
234
274
  it "updates the app's buildpack" do
235
275
  push.stub(:line)
236
276
  app.should_receive(:update!)
237
- expect { subject }.to change { app.buildpack }.from(old).to(new)
277
+ expect do
278
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
279
+ push.push
280
+ end.to change { app.buildpack }.from(old).to(new)
238
281
  end
239
282
 
240
283
  it "outputs the changed buildpack with single quotes" do
241
284
  push.should_receive(:line).with("Changes:")
242
285
  push.should_receive(:line).with("buildpack: '' -> '#{new}'")
243
286
  app.stub(:update!)
244
- subject
287
+ push.input = Mothership::Inputs.new(nil, push, inputs, {}, global)
288
+ push.push
245
289
  end
246
290
 
247
- include_examples "common tests for inputs", :buildpack
291
+ it_behaves_like "an input", :buildpack
248
292
  end
249
293
  end
250
294
  end
@@ -254,11 +298,11 @@ module CF
254
298
  let(:host) { "" }
255
299
  let(:domain) { build(:domain) }
256
300
  let(:inputs) do
257
- { :name => "some-app",
258
- :instances => 2,
259
- :memory => 1024,
260
- :host => host,
261
- :domain => domain
301
+ {:name => "some-app",
302
+ :instances => 2,
303
+ :memory => 1024,
304
+ :host => host,
305
+ :domain => domain
262
306
  }
263
307
  end
264
308
  let(:global) { {:quiet => true, :color => false, :force => true} }
@@ -66,7 +66,7 @@ module CF
66
66
  before do
67
67
  app.stub(:instances) do
68
68
  [CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "DOWN"),
69
- CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING")
69
+ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "DOWN")
70
70
  ]
71
71
  end
72
72
 
@@ -75,10 +75,10 @@ module CF
75
75
  end
76
76
  end
77
77
 
78
- context "when all instances become running" do
78
+ context "when one instance becomes running" do
79
79
  let(:final_instances) do
80
80
  [CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING"),
81
- CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "RUNNING")
81
+ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "DOWN")
82
82
  ]
83
83
  end
84
84
 
@@ -86,7 +86,7 @@ module CF
86
86
  execute_start_app
87
87
  expect(output).to say("Checking status of app '#{app.name}'...")
88
88
  expect(output).to say("1 running, 1 down")
89
- expect(output).to say("2 running")
89
+ expect(output).to say("Push successful!")
90
90
  end
91
91
  end
92
92
 
@@ -122,17 +122,19 @@ module CF
122
122
  end
123
123
 
124
124
  context "when any instance becomes flapping" do
125
- let(:final_instances) do
126
- [CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "FLAPPING"),
127
- CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "STARTING")
128
- ]
125
+ before do
126
+ app.stub(:instances) do
127
+ [
128
+ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "FLAPPING"),
129
+ CFoundry::V2::App::Instance.new(nil, nil, nil, :state => "DOWN"),
130
+ ]
131
+ end
129
132
  end
130
133
 
131
134
  it "says app failed to start" do
132
135
  execute_start_app
133
136
  expect(output).to say("Checking status of app '#{app.name}'...")
134
- expect(output).to say("1 running, 1 down")
135
- expect(output).to say("1 starting, 1 flapping")
137
+ expect(output).to say("1 crashing, 1 down")
136
138
  expect(error_output).to say("Push unsuccessful.")
137
139
  end
138
140
  end
data/spec/cf/cli_spec.rb CHANGED
@@ -58,11 +58,6 @@ module CF
58
58
  subject
59
59
  end
60
60
 
61
- it "does mention ~/.cf/crash" do
62
- subject
63
- expect(stderr.string).to include CF::CRASH_FILE
64
- end
65
-
66
61
  it "logs the error" do
67
62
  context.should_receive(:log_error).with(anything)
68
63
  subject
@@ -145,16 +140,13 @@ module CF
145
140
  end
146
141
 
147
142
  context "with an arbitrary exception" do
148
- let(:action) { proc { raise "foo bar" } }
149
-
150
- it "logs the error" do
151
- context.should_receive(:log_error).with(anything)
152
- subject
153
- end
143
+ let(:error) { RuntimeError.new("ahhhh it's all broken!!!!") }
144
+ let(:action) { proc { raise error } }
154
145
 
155
146
  it "prints the message" do
156
147
  subject
157
- expect(stderr.string).to include "RuntimeError: foo bar"
148
+ expect(stderr.string).to include "RuntimeError: ahhhh it's all broken!!!!"
149
+ expect(stderr.string).to include "spec/cf/cli_spec.rb" #to check that we're printing the backtrace
158
150
  end
159
151
 
160
152
  it "sets the exit code to 1" do
@@ -162,11 +154,6 @@ module CF
162
154
  subject
163
155
  end
164
156
 
165
- it "tells the user to check ~/.cf/crash" do
166
- subject
167
- expect(stderr.string).to include CF::CRASH_FILE
168
- end
169
-
170
157
  context "when we are debugging" do
171
158
  let(:inputs) { {:debug => true} }
172
159