trucker-cli 0.0.1

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.
Files changed (294) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +1277 -0
  3. data/Rakefile +13 -0
  4. data/bin/truck +18 -0
  5. data/lib/admin/README.md +30 -0
  6. data/lib/admin/curl.rb +59 -0
  7. data/lib/admin/guid.rb +89 -0
  8. data/lib/admin/plugin.rb +8 -0
  9. data/lib/admin/service_auth_token.rb +93 -0
  10. data/lib/admin/service_broker/add.rb +54 -0
  11. data/lib/admin/service_broker/remove.rb +33 -0
  12. data/lib/admin/service_broker/service_brokers.rb +29 -0
  13. data/lib/admin/service_broker/update.rb +60 -0
  14. data/lib/admin/set_quota.rb +44 -0
  15. data/lib/cf.rb +14 -0
  16. data/lib/cf/cli.rb +495 -0
  17. data/lib/cf/cli/app/app.rb +43 -0
  18. data/lib/cf/cli/app/apps.rb +87 -0
  19. data/lib/cf/cli/app/base.rb +72 -0
  20. data/lib/cf/cli/app/delete.rb +95 -0
  21. data/lib/cf/cli/app/deprecated.rb +11 -0
  22. data/lib/cf/cli/app/env.rb +99 -0
  23. data/lib/cf/cli/app/events.rb +45 -0
  24. data/lib/cf/cli/app/files.rb +137 -0
  25. data/lib/cf/cli/app/health.rb +26 -0
  26. data/lib/cf/cli/app/instances.rb +53 -0
  27. data/lib/cf/cli/app/logs.rb +76 -0
  28. data/lib/cf/cli/app/push.rb +104 -0
  29. data/lib/cf/cli/app/push/create.rb +108 -0
  30. data/lib/cf/cli/app/push/interactions.rb +90 -0
  31. data/lib/cf/cli/app/push/sync.rb +57 -0
  32. data/lib/cf/cli/app/rename.rb +35 -0
  33. data/lib/cf/cli/app/restart.rb +31 -0
  34. data/lib/cf/cli/app/scale.rb +63 -0
  35. data/lib/cf/cli/app/start.rb +175 -0
  36. data/lib/cf/cli/app/stats.rb +66 -0
  37. data/lib/cf/cli/app/stop.rb +27 -0
  38. data/lib/cf/cli/domain/base.rb +9 -0
  39. data/lib/cf/cli/domain/domains.rb +40 -0
  40. data/lib/cf/cli/domain/map.rb +55 -0
  41. data/lib/cf/cli/domain/unmap.rb +56 -0
  42. data/lib/cf/cli/help.rb +15 -0
  43. data/lib/cf/cli/interactive.rb +104 -0
  44. data/lib/cf/cli/login_requirements.rb +13 -0
  45. data/lib/cf/cli/organization/base.rb +12 -0
  46. data/lib/cf/cli/organization/create.rb +36 -0
  47. data/lib/cf/cli/organization/delete.rb +61 -0
  48. data/lib/cf/cli/organization/org.rb +45 -0
  49. data/lib/cf/cli/organization/orgs.rb +30 -0
  50. data/lib/cf/cli/organization/rename.rb +36 -0
  51. data/lib/cf/cli/populators/base.rb +16 -0
  52. data/lib/cf/cli/populators/organization.rb +32 -0
  53. data/lib/cf/cli/populators/populator_methods.rb +64 -0
  54. data/lib/cf/cli/populators/space.rb +33 -0
  55. data/lib/cf/cli/populators/target.rb +14 -0
  56. data/lib/cf/cli/route/base.rb +9 -0
  57. data/lib/cf/cli/route/delete.rb +28 -0
  58. data/lib/cf/cli/route/map.rb +68 -0
  59. data/lib/cf/cli/route/routes.rb +26 -0
  60. data/lib/cf/cli/route/unmap.rb +56 -0
  61. data/lib/cf/cli/service/base.rb +9 -0
  62. data/lib/cf/cli/service/bind.rb +43 -0
  63. data/lib/cf/cli/service/create.rb +158 -0
  64. data/lib/cf/cli/service/delete.rb +82 -0
  65. data/lib/cf/cli/service/rename.rb +35 -0
  66. data/lib/cf/cli/service/service.rb +40 -0
  67. data/lib/cf/cli/service/service_helper.rb +25 -0
  68. data/lib/cf/cli/service/service_instance_helper.rb +100 -0
  69. data/lib/cf/cli/service/services.rb +110 -0
  70. data/lib/cf/cli/service/unbind.rb +36 -0
  71. data/lib/cf/cli/space/base.rb +27 -0
  72. data/lib/cf/cli/space/create.rb +66 -0
  73. data/lib/cf/cli/space/delete.rb +55 -0
  74. data/lib/cf/cli/space/rename.rb +38 -0
  75. data/lib/cf/cli/space/space.rb +66 -0
  76. data/lib/cf/cli/space/spaces.rb +57 -0
  77. data/lib/cf/cli/space/switch.rb +18 -0
  78. data/lib/cf/cli/start/base.rb +35 -0
  79. data/lib/cf/cli/start/colors.rb +13 -0
  80. data/lib/cf/cli/start/login.rb +104 -0
  81. data/lib/cf/cli/start/logout.rb +17 -0
  82. data/lib/cf/cli/start/target.rb +50 -0
  83. data/lib/cf/cli/start/target_prettifier.rb +35 -0
  84. data/lib/cf/cli/start/targets.rb +16 -0
  85. data/lib/cf/cli/user/base.rb +29 -0
  86. data/lib/cf/cli/user/create.rb +51 -0
  87. data/lib/cf/cli/user/passwd.rb +36 -0
  88. data/lib/cf/cli/user/register.rb +42 -0
  89. data/lib/cf/cli/user/users.rb +32 -0
  90. data/lib/cf/constants.rb +10 -0
  91. data/lib/cf/errors.rb +19 -0
  92. data/lib/cf/plugin.rb +56 -0
  93. data/lib/cf/spacing.rb +89 -0
  94. data/lib/cf/spec_helper.rb +1 -0
  95. data/lib/cf/test_support.rb +6 -0
  96. data/lib/cf/version.rb +3 -0
  97. data/lib/console/README.md +16 -0
  98. data/lib/console/console.rb +187 -0
  99. data/lib/console/plugin.rb +32 -0
  100. data/lib/manifests/errors.rb +35 -0
  101. data/lib/manifests/loader.rb +31 -0
  102. data/lib/manifests/loader/builder.rb +39 -0
  103. data/lib/manifests/loader/normalizer.rb +145 -0
  104. data/lib/manifests/loader/resolver.rb +79 -0
  105. data/lib/manifests/manifests.rb +343 -0
  106. data/lib/manifests/plugin.rb +140 -0
  107. data/lib/micro/README.md +25 -0
  108. data/lib/micro/errors.rb +4 -0
  109. data/lib/micro/micro.rb +56 -0
  110. data/lib/micro/plugin.rb +197 -0
  111. data/lib/micro/switcher/base.rb +79 -0
  112. data/lib/micro/switcher/darwin.rb +21 -0
  113. data/lib/micro/switcher/dummy.rb +15 -0
  114. data/lib/micro/switcher/linux.rb +16 -0
  115. data/lib/micro/switcher/windows.rb +31 -0
  116. data/lib/micro/vmrun.rb +175 -0
  117. data/lib/tasks/gem_release.rake +56 -0
  118. data/lib/tasks/windows_build.rake +14 -0
  119. data/lib/tunnel/README.md +29 -0
  120. data/lib/tunnel/config/clients.yml +17 -0
  121. data/lib/tunnel/helper-app/Gemfile +10 -0
  122. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  123. data/lib/tunnel/helper-app/server.rb +43 -0
  124. data/lib/tunnel/plugin.rb +183 -0
  125. data/lib/tunnel/tunnel.rb +295 -0
  126. data/spec/admin/curl_spec.rb +52 -0
  127. data/spec/admin/guid_spec.rb +85 -0
  128. data/spec/admin/service_broker/add_spec.rb +64 -0
  129. data/spec/admin/service_broker/remove_spec.rb +46 -0
  130. data/spec/admin/service_broker/service_brokers_spec.rb +34 -0
  131. data/spec/admin/service_broker/update_spec.rb +51 -0
  132. data/spec/admin/set_quota_spec.rb +89 -0
  133. data/spec/assets/env/Gemfile +4 -0
  134. data/spec/assets/env/Gemfile.lock +20 -0
  135. data/spec/assets/env/env_test.rb +58 -0
  136. data/spec/assets/hello-sinatra/Gemfile +3 -0
  137. data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
  138. data/spec/assets/hello-sinatra/config.ru +3 -0
  139. data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
  140. data/spec/assets/hello-sinatra/main.rb +8 -0
  141. data/spec/assets/rails328_ruby187_app/Gemfile +39 -0
  142. data/spec/assets/rails328_ruby187_app/README.rdoc +261 -0
  143. data/spec/assets/rails328_ruby187_app/Rakefile +7 -0
  144. data/spec/assets/rails328_ruby187_app/app/assets/images/rails.png +0 -0
  145. data/spec/assets/rails328_ruby187_app/app/assets/javascripts/application.js +15 -0
  146. data/spec/assets/rails328_ruby187_app/app/assets/stylesheets/application.css +13 -0
  147. data/spec/assets/rails328_ruby187_app/app/controllers/application_controller.rb +3 -0
  148. data/spec/assets/rails328_ruby187_app/app/helpers/application_helper.rb +2 -0
  149. data/spec/assets/rails328_ruby187_app/app/views/layouts/application.html.erb +14 -0
  150. data/spec/assets/rails328_ruby187_app/config.ru +4 -0
  151. data/spec/assets/rails328_ruby187_app/config/application.rb +62 -0
  152. data/spec/assets/rails328_ruby187_app/config/boot.rb +6 -0
  153. data/spec/assets/rails328_ruby187_app/config/database.yml +25 -0
  154. data/spec/assets/rails328_ruby187_app/config/environment.rb +5 -0
  155. data/spec/assets/rails328_ruby187_app/config/environments/development.rb +37 -0
  156. data/spec/assets/rails328_ruby187_app/config/environments/production.rb +67 -0
  157. data/spec/assets/rails328_ruby187_app/config/environments/test.rb +37 -0
  158. data/spec/assets/rails328_ruby187_app/config/initializers/backtrace_silencers.rb +7 -0
  159. data/spec/assets/rails328_ruby187_app/config/initializers/inflections.rb +15 -0
  160. data/spec/assets/rails328_ruby187_app/config/initializers/mime_types.rb +5 -0
  161. data/spec/assets/rails328_ruby187_app/config/initializers/secret_token.rb +7 -0
  162. data/spec/assets/rails328_ruby187_app/config/initializers/session_store.rb +8 -0
  163. data/spec/assets/rails328_ruby187_app/config/initializers/wrap_parameters.rb +14 -0
  164. data/spec/assets/rails328_ruby187_app/config/locales/en.yml +5 -0
  165. data/spec/assets/rails328_ruby187_app/config/routes.rb +58 -0
  166. data/spec/assets/rails328_ruby187_app/db/seeds.rb +7 -0
  167. data/spec/assets/rails328_ruby187_app/doc/README_FOR_APP +2 -0
  168. data/spec/assets/rails328_ruby187_app/manifest.yml +7 -0
  169. data/spec/assets/rails328_ruby187_app/public/404.html +26 -0
  170. data/spec/assets/rails328_ruby187_app/public/422.html +26 -0
  171. data/spec/assets/rails328_ruby187_app/public/500.html +25 -0
  172. data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css +0 -0
  173. data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css.gz +0 -0
  174. data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js +17 -0
  175. data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js.gz +0 -0
  176. data/spec/assets/rails328_ruby187_app/public/assets/application.css +0 -0
  177. data/spec/assets/rails328_ruby187_app/public/assets/application.css.gz +0 -0
  178. data/spec/assets/rails328_ruby187_app/public/assets/application.js +17 -0
  179. data/spec/assets/rails328_ruby187_app/public/assets/application.js.gz +0 -0
  180. data/spec/assets/rails328_ruby187_app/public/assets/manifest.yml +4 -0
  181. data/spec/assets/rails328_ruby187_app/public/assets/rails-be8732dac73d845ac5b142c8fb5f9fb0.png +0 -0
  182. data/spec/assets/rails328_ruby187_app/public/assets/rails.png +0 -0
  183. data/spec/assets/rails328_ruby187_app/public/favicon.ico +0 -0
  184. data/spec/assets/rails328_ruby187_app/public/index.html +241 -0
  185. data/spec/assets/rails328_ruby187_app/public/robots.txt +5 -0
  186. data/spec/assets/rails328_ruby187_app/script/rails +6 -0
  187. data/spec/assets/rails328_ruby187_app/test/performance/browsing_test.rb +12 -0
  188. data/spec/assets/rails328_ruby187_app/test/test_helper.rb +13 -0
  189. data/spec/cf/cli/app/base_spec.rb +17 -0
  190. data/spec/cf/cli/app/delete_spec.rb +197 -0
  191. data/spec/cf/cli/app/env_spec.rb +261 -0
  192. data/spec/cf/cli/app/events_spec.rb +72 -0
  193. data/spec/cf/cli/app/help_spec.rb +39 -0
  194. data/spec/cf/cli/app/instances_spec.rb +69 -0
  195. data/spec/cf/cli/app/push/create_spec.rb +444 -0
  196. data/spec/cf/cli/app/push/interactions_spec.rb +32 -0
  197. data/spec/cf/cli/app/push_spec.rb +332 -0
  198. data/spec/cf/cli/app/rename_spec.rb +108 -0
  199. data/spec/cf/cli/app/restart_spec.rb +47 -0
  200. data/spec/cf/cli/app/scale_spec.rb +63 -0
  201. data/spec/cf/cli/app/start_spec.rb +255 -0
  202. data/spec/cf/cli/app/stats_spec.rb +66 -0
  203. data/spec/cf/cli/domain/help_spec.rb +39 -0
  204. data/spec/cf/cli/domain/map_spec.rb +140 -0
  205. data/spec/cf/cli/domain/unmap_spec.rb +77 -0
  206. data/spec/cf/cli/help_spec.rb +21 -0
  207. data/spec/cf/cli/organization/create_spec.rb +121 -0
  208. data/spec/cf/cli/organization/delete_spec.rb +105 -0
  209. data/spec/cf/cli/organization/help_spec.rb +39 -0
  210. data/spec/cf/cli/organization/orgs_spec.rb +116 -0
  211. data/spec/cf/cli/organization/rename_spec.rb +116 -0
  212. data/spec/cf/cli/populators/organization_spec.rb +179 -0
  213. data/spec/cf/cli/populators/space_spec.rb +156 -0
  214. data/spec/cf/cli/populators/target_spec.rb +39 -0
  215. data/spec/cf/cli/route/delete_spec.rb +92 -0
  216. data/spec/cf/cli/route/help_spec.rb +32 -0
  217. data/spec/cf/cli/route/map_spec.rb +148 -0
  218. data/spec/cf/cli/route/unmap_spec.rb +114 -0
  219. data/spec/cf/cli/service/bind_spec.rb +25 -0
  220. data/spec/cf/cli/service/create_spec.rb +147 -0
  221. data/spec/cf/cli/service/delete_spec.rb +22 -0
  222. data/spec/cf/cli/service/help_spec.rb +39 -0
  223. data/spec/cf/cli/service/rename_spec.rb +103 -0
  224. data/spec/cf/cli/service/service_helper_spec.rb +66 -0
  225. data/spec/cf/cli/service/service_instance_helper_spec.rb +155 -0
  226. data/spec/cf/cli/service/service_spec.rb +23 -0
  227. data/spec/cf/cli/service/services_spec.rb +156 -0
  228. data/spec/cf/cli/service/unbind_spec.rb +25 -0
  229. data/spec/cf/cli/space/base_spec.rb +49 -0
  230. data/spec/cf/cli/space/create_spec.rb +144 -0
  231. data/spec/cf/cli/space/delete_spec.rb +109 -0
  232. data/spec/cf/cli/space/help_spec.rb +39 -0
  233. data/spec/cf/cli/space/rename_spec.rb +110 -0
  234. data/spec/cf/cli/space/space_spec.rb +80 -0
  235. data/spec/cf/cli/space/spaces_spec.rb +107 -0
  236. data/spec/cf/cli/space/switch_space_spec.rb +57 -0
  237. data/spec/cf/cli/start/help_spec.rb +39 -0
  238. data/spec/cf/cli/start/login_spec.rb +142 -0
  239. data/spec/cf/cli/start/logout_spec.rb +49 -0
  240. data/spec/cf/cli/start/target_prettifier_spec.rb +78 -0
  241. data/spec/cf/cli/start/target_spec.rb +123 -0
  242. data/spec/cf/cli/user/create_spec.rb +98 -0
  243. data/spec/cf/cli/user/help_spec.rb +32 -0
  244. data/spec/cf/cli/user/passwd_spec.rb +94 -0
  245. data/spec/cf/cli/user/register_spec.rb +145 -0
  246. data/spec/cf/cli_spec.rb +474 -0
  247. data/spec/console/console_spec.rb +189 -0
  248. data/spec/factories/cfoundry/v2/apps_factory.rb +12 -0
  249. data/spec/factories/cfoundry/v2/clients_factory.rb +7 -0
  250. data/spec/factories/cfoundry/v2/domains_factory.rb +8 -0
  251. data/spec/factories/cfoundry/v2/managed_service_instances_factory.rb +13 -0
  252. data/spec/factories/cfoundry/v2/organizations_factory.rb +14 -0
  253. data/spec/factories/cfoundry/v2/quota_definitions.rb +13 -0
  254. data/spec/factories/cfoundry/v2/routes_factory.rb +8 -0
  255. data/spec/factories/cfoundry/v2/service_bindings_factory.rb +11 -0
  256. data/spec/factories/cfoundry/v2/service_brokers_factory.rb +11 -0
  257. data/spec/factories/cfoundry/v2/service_plans_factory.rb +17 -0
  258. data/spec/factories/cfoundry/v2/services_factory.rb +14 -0
  259. data/spec/factories/cfoundry/v2/spaces_factory.rb +13 -0
  260. data/spec/factories/cfoundry/v2/stacks_factory.rb +11 -0
  261. data/spec/factories/cfoundry/v2/user_provided_service_instances_factory.rb +12 -0
  262. data/spec/factories/cfoundry/v2/users_factory.rb +7 -0
  263. data/spec/features/backspace_spec.rb +46 -0
  264. data/spec/features/create_user_spec.rb +74 -0
  265. data/spec/features/delete_orphaned_service_spec.rb +64 -0
  266. data/spec/features/login_spec.rb +65 -0
  267. data/spec/features/manifests_spec.rb +86 -0
  268. data/spec/features/org_spec.rb +50 -0
  269. data/spec/features/push_flow_spec.rb +169 -0
  270. data/spec/features/service_brokers_spec.rb +173 -0
  271. data/spec/features/services_spec.rb +122 -0
  272. data/spec/features/space_spec.rb +107 -0
  273. data/spec/features/switching_targets_spec.rb +70 -0
  274. data/spec/manifests/errors_spec.rb +43 -0
  275. data/spec/manifests/loader/builder_spec.rb +80 -0
  276. data/spec/manifests/loader/normalizer_spec.rb +158 -0
  277. data/spec/manifests/manifests_spec.rb +335 -0
  278. data/spec/manifests/plugin_spec.rb +410 -0
  279. data/spec/micro/plugin_spec.rb +64 -0
  280. data/spec/spec_helper.rb +69 -0
  281. data/spec/support/cli_helper.rb +87 -0
  282. data/spec/support/config_helper.rb +15 -0
  283. data/spec/support/factory_girl.rb +6 -0
  284. data/spec/support/fake_home_dir.rb +55 -0
  285. data/spec/support/features_helper.rb +99 -0
  286. data/spec/support/interact_helper.rb +27 -0
  287. data/spec/support/matchers.rb +16 -0
  288. data/spec/support/mock_commands/mock_restart.rb +16 -0
  289. data/spec/support/mock_commands/mock_start.rb +17 -0
  290. data/spec/support/shared_examples/errors.rb +40 -0
  291. data/spec/support/shared_examples/input.rb +14 -0
  292. data/spec/tunnel/plugin_spec.rb +31 -0
  293. data/spec/tunnel/tunnel_spec.rb +54 -0
  294. metadata +814 -0
@@ -0,0 +1,261 @@
1
+ require "spec_helper"
2
+ require "cf/cli/app/env"
3
+
4
+ module CF
5
+ module App
6
+ describe Env do
7
+ before do
8
+ stub_client
9
+ end
10
+
11
+ describe '#set_env' do
12
+ let(:mock_restart_command) { MockRestartCommand.new }
13
+ let(:mock_start_command) { MockStartCommand.new }
14
+ let(:client) { build(:client) }
15
+ let(:app) { build(:app, client: client, name: 'puppies-r-us-website') }
16
+ let(:env) { Env.new(Mothership.commands[:set_env]) }
17
+
18
+ before do
19
+ client.stub(:app_by_name).and_return(app)
20
+ env.input = Mothership::Inputs.new(Mothership.commands[:set_env], env, inputs, {}, {})
21
+ end
22
+
23
+ context 'when name and value are specified' do
24
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value'} }
25
+
26
+ it 'updates the app with the new environment variable' do
27
+ expect(app.env['MY_LOVELY_SETTING']).to eq(nil)
28
+ expect(app).to receive(:update!) do
29
+ expect(app.env['MY_LOVELY_SETTING']).to eq('oh_what_a_value')
30
+ end
31
+
32
+ capture_output { env.set_env }
33
+ end
34
+ end
35
+
36
+ context "when the environment variable is specified with the 'VAR=VALUE' format" do
37
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING=oh_what_a_value'} }
38
+
39
+ it 'updates the app with the new environment variable' do
40
+ expect(app.env['MY_LOVELY_SETTING']).to eq(nil)
41
+ expect(app).to receive(:update!) do
42
+ expect(app.env['MY_LOVELY_SETTING']).to eq('oh_what_a_value')
43
+ end
44
+
45
+ capture_output { env.set_env }
46
+ end
47
+ end
48
+
49
+ describe "environment variable format" do
50
+ context "when the name has only letters, numbers, and underscores" do
51
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123', value: "oh_what_a_value"} }
52
+ it "gets the value from the input[:value]" do
53
+ expect(app.env['MY_LOVELY_SETTING123']).to eq(nil)
54
+ app.stub(:update!)
55
+
56
+ capture_output { env.set_env }
57
+ expect(app.env['MY_LOVELY_SETTING123']).to eq("oh_what_a_value")
58
+ end
59
+ end
60
+
61
+ context "when the name has one equal sign, and is otherwise valid" do
62
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value'} }
63
+ it "gets the value by parsing the name" do
64
+ expect(app.env['MY_LOVELY_SETTING123']).to eq(nil)
65
+ app.stub(:update!)
66
+
67
+ capture_output { env.set_env }
68
+ expect(app.env['MY_LOVELY_SETTING123']).to eq("oh_what_a_value")
69
+ end
70
+
71
+ context "but provides a value anyway" do
72
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value', value: 'my_other_value'} }
73
+
74
+ it "gives the user an error" do
75
+ capture_exceptional_output { env.set_env }
76
+ expect(error_output).to say "You attempted to specify the value of MY_LOVELY_SETTING123 twice."
77
+ end
78
+ end
79
+ end
80
+
81
+ context "when the name has more than one equal sign" do
82
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING123=oh_what_a_value=badbadbad'} }
83
+ it "gives the user an error" do
84
+ capture_exceptional_output { env.set_env }
85
+ expect(error_output).to say "Invalid format: environment variable definition contains too many occurences of '='"
86
+ end
87
+ end
88
+
89
+ context "when there are characters that are not letters, numbers, or underscores" do
90
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING1?#$=value'} }
91
+ it "raises an error" do
92
+ capture_exceptional_output { env.set_env }
93
+ expect(error_output).to say "Invalid format: environment variable names can only contain alphanumeric characters and underscores"
94
+ end
95
+ end
96
+
97
+ context "when the name starts with a number" do
98
+ let(:inputs) { {app: app, name: '1MY_LOVELY_SETTING', value: 'oh_what_a_value'} }
99
+ it "raises an error" do
100
+ capture_exceptional_output { env.set_env }
101
+ expect(error_output).to say "Invalid format: environment variable names cannot start with a number"
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'when the app is not started' do
107
+ context 'with the --restart flag' do
108
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: true} }
109
+ before { Start.stub(:new).and_return(mock_start_command) }
110
+
111
+ it 'starts the app' do
112
+ expect(app).to receive(:update!) do
113
+ expect(mock_start_command.started_apps).to be_empty
114
+ end
115
+
116
+ capture_output { env.set_env }
117
+ expect(output).to say "Your app was unstarted. Starting now."
118
+
119
+ expect(mock_start_command.started_apps).to eq [app]
120
+ end
121
+ end
122
+
123
+ context 'without the --restart flag' do
124
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: false} }
125
+
126
+ before do
127
+ app.stub(:update!)
128
+ end
129
+
130
+ it "suggests a 'truck push' to the user" do
131
+ capture_output { env.set_env }
132
+ expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
133
+ end
134
+ end
135
+ end
136
+
137
+ context 'when the app is already started' do
138
+ before do
139
+ app.stub(:started?) { true }
140
+ Restart.stub(:new).and_return(mock_restart_command)
141
+ end
142
+
143
+ context 'with the --restart flag' do
144
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: true} }
145
+
146
+ it 'restarts the app' do
147
+ expect(app).to receive(:update!) do
148
+ expect(mock_restart_command.restarted_apps).to be_empty
149
+ end
150
+
151
+ capture_output { env.set_env }
152
+
153
+ expect(mock_restart_command.restarted_apps).to eq([app])
154
+ end
155
+ end
156
+
157
+ context 'without the --restart flag' do
158
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', value: 'oh_what_a_value', restart: false} }
159
+ before do
160
+ app.stub(:update!)
161
+ end
162
+
163
+ it 'does not restart the app but suggests a cf push' do
164
+ capture_output { env.set_env }
165
+ expect(mock_restart_command.restarted_apps).to be_empty
166
+ expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ describe '#unset_env' do
173
+ let(:app) { build(:app, client: client, name: 'puppies-r-us-website', environment_json: {'MY_LOVELY_SETTING' => 'oh_so_lovely'}) }
174
+ let(:client) { build(:client) }
175
+ let(:env) { Env.new(Mothership.commands[:unset_env]) }
176
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING'} }
177
+ let(:mock_start_command) { MockStartCommand.new }
178
+ let(:mock_restart_command) { MockRestartCommand.new }
179
+
180
+ before do
181
+ env.input = Mothership::Inputs.new(Mothership.commands[:unset_env], env, inputs, {}, {})
182
+ end
183
+
184
+ it 'unsets the environment variable and updates the app' do
185
+ expect(app.env['MY_LOVELY_SETTING']).to eq('oh_so_lovely')
186
+ expect(app).to receive(:update!) do
187
+ expect(app.env['MY_LOVELY_SETTING']).to be_nil
188
+ end
189
+
190
+ capture_output { env.unset_env }
191
+ end
192
+
193
+ context 'when the app is not started' do
194
+ context 'with the --restart flag' do
195
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: true} }
196
+ before { Start.stub(:new).and_return(mock_start_command) }
197
+
198
+ it 'starts the app' do
199
+ expect(app).to receive(:update!) do
200
+ expect(mock_start_command.started_apps).to be_empty
201
+ end
202
+
203
+ capture_output { env.unset_env }
204
+ expect(output).to say "Your app was unstarted. Starting now."
205
+
206
+ expect(mock_start_command.started_apps).to eq [app]
207
+ end
208
+ end
209
+
210
+ context 'without the --restart flag' do
211
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING'} }
212
+
213
+ before do
214
+ app.stub(:update!)
215
+ end
216
+
217
+ it "suggests a 'truck push' to the user" do
218
+ capture_output { env.unset_env }
219
+ expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
220
+ end
221
+ end
222
+ end
223
+
224
+ context 'when the app is already started' do
225
+ before do
226
+ app.stub(:started?) { true }
227
+ Restart.stub(:new).and_return(mock_restart_command)
228
+ end
229
+
230
+ context 'with the --restart flag' do
231
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: true} }
232
+
233
+ it 'restarts the app' do
234
+ expect(app).to receive(:update!) do
235
+ expect(mock_restart_command.restarted_apps).to be_empty
236
+ end
237
+
238
+ capture_output { env.unset_env }
239
+
240
+ expect(mock_restart_command.restarted_apps).to eq([app])
241
+ end
242
+ end
243
+
244
+ context 'without the --restart flag' do
245
+ let(:inputs) { {app: app, name: 'MY_LOVELY_SETTING', restart: false} }
246
+ before do
247
+ app.stub(:update!)
248
+ end
249
+
250
+ it 'does not restart the app but suggests a cf push' do
251
+ capture_output { env.unset_env }
252
+ expect(mock_restart_command.restarted_apps).to be_empty
253
+ expect(output).to say "TIP: Use 'truck push' to ensure your env variable changes take effect."
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end
261
+
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+
3
+ module CF
4
+ module App
5
+ describe Events do
6
+ let(:global) { {} }
7
+ let(:given) { {} }
8
+ let(:inputs) { {:app => apps[0]} }
9
+ let(:apps) { [build(:app)] }
10
+
11
+ before do
12
+ inputs[:app].stub(:events) do
13
+ [double("AppEvent", {
14
+ :instance_guid => "some_guid",
15
+ :instance_index => 1,
16
+ :exit_status => -1,
17
+ :exit_description => "Something very interesting",
18
+ :timestamp => "2013-05-15 18:52:17 +0000" }),
19
+ double("AppEvent", {
20
+ :instance_guid => "some_other_guid",
21
+ :instance_index => 0,
22
+ :exit_status => 0,
23
+ :exit_description => "Something less interesting",
24
+ :timestamp => "2013-05-15 18:52:15 +0000" })]
25
+ end
26
+ end
27
+
28
+ subject do
29
+ capture_output { Mothership.new.invoke(:events, inputs, given, global) }
30
+ end
31
+
32
+ describe "metadata" do
33
+ let(:command) { Mothership.commands[:events] }
34
+
35
+ describe "command" do
36
+ subject { command }
37
+ its(:description) { should eq "Display application events" }
38
+ it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
39
+ end
40
+
41
+ include_examples "inputs must have descriptions"
42
+
43
+ describe "arguments" do
44
+ subject { command.arguments }
45
+ it "has arguments that are not needed with a manifest" do
46
+ should eq([:name => :app, :type => :optional, :value => nil])
47
+ end
48
+ end
49
+ end
50
+
51
+ it "prints out progress" do
52
+ subject
53
+ stdout.rewind
54
+ expect(stdout.readlines.first).to match /Getting events for #{apps.first.name}/
55
+ end
56
+
57
+ it "prints out headers" do
58
+ subject
59
+ stdout.rewind
60
+ expect(stdout.readlines[2]).to match /time\s+instance\s+index\s+description\s+exit\s+status/
61
+ end
62
+
63
+ it "prints out the events in order" do
64
+ subject
65
+ stdout.rewind
66
+ expect(stdout.readlines[3]).to match /.*2013-05-15 18:52:15 \+0000\s+0\s+Something less interesting\s+Success \(0\).*/
67
+ stdout.rewind
68
+ expect(stdout.readlines[4]).to match /.*2013-05-15 18:52:17 \+0000\s+1\s+Something very interesting\s+Failure \(-1\).*/
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ module CF
4
+ module App
5
+ describe "Help" do
6
+ let(:global) { {} }
7
+ let(:given) { {} }
8
+
9
+ subject do
10
+ capture_output { Mothership.new.invoke(:help, :command => "app") }
11
+ end
12
+
13
+ it "describes the command" do
14
+ subject
15
+ stdout.rewind
16
+ expect(stdout.readlines.first).to match /Show app information/
17
+ end
18
+
19
+ it "prints the options" do
20
+ subject
21
+ stdout.rewind
22
+ expect(stdout.readlines.any? {|line| line =~ /Options:/ }).to be_true
23
+
24
+ end
25
+
26
+ context "when the user is not logged in" do
27
+ before do
28
+ capture_output { Mothership.new.invoke(:logout) }
29
+ end
30
+
31
+ it "does not require login" do
32
+ subject
33
+ stdout.rewind
34
+ expect(stdout.readlines.first).to_not match /Please log in first to proceed/
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+ require "stringio"
3
+
4
+ module CF
5
+ module App
6
+ describe Stats do
7
+ let(:global) { {:color => false} }
8
+ let(:inputs) { {:app => apps[0]} }
9
+ let(:given) { {} }
10
+ let(:client) { build(:client) }
11
+ let(:apps) { [build(:app, :client => client, :name => "basic-app-name")] }
12
+ let(:time) { Time.local(2012, 11, 1, 2, 30) }
13
+
14
+ before do
15
+ client.stub(:apps).and_return(apps)
16
+ CF::CLI.any_instance.stub(:client).and_return(client)
17
+ CF::CLI.any_instance.stub(:precondition).and_return(nil)
18
+
19
+ client.base.stub(:instances).with(anything) do
20
+ {
21
+ "12" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
22
+ "1" => {:state => "STOPPED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"},
23
+ "2" => {:state => "STARTED", :since => time.to_i, :debug_ip => "foo", :debug_port => "bar", :console_ip => "baz", :console_port => "qux"}
24
+ }
25
+ end
26
+ end
27
+
28
+ subject do
29
+ capture_output do
30
+ Mothership.new.invoke(:instances, inputs, given, global)
31
+ end
32
+ end
33
+
34
+ describe "metadata" do
35
+ let(:command) { Mothership.commands[:instances] }
36
+
37
+ describe "command" do
38
+ subject { command }
39
+ its(:description) { should eq "List an app's instances" }
40
+ it { expect(Mothership::Help.group(:apps, :info)).to include(subject) }
41
+ end
42
+
43
+ include_examples "inputs must have descriptions"
44
+
45
+ describe "arguments" do
46
+ subject { command.arguments }
47
+ it "has no arguments" do
48
+ should eq([{:type => :splat, :value => nil, :name => :apps}])
49
+ end
50
+ end
51
+ end
52
+
53
+ it "prints out the instances in the correct order" do
54
+ subject
55
+ expect(output).to say("instance #1")
56
+ expect(output).to say("instance #2")
57
+ expect(output).to say("instance #12")
58
+ end
59
+
60
+ it "prints out one of the instances correctly" do
61
+ subject
62
+ expect(output).to say("instance #2: started")
63
+ expect(output).to say(" started: #{time.strftime("%F %r")}")
64
+ expect(output).to say(" debugger: port bar at foo")
65
+ expect(output).to say(" console: port qux at baz")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,444 @@
1
+ require "spec_helper"
2
+
3
+ module CF
4
+ module App
5
+ describe Create do
6
+ let(:inputs) { {} }
7
+ let(:given) { {} }
8
+ let(:global) { {:color => false, :quiet => true} }
9
+
10
+ let(:service_instances) { Array.new(5) { build(:managed_service_instance) } }
11
+ let(:lucid64) { build(:stack, :name => "lucid64") }
12
+ let(:client) { build(:client) }
13
+
14
+ before do
15
+ CF::CLI.any_instance.stub(:client).and_return(client)
16
+ client.stub(:service_instances).and_return(service_instances)
17
+ client.stub(:stacks).and_return([lucid64])
18
+ end
19
+
20
+ let(:path) { "some-path" }
21
+
22
+
23
+ def setup_create
24
+ command = Mothership.commands[:push]
25
+ push_command = CF::App::Push.new(command)
26
+ push_command.path = path
27
+ push_command.input = Mothership::Inputs.new(command, push_command, inputs, given, global)
28
+ push_command.extend CF::App::PushInteractions
29
+ push_command
30
+ end
31
+
32
+ let(:push_command) { setup_create }
33
+
34
+ describe "#get_inputs" do
35
+ subject { push_command.get_inputs }
36
+
37
+ let(:given) do
38
+ {:name => "some-name",
39
+ :instances => "1",
40
+ :plan => "100",
41
+ :memory => "1G",
42
+ :command => "ruby main.rb",
43
+ :buildpack => "git://example.com",
44
+ :stack => "lucid64"
45
+ }
46
+ end
47
+
48
+ context "when all the inputs are given" do
49
+ its([:name]) { should eq "some-name" }
50
+ its([:total_instances]) { should eq 1 }
51
+ its([:space]) { should eq client.current_space }
52
+ its([:command]) { should eq "ruby main.rb" }
53
+ its([:memory]) { should eq 1024 }
54
+ its([:stack]) { should eq lucid64 }
55
+ end
56
+
57
+ context "when the command is given" do
58
+ context "and there is a Procfile in the application's root" do
59
+ before do
60
+ FakeFS.activate!
61
+ Dir.mkdir(path)
62
+
63
+ File.open("#{path}/Procfile", "w") do |file|
64
+ file.write("this is a procfile")
65
+ end
66
+ end
67
+
68
+ after do
69
+ FakeFS.deactivate!
70
+ FakeFS::FileSystem.clear
71
+ end
72
+
73
+ its([:command]) { should eq "ruby main.rb" }
74
+ end
75
+ end
76
+
77
+ context "when certain inputs are not given" do
78
+ it "asks for the name" do
79
+ given.delete(:name)
80
+ should_ask("Name") { "some-name" }
81
+ subject
82
+ end
83
+
84
+ it "asks for the total instances" do
85
+ given.delete(:instances)
86
+ should_ask("Instances", anything) { 1 }
87
+ subject
88
+ end
89
+
90
+ context "when the command is not given" do
91
+ before { given.delete(:command) }
92
+
93
+ it "defaults to nil" do
94
+ expect(subject[:command]).to be_nil
95
+ end
96
+
97
+ describe "getting the start command" do
98
+ before do
99
+ FakeFS.activate!
100
+ Dir.mkdir(path)
101
+ end
102
+
103
+ after do
104
+ FakeFS.deactivate!
105
+ FakeFS::FileSystem.clear
106
+ end
107
+
108
+ context "when there is a Procfile in the app's root" do
109
+ before do
110
+ File.open("#{path}/Procfile", "w") do |file|
111
+ file.write("this is a procfile")
112
+ end
113
+ end
114
+
115
+ it "does not ask for a start command" do
116
+ dont_allow_ask("Startup command")
117
+ subject
118
+ end
119
+ end
120
+
121
+ context "when there is no Procfile in the app's root" do
122
+ it "is nil" do
123
+ expect(subject[:command]).to be_nil
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ it "asks for the memory" do
130
+ given.delete(:memory)
131
+
132
+ memory_choices = %w(64M 128M 256M 512M 1G)
133
+ push_command.stub(:memory_choices).and_return(memory_choices)
134
+
135
+ should_ask("Memory Limit", anything) do |_, options|
136
+ expect(options[:choices]).to eq memory_choices
137
+ expect(options[:default]).to eq "256M"
138
+ "1G"
139
+ end
140
+
141
+ subject
142
+ end
143
+ end
144
+ end
145
+
146
+ describe "#create_app" do
147
+ before { dont_allow_ask }
148
+
149
+ let(:app) { double(:app, :name => "some-app").as_null_object }
150
+ let(:space) { double(:space, :name => "some-space") }
151
+
152
+ let(:attributes) do
153
+ {:name => "some-app",
154
+ :total_instances => 2,
155
+ :memory => 1024,
156
+ :buildpack => "git://example.com"
157
+ }
158
+ end
159
+
160
+ before do
161
+ client.stub(:app).and_return(app)
162
+ client.stub(:current_space).and_return(space)
163
+ end
164
+
165
+ subject { push_command.create_app(attributes) }
166
+
167
+ context "when the user does not have permission to create apps" do
168
+ it "fails with a friendly message" do
169
+ app.stub(:create!).and_raise(CFoundry::NotAuthorized, "foo")
170
+
171
+ expect { subject }.to raise_error(
172
+ CF::UserError,
173
+ "You need the Project Developer role in some-space to push.")
174
+ end
175
+ end
176
+
177
+ context "with an invalid buildpack" do
178
+ before do
179
+ app.stub(:create!) do
180
+ raise CFoundry::MessageParseError.new(
181
+ "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/",
182
+ 1001)
183
+ end
184
+ end
185
+
186
+ it "fails and prints a pretty message" do
187
+ push_command.stub(:line).with(anything)
188
+ expect { subject }.to raise_error(
189
+ CF::UserError, "Buildpack must be a public git repository URI.")
190
+ end
191
+ end
192
+ end
193
+
194
+ describe "#map_url" do
195
+ let(:app) { double(:app, :space => space, name: "app-name").as_null_object }
196
+ let(:space) { double(:space, :domains => domains) }
197
+ let(:domains) { [double(:domain, :name => "foo.com")] }
198
+ let(:hosts) { [app.name] }
199
+
200
+ subject { push_command.map_route(app) }
201
+
202
+ it "asks for a subdomain with 'none' as an option" do
203
+ should_ask("Subdomain", anything) do |_, options|
204
+ expect(options[:choices]).to eq(hosts + %w(none))
205
+ expect(options[:default]).to eq hosts.first
206
+ hosts.first
207
+ end
208
+
209
+ stub_ask("Domain", anything) { domains.first }
210
+
211
+ push_command.stub(:invoke)
212
+
213
+ subject
214
+ end
215
+
216
+ it "asks for a domain with 'none' as an option" do
217
+ stub_ask("Subdomain", anything) { hosts.first }
218
+
219
+ should_ask("Domain", anything) do |_, options|
220
+ expect(options[:choices]).to eq(domains + %w(none))
221
+ expect(options[:default]).to eq domains.first
222
+ domains.first
223
+ end
224
+
225
+ push_command.stub(:invoke)
226
+
227
+ subject
228
+ end
229
+
230
+ it "maps the host and domain after both are given" do
231
+ stub_ask("Subdomain", anything) { hosts.first }
232
+ stub_ask("Domain", anything) { domains.first }
233
+
234
+ push_command.should_receive(:invoke).with(:map,
235
+ :app => app, :host => hosts.first,
236
+ :domain => domains.first)
237
+
238
+ subject
239
+ end
240
+
241
+ context "when 'none' is given as the host" do
242
+ context "and a domain is provided afterwards" do
243
+ it "invokes 'map' with an empty host" do
244
+ should_ask("Subdomain", anything) { "none" }
245
+ stub_ask("Domain", anything) { domains.first }
246
+
247
+ push_command.should_receive(:invoke).with(:map,
248
+ :host => "", :domain => domains.first, :app => app)
249
+
250
+ subject
251
+ end
252
+ end
253
+ end
254
+
255
+ context "when 'none' is given as the domain" do
256
+ it "does not perform any mapping" do
257
+ stub_ask("Subdomain", anything) { "foo" }
258
+ should_ask("Domain", anything) { "none" }
259
+
260
+ push_command.should_not_receive(:invoke).with(:map, anything)
261
+
262
+ subject
263
+ end
264
+ end
265
+
266
+ context "when mapping fails" do
267
+ before do
268
+ should_ask("Subdomain", anything) { "foo" }
269
+ should_ask("Domain", anything) { domains.first }
270
+
271
+ push_command.should_receive(:invoke).with(:map,
272
+ :host => "foo", :domain => domains.first, :app => app) do
273
+ raise CFoundry::RouteHostTaken.new("foo", 1234)
274
+ end
275
+ end
276
+
277
+ it "asks again" do
278
+ push_command.stub(:line)
279
+
280
+ should_ask("Subdomain", anything) { hosts.first }
281
+ should_ask("Domain", anything) { domains.first }
282
+
283
+ push_command.stub(:invoke)
284
+
285
+ subject
286
+ end
287
+
288
+ it "reports the failure message" do
289
+ push_command.should_receive(:line).with("foo")
290
+ push_command.should_receive(:line)
291
+
292
+ stub_ask("Subdomain", anything) { hosts.first }
293
+ stub_ask("Domain", anything) { domains.first }
294
+
295
+ push_command.stub(:invoke)
296
+
297
+ subject
298
+ end
299
+ end
300
+ end
301
+
302
+ describe "#create_services" do
303
+ let(:app) { build(:app, :client => client) }
304
+ subject { push_command.create_services(app) }
305
+
306
+ context "when forcing" do
307
+ let(:inputs) { {:force => true} }
308
+
309
+ it "does not ask to create any services" do
310
+ dont_allow_ask("Create services for application?", anything)
311
+ subject
312
+ end
313
+
314
+ it "does not create any services" do
315
+ push_command.should_not_receive(:invoke).with(:create_service, anything)
316
+ subject
317
+ end
318
+ end
319
+
320
+ context "when not forcing" do
321
+ let(:inputs) { {:force => false} }
322
+
323
+ it "does not create the service if asked not to" do
324
+ should_ask("Create services for application?", anything) { false }
325
+ push_command.should_not_receive(:invoke).with(:create_service, anything)
326
+
327
+ subject
328
+ end
329
+
330
+ it "asks again to create a service" do
331
+ should_ask("Create services for application?", anything) { true }
332
+ push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
333
+
334
+ should_ask("Create another service?", :default => false) { true }
335
+ push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
336
+
337
+ should_ask("Create another service?", :default => false) { true }
338
+ push_command.should_receive(:invoke).with(:create_service, {:app => app}, :plan => :interact).ordered
339
+
340
+ should_ask("Create another service?", :default => false) { false }
341
+ push_command.should_not_receive(:invoke).with(:create_service, anything).ordered
342
+
343
+ subject
344
+ end
345
+ end
346
+ end
347
+
348
+ describe "#bind_services" do
349
+ let(:app) { double(:app).as_null_object }
350
+
351
+ subject { push_command.bind_services(app) }
352
+
353
+ context "when forcing" do
354
+ let(:global) { {:force => true, :color => false, :quiet => true} }
355
+
356
+ it "does not ask to bind any services" do
357
+ dont_allow_ask("Bind other services to application?", anything)
358
+ subject
359
+ end
360
+
361
+ it "does not bind any services" do
362
+ push_command.should_not_receive(:invoke).with(:bind_service, anything)
363
+ subject
364
+ end
365
+ end
366
+
367
+ context "when not forcing" do
368
+ it "does not bind the service if asked not to" do
369
+ should_ask("Bind other services to application?", anything) { false }
370
+ push_command.should_not_receive(:invoke).with(:bind_service, anything)
371
+
372
+ subject
373
+ end
374
+
375
+ it "asks again to bind a service" do
376
+ bind_times = 3
377
+ call_count = 0
378
+
379
+ should_ask("Bind other services to application?", anything) { true }
380
+
381
+ push_command.should_receive(:invoke).with(:bind_service, :app => app).exactly(bind_times).times do
382
+ call_count += 1
383
+ app.stub(:services).and_return(service_instances.first(call_count))
384
+ end
385
+
386
+ should_ask("Bind another service?", anything).exactly(bind_times).times do
387
+ call_count < bind_times
388
+ end
389
+
390
+ subject
391
+ end
392
+
393
+ it "stops asking if there are no more services to bind" do
394
+ bind_times = service_instances.size
395
+ call_count = 0
396
+
397
+ should_ask("Bind other services to application?", anything) { true }
398
+
399
+ push_command.should_receive(:invoke).with(:bind_service, :app => app).exactly(bind_times).times do
400
+ call_count += 1
401
+ app.stub(:services).and_return(service_instances.first(call_count))
402
+ end
403
+
404
+ should_ask("Bind another service?", anything).exactly(bind_times-1).times { true }
405
+
406
+ subject
407
+ end
408
+
409
+ context "when there are no services" do
410
+ let(:service_instances) { [] }
411
+
412
+ it "does not ask to bind anything" do
413
+ dont_allow_ask
414
+ subject
415
+ end
416
+ end
417
+ end
418
+ end
419
+
420
+ describe "#start_app" do
421
+ let(:app) { build(:app, :client => client) }
422
+ subject { push_command.start_app(app) }
423
+
424
+ context "when the start flag is provided" do
425
+ let(:inputs) { {:start => true} }
426
+
427
+ it "invokes the start command" do
428
+ push_command.should_receive(:invoke).with(:start, :app => app)
429
+ subject
430
+ end
431
+ end
432
+
433
+ context "when the start flag is not provided" do
434
+ let(:inputs) { {:start => false} }
435
+
436
+ it "invokes the start command" do
437
+ push_command.should_not_receive(:invoke).with(:start, anything)
438
+ subject
439
+ end
440
+ end
441
+ end
442
+ end
443
+ end
444
+ end