cf 0.6.1.rc9 → 0.6.1.rc10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/lib/cf.rb +4 -0
  2. data/lib/cf/cli.rb +8 -3
  3. data/lib/cf/version.rb +1 -1
  4. data/lib/console/README.md +16 -0
  5. data/lib/console/console.rb +187 -0
  6. data/lib/console/plugin.rb +30 -0
  7. data/lib/manifests/README.md +13 -0
  8. data/lib/manifests/errors.rb +35 -0
  9. data/lib/manifests/loader.rb +31 -0
  10. data/lib/manifests/loader/builder.rb +39 -0
  11. data/lib/manifests/loader/normalizer.rb +145 -0
  12. data/lib/manifests/loader/resolver.rb +79 -0
  13. data/lib/manifests/manifests.rb +304 -0
  14. data/lib/manifests/plugin.rb +141 -0
  15. data/lib/tunnel/README.md +29 -0
  16. data/lib/tunnel/helper-app/Gemfile +11 -0
  17. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  18. data/lib/tunnel/helper-app/server.rb +43 -0
  19. data/lib/tunnel/plugin.rb +183 -0
  20. data/lib/tunnel/tunnel.rb +305 -0
  21. data/spec/assets/rails328_ruby187_app/Gemfile +39 -0
  22. data/spec/assets/rails328_ruby187_app/README.rdoc +261 -0
  23. data/spec/assets/rails328_ruby187_app/Rakefile +7 -0
  24. data/spec/assets/rails328_ruby187_app/app/assets/images/rails.png +0 -0
  25. data/spec/assets/rails328_ruby187_app/app/assets/javascripts/application.js +15 -0
  26. data/spec/assets/rails328_ruby187_app/app/assets/stylesheets/application.css +13 -0
  27. data/spec/assets/rails328_ruby187_app/app/controllers/application_controller.rb +3 -0
  28. data/spec/assets/rails328_ruby187_app/app/helpers/application_helper.rb +2 -0
  29. data/spec/assets/rails328_ruby187_app/app/views/layouts/application.html.erb +14 -0
  30. data/spec/assets/rails328_ruby187_app/config.ru +4 -0
  31. data/spec/assets/rails328_ruby187_app/config/application.rb +62 -0
  32. data/spec/assets/rails328_ruby187_app/config/boot.rb +6 -0
  33. data/spec/assets/rails328_ruby187_app/config/database.yml +25 -0
  34. data/spec/assets/rails328_ruby187_app/config/environment.rb +5 -0
  35. data/spec/assets/rails328_ruby187_app/config/environments/development.rb +37 -0
  36. data/spec/assets/rails328_ruby187_app/config/environments/production.rb +67 -0
  37. data/spec/assets/rails328_ruby187_app/config/environments/test.rb +37 -0
  38. data/spec/assets/rails328_ruby187_app/config/initializers/backtrace_silencers.rb +7 -0
  39. data/spec/assets/rails328_ruby187_app/config/initializers/inflections.rb +15 -0
  40. data/spec/assets/rails328_ruby187_app/config/initializers/mime_types.rb +5 -0
  41. data/spec/assets/rails328_ruby187_app/config/initializers/secret_token.rb +7 -0
  42. data/spec/assets/rails328_ruby187_app/config/initializers/session_store.rb +8 -0
  43. data/spec/assets/rails328_ruby187_app/config/initializers/wrap_parameters.rb +14 -0
  44. data/spec/assets/rails328_ruby187_app/config/locales/en.yml +5 -0
  45. data/spec/assets/rails328_ruby187_app/config/routes.rb +58 -0
  46. data/spec/assets/rails328_ruby187_app/db/seeds.rb +7 -0
  47. data/spec/assets/rails328_ruby187_app/doc/README_FOR_APP +2 -0
  48. data/spec/assets/rails328_ruby187_app/manifest.yml +7 -0
  49. data/spec/assets/rails328_ruby187_app/public/404.html +26 -0
  50. data/spec/assets/rails328_ruby187_app/public/422.html +26 -0
  51. data/spec/assets/rails328_ruby187_app/public/500.html +25 -0
  52. data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css +0 -0
  53. data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css.gz +0 -0
  54. data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js +17 -0
  55. data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js.gz +0 -0
  56. data/spec/assets/rails328_ruby187_app/public/assets/application.css +0 -0
  57. data/spec/assets/rails328_ruby187_app/public/assets/application.css.gz +0 -0
  58. data/spec/assets/rails328_ruby187_app/public/assets/application.js +17 -0
  59. data/spec/assets/rails328_ruby187_app/public/assets/application.js.gz +0 -0
  60. data/spec/assets/rails328_ruby187_app/public/assets/manifest.yml +4 -0
  61. data/spec/assets/rails328_ruby187_app/public/assets/rails-be8732dac73d845ac5b142c8fb5f9fb0.png +0 -0
  62. data/spec/assets/rails328_ruby187_app/public/assets/rails.png +0 -0
  63. data/spec/assets/rails328_ruby187_app/public/favicon.ico +0 -0
  64. data/spec/assets/rails328_ruby187_app/public/index.html +241 -0
  65. data/spec/assets/rails328_ruby187_app/public/robots.txt +5 -0
  66. data/spec/assets/rails328_ruby187_app/script/rails +6 -0
  67. data/spec/assets/rails328_ruby187_app/test/performance/browsing_test.rb +12 -0
  68. data/spec/assets/rails328_ruby187_app/test/test_helper.rb +13 -0
  69. data/spec/cf/cli/app/stats_spec.rb +20 -20
  70. data/spec/cf/cli_spec.rb +37 -18
  71. data/spec/console/console_spec.rb +189 -0
  72. data/spec/features/push_flow_spec.rb +1 -1
  73. data/spec/manifests/errors_spec.rb +43 -0
  74. data/spec/manifests/loader/builder_spec.rb +80 -0
  75. data/spec/manifests/loader/normalizer_spec.rb +158 -0
  76. data/spec/manifests/manifests_spec.rb +309 -0
  77. data/spec/manifests/plugin_spec.rb +362 -0
  78. data/spec/tunnel/plugin_spec.rb +31 -0
  79. metadata +184 -25
@@ -0,0 +1,309 @@
1
+ require 'spec_helper'
2
+
3
+ describe CFManifests do
4
+ let(:inputs_hash) { {} }
5
+ let(:given_hash) { {} }
6
+ let(:global_hash) { {} }
7
+ let(:inputs) { Mothership::Inputs.new(nil, nil, inputs_hash, given_hash, global_hash) }
8
+
9
+ let(:cmd) do
10
+ manifest = CF::App::Push.new(nil, inputs)
11
+ manifest.extend CFManifests
12
+ stub(manifest).client { client }
13
+ manifest
14
+ end
15
+
16
+ let(:target_base) { "some-cloud.com" }
17
+
18
+ let(:foo) { fake(:app, :name => "foo") }
19
+ let(:bar) { fake(:app, :name => "bar") }
20
+ let(:baz) { fake(:app, :name => "baz") }
21
+ let(:xxx) { fake(:app, :name => "xxx") }
22
+ let(:yyy) { fake(:app, :name => "yyy") }
23
+
24
+ let(:client) do
25
+ fake_client :apps => [foo, bar, baz, xxx, yyy]
26
+ end
27
+
28
+ let(:manifest_file) { "/abc/manifest.yml" }
29
+
30
+ before do
31
+ stub(cmd).target_base { target_base }
32
+
33
+ stub(cmd).manifest { manifest }
34
+ stub(cmd).manifest_file { manifest_file }
35
+ end
36
+
37
+ describe '#find_apps' do
38
+ subject { cmd.find_apps(nil) }
39
+
40
+ context 'when there is no manifest file' do
41
+ before { stub(cmd).manifest { nil } }
42
+ it { should eq [] }
43
+ end
44
+ end
45
+
46
+ describe '#create_manifest_for' do
47
+ let(:app) {
48
+ fake :app,
49
+ :memory => 2048,
50
+ :total_instances => 2,
51
+ :command => "ruby main.rb",
52
+ :buildpack => "git://example.com/foo.git",
53
+ :routes => [
54
+ fake(:route,
55
+ :host => "some-app-name",
56
+ :domain => fake(:domain, :name => target_base))
57
+ ],
58
+ :service_bindings => [
59
+ fake(
60
+ :service_binding,
61
+ :service_instance =>
62
+ fake(
63
+ :service_instance,
64
+ :name => "service-1",
65
+ :service_plan =>
66
+ fake(
67
+ :service_plan,
68
+ :name => "P200",
69
+ :service => fake(:service))))
70
+ ]
71
+ }
72
+
73
+ subject { cmd.create_manifest_for(app, "some-path") }
74
+
75
+ its(["name"]) { should eq app.name }
76
+ its(["memory"]) { should eq "2G" }
77
+ its(["instances"]) { should eq 2 }
78
+ its(["path"]) { should eq "some-path" }
79
+ its(["url"]) { should eq "some-app-name.${target-base}" }
80
+ its(["command"]) { should eq "ruby main.rb" }
81
+ its(["buildpack"]) { should eq "git://example.com/foo.git" }
82
+
83
+ it "contains the service information" do
84
+ expect(subject["services"]).to be_a Hash
85
+
86
+ services = subject["services"]
87
+ app.service_bindings.each do |b|
88
+ service = b.service_instance
89
+
90
+ expect(services).to include service.name
91
+
92
+ info = services[service.name]
93
+
94
+ plan = service.service_plan
95
+ offering = plan.service
96
+
97
+ { "plan" => plan.name,
98
+ "label" => offering.label,
99
+ "provider" => offering.provider,
100
+ "version" => offering.version
101
+ }.each do |attr, val|
102
+ expect(info).to include attr
103
+ expect(info[attr]).to eq val
104
+ end
105
+ end
106
+ end
107
+
108
+ context 'when there is no url' do
109
+ let(:app) {
110
+ fake :app,
111
+ :memory => 2048,
112
+ :total_instances => 2
113
+ }
114
+
115
+ its(["url"]) { should eq "none" }
116
+ end
117
+
118
+ context 'when there is no command' do
119
+ let(:app) {
120
+ fake :app,
121
+ :memory => 2048,
122
+ :total_instances => 2
123
+ }
124
+
125
+ it { should_not include "command" }
126
+ end
127
+
128
+ context 'when there are no service bindings' do
129
+ let(:app) {
130
+ fake :app,
131
+ :memory => 2048,
132
+ :total_instances => 2
133
+ }
134
+
135
+ it { should_not include "services" }
136
+ end
137
+ end
138
+
139
+ describe "#setup_services" do
140
+ let(:service_bindings) { [] }
141
+ let(:app) { fake :app, :service_bindings => service_bindings }
142
+
143
+ before do
144
+ dont_allow_ask(anything, anything)
145
+ end
146
+
147
+ context "when services are defined in the manifest" do
148
+ let(:info) {
149
+ { :services => { "service-1" => { :label => "mysql", :plan => "100" } } }
150
+ }
151
+
152
+ let(:service_1) { fake(:service_instance, :name => "service-1") }
153
+
154
+ let(:plan_100) { fake :service_plan, :name => "100" }
155
+
156
+ let(:mysql) {
157
+ fake(
158
+ :service,
159
+ :label => "mysql",
160
+ :provider => "core",
161
+ :service_plans => [plan_100])
162
+ }
163
+
164
+ let(:service_instances) { [] }
165
+
166
+ let(:client) {
167
+ fake_client :services => [mysql], :service_instances => service_instances
168
+ }
169
+
170
+ context "and the services exist" do
171
+ let(:service_instances) { [service_1] }
172
+
173
+ context "and are already bound" do
174
+ let(:service_bindings) { [fake(:service_binding, :service_instance => service_1)] }
175
+
176
+ it "does neither create nor bind the service again" do
177
+ dont_allow(cmd).invoke :create_service, anything
178
+ dont_allow(cmd).invoke :bind_service, anything
179
+ cmd.send(:setup_services, app, info)
180
+ end
181
+ end
182
+
183
+ context "but are not bound" do
184
+ it "does not create the services" do
185
+ dont_allow(cmd).invoke :create_service, anything
186
+ stub(cmd).invoke :bind_service, anything
187
+ cmd.send(:setup_services, app, info)
188
+ end
189
+
190
+ it "binds the service" do
191
+ mock(cmd).invoke :bind_service, :app => app, :service => service_1
192
+ cmd.send(:setup_services, app, info)
193
+ end
194
+ end
195
+ end
196
+
197
+ context "and the services do not exist" do
198
+ it "creates the services" do
199
+ mock(cmd).invoke :create_service, :app => app,
200
+ :name => service_1.name, :offering => mysql, :plan => plan_100
201
+ dont_allow(cmd).invoke :bind_service, anything
202
+ cmd.send(:setup_services, app, info)
203
+ end
204
+ end
205
+ end
206
+
207
+ context "when there are no services defined" do
208
+ let(:info) { {} }
209
+
210
+ it "does not ask anything" do
211
+ cmd.send(:setup_services, app, info)
212
+ end
213
+ end
214
+ end
215
+
216
+ describe "#apps_in_manifest" do
217
+ let(:foo_hash) { { :name => "foo", :path => "/abc/foo" } }
218
+ let(:bar_hash) { { :name => "bar", :path => "/abc/bar" } }
219
+ let(:baz_hash) { { :name => "baz", :path => "/abc/baz" } }
220
+
221
+ let(:manifest) { { :applications => [foo_hash, bar_hash, baz_hash] } }
222
+
223
+ subject { cmd.apps_in_manifest(inputs) }
224
+
225
+ context "when no apps are passed" do
226
+ let(:given_hash) { {} }
227
+
228
+ its(:first) { should eq [] }
229
+ its(:last) { should eq [] }
230
+ end
231
+
232
+ context "when app names are passed" do
233
+ context "and all of them are in the manifest" do
234
+ let(:given_hash) { { :apps => ["foo", "bar"] } }
235
+
236
+ its(:first) { should eq [foo_hash, bar_hash] }
237
+ its(:last) { should eq [] }
238
+ end
239
+
240
+ context "and one of them is in the manifest" do
241
+ let(:given_hash) { { :apps => ["foo", "xxx"] } }
242
+
243
+ its(:first) { should eq [foo_hash] }
244
+ its(:last) { should eq ["xxx"] }
245
+ end
246
+
247
+ context "and none of them are in the manifest" do
248
+ let(:given_hash) { { :apps => ["xxx", "yyy"] } }
249
+
250
+ its(:first) { should eq [] }
251
+ its(:last) { should eq ["xxx", "yyy"] }
252
+ end
253
+ end
254
+
255
+ context "when apps are passed as paths" do
256
+ context "and the paths are in the manifest" do
257
+ let(:given_hash) { { :apps => ["/abc/foo"] } }
258
+
259
+ its(:first) { should eq [foo_hash] }
260
+ its(:last) { should eq [] }
261
+ end
262
+
263
+ context "and any path is not in the manifest" do
264
+ let(:given_hash) { { :apps => ["/abc/xxx"] } }
265
+
266
+ it "fails with a manifest-specific method (i.e. path not in manifest)" do
267
+ expect { subject }.to raise_error(CF::UserError, /Path .+ is not present in manifest/)
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ describe "#all_apps" do
274
+ let(:applications) do
275
+ [
276
+ {:name => "foo", :path => "/abc"},
277
+ {:name => "bar", :path => "/abc"},
278
+ {:name => "baz", :path => "/abc/baz"}
279
+ ]
280
+ end
281
+
282
+ let(:manifest) do
283
+ { :applications => applications }
284
+ end
285
+
286
+ subject { cmd.all_apps }
287
+
288
+ it "returns all of the apps described in the manifest, as hashes" do
289
+ expect(subject).to eq applications
290
+ end
291
+ end
292
+
293
+ describe "#current_apps" do
294
+ let(:manifest) do
295
+ {:applications => [
296
+ {:name => "foo", :path => "/abc"},
297
+ {:name => "bar", :path => "/abc"},
298
+ {:name => "baz", :path => "/abc/baz"}
299
+ ]}
300
+ end
301
+
302
+ subject { cmd.current_apps }
303
+
304
+ it "returns the applications with the cwd as their path" do
305
+ stub(Dir).pwd { "/abc" }
306
+ expect(subject).to eq [{ :name => "foo", :path => "/abc"}, { :name => "bar", :path => "/abc" }]
307
+ end
308
+ end
309
+ end
@@ -0,0 +1,362 @@
1
+ require "spec_helper"
2
+
3
+ describe ManifestsPlugin do
4
+ let(:manifest) { {} }
5
+ let(:manifest_file) { nil }
6
+ let(:inputs_hash) { {} }
7
+ let(:given_hash) { {} }
8
+ let(:global_hash) { { :quiet => true } }
9
+ let(:command) { nil }
10
+ let(:inputs) { Mothership::Inputs.new(Mothership.commands[:push], nil, inputs_hash, given_hash, global_hash) }
11
+ let(:plugin) { ManifestsPlugin.new(command, inputs) }
12
+
13
+ let(:client) { fake_client }
14
+
15
+ before do
16
+ stub(plugin).manifest { manifest }
17
+ stub(plugin).manifest_file { manifest_file } if manifest_file
18
+ stub(plugin).client { client }
19
+ end
20
+
21
+ describe "#wrap_with_optional_name" do
22
+ let(:name_made_optional) { true }
23
+ let(:wrapped) { mock! }
24
+
25
+ subject { plugin.send(:wrap_with_optional_name, name_made_optional, wrapped, inputs) }
26
+
27
+ context "when --all is given" do
28
+ let(:inputs_hash) { { :all => true } }
29
+
30
+ it "skips all manifest-related logic, and invokes the command" do
31
+ mock(wrapped).call
32
+ dont_allow(plugin).show_manifest_usage
33
+ subject
34
+ end
35
+ end
36
+
37
+ context "when there is no manifest" do
38
+ let(:manifest) { nil }
39
+
40
+ context "and an app is given" do
41
+ let(:given_hash) { { :app => "foo" } }
42
+
43
+ it "passes through to the command" do
44
+ mock(wrapped).call
45
+ dont_allow(plugin).show_manifest_usage
46
+ subject
47
+ end
48
+ end
49
+
50
+ context "and an app is NOT given" do
51
+ let(:inputs_hash) { {} }
52
+
53
+ context "and we made it optional" do
54
+ it "fails manually" do
55
+ mock(plugin).no_apps
56
+ subject
57
+ end
58
+ end
59
+
60
+ context "and we did NOT make it optional" do
61
+ let(:name_made_optional) { false }
62
+
63
+ it "passes through to the command" do
64
+ mock(wrapped).call
65
+ dont_allow(plugin).show_manifest_usage
66
+ subject
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context "when there is a manifest" do
73
+ let(:manifest_file) { "/abc/manifest.yml" }
74
+
75
+ before do
76
+ stub(plugin).show_manifest_usage
77
+ end
78
+
79
+ context "when no apps are given" do
80
+ context "and the user's working directory matches a particular app in the manifest" do
81
+ let(:manifest) { { :applications => [{ :name => "foo", :path => "/abc/foo" }] } }
82
+
83
+ it "calls the command for only that app" do
84
+ mock(wrapped).call(anything) do |inputs|
85
+ expect(inputs.given[:app]).to eq "foo"
86
+ end
87
+
88
+ stub(Dir).pwd { "/abc/foo" }
89
+
90
+ subject
91
+ end
92
+ end
93
+
94
+ context "and the user's working directory isn't in the manifest" do
95
+ let(:manifest) { { :applications => [{ :name => "foo" }, { :name => "bar" }] } }
96
+
97
+ it "calls the command for all apps in the manifest" do
98
+ uncalled_apps = ["foo", "bar"]
99
+ mock(wrapped).call(anything).twice do |inputs|
100
+ uncalled_apps.delete inputs.given[:app]
101
+ end
102
+
103
+ subject
104
+
105
+ expect(uncalled_apps).to be_empty
106
+ end
107
+ end
108
+ end
109
+
110
+ context "when any of the given apps are not in the manifest" do
111
+ let(:manifest) { { :applications => [{ :name => "a" }, { :name => "b" }] } }
112
+
113
+ context "and --apps is given" do
114
+ let(:given_hash) { { :apps => ["x", "a"] } }
115
+
116
+ it "passes through to the original command" do
117
+ mock(plugin).show_manifest_usage
118
+
119
+ uncalled_apps = ["a", "x"]
120
+ mock(wrapped).call(anything).twice do |inputs|
121
+ uncalled_apps.delete inputs.given[:app]
122
+ end
123
+
124
+ subject
125
+
126
+ expect(uncalled_apps).to be_empty
127
+ subject
128
+ end
129
+ end
130
+ end
131
+
132
+ context "when none of the given apps are in the manifest" do
133
+ let(:manifest) { { :applications => [{ :name => "a" }, { :name => "b" }] } }
134
+
135
+ context "and --apps is given" do
136
+ let(:given_hash) { { :apps => ["x", "y"] } }
137
+
138
+ it "passes through to the original command" do
139
+ dont_allow(plugin).show_manifest_usage
140
+ mock(wrapped).call
141
+ subject
142
+ end
143
+ end
144
+ end
145
+
146
+ context "when an app name that's in the manifest is given" do
147
+ let(:manifest) { { :applications => [{ :name => "foo" }] } }
148
+ let(:given_hash) { { :app => "foo" } }
149
+
150
+ it "calls the command with that app" do
151
+ mock(wrapped).call(anything) do |inputs|
152
+ expect(inputs.given[:app]).to eq "foo"
153
+ end
154
+
155
+ subject
156
+ end
157
+ end
158
+
159
+ context "when a path to an app that's in the manifest is given" do
160
+ let(:manifest) { { :applications => [{ :name => "foo", :path => "/abc/foo" }] } }
161
+ let(:given_hash) { { :app => "/abc/foo" } }
162
+
163
+ it "calls the command with that app" do
164
+ mock(wrapped).call(anything) do |inputs|
165
+ expect(inputs.given[:app]).to eq "foo"
166
+ end
167
+
168
+ subject
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ describe "#wrap_push" do
175
+ let(:wrapped) { mock! }
176
+ let(:command) { Mothership.commands[:push] }
177
+
178
+ subject { plugin.send(:wrap_push, wrapped, inputs) }
179
+
180
+ before do
181
+ stub(plugin).show_manifest_usage
182
+ end
183
+
184
+ context "with a manifest" do
185
+ let(:manifest_file) { "/abc/manifest.yml" }
186
+
187
+ let(:manifest) do
188
+ { :applications => [
189
+ { :name => "a",
190
+ :path => "/abc/a",
191
+ :instances => "200",
192
+ :memory => "128M"
193
+ }
194
+ ]
195
+ }
196
+ end
197
+
198
+ # cf push foo
199
+ context "and a name is given" do
200
+ context "and the name is present in the manifest" do
201
+ let(:given_hash) { { :name => "a" } }
202
+
203
+ context "and the app exists" do
204
+ let(:app) { fake :app, :name => "a" }
205
+ let(:client) { fake_client :apps => [app] }
206
+
207
+ context "and --reset was given" do
208
+ let(:inputs_hash) { { :reset => true } }
209
+ let(:given_hash) { { :name => "a", :instances => "100" } }
210
+
211
+ it "rebases their inputs on the manifest's values" do
212
+ mock(wrapped).call(anything) do |inputs|
213
+ expect(inputs.given).to eq(
214
+ :name => "a", :path => "/abc/a", :instances => "100", :memory => "128M")
215
+ end
216
+
217
+ subject
218
+ end
219
+ end
220
+ end
221
+
222
+ context "and the app does NOT exist" do
223
+ it "pushes a new app with the inputs from the manifest" do
224
+ mock(wrapped).call(anything) do |inputs|
225
+ expect(inputs.given).to eq(
226
+ :name => "a", :path => "/abc/a", :instances => "200", :memory => "128M")
227
+ end
228
+
229
+ subject
230
+ end
231
+ end
232
+ end
233
+
234
+ context "and the name is NOT present in the manifest" do
235
+ let(:given_hash) { { :name => "x" } }
236
+
237
+ it "fails, saying that name was not found in the manifest" do
238
+ expect { subject }.to raise_error(CF::UserError, /Could not find .+ in the manifest./)
239
+ end
240
+ end
241
+ end
242
+
243
+ # cf push ./abc
244
+ context "and a path is given" do
245
+ context "and there are apps matching that path in the manifest" do
246
+ let(:manifest) do
247
+ { :applications => [
248
+ { :name => "a",
249
+ :path => "/abc/a",
250
+ :instances => "200",
251
+ :memory => "128M"
252
+ },
253
+ { :name => "b",
254
+ :path => "/abc/a",
255
+ :instances => "200",
256
+ :memory => "128M"
257
+ }
258
+ ]
259
+ }
260
+ end
261
+
262
+ let(:given_hash) { { :name => "/abc/a" } }
263
+
264
+ it "pushes the found apps" do
265
+ pushed_apps = []
266
+ mock(wrapped).call(anything).twice do |inputs|
267
+ pushed_apps << inputs[:name]
268
+ end
269
+
270
+ subject
271
+
272
+ expect(pushed_apps).to eq(["a", "b"])
273
+ end
274
+ end
275
+
276
+ context "and there are NOT apps matching that path in the manifest" do
277
+ let(:given_hash) { { :name => "/abc/x" } }
278
+
279
+ it "fails, saying that the path was not found in the manifest" do
280
+ expect { subject }.to raise_error(CF::UserError, /Path .+ is not present in manifest/)
281
+ end
282
+ end
283
+ end
284
+ end
285
+
286
+ context "without a manifest" do
287
+ let(:app) { mock! }
288
+ let(:manifest) { nil }
289
+
290
+ it "asks to save the manifest when uploading the application" do
291
+ mock_ask("Save configuration?", :default => false)
292
+ stub(wrapped).call { plugin.filter(:push_app, app) }
293
+ subject
294
+ end
295
+ end
296
+ end
297
+
298
+ describe "#push_input_for" do
299
+ context "with an existing app" do
300
+ before do
301
+ stub(plugin).from_manifest { "PATH" }
302
+ app.changes.clear
303
+ end
304
+
305
+ let(:client) { fake_client(:apps => [app]) }
306
+ let(:manifest_memory) { "256M" }
307
+ let(:app) { fake :app, :name => "a", :memory => 256 }
308
+ let(:manifest) { { :name => "a", :memory => manifest_memory } }
309
+
310
+ subject { plugin.send(:push_input_for, manifest, inputs) }
311
+
312
+ context "with --reset" do
313
+ let(:inputs_hash) { { :reset => true } }
314
+
315
+ context "with changes" do
316
+ let(:manifest_memory) { "128M" }
317
+
318
+ it "applies the changes" do
319
+ subject[:memory].should == "128M"
320
+ end
321
+
322
+ it "does not ask to set --reset" do
323
+ dont_allow(plugin).warn_reset_changes
324
+ subject
325
+ end
326
+ end
327
+
328
+ context "without changes" do
329
+ it "does not ask to set --reset" do
330
+ dont_allow(plugin).warn_reset_changes
331
+ subject
332
+ end
333
+ end
334
+ end
335
+
336
+ context "without --reset" do
337
+ let(:inputs_hash) { {} }
338
+
339
+ context "with changes" do
340
+ let(:manifest_memory) { "128M" }
341
+
342
+ it "asks user to provide --reset" do
343
+ mock(plugin).warn_reset_changes
344
+ subject
345
+ end
346
+
347
+ it "does not apply changes" do
348
+ stub(plugin).warn_reset_changes
349
+ subject[:memory].should == nil
350
+ end
351
+ end
352
+
353
+ context "without changes" do
354
+ it "does not ask to set --reset" do
355
+ dont_allow(plugin).warn_reset_changes
356
+ subject
357
+ end
358
+ end
359
+ end
360
+ end
361
+ end
362
+ end