engineyard-serverside 2.8.0.pre4 → 2.8.0

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/features/enable_maintenance/step_definitions/enable_maintenance_steps.rb +43 -0
  3. data/features/hook/running-a-deploy-hook.feature +277 -0
  4. data/features/hook/step_definitions/running-a-deploy-hook-steps.rb +200 -0
  5. data/features/step_definitions/app_steps.rb +10 -0
  6. data/features/step_definitions/command_steps.rb +8 -0
  7. data/features/step_definitions/server_steps.rb +14 -0
  8. data/features/step_definitions/version_steps.rb +5 -0
  9. data/features/support/env.rb +63 -0
  10. data/features/support/error_codes.rb +17 -0
  11. data/features/support/fs_helpers.rb +82 -0
  12. data/features/support/output_helpers.rb +7 -0
  13. data/features/support/runner.rb +41 -0
  14. data/features/version.feature +7 -0
  15. data/lib/engineyard-serverside/cli/app.rb +6 -0
  16. data/lib/engineyard-serverside/shell.rb +38 -10
  17. data/lib/engineyard-serverside/version.rb +1 -1
  18. data/spec/engineyard-serverside/callbacks/collection/combined_spec.rb +232 -0
  19. data/spec/engineyard-serverside/callbacks/collection/deploy_hooks_spec.rb +170 -0
  20. data/spec/engineyard-serverside/callbacks/collection/service_hooks/collection_spec.rb +171 -0
  21. data/spec/engineyard-serverside/callbacks/collection/service_hooks/combined_spec.rb +174 -0
  22. data/spec/engineyard-serverside/callbacks/collection/service_hooks_spec.rb +31 -0
  23. data/spec/engineyard-serverside/callbacks/collection_spec.rb +49 -0
  24. data/spec/engineyard-serverside/callbacks/distributor/remote_spec.rb +135 -0
  25. data/spec/engineyard-serverside/callbacks/distributor/viability_filter_spec.rb +208 -0
  26. data/spec/engineyard-serverside/callbacks/distributor_spec.rb +43 -0
  27. data/spec/engineyard-serverside/callbacks/executor/executable_spec.rb +386 -0
  28. data/spec/engineyard-serverside/callbacks/executor/ruby/context_spec.rb +538 -0
  29. data/spec/engineyard-serverside/callbacks/executor/ruby/executor_spec.rb +313 -0
  30. data/spec/engineyard-serverside/callbacks/executor/ruby_spec.rb +35 -0
  31. data/spec/engineyard-serverside/callbacks/executor_spec.rb +45 -0
  32. data/spec/engineyard-serverside/callbacks_spec.rb +31 -0
  33. data/spec/engineyard-serverside/cli/workflows/base_spec.rb +237 -0
  34. data/spec/engineyard-serverside/cli/workflows/calling_deploy_hooks_spec.rb +65 -0
  35. data/spec/engineyard-serverside/cli/workflows/deploying_applications_spec.rb +61 -0
  36. data/spec/engineyard-serverside/cli/workflows/disabling_maintenance_spec.rb +61 -0
  37. data/spec/engineyard-serverside/cli/workflows/enabling_maintenance_spec.rb +61 -0
  38. data/spec/engineyard-serverside/cli/workflows/helpers_spec.rb +64 -0
  39. data/spec/engineyard-serverside/cli/workflows/rolling_back_applications_spec.rb +61 -0
  40. data/spec/engineyard-serverside/cli/workflows/showing_maintenance_status_spec.rb +60 -0
  41. data/spec/engineyard-serverside/cli/workflows_spec.rb +87 -0
  42. data/spec/engineyard-serverside/dependency_manager/base_spec.rb +139 -0
  43. data/spec/engineyard-serverside/paths_spec.rb +820 -0
  44. data/spec/engineyard-serverside/propagator_spec.rb +56 -0
  45. data/spec/engineyard-serverside/server_spec.rb +390 -0
  46. data/spec/engineyard-serverside/shell/helpers_spec.rb +98 -0
  47. data/spec/engineyard-serverside/shell/yieldio_spec.rb +33 -0
  48. data/spec/engineyard-serverside/shell_spec.rb +543 -0
  49. data/spec/engineyard-serverside/slug/distributor_spec.rb +199 -0
  50. data/spec/engineyard-serverside/slug/enabler_spec.rb +191 -0
  51. data/spec/engineyard-serverside/slug/failure_handler_spec.rb +114 -0
  52. data/spec/engineyard-serverside/slug/finalizer_spec.rb +191 -0
  53. data/spec/engineyard-serverside/slug/generator_spec.rb +82 -0
  54. data/spec/engineyard-serverside/slug/migrator_spec.rb +137 -0
  55. data/spec/engineyard-serverside/slug/restarter_spec.rb +226 -0
  56. data/spec/engineyard-serverside/slug/source/updater_spec.rb +710 -0
  57. data/spec/engineyard-serverside/slug/source_spec.rb +40 -0
  58. data/spec/engineyard-serverside/source_spec.rb +171 -0
  59. data/spec/railway_spec.rb +130 -0
  60. data/spec/result/failure_spec.rb +113 -0
  61. data/spec/result/success_spec.rb +109 -0
  62. data/spec/result_spec.rb +23 -0
  63. data/spec/spec_helper.rb +3 -349
  64. metadata +182 -404
  65. data/spec/archive_deploy_spec.rb +0 -53
  66. data/spec/basic_deploy_spec.rb +0 -26
  67. data/spec/bundler_deploy_spec.rb +0 -160
  68. data/spec/configuration_spec.rb +0 -206
  69. data/spec/custom_deploy_spec.rb +0 -128
  70. data/spec/deploy_hook_spec.rb +0 -378
  71. data/spec/deprecation_spec.rb +0 -23
  72. data/spec/ey_yml_customized_deploy_spec.rb +0 -99
  73. data/spec/fixtures/gitrepo.tar.gz +0 -0
  74. data/spec/fixtures/invalid_hook.rb +0 -1
  75. data/spec/fixtures/lockfiles/0.9-no-bundler +0 -111
  76. data/spec/fixtures/lockfiles/0.9-with-bundler +0 -117
  77. data/spec/fixtures/lockfiles/1.0-no-bundler +0 -54
  78. data/spec/fixtures/lockfiles/1.0.0.rc.1-with-bundler +0 -162
  79. data/spec/fixtures/lockfiles/1.0.18-do_mysql +0 -88
  80. data/spec/fixtures/lockfiles/1.0.18-do_postgres +0 -79
  81. data/spec/fixtures/lockfiles/1.0.18-mysql +0 -43
  82. data/spec/fixtures/lockfiles/1.0.18-mysql2 +0 -43
  83. data/spec/fixtures/lockfiles/1.0.18-pg +0 -43
  84. data/spec/fixtures/lockfiles/1.0.6-no-bundler +0 -51
  85. data/spec/fixtures/lockfiles/1.0.6-with-any-bundler +0 -52
  86. data/spec/fixtures/lockfiles/1.0.6-with-bundler +0 -52
  87. data/spec/fixtures/lockfiles/1.15.1-no-bundler +0 -51
  88. data/spec/fixtures/lockfiles/1.3.1-rails-3.2.13 +0 -112
  89. data/spec/fixtures/lockfiles/not-a-lockfile +0 -1
  90. data/spec/fixtures/repos/assets_detected/Gemfile +0 -5
  91. data/spec/fixtures/repos/assets_detected/Gemfile.lock +0 -88
  92. data/spec/fixtures/repos/assets_detected/README +0 -1
  93. data/spec/fixtures/repos/assets_detected/Rakefile +0 -5
  94. data/spec/fixtures/repos/assets_detected/app/assets/empty +0 -0
  95. data/spec/fixtures/repos/assets_detected/config/application.rb +0 -5
  96. data/spec/fixtures/repos/assets_detected/config/ey.yml +0 -3
  97. data/spec/fixtures/repos/assets_disabled/Gemfile +0 -5
  98. data/spec/fixtures/repos/assets_disabled/Gemfile.lock +0 -88
  99. data/spec/fixtures/repos/assets_disabled/README +0 -1
  100. data/spec/fixtures/repos/assets_disabled/Rakefile +0 -6
  101. data/spec/fixtures/repos/assets_disabled/app/assets/empty +0 -0
  102. data/spec/fixtures/repos/assets_disabled/config/application.rb +0 -5
  103. data/spec/fixtures/repos/assets_disabled/config/ey.yml +0 -3
  104. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +0 -5
  105. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +0 -88
  106. data/spec/fixtures/repos/assets_disabled_in_ey_yml/README +0 -1
  107. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +0 -6
  108. data/spec/fixtures/repos/assets_disabled_in_ey_yml/app/assets/empty +0 -0
  109. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/application.rb +0 -5
  110. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +0 -5
  111. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile +0 -5
  112. data/spec/fixtures/repos/assets_disabled_utf8/Gemfile.lock +0 -88
  113. data/spec/fixtures/repos/assets_disabled_utf8/README +0 -3
  114. data/spec/fixtures/repos/assets_disabled_utf8/Rakefile +0 -5
  115. data/spec/fixtures/repos/assets_disabled_utf8/app/assets/empty +0 -0
  116. data/spec/fixtures/repos/assets_disabled_utf8/config/application.rb +0 -7
  117. data/spec/fixtures/repos/assets_disabled_utf8/config/ey.yml +0 -3
  118. data/spec/fixtures/repos/assets_enabled_all/Gemfile +0 -5
  119. data/spec/fixtures/repos/assets_enabled_all/Gemfile.lock +0 -88
  120. data/spec/fixtures/repos/assets_enabled_all/README +0 -1
  121. data/spec/fixtures/repos/assets_enabled_all/app/assets/empty +0 -0
  122. data/spec/fixtures/repos/assets_enabled_all/config/application.rb +0 -5
  123. data/spec/fixtures/repos/assets_enabled_all/config/ey.yml +0 -6
  124. data/spec/fixtures/repos/assets_enabled_all/script/assets +0 -5
  125. data/spec/fixtures/repos/assets_enabled_all/tmp/obstruction +0 -1
  126. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile +0 -3
  127. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile.lock +0 -10
  128. data/spec/fixtures/repos/assets_enabled_in_ey_yml/README +0 -1
  129. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +0 -8
  130. data/spec/fixtures/repos/assets_enabled_in_ey_yml/config/ey.yml +0 -4
  131. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile +0 -5
  132. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile.lock +0 -88
  133. data/spec/fixtures/repos/assets_enabled_util_only/README +0 -1
  134. data/spec/fixtures/repos/assets_enabled_util_only/Rakefile +0 -6
  135. data/spec/fixtures/repos/assets_enabled_util_only/app/assets/empty +0 -0
  136. data/spec/fixtures/repos/assets_enabled_util_only/config/application.rb +0 -5
  137. data/spec/fixtures/repos/assets_enabled_util_only/config/ey.yml +0 -6
  138. data/spec/fixtures/repos/assets_error/Gemfile +0 -5
  139. data/spec/fixtures/repos/assets_error/Gemfile.lock +0 -88
  140. data/spec/fixtures/repos/assets_error/README +0 -1
  141. data/spec/fixtures/repos/assets_error/Rakefile +0 -4
  142. data/spec/fixtures/repos/assets_error/app/assets/empty +0 -0
  143. data/spec/fixtures/repos/assets_error/config/application.rb +0 -5
  144. data/spec/fixtures/repos/assets_error/config/ey.yml +0 -4
  145. data/spec/fixtures/repos/assets_in_hook/Gemfile +0 -5
  146. data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +0 -88
  147. data/spec/fixtures/repos/assets_in_hook/README +0 -2
  148. data/spec/fixtures/repos/assets_in_hook/Rakefile +0 -5
  149. data/spec/fixtures/repos/assets_in_hook/app/assets/empty +0 -0
  150. data/spec/fixtures/repos/assets_in_hook/config/application.rb +0 -5
  151. data/spec/fixtures/repos/assets_in_hook/config/ey.yml +0 -3
  152. data/spec/fixtures/repos/assets_in_hook/deploy/before_compile_assets.rb +0 -2
  153. data/spec/fixtures/repos/bundle_fails/Gemfile +0 -1
  154. data/spec/fixtures/repos/bundle_fails/README +0 -1
  155. data/spec/fixtures/repos/bundle_fails/deploy/after_bundle.rb +0 -1
  156. data/spec/fixtures/repos/bundler_disabled/Gemfile +0 -4
  157. data/spec/fixtures/repos/bundler_disabled/Gemfile.lock +0 -12
  158. data/spec/fixtures/repos/bundler_disabled/README +0 -1
  159. data/spec/fixtures/repos/bundler_disabled/config/ey.yml +0 -2
  160. data/spec/fixtures/repos/bundler_disabled/deploy/after_bundle.rb +0 -1
  161. data/spec/fixtures/repos/bundler_disabled/deploy/before_bundle.rb +0 -1
  162. data/spec/fixtures/repos/bundler_old/Gemfile +0 -5
  163. data/spec/fixtures/repos/bundler_old/Gemfile.lock +0 -15
  164. data/spec/fixtures/repos/bundler_old/README +0 -1
  165. data/spec/fixtures/repos/default/Gemfile +0 -4
  166. data/spec/fixtures/repos/default/Gemfile.lock +0 -12
  167. data/spec/fixtures/repos/default/README +0 -5
  168. data/spec/fixtures/repos/default/ey.yml +0 -3
  169. data/spec/fixtures/repos/executable_hooks/README +0 -1
  170. data/spec/fixtures/repos/executable_hooks/deploy/before_restart +0 -72
  171. data/spec/fixtures/repos/executable_hooks_not_executable/README +0 -3
  172. data/spec/fixtures/repos/executable_hooks_not_executable/deploy/before_restart +0 -3
  173. data/spec/fixtures/repos/ey_yml/Gemfile +0 -4
  174. data/spec/fixtures/repos/ey_yml/Gemfile.lock +0 -12
  175. data/spec/fixtures/repos/ey_yml/README +0 -1
  176. data/spec/fixtures/repos/ey_yml/config/ey.yml +0 -18
  177. data/spec/fixtures/repos/ey_yml/deploy/before_migrate.rb +0 -6
  178. data/spec/fixtures/repos/ey_yml_alt/Gemfile +0 -4
  179. data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +0 -12
  180. data/spec/fixtures/repos/ey_yml_alt/README +0 -1
  181. data/spec/fixtures/repos/ey_yml_alt/deploy/before_migrate.rb +0 -6
  182. data/spec/fixtures/repos/ey_yml_alt/ey.yml +0 -12
  183. data/spec/fixtures/repos/hook_fails/README +0 -1
  184. data/spec/fixtures/repos/hook_fails/deploy/before_deploy.rb +0 -1
  185. data/spec/fixtures/repos/hooks/README +0 -1
  186. data/spec/fixtures/repos/hooks/deploy/after_bundle.rb +0 -1
  187. data/spec/fixtures/repos/hooks/deploy/after_compile_assets.rb +0 -1
  188. data/spec/fixtures/repos/hooks/deploy/after_deploy.rb +0 -1
  189. data/spec/fixtures/repos/hooks/deploy/after_migrate.rb +0 -1
  190. data/spec/fixtures/repos/hooks/deploy/after_restart.rb +0 -1
  191. data/spec/fixtures/repos/hooks/deploy/after_symlink.rb +0 -1
  192. data/spec/fixtures/repos/hooks/deploy/before_bundle.rb +0 -1
  193. data/spec/fixtures/repos/hooks/deploy/before_compile_assets.rb +0 -1
  194. data/spec/fixtures/repos/hooks/deploy/before_deploy.rb +0 -1
  195. data/spec/fixtures/repos/hooks/deploy/before_migrate.rb +0 -1
  196. data/spec/fixtures/repos/hooks/deploy/before_restart.rb +0 -1
  197. data/spec/fixtures/repos/hooks/deploy/before_symlink.rb +0 -1
  198. data/spec/fixtures/repos/multi_dep_manager/README +0 -1
  199. data/spec/fixtures/repos/multi_dep_manager/composer.json +0 -5
  200. data/spec/fixtures/repos/multi_dep_manager/composer.lock +0 -462
  201. data/spec/fixtures/repos/multi_dep_manager/package.json +0 -7
  202. data/spec/fixtures/repos/multi_dep_manager/public/index.php +0 -4
  203. data/spec/fixtures/repos/no_ey_config/Gemfile +0 -3
  204. data/spec/fixtures/repos/no_ey_config/Gemfile.lock +0 -10
  205. data/spec/fixtures/repos/no_ey_config/README +0 -1
  206. data/spec/fixtures/repos/no_ey_config/ey.yml +0 -3
  207. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile +0 -3
  208. data/spec/fixtures/repos/no_ey_config_no_warning/Gemfile.lock +0 -10
  209. data/spec/fixtures/repos/no_ey_config_no_warning/README +0 -1
  210. data/spec/fixtures/repos/no_ey_config_no_warning/ey.yml +0 -5
  211. data/spec/fixtures/repos/no_gemfile_lock/Gemfile +0 -4
  212. data/spec/fixtures/repos/no_gemfile_lock/README +0 -1
  213. data/spec/fixtures/repos/no_gemfile_lock/ey.yml +0 -3
  214. data/spec/fixtures/repos/nodejs/README +0 -1
  215. data/spec/fixtures/repos/nodejs/package.json +0 -7
  216. data/spec/fixtures/repos/not_bundled/README +0 -1
  217. data/spec/fixtures/repos/npm_disabled/README +0 -1
  218. data/spec/fixtures/repos/npm_disabled/config/ey.yml +0 -2
  219. data/spec/fixtures/repos/npm_disabled/package.json +0 -7
  220. data/spec/fixtures/repos/php_composer_disabled/README +0 -1
  221. data/spec/fixtures/repos/php_composer_disabled/composer.json +0 -5
  222. data/spec/fixtures/repos/php_composer_disabled/composer.lock +0 -462
  223. data/spec/fixtures/repos/php_composer_disabled/config/ey.yml +0 -2
  224. data/spec/fixtures/repos/php_composer_disabled/public/index.php +0 -4
  225. data/spec/fixtures/repos/php_composer_lock/README +0 -1
  226. data/spec/fixtures/repos/php_composer_lock/composer.json +0 -5
  227. data/spec/fixtures/repos/php_composer_lock/composer.lock +0 -462
  228. data/spec/fixtures/repos/php_composer_lock/public/index.php +0 -4
  229. data/spec/fixtures/repos/php_no_composer_lock/README +0 -1
  230. data/spec/fixtures/repos/php_no_composer_lock/composer.json +0 -21
  231. data/spec/fixtures/repos/php_no_composer_lock/public/index.php +0 -4
  232. data/spec/fixtures/repos/public_system/Gemfile +0 -4
  233. data/spec/fixtures/repos/public_system/Gemfile.lock +0 -12
  234. data/spec/fixtures/repos/public_system/README +0 -5
  235. data/spec/fixtures/repos/public_system/ey.yml +0 -3
  236. data/spec/fixtures/repos/public_system/public/system/cant_touch_this.txt +0 -3
  237. data/spec/fixtures/repos/sqlite3/Gemfile +0 -4
  238. data/spec/fixtures/repos/sqlite3/Gemfile.lock +0 -89
  239. data/spec/fixtures/repos/sqlite3/README +0 -1
  240. data/spec/fixtures/retwisj.war +0 -0
  241. data/spec/fixtures/valid_hook.rb +0 -1
  242. data/spec/git_strategy_spec.rb +0 -34
  243. data/spec/lockfile_parser_spec.rb +0 -126
  244. data/spec/maintenance_spec.rb +0 -44
  245. data/spec/multi_dependency_manager_spec.rb +0 -25
  246. data/spec/nodejs_deploy_spec.rb +0 -30
  247. data/spec/php_deploy_spec.rb +0 -81
  248. data/spec/platform_configure_spec.rb +0 -61
  249. data/spec/rails31_deploy_spec.rb +0 -172
  250. data/spec/restart_spec.rb +0 -43
  251. data/spec/rollback_spec.rb +0 -87
  252. data/spec/server_spec.rb +0 -70
  253. data/spec/services_deploy_spec.rb +0 -165
  254. data/spec/shell_spec.rb +0 -57
  255. data/spec/source/archive_spec.rb +0 -33
  256. data/spec/source/git_spec.rb +0 -44
  257. data/spec/sqlite3_deploy_spec.rb +0 -38
  258. data/spec/support/integration.rb +0 -103
  259. data/spec/support/source_doubles.rb +0 -28
  260. data/spec/support/timecop.rb +0 -5
  261. data/spec/symlink_spec.rb +0 -15
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ require 'engineyard-serverside/propagator'
4
+
5
+ module EY
6
+ module Serverside
7
+ describe Propagator do
8
+ let(:spawner) {Object.new}
9
+ let(:shell) {Object.new}
10
+ let(:server1) {EY::Serverside::Server.new('server1', nil, nil, nil)}
11
+ let(:server2) {EY::Serverside::Server.new('server2', nil, nil, nil)}
12
+ let(:servers) {EY::Serverside::Servers.new([server1, server2], shell)}
13
+
14
+ let(:propagator) {described_class.new(servers, shell)}
15
+
16
+ before(:each) do
17
+ allow(shell).to receive(:status)
18
+ allow(EY::Serverside::Spawner).to receive(:new).and_return(spawner)
19
+ allow(spawner).to receive(:add)
20
+ allow(spawner).to receive(:run).and_return([])
21
+ end
22
+
23
+ describe '#propagate' do
24
+ let(:propagate) {propagator.propagate}
25
+
26
+ it 'announces the propagation on the shell' do
27
+ expect(shell).
28
+ to receive(:status).
29
+ with("Verifying and propagating #{EY::Serverside::About.name_with_version} to all servers.")
30
+
31
+ propagate
32
+ end
33
+
34
+ it 'runs the propagation command on each server' do
35
+ servers.each do |server|
36
+ command = propagator.instance_eval {
37
+ propagation_command_for(server)
38
+ }
39
+
40
+ expect(spawner).
41
+ to receive(:add).
42
+ with(
43
+ command,
44
+ shell,
45
+ server
46
+ )
47
+ end
48
+
49
+ expect(spawner).to receive(:run).and_return([])
50
+
51
+ propagate
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,390 @@
1
+ require 'spec_helper'
2
+
3
+ require 'engineyard-serverside/server'
4
+
5
+ module EY
6
+ module Serverside
7
+
8
+ describe Server do
9
+ let(:hostname) {'nosuch.server.com'}
10
+ let(:roles) {[:romeo, :mercutio, :tybalt]}
11
+ let(:name) {'superserverx5000'}
12
+ let(:user) {'joe'}
13
+ let(:server_hash) {{
14
+ :hostname => hostname,
15
+ :roles => roles,
16
+ :name => name,
17
+ :user => user
18
+ }}
19
+
20
+ let(:server) {described_class.from_hash(server_hash)}
21
+
22
+ describe '.from_hash' do
23
+ let(:role_set) {Object.new}
24
+ let(:expected) {Object.new}
25
+
26
+ let(:result) {described_class.from_hash(server_hash)}
27
+
28
+ before(:each) do
29
+ # Stub out the parts of the Set API that we need to be able to express
30
+ # its use.
31
+ allow(Set).to receive(:new).with(roles).and_return(role_set)
32
+
33
+ # This is a little dirty, but not incredibly. Server is a Struct with
34
+ # specific attributes. As such, it doesn't have an initializer of its
35
+ # own, and our seam is between Server and Struct, so we can stub out
36
+ # instantiation and check to ensure that it's given the proper values.
37
+ allow(described_class).to receive(:new).and_return(expected)
38
+ end
39
+
40
+ it 'instantiates a new Server from a server hash' do
41
+ expect(described_class).
42
+ to receive(:new).
43
+ with(hostname, role_set, name, user)
44
+
45
+ result
46
+ end
47
+
48
+ it 'is the newly instantiated Server instance' do
49
+ expect(result).to eql(expected)
50
+ end
51
+ end
52
+
53
+ describe '.known_hosts_file' do
54
+ let(:tmp) {Object.new}
55
+ let(:result) {described_class.known_hosts_file}
56
+
57
+ before(:each) do
58
+ # Of all the design decisions that could have been made here, this
59
+ # class method is stateful, so we have to blow away that state to
60
+ # gurantee the idempotence of the examples here.
61
+ described_class.class_eval do
62
+ @known_hosts_file = nil
63
+ end
64
+
65
+ # Stub out the pieces of the Tempfile interface that we use so as to
66
+ # cut down on test artifacts.
67
+ allow(Tempfile).
68
+ to receive(:new).
69
+ with('ey-ss-known-hosts').
70
+ and_return(tmp)
71
+ end
72
+
73
+ context 'on initial use' do
74
+ it 'generates a temp file' do
75
+ expect(Tempfile).
76
+ to receive(:new).
77
+ with('ey-ss-known-hosts').
78
+ and_return(tmp)
79
+
80
+ result
81
+ end
82
+
83
+ it 'returns the generated temp file' do
84
+ expect(result).to eql(tmp)
85
+ end
86
+ end
87
+
88
+ context 'on subsequent uses' do
89
+ let(:tmp) {'an established temp file'}
90
+
91
+ before(:each) do
92
+ described_class.class_eval do
93
+ @known_hosts_file = tmp
94
+ end
95
+
96
+ it 'reuses its existing temp file' do
97
+ expect(Tempfile).not_to receive(:new)
98
+
99
+ expect(result).to eql(tmp)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#authority' do
106
+ let(:result) {server.authority}
107
+
108
+ it 'is the SSH signature for the server' do
109
+ expect(result).to eql(user + '@' + hostname)
110
+ end
111
+ end
112
+
113
+ describe '#inspect' do
114
+ let(:result) {server.inspect}
115
+
116
+ it 'begins with the hostname and role' do
117
+ expect(result).to match(%r{^#{hostname}\(#{server.role}})
118
+ end
119
+
120
+ context 'when the server has a name' do
121
+ let(:name) {'wiggly'}
122
+
123
+ it 'includes the server name' do
124
+ expect(result).to match(%r{#{name}\)$})
125
+ end
126
+ end
127
+
128
+ context 'when the server has no name' do
129
+ before(:each) do
130
+ server_hash.delete(:name)
131
+ end
132
+
133
+ it 'does not include a server name' do
134
+ expect(result).to match(%r{#{server.role}\)$})
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#role' do
140
+ let(:result) {server.role}
141
+
142
+ it 'is the first role in the role list' do
143
+ expect(result).to eql(Set.new(roles).to_a.first)
144
+ end
145
+ end
146
+
147
+ describe '#matches_roles?' do
148
+ let(:candidates) {[]}
149
+ let(:result) {server.matches_roles?(candidates)}
150
+
151
+ context 'when the server has all of the candidate roles' do
152
+ let(:candidates) {[:tybalt, :romeo, :mercutio]}
153
+
154
+ it 'is true' do
155
+ expect(result).to eql(true)
156
+ end
157
+ end
158
+
159
+ context 'when the server has some of the candidate roles' do
160
+ let(:candidates) {[:romeo, :tybalt]}
161
+
162
+ it 'is true' do
163
+ expect(result).to eql(true)
164
+ end
165
+ end
166
+
167
+ context 'when the server has none of the candidate roles' do
168
+ let(:candidates) {[:benvolio, :gildenstern]}
169
+
170
+ it 'is false' do
171
+ expect(result).to eql(false)
172
+ end
173
+ end
174
+
175
+ context 'when the candidates list is empty' do
176
+ let(:candidates) {[]}
177
+
178
+ it 'is false' do
179
+ expect(result).to eql(false)
180
+ end
181
+ end
182
+ end
183
+
184
+ describe '#roles=' do
185
+ let(:candidates) {[:benvolio, :gildenstern]}
186
+ let(:result) {server.roles = candidates}
187
+
188
+ it 'removes the original roles' do
189
+ result
190
+
191
+ roles.each do |role|
192
+ expect(server.matches_roles?([role])).to eql(false)
193
+ end
194
+ end
195
+
196
+ it 'adds the candidate roles' do
197
+ result
198
+
199
+ candidates.each do |role|
200
+ expect(server.matches_roles?([role])).to eql(true)
201
+ end
202
+ end
203
+ end
204
+
205
+ describe '#local?' do
206
+ let(:result) {server.local?}
207
+
208
+ context 'when the hostname is localhost' do
209
+ let(:hostname) {'localhost'}
210
+
211
+ it 'is true' do
212
+ expect(result).to eql(true)
213
+ end
214
+ end
215
+
216
+ context 'when the hostname is not localhost' do
217
+ let(:hostname) {'a.b.c.d'}
218
+
219
+ it 'is false' do
220
+ expect(result).to eql(false)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe '#sync_directory_command' do
226
+ let(:directory) {'/path/to/something/interesting'}
227
+ let(:result) {server.sync_directory_command(directory)}
228
+
229
+ context 'when the server is local' do
230
+ let(:hostname) {'localhost'}
231
+
232
+ it 'is nil' do
233
+ expect(result).to eql(nil)
234
+ end
235
+ end
236
+
237
+ context 'when the server is not local' do
238
+ let(:ssh_command) {'dummy_ssh_command'}
239
+ let(:remote_mkdir) {'remote_mkdir'}
240
+ let(:rsync_command) {'rsync_command'}
241
+ let(:hostname) {'donkey.kong'}
242
+
243
+ before(:each) do
244
+ allow(server).to receive(:ssh_command).and_return(ssh_command)
245
+ allow(server).to receive(:remote_command).and_return(remote_mkdir)
246
+
247
+ allow(Escape).to receive(:shell_command).and_return(rsync_command)
248
+ end
249
+
250
+ it 'generates a command to create the full path to the directory remotely' do
251
+ expect(server).to receive(:remote_command).with("mkdir -p #{directory}")
252
+
253
+ result
254
+ end
255
+
256
+ it 'generates a command to sync the directory to the remote server' do
257
+ expect(Escape).
258
+ to receive(:shell_command).
259
+ with([
260
+ 'rsync',
261
+ '--delete',
262
+ '-rlpgoDq',
263
+ '-e',
264
+ ssh_command,
265
+ "#{directory}/",
266
+ "#{user}@#{hostname}:#{directory}"
267
+ ])
268
+
269
+ result
270
+ end
271
+
272
+ context 'when existing files are to be ignored' do
273
+ let(:result) {server.sync_directory_command(directory, true)}
274
+
275
+ it 'adds the ignore existing flag to the rsync command' do
276
+ expect(Escape).
277
+ to receive(:shell_command).
278
+ with([
279
+ 'rsync',
280
+ '--delete',
281
+ '-rlpgoDq',
282
+ '--ignore-existing',
283
+ '-e',
284
+ ssh_command,
285
+ "#{directory}/",
286
+ "#{user}@#{hostname}:#{directory}"
287
+ ])
288
+
289
+ result
290
+ end
291
+ end
292
+
293
+ it 'is the remote mkdir and the rsync separated by a shell AND operation' do
294
+ expect(result).to eql("#{remote_mkdir} && #{rsync_command}")
295
+ end
296
+ end
297
+ end
298
+
299
+ describe '#scp_command' do
300
+ end
301
+
302
+ describe '#command_on_server' do
303
+ end
304
+
305
+ describe '#run' do
306
+ let(:command) {'echo'}
307
+
308
+ context 'when the server is local' do
309
+ let(:hostname) {'localhost'}
310
+
311
+ it 'yields the command unalertered to the given block' do
312
+ server.run(command) do |cmd|
313
+ expect(cmd).to eql(command)
314
+ end
315
+ end
316
+ end
317
+
318
+ context 'when the server is not local' do
319
+ let(:hostname) {'pac.man'}
320
+
321
+ before(:each) do
322
+ allow(server).to receive(:remote_command) {'totally remote my dude'}
323
+ end
324
+
325
+ it 'yields the remote version of the command to the given block' do
326
+ server.run(command) do |cmd|
327
+ expect(cmd).to eql(server.remote_command(command))
328
+ end
329
+ end
330
+ end
331
+ end
332
+
333
+ describe '#remote_command' do
334
+ let(:command) {'touch toes'}
335
+ let(:result) {server.remote_command(command)}
336
+
337
+ before(:each) do
338
+ allow(server).to receive(:ssh_command).and_return('default ssh command')
339
+ end
340
+
341
+ it 'is an SSH command that would run the escaped command on the remote server' do
342
+ expect(result).to eql("#{server.ssh_command} #{user}@#{hostname} '#{command}'")
343
+ end
344
+ end
345
+
346
+ describe '#ssh_command' do
347
+ let(:result) {server.ssh_command}
348
+ let(:known_hosts_file) {Object.new}
349
+
350
+ before(:each) do
351
+ allow(described_class).
352
+ to receive(:known_hosts_file).
353
+ and_return(known_hosts_file)
354
+
355
+ allow(known_hosts_file).
356
+ to receive(:path).
357
+ and_return('less_followed')
358
+ end
359
+
360
+ it 'is an ssh invocation' do
361
+ expect(result).to match(%r{^ssh })
362
+ end
363
+
364
+ it 'uses the internal ssh key' do
365
+ expect(result).to match(%r{\s-i #{ENV['HOME']}\/\.ssh\/internal\s+})
366
+ end
367
+
368
+ it 'disables strict host key checking' do
369
+ expect(result).to match(%r{\s+-o StrictHostKeyChecking=no\s+})
370
+ end
371
+
372
+ it 'disables password authentication' do
373
+ expect(result).to match(%r{\s+-o PasswordAuthentication=no\s+})
374
+ end
375
+
376
+ it 'sets the keepalive to one minute' do
377
+ expect(result).to match(%r{\s+-o ServerAliveInterval=60})
378
+ end
379
+
380
+ it 'specifies a known hosts file' do
381
+ expect(result).
382
+ to match(
383
+ %r{\s+-o UserKnownHostsFile=#{described_class.known_hosts_file.path}}
384
+ )
385
+ end
386
+ end
387
+ end
388
+
389
+ end
390
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ require 'engineyard-serverside/shell/helpers'
5
+
6
+ module EY
7
+ module Serverside
8
+ class Shell
9
+
10
+ describe Helpers do
11
+ let(:shell) {Object.new}
12
+ let(:verbosity) {false}
13
+
14
+ let(:extended) {Object.new.extend(described_class)}
15
+
16
+ before(:each) do
17
+ allow(extended).to receive(:shell).and_return shell
18
+
19
+ allow(shell).to receive(:verbose?).and_return(verbosity)
20
+ allow(shell).to receive(:warning)
21
+ allow(shell).to receive(:info)
22
+ allow(shell).to receive(:debug)
23
+ allow(shell).to receive(:logged_system)
24
+ end
25
+
26
+ describe '#verbose?' do
27
+ let(:result) {extended.verbose?}
28
+
29
+ context 'when the shell is configured for verbosity' do
30
+ let(:verbosity) {true}
31
+
32
+ it 'is true' do
33
+ expect(result).to eql(true)
34
+ end
35
+ end
36
+
37
+ context 'when the shell is not configured for vverbosity' do
38
+ let(:verbosity) {false}
39
+
40
+ it 'is false' do
41
+ expect(result).to eql(false)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#warning' do
47
+ let(:foo) {'foo'}
48
+ let(:bar) {'bar'}
49
+ let(:result) {extended.warning(foo, bar)}
50
+
51
+ it 'forwards the request to the shell' do
52
+ expect(shell).to receive(:warning).with(foo, bar)
53
+
54
+ result
55
+ end
56
+ end
57
+
58
+ describe '#info' do
59
+ let(:foo) {'foo'}
60
+ let(:bar) {'bar'}
61
+ let(:result) {extended.info(foo, bar)}
62
+
63
+ it 'forwards the request to the shell' do
64
+ expect(shell).to receive(:info).with(foo, bar)
65
+
66
+ result
67
+ end
68
+
69
+ end
70
+
71
+ describe '#debug' do
72
+ let(:foo) {'foo'}
73
+ let(:bar) {'bar'}
74
+ let(:result) {extended.debug(foo, bar)}
75
+
76
+ it 'forwards the request to the shell' do
77
+ expect(shell).to receive(:debug).with(foo, bar)
78
+
79
+ result
80
+ end
81
+ end
82
+
83
+ describe '#logged_system' do
84
+ let(:foo) {'foo'}
85
+ let(:bar) {'bar'}
86
+ let(:result) {extended.logged_system(foo, bar)}
87
+
88
+ it 'forwards the request to the shell' do
89
+ expect(shell).to receive(:logged_system).with(foo, bar)
90
+
91
+ result
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+ end
98
+ end