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,474 @@
1
+ require "spec_helper"
2
+
3
+ module CF
4
+ describe CLI do
5
+ let(:context) { CF::CLI.new }
6
+ let(:command) { nil }
7
+
8
+ let(:fake_home_dir) { nil }
9
+ stub_home_dir_with { fake_home_dir }
10
+
11
+ describe "#wrap_errors" do
12
+ let(:inputs) { {} }
13
+
14
+ subject do
15
+ capture_output do
16
+ context.stub(:input) { inputs }
17
+ context.wrap_errors { action.call }
18
+ end
19
+ end
20
+
21
+ context "with a CFoundry::Timeout" do
22
+ let(:action) { proc { raise CFoundry::Timeout.new(123, "fizzbuzz") } }
23
+
24
+ it_behaves_like "an error that's obvious to the user", :with_message => "fizzbuzz"
25
+ end
26
+
27
+ context "with a UserError" do
28
+ let(:action) { proc { context.fail "foo bar" } }
29
+
30
+ it_behaves_like "an error that's obvious to the user",
31
+ :with_message => "foo bar"
32
+
33
+ it "saves it in the crashlog" do
34
+ context.should_receive(:log_error)
35
+ subject
36
+ end
37
+ end
38
+
39
+ context "with a UserFriendlyError" do
40
+ let(:action) { proc { raise CF::UserFriendlyError.new("user friendly") } }
41
+
42
+ it_behaves_like "an error that's obvious to the user",
43
+ :with_message => "user friendly"
44
+ end
45
+
46
+ context "with a CFoundry::StagingError" do
47
+ let(:exception) { CFoundry::StagingError.new("whatever", 170001, nil, nil) }
48
+ let(:action) { proc { raise exception } }
49
+ before { exception.should_receive(:backtrace).at_least(1).times.and_return([]) }
50
+
51
+ it "prints the message" do
52
+ subject
53
+ expect(stderr.string).to include "Application failed to stage"
54
+ end
55
+
56
+ it "sets the exit code to 1" do
57
+ context.should_receive(:exit_status).with(1)
58
+ subject
59
+ end
60
+
61
+ it "logs the error" do
62
+ context.should_receive(:log_error).with(anything)
63
+ subject
64
+ end
65
+ end
66
+
67
+ context "with a SystemExit" do
68
+ let(:action) { proc { exit 1 } }
69
+
70
+ it_behaves_like "an error that gets passed through",
71
+ :with_exception => SystemExit
72
+ end
73
+
74
+ context "with a Mothership::Error" do
75
+ let(:action) { proc { raise Mothership::Error } }
76
+
77
+ it_behaves_like "an error that gets passed through",
78
+ :with_exception => Mothership::Error
79
+ end
80
+
81
+ context "with an Interrupt" do
82
+ let(:action) { proc { raise Interrupt } }
83
+
84
+ it "sets the exit code to 130" do
85
+ context.should_receive(:exit_status).with(130)
86
+ subject
87
+ end
88
+ end
89
+
90
+ context "when CC can't decode the auth token" do
91
+ let(:action) { proc { raise CFoundry::InvalidAuthToken.new("foo bar") } }
92
+ let(:asked) { false }
93
+
94
+ before do
95
+ $cf_asked_auth = asked
96
+ end
97
+
98
+ it "tells the user they are not authenticated" do
99
+ subject
100
+ expect(stdout.string).to include "Invalid authentication token. Try logging in again with 'truck login'. If problems continue, please contact your Cloud Operator."
101
+ end
102
+
103
+ it "exits without attempting to login again" do
104
+ context.should_not_receive(:invoke)
105
+ subject
106
+ end
107
+ end
108
+
109
+ context "with a CFoundry authentication error" do
110
+ let(:action) { proc { raise CFoundry::Forbidden.new("foo bar") } }
111
+ let(:asked) { false }
112
+
113
+ before do
114
+ $cf_asked_auth = asked
115
+ end
116
+
117
+ it "tells the user they are not authenticated" do
118
+ context.stub(:invoke)
119
+ subject
120
+ expect(stdout.string).to include "Not authenticated! Try logging in:"
121
+ expect($cf_asked_auth).to be_true
122
+ end
123
+
124
+ it "asks the user to log in" do
125
+ context.should_receive(:invoke).with(:login)
126
+ subject
127
+ end
128
+
129
+ context "and after logging in they got another authentication error" do
130
+ let(:asked) { true }
131
+
132
+ it "does not ask them to log in" do
133
+ context.should_not_receive(:invoke)
134
+ subject
135
+ end
136
+
137
+ it_behaves_like "an error that's obvious to the user",
138
+ :with_message => "Denied: foo bar"
139
+ end
140
+ end
141
+
142
+ context "with a CFoundry API error" do
143
+ let(:error) { CFoundry::APIError.new("CC had a problem", 123) }
144
+ let(:action) { proc { raise error } }
145
+
146
+ it "prints the error message" do
147
+ subject
148
+ expect(stderr.string).to include "APIError: 123: CC had a problem"
149
+ end
150
+
151
+ it "does not include the crash log" do
152
+ subject
153
+ expect(stderr.string).to_not include "spec/cf/cli_spec.rb"
154
+ end
155
+ end
156
+
157
+ context "with an arbitrary exception" do
158
+ let(:error) { RuntimeError.new("ahhhh it's all broken!!!!") }
159
+ let(:action) { proc { raise error } }
160
+
161
+ it "prints the error message" do
162
+ subject
163
+ expect(stderr.string).to include "RuntimeError: ahhhh it's all broken!!!!"
164
+ end
165
+
166
+ it "prints the crash log" do
167
+ subject
168
+ expect(stderr.string).to include "spec/cf/cli_spec.rb"
169
+ end
170
+
171
+ it "sets the exit code to 1" do
172
+ context.should_receive(:exit_status).with(1)
173
+ subject
174
+ end
175
+
176
+ context "when we are debugging" do
177
+ let(:inputs) { {:debug => true} }
178
+
179
+ it_behaves_like "an error that gets passed through",
180
+ :with_exception => RuntimeError
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "#execute" do
186
+ let(:inputs) { {} }
187
+ let(:client) { build(:client) }
188
+
189
+ before do
190
+ stub_client
191
+ end
192
+
193
+ subject do
194
+ capture_output do
195
+ context.stub(:input) { inputs }
196
+ context.execute(command, [])
197
+ end
198
+ end
199
+
200
+ describe "token refreshing" do
201
+ let(:context) { TokenRefreshDummy.new }
202
+ let(:command) { Mothership.commands[:refresh_token] }
203
+ let(:auth_token) { CFoundry::AuthToken.new("old-header") }
204
+ let(:new_auth_token) { CFoundry::AuthToken.new("new-header") }
205
+
206
+ class TokenRefreshDummy < CF::CLI
207
+ class << self
208
+ attr_accessor :new_token
209
+ end
210
+
211
+ def precondition;
212
+ end
213
+
214
+ def refresh_token
215
+ if client
216
+ client.token = self.class.new_token
217
+ end
218
+ end
219
+ end
220
+
221
+ context "when there is a target" do
222
+ before do
223
+ TokenRefreshDummy.new_token = nil
224
+ client.token = auth_token
225
+ end
226
+
227
+ context "when the token refreshes" do
228
+ it "saves to the target file" do
229
+ TokenRefreshDummy.any_instance.stub(:target_info) { {} }
230
+ TokenRefreshDummy.any_instance.stub(:save_target_info).with(anything) do |info|
231
+ expect(info[:token]).to eq new_auth_token.auth_header
232
+ end
233
+
234
+ subject
235
+ end
236
+ end
237
+
238
+ context "but there is no token initially" do
239
+ let(:auth_token) { nil }
240
+
241
+ it "doesn't save the new token because something else probably did" do
242
+ context.should_not_receive(:save_target_info)
243
+ subject
244
+ end
245
+ end
246
+
247
+ context "and the token becomes nil" do
248
+ let(:new_auth_token) { nil }
249
+
250
+ it "doesn't save the nil token" do
251
+ context.should_not_receive(:save_target_info)
252
+ subject
253
+ end
254
+ end
255
+ end
256
+
257
+ context "when there is no target" do
258
+ let(:client) { nil }
259
+
260
+ it "doesn't try to compare the tokens" do
261
+ expect { subject }.to_not raise_error
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ describe "#log_error" do
268
+ subject do
269
+ context.log_error(exception)
270
+ File.read(File.expand_path(CF::CRASH_FILE))
271
+ end
272
+
273
+ context "when the exception is a normal error" do
274
+ let(:exception) do
275
+ error = StandardError.new("gemfiles are kinda hard")
276
+ error.set_backtrace(["fo/gems/bar", "baz quick"])
277
+ error
278
+ end
279
+
280
+ it { should include "Time of crash:" }
281
+ it { should include "gemfiles are kinda hard" }
282
+ it { should include "bar" }
283
+ it { should_not include "fo/gems/bar" }
284
+ it { should include "baz quick" }
285
+ end
286
+
287
+ context "when the exception is an APIError" do
288
+ let(:request) { {:method => "GET", :url => "http://api.cloudfoundry.com/foo", :headers => {}, :body => nil} }
289
+ let(:response) { {:status => 404, :body => "bar", :headers => {}} }
290
+ let(:exception) do
291
+ error = CFoundry::APIError.new(nil, nil, request, response)
292
+ error.set_backtrace(["fo/gems/bar", "baz quick"])
293
+ error
294
+ end
295
+
296
+ before do
297
+ response.stub(:body) { "Response Body" }
298
+ end
299
+
300
+ it { should include "REQUEST: " }
301
+ it { should include "RESPONSE: " }
302
+ end
303
+ end
304
+
305
+ describe "#client_target" do
306
+ subject { context.client_target }
307
+
308
+ context "when a ~/.truck/target exists" do
309
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
310
+
311
+ it "returns the target in that file" do
312
+ expect(subject).to eq "https://api.some-domain.com"
313
+ end
314
+ end
315
+
316
+ context "when no target file exists" do
317
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
318
+
319
+ it "returns nil" do
320
+ expect(subject).to eq nil
321
+ end
322
+ end
323
+ end
324
+
325
+ describe "#targets_info" do
326
+ subject { context.targets_info }
327
+
328
+ context "when a ~/.truck/tokens.yml exists" do
329
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
330
+
331
+ it "returns the file's contents as a hash" do
332
+ expect(subject).to eq({
333
+ "https://api.some-domain.com" => {
334
+ :token => "bearer some-token",
335
+ :version => 2
336
+ }
337
+ })
338
+ end
339
+ end
340
+
341
+ context "when no token file exists" do
342
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
343
+
344
+ it "returns an empty hash" do
345
+ expect(subject).to eq({})
346
+ end
347
+ end
348
+ end
349
+
350
+ describe "#target_info" do
351
+ subject { CF::CLI.new.target_info("https://api.some-domain.com") }
352
+
353
+ context "when a ~/.truck/tokens.yml exists" do
354
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
355
+
356
+ it "returns the info for the given url" do
357
+ expect(subject).to eq({
358
+ :token => "bearer some-token",
359
+ :version => 2
360
+ })
361
+ end
362
+ end
363
+
364
+ context "when no token file exists" do
365
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
366
+
367
+ it "returns an empty hash" do
368
+ expect(subject).to eq({})
369
+ end
370
+ end
371
+ end
372
+
373
+ describe "methods that update the token info" do
374
+ before do
375
+ context.stub(:targets_info) do
376
+ {
377
+ "https://api.some-domain.com" => {:token => "bearer token1"},
378
+ "https://api.some-other-domain.com" => {:token => "bearer token2"}
379
+ }
380
+ end
381
+ end
382
+
383
+ describe "#save_target_info" do
384
+ it "adds the given target info, and writes the result to ~/.truck/tokens.yml" do
385
+ context.save_target_info({:token => "bearer token3"}, "https://api.some-domain.com")
386
+ YAML.load_file(File.expand_path("~/.truck/tokens.yml")).should == {
387
+ "https://api.some-domain.com" => {:token => "bearer token3"},
388
+ "https://api.some-other-domain.com" => {:token => "bearer token2"}
389
+ }
390
+ end
391
+ end
392
+
393
+ describe "#remove_target_info" do
394
+ it "removes the given target, and writes the result to ~/.truck/tokens.yml" do
395
+ context.remove_target_info("https://api.some-domain.com")
396
+ YAML.load_file(File.expand_path("~/.truck/tokens.yml")).should == {
397
+ "https://api.some-other-domain.com" => {:token => "bearer token2"}
398
+ }
399
+ end
400
+ end
401
+ end
402
+
403
+ describe "#client" do
404
+ let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
405
+
406
+ before { context.stub(:input).and_return({}) }
407
+
408
+ describe "the client's token" do
409
+ it "constructs an AuthToken object with the data from the tokens.yml file" do
410
+ expect(context.client.token).to be_a(CFoundry::AuthToken)
411
+ expect(context.client.token.auth_header).to eq("bearer some-token")
412
+ end
413
+
414
+ it "does not assign an AuthToken on the client if there is no token stored" do
415
+ context.should_receive(:target_info).with("some-fake-target") { {:version => 2} }
416
+ expect(context.client("some-fake-target").token).to be_nil
417
+ end
418
+ end
419
+
420
+ describe "the client's version" do
421
+ it "uses the version stored in the yml file" do
422
+ expect(context.client.version).to eq(2)
423
+ end
424
+ end
425
+
426
+ context "with a cloud controller" do
427
+ before do
428
+ context.stub(:target_info) { {:version => 2} }
429
+ end
430
+
431
+ it "connects using the v2 api" do
432
+ expect(context.client).to be_a(CFoundry::V2::Client)
433
+ end
434
+
435
+ %w{https_proxy HTTPS_PROXY http_proxy HTTP_PROXY}.each do |variable|
436
+ proxy_name = variable.downcase.to_sym
437
+
438
+ context "when ENV['#{variable}'] is set" do
439
+ before { ENV[variable] = "http://lower.example.com:80" }
440
+ after { ENV.delete(variable) }
441
+
442
+ it "uses the #{proxy_name} proxy URI on the environment variable" do
443
+ expect(context.client.send(proxy_name)).to eq("http://lower.example.com:80")
444
+ end
445
+ end
446
+ end
447
+
448
+ context "when both input and environment variable are provided" do
449
+ before do
450
+ ENV["HTTPS_PROXY"] = "http://should.be.overwritten.example.com:80"
451
+ context.stub(:input) { {:https_proxy => "http://arg.example.com:80"} }
452
+ end
453
+
454
+ after { ENV.delete("HTTPS_PROXY") }
455
+
456
+ it "uses the provided https proxy URI" do
457
+ expect(context.client.https_proxy).to eq("http://arg.example.com:80")
458
+ end
459
+ end
460
+ end
461
+ end
462
+
463
+ describe "#sane_target_url" do
464
+ it "removes any trailing slashes" do
465
+ expect(context.sane_target_url("http://example.com/")).to eq "http://example.com"
466
+ expect(context.sane_target_url("https://example.com/")).to eq "https://example.com"
467
+ end
468
+
469
+ it "defaults to https when the given url has no http(s) scheme" do
470
+ expect(context.sane_target_url("example.com")).to eq "https://example.com"
471
+ end
472
+ end
473
+ end
474
+ end