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,335 @@
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
+ manifest.stub(:client) { client }
13
+ manifest
14
+ end
15
+
16
+ let(:target_base) { "some-cloud.com" }
17
+
18
+ let(:foo) { build(:app, :name => "foo") }
19
+ let(:bar) { build(:app, :name => "bar") }
20
+ let(:baz) { build(:app, :name => "baz") }
21
+ let(:xxx) { build(:app, :name => "xxx") }
22
+ let(:yyy) { build(:app, :name => "yyy") }
23
+
24
+ let(:client) do
25
+ build(:client).tap { |client| client.stub(:apps => [foo, bar, baz, xxx, yyy]) }
26
+ end
27
+
28
+ let(:manifest_file) { "/abc/manifest.yml" }
29
+
30
+ before do
31
+ cmd.stub(:manifest) { manifest }
32
+ cmd.stub(:manifest_file) { manifest_file }
33
+ end
34
+
35
+ describe "#resolve_symbol" do
36
+ it "resolves target-base for old manifest files" do
37
+ cmd.stub(:target_base) { 'the_really_great_target_base' }
38
+ cmd.resolve_symbol("target-base").should == 'the_really_great_target_base'
39
+ end
40
+ end
41
+
42
+ describe "#find_apps" do
43
+ subject { cmd.find_apps(nil) }
44
+
45
+ context "when there is no manifest file" do
46
+ before { cmd.stub(:manifest).and_return(nil) }
47
+ it { should eq [] }
48
+ end
49
+ end
50
+
51
+ describe "#create_manifest_for" do
52
+ let(:app) do
53
+ build :app,
54
+ :memory => 2048,
55
+ :total_instances => 2,
56
+ :command => "ruby main.rb",
57
+ :buildpack => "git://example.com/foo.git",
58
+ :routes => [
59
+ build(:route,
60
+ :host => "some-app-name",
61
+ :domain => build(:domain, :name => target_base))
62
+ ],
63
+ :service_bindings => [
64
+ build(
65
+ :service_binding,
66
+ :service_instance =>
67
+ build(
68
+ :managed_service_instance,
69
+ :name => "service-1",
70
+ :service_plan =>
71
+ build(
72
+ :service_plan,
73
+ :name => "P200",
74
+ :service => build(:service,
75
+ label: "managed",
76
+ provider: "hamazon",
77
+ version: "v3"
78
+ )
79
+ )
80
+ )
81
+ ),
82
+ build(
83
+ :service_binding,
84
+ :service_instance =>
85
+ build(
86
+ :user_provided_service_instance,
87
+ :name => "service-2",
88
+ :credentials => { uri: "mysql://example.com" }
89
+ )
90
+ )
91
+ ]
92
+ end
93
+
94
+ subject { cmd.create_manifest_for(app, "some-path") }
95
+
96
+ its(["name"]) { should eq app.name }
97
+ its(["memory"]) { should eq "2G" }
98
+ its(["instances"]) { should eq 2 }
99
+ its(["path"]) { should eq "some-path" }
100
+ its(["host"]) { should eq "some-app-name" }
101
+ its(["domain"]) { should eq app.domain }
102
+ its(["command"]) { should eq "ruby main.rb" }
103
+ its(["buildpack"]) { should eq "git://example.com/foo.git" }
104
+
105
+ it "contains the service information" do
106
+ expect(subject["services"]).to eq(
107
+ "service-1" => {
108
+ "plan" => "P200",
109
+ "label" => "managed",
110
+ "provider" => "hamazon",
111
+ "version" => "v3",
112
+ },
113
+ "service-2" => {
114
+ "credentials" => {"uri" => "mysql://example.com"},
115
+ "label" => "user-provided"
116
+ },
117
+ )
118
+ end
119
+
120
+ context "with only minimum configuration" do
121
+ let(:app) {
122
+ build :app,
123
+ :memory => 2048,
124
+ :total_instances => 2,
125
+ :routes => [],
126
+ :service_bindings => []
127
+ }
128
+
129
+ its(["host"]) { should eq "none" }
130
+ its(["domain"]) { should eq "none" }
131
+ it { should_not include "command" }
132
+ it { should_not include "services" }
133
+ end
134
+ end
135
+
136
+ describe "#setup_services" do
137
+ let(:service_bindings) { [] }
138
+ let(:app) { build :app, :service_bindings => service_bindings }
139
+
140
+ before do
141
+ dont_allow_ask(anything, anything)
142
+ end
143
+
144
+ context "when user-provided services are defined in the manifest" do
145
+ let(:client) do
146
+ build(:client).tap { |client| client.stub(:services => [], :service_instances => []) }
147
+ end
148
+
149
+ let(:info) { {:services => {'moracle' => {:label => "user-provided", :credentials =>{"k" => "v"}}}}}
150
+
151
+ it "creates the service with label user-provided" do
152
+ cmd.should_receive(:invoke).with(:create_service,
153
+ :name => 'moracle', :offering => has_label("user-provided"), :app => app, :credentials => {"k" => "v"}
154
+ )
155
+ cmd.send("setup_services", app, info)
156
+ end
157
+ end
158
+
159
+ context "when services are defined in the manifest" do
160
+ let(:info) do
161
+ {:services => {"service-1" => {:label => "mysql", :plan => "100"}}}
162
+ end
163
+
164
+ let(:service_1) { build(:managed_service_instance, :name => "service-1") }
165
+ let(:plan_100) { build :service_plan, :name => "100" }
166
+
167
+ let(:mysql) do
168
+ build(
169
+ :service,
170
+ :label => "mysql",
171
+ :provider => "core",
172
+ :service_plans => [plan_100])
173
+ end
174
+
175
+ let(:service_instances) { [] }
176
+
177
+ let(:client) do
178
+ build(:client).tap { |client| client.stub(:services => [mysql], :service_instances => service_instances) }
179
+ end
180
+
181
+ context "and the services exist" do
182
+ let(:service_instances) { [service_1] }
183
+
184
+ context "and are already bound" do
185
+ let(:service_bindings) { [build(:service_binding, :service_instance => service_1)] }
186
+
187
+ it "does neither create nor bind the service again" do
188
+ cmd.should_not_receive(:invoke).with(:create_service, anything)
189
+ cmd.should_not_receive(:invoke).with(:bind_service, anything)
190
+ cmd.send(:setup_services, app, info)
191
+ end
192
+ end
193
+
194
+ context "but are not bound" do
195
+ it "does not create the services" do
196
+ cmd.should_not_receive(:invoke).with(:create_service, anything)
197
+ cmd.stub(:invoke).with(:bind_service, anything)
198
+ cmd.send(:setup_services, app, info)
199
+ end
200
+
201
+ it "binds the service" do
202
+ cmd.should_receive(:invoke).with(:bind_service, :app => app, :service => service_1)
203
+ cmd.send(:setup_services, app, info)
204
+ end
205
+ end
206
+ end
207
+
208
+ context "and the services do not exist" do
209
+ it "creates the services" do
210
+ cmd.should_receive(:invoke).with(:create_service, :app => app,
211
+ :name => service_1.name, :offering => mysql, :plan => plan_100)
212
+ cmd.should_not_receive(:invoke).with(:bind_service, anything)
213
+ cmd.send(:setup_services, app, info)
214
+ end
215
+ end
216
+ end
217
+
218
+ context "when there are no services defined" do
219
+ let(:info) { {} }
220
+
221
+ it "does not ask anything" do
222
+ cmd.send(:setup_services, app, info)
223
+ end
224
+ end
225
+ end
226
+
227
+ describe "#apps_in_manifest" do
228
+ let(:foo_hash) { {:name => "foo", :path => "/abc/foo"} }
229
+ let(:bar_hash) { {:name => "bar", :path => "/abc/bar"} }
230
+ let(:baz_hash) { {:name => "baz", :path => "/abc/baz"} }
231
+
232
+ let(:manifest) { {:applications => [foo_hash, bar_hash, baz_hash]} }
233
+
234
+ subject { cmd.apps_in_manifest(inputs) }
235
+
236
+ context "when no apps are passed" do
237
+ let(:given_hash) { {} }
238
+
239
+ its(:first) { should eq [] }
240
+ its(:last) { should eq [] }
241
+ end
242
+
243
+ context "when app names are passed" do
244
+ context "and all of them are in the manifest" do
245
+ let(:given_hash) { {:apps => ["foo", "bar"]} }
246
+
247
+ its(:first) { should eq [foo_hash, bar_hash] }
248
+ its(:last) { should eq [] }
249
+ end
250
+
251
+ context "and one of them is in the manifest" do
252
+ let(:given_hash) { {:apps => ["foo", "xxx"]} }
253
+
254
+ its(:first) { should eq [foo_hash] }
255
+ its(:last) { should eq ["xxx"] }
256
+ end
257
+
258
+ context "and none of them are in the manifest" do
259
+ let(:given_hash) { {:apps => ["xxx", "yyy"]} }
260
+
261
+ its(:first) { should eq [] }
262
+ its(:last) { should eq ["xxx", "yyy"] }
263
+ end
264
+ end
265
+
266
+ context "when apps are passed as paths" do
267
+ context "and the paths are in the manifest" do
268
+ let(:given_hash) { {:apps => ["/abc/foo"]} }
269
+
270
+ its(:first) { should eq [foo_hash] }
271
+ its(:last) { should eq [] }
272
+ end
273
+
274
+ context "and any path is not in the manifest" do
275
+ let(:given_hash) { {:apps => ["/abc/xxx"]} }
276
+
277
+ it "fails with a manifest-specific method (i.e. path not in manifest)" do
278
+ expect { subject }.to raise_error(CF::UserError, /Path .+ is not present in manifest/)
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ describe "#all_apps" do
285
+ let(:applications) do
286
+ [
287
+ {:name => "foo", :path => "/abc"},
288
+ {:name => "bar", :path => "/abc"},
289
+ {:name => "baz", :path => "/abc/baz"}
290
+ ]
291
+ end
292
+
293
+ let(:manifest) do
294
+ {:applications => applications}
295
+ end
296
+
297
+ subject { cmd.all_apps }
298
+
299
+ it "returns all of the apps described in the manifest, as hashes" do
300
+ expect(subject).to eq applications
301
+ end
302
+ end
303
+
304
+ describe "#current_apps" do
305
+ let(:manifest) do
306
+ {:applications => [
307
+ {:name => "foo", :path => "/abc"},
308
+ {:name => "bar", :path => "/abc"},
309
+ {:name => "baz", :path => "/abc/baz"}
310
+ ]}
311
+ end
312
+
313
+ subject { cmd.current_apps }
314
+
315
+ it "returns the applications with the cwd as their path" do
316
+ Dir.stub(:pwd) { "/abc" }
317
+ expect(subject).to eq [{:name => "foo", :path => "/abc"}, {:name => "bar", :path => "/abc"}]
318
+ end
319
+ end
320
+
321
+ describe "#check_manifest!" do
322
+
323
+ it "prints a warning if there is some unknown attribute" do
324
+ wrong_manifest_hash = {:applications => [{:bad_attr => 'boom'}]}
325
+ output = double('output')
326
+
327
+ msg = "\033[31mWarning: bad_attr is not a valid manifest attribute. "+
328
+ "Please remove this attribute from your manifest to get rid of this"+
329
+ " warning\033[0m"
330
+
331
+ output.should_receive(:puts).with(msg)
332
+ cmd.check_manifest!(wrong_manifest_hash, output)
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,410 @@
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) { build(:client) }
14
+
15
+ before do
16
+ plugin.stub(:manifest) { manifest }
17
+ plugin.stub(:manifest_file) { manifest_file } if manifest_file
18
+ plugin.stub(:client) { client }
19
+ end
20
+
21
+ describe ".use_manifest_for_app_input" do
22
+ it "makes the app argument optional and wraps it in an around that gets the app from the manifest" do
23
+ command = described_class.commands[:app]
24
+ command.instance_variable_set(:@arguments, [{:name => :app, :type => :required, :value => nil}])
25
+
26
+ expect(command.arguments).to eq [{:name => :app, :type => :required, :value => nil}]
27
+ expect(command.around.size).to eq 1
28
+
29
+ described_class.default_to_app_from_manifest :app, false
30
+
31
+ expect(command.arguments).to eq [{:name => :app, :type => :optional, :value => nil}]
32
+ expect(command.around.size).to eq 2
33
+ end
34
+ end
35
+
36
+ describe "#wrap_with_optional_name" do
37
+ let(:name_made_optional) { true }
38
+ let(:fail_without_app) { true }
39
+ let(:wrapped) { double(:wrapped).as_null_object }
40
+
41
+ subject { plugin.send(:wrap_with_optional_name, name_made_optional, wrapped, inputs, fail_without_app) }
42
+
43
+ context "when --all is given" do
44
+ let(:inputs_hash) { { :all => true } }
45
+
46
+ it "skips all manifest-related logic, and invokes the command" do
47
+ wrapped.should_receive(:call)
48
+ plugin.should_not_receive(:show_manifest_usage)
49
+ subject
50
+ end
51
+ end
52
+
53
+ context "when there is no manifest" do
54
+ let(:manifest) { nil }
55
+
56
+ context "and an app is given" do
57
+ let(:given_hash) { { :app => "foo" } }
58
+
59
+ it "passes through to the command" do
60
+ wrapped.should_receive(:call)
61
+ plugin.should_not_receive(:show_manifest_usage)
62
+ subject
63
+ end
64
+ end
65
+
66
+ context "and an app is NOT given" do
67
+ let(:inputs_hash) { {} }
68
+
69
+ context "and we made it optional" do
70
+ it "fails manually" do
71
+ plugin.should_receive(:no_apps)
72
+ subject
73
+ end
74
+
75
+ context "when it is not supposed to fail" do
76
+ let(:fail_without_app) { false }
77
+ it "doesnt fail" do
78
+ plugin.should_not_receive(:no_apps)
79
+ subject
80
+ end
81
+ end
82
+ end
83
+
84
+ context "and we did NOT make it optional" do
85
+ let(:name_made_optional) { false }
86
+
87
+ it "passes through to the command" do
88
+ wrapped.should_receive(:call)
89
+ plugin.should_not_receive(:show_manifest_usage)
90
+ subject
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ context "when there is a manifest" do
97
+ let(:manifest_file) { "/abc/manifest.yml" }
98
+
99
+ before do
100
+ plugin.stub(:show_manifest_usage)
101
+ end
102
+
103
+ context "when no apps are given" do
104
+ context "and the user's working directory matches a particular app in the manifest" do
105
+ let(:manifest) { { :applications => [{ :name => "foo", :path => "/abc/foo" }] } }
106
+
107
+ it "calls the command for only that app" do
108
+ wrapped.should_receive(:call).with(anything) do |inputs|
109
+ expect(inputs.given[:app]).to eq "foo"
110
+ end
111
+
112
+ Dir.stub(:pwd) { "/abc/foo" }
113
+
114
+ subject
115
+ end
116
+ end
117
+
118
+ context "and the user's working directory isn't in the manifest" do
119
+ let(:manifest) { { :applications => [{ :name => "foo" }, { :name => "bar" }] } }
120
+
121
+ it "calls the command for all apps in the manifest" do
122
+ uncalled_apps = ["foo", "bar"]
123
+ wrapped.should_receive(:call).with(anything).twice do |inputs|
124
+ uncalled_apps.delete inputs.given[:app]
125
+ end
126
+
127
+ subject
128
+
129
+ expect(uncalled_apps).to be_empty
130
+ end
131
+ end
132
+ end
133
+
134
+ context "when any of the given apps are not in the manifest" do
135
+ let(:manifest) { { :applications => [{ :name => "a" }, { :name => "b" }] } }
136
+
137
+ context "and --apps is given" do
138
+ let(:given_hash) { { :apps => ["x", "a"] } }
139
+
140
+ it "passes through to the original command" do
141
+ plugin.should_receive(:show_manifest_usage)
142
+
143
+ uncalled_apps = ["a", "x"]
144
+ wrapped.should_receive(:call).with(anything).twice do |inputs|
145
+ uncalled_apps.delete inputs.given[:app]
146
+ end
147
+
148
+ subject
149
+
150
+ expect(uncalled_apps).to be_empty
151
+ subject
152
+ end
153
+ end
154
+ end
155
+
156
+ context "when none of the given apps are in the manifest" do
157
+ let(:manifest) { { :applications => [{ :name => "a" }, { :name => "b" }] } }
158
+
159
+ context "and --apps is given" do
160
+ let(:given_hash) { { :apps => ["x", "y"] } }
161
+
162
+ it "passes through to the original command" do
163
+ wrapped.should_receive(:call)
164
+ plugin.should_not_receive(:show_manifest_usage)
165
+ subject
166
+ end
167
+ end
168
+ end
169
+
170
+ context "when an app name that's in the manifest is given" do
171
+ let(:manifest) { { :applications => [{ :name => "foo" }] } }
172
+ let(:given_hash) { { :app => "foo" } }
173
+
174
+ it "calls the command with that app" do
175
+ wrapped.should_receive(:call).with(anything) do |inputs|
176
+ expect(inputs.given[:app]).to eq "foo"
177
+ end
178
+
179
+ subject
180
+ end
181
+ end
182
+
183
+ context "when a path to an app that's in the manifest is given" do
184
+ let(:manifest) { { :applications => [{ :name => "foo", :path => "/abc/foo" }] } }
185
+ let(:given_hash) { { :app => "/abc/foo" } }
186
+
187
+ it "calls the command with that app" do
188
+ wrapped.should_receive(:call).with(anything) do |inputs|
189
+ expect(inputs.given[:app]).to eq "foo"
190
+ end
191
+
192
+ subject
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ describe "#wrap_push" do
199
+ let(:wrapped) { double(:wrapped).as_null_object }
200
+ let(:command) { Mothership.commands[:push] }
201
+
202
+ subject { plugin.send(:wrap_push, wrapped, inputs) }
203
+
204
+ before do
205
+ plugin.stub(:show_manifest_usage)
206
+ end
207
+
208
+ context "with a manifest" do
209
+ let(:manifest_file) { "/abc/manifest.yml" }
210
+
211
+ let(:manifest) do
212
+ { :applications => [
213
+ { :name => "a",
214
+ :path => "/abc/a",
215
+ :instances => "200",
216
+ :memory => "128M"
217
+ }
218
+ ]
219
+ }
220
+ end
221
+
222
+ # cf push foo
223
+ context "and a name is given" do
224
+ context "and the name is present in the manifest" do
225
+ let(:given_hash) { { :name => "a" } }
226
+ let(:app) { build :app, :name => "a" }
227
+
228
+ before do
229
+ client.stub(:apps => [app])
230
+ client.stub(:app_by_name).with("a").and_return(app)
231
+ end
232
+
233
+ context "and the app exists" do
234
+
235
+ context "and --reset was given" do
236
+ let(:inputs_hash) { { :reset => true } }
237
+ let(:given_hash) { { :name => "a", :instances => "100" } }
238
+
239
+ it "rebases their inputs on the manifest's values" do
240
+ wrapped.should_receive(:call).with(anything) do |inputs|
241
+ expect(inputs.given).to eq(
242
+ :name => "a", :path => "/abc/a", :instances => "100", :memory => "128M")
243
+ end
244
+
245
+ subject
246
+ end
247
+ end
248
+ end
249
+
250
+ context "and the app does NOT exist" do
251
+ let(:app) { nil }
252
+
253
+ it "pushes a new app with the inputs from the manifest" do
254
+ wrapped.should_receive(:call).with(anything) do |inputs|
255
+ expect(inputs.given).to eq(
256
+ :name => "a", :path => "/abc/a", :instances => "200", :memory => "128M")
257
+ end
258
+
259
+ subject
260
+ end
261
+ end
262
+ end
263
+
264
+ context "and the name is NOT present in the manifest" do
265
+ let(:given_hash) { { :name => "x" } }
266
+
267
+ it "fails, saying that name was not found in the manifest" do
268
+ expect { subject }.to raise_error(CF::UserError, /Could not find .+ in the manifest./)
269
+ end
270
+ end
271
+ end
272
+
273
+ # cf push ./abc
274
+ context "and a path is given" do
275
+ context "and there are apps matching that path in the manifest" do
276
+ before do
277
+ client.stub(:apps => [build(:app), build(:app)])
278
+ client.stub(:app_by_name)
279
+ end
280
+
281
+ let(:manifest) do
282
+ { :applications => [
283
+ { :name => "a",
284
+ :path => "/abc/a",
285
+ :instances => "200",
286
+ :memory => "128M"
287
+ },
288
+ { :name => "b",
289
+ :path => "/abc/a",
290
+ :instances => "200",
291
+ :memory => "128M"
292
+ }
293
+ ]
294
+ }
295
+ end
296
+
297
+ let(:given_hash) { { :name => "/abc/a" } }
298
+
299
+ it "pushes the found apps" do
300
+ pushed_apps = []
301
+ wrapped.should_receive(:call).with(anything).twice do |inputs|
302
+ pushed_apps << inputs[:name]
303
+ end
304
+
305
+ subject
306
+
307
+ expect(pushed_apps).to eq(["a", "b"])
308
+ end
309
+ end
310
+
311
+ context "and there are NOT apps matching that path in the manifest" do
312
+ let(:given_hash) { { :name => "/abc/x" } }
313
+
314
+ it "fails, saying that the path was not found in the manifest" do
315
+ expect { subject }.to raise_error(CF::UserError, /Path .+ is not present in manifest/)
316
+ end
317
+ end
318
+ end
319
+
320
+ context "and --path is specified too" do
321
+ let(:given_hash) { { :path => "/somewhere/else" } }
322
+
323
+ it "warns the user that --path will be ignored" do
324
+ plugin.stub(:line)
325
+ plugin.stub(:push_with_manifest)
326
+
327
+ subject
328
+
329
+ expect(plugin).to have_received(:line).with("--path is ignored when using a manifest. Please specify the path in the manifest.")
330
+ end
331
+ end
332
+ end
333
+
334
+ context "without a manifest" do
335
+ let(:app) { double(:app).as_null_object }
336
+ let(:manifest) { nil }
337
+
338
+ it "asks to save the manifest when uploading the application" do
339
+ should_ask("Save configuration?", :default => false)
340
+ wrapped.stub(:call) { plugin.filter(:push_app, app) }
341
+ subject
342
+ end
343
+ end
344
+ end
345
+
346
+ describe "#push_input_for" do
347
+ context "with an existing app" do
348
+ before do
349
+ plugin.stub(:from_manifest) { "PATH" }
350
+ app.changes.clear
351
+ client.stub(:apps => [app])
352
+ end
353
+
354
+ let(:manifest_memory) { "256M" }
355
+ let(:app) { build(:app, :name => "a", :memory => 256) }
356
+ let(:manifest) { { :name => "a", :memory => manifest_memory } }
357
+
358
+ subject { plugin.send(:push_input_for, manifest, inputs) }
359
+
360
+ context "with --reset" do
361
+ let(:inputs_hash) { { :reset => true } }
362
+
363
+ context "with changes" do
364
+ let(:manifest_memory) { "128M" }
365
+
366
+ it "applies the changes" do
367
+ subject[:memory].should == "128M"
368
+ end
369
+
370
+ it "does not ask to set --reset" do
371
+ plugin.should_not_receive(:warn_reset_changes)
372
+ subject
373
+ end
374
+ end
375
+
376
+ context "without changes" do
377
+ it "does not ask to set --reset" do
378
+ plugin.should_not_receive(:warn_reset_changes)
379
+ subject
380
+ end
381
+ end
382
+ end
383
+
384
+ context "without --reset" do
385
+ let(:inputs_hash) { {} }
386
+
387
+ context "with changes" do
388
+ let(:manifest_memory) { "128M" }
389
+
390
+ it "asks user to provide --reset" do
391
+ plugin.should_receive(:warn_reset_changes)
392
+ subject
393
+ end
394
+
395
+ it "does not apply changes" do
396
+ plugin.stub(:warn_reset_changes)
397
+ subject[:memory].should == nil
398
+ end
399
+ end
400
+
401
+ context "without changes" do
402
+ it "does not ask to set --reset" do
403
+ plugin.should_not_receive(:warn_reset_changes)
404
+ subject
405
+ end
406
+ end
407
+ end
408
+ end
409
+ end
410
+ end