capistrano 2.8.0 → 3.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) hide show
  1. checksums.yaml +7 -0
  2. data/.docker/Dockerfile +7 -0
  3. data/.docker/ssh_key_rsa +49 -0
  4. data/.docker/ssh_key_rsa.pub +1 -0
  5. data/.docker/ubuntu_setup.sh +23 -0
  6. data/.github/issue_template.md +19 -0
  7. data/.github/pull_request_template.md +22 -0
  8. data/.github/release-drafter.yml +25 -0
  9. data/.github/workflows/ci.yml +80 -0
  10. data/.github/workflows/release-drafter.yml +18 -0
  11. data/.gitignore +23 -8
  12. data/.rubocop.yml +62 -0
  13. data/CHANGELOG.md +1 -0
  14. data/CONTRIBUTING.md +63 -0
  15. data/DEVELOPMENT.md +112 -0
  16. data/Gemfile +42 -9
  17. data/LICENSE.txt +21 -0
  18. data/README.md +221 -0
  19. data/RELEASING.md +17 -0
  20. data/Rakefile +17 -8
  21. data/UPGRADING-3.7.md +86 -0
  22. data/bin/cap +2 -3
  23. data/bin/capify +7 -89
  24. data/capistrano.gemspec +29 -43
  25. data/docker-compose.yml +8 -0
  26. data/features/configuration.feature +28 -0
  27. data/features/deploy.feature +92 -0
  28. data/features/deploy_failure.feature +17 -0
  29. data/features/doctor.feature +11 -0
  30. data/features/installation.feature +21 -0
  31. data/features/sshconnect.feature +11 -0
  32. data/features/stage_failure.feature +9 -0
  33. data/features/step_definitions/assertions.rb +162 -0
  34. data/features/step_definitions/cap_commands.rb +21 -0
  35. data/features/step_definitions/setup.rb +91 -0
  36. data/features/subdirectory.feature +9 -0
  37. data/features/support/docker_gateway.rb +53 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/remote_command_helpers.rb +29 -0
  40. data/features/support/remote_ssh_helpers.rb +33 -0
  41. data/lib/Capfile +3 -0
  42. data/lib/capistrano/all.rb +17 -0
  43. data/lib/capistrano/application.rb +153 -0
  44. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  45. data/lib/capistrano/configuration/filter.rb +26 -0
  46. data/lib/capistrano/configuration/host_filter.rb +29 -0
  47. data/lib/capistrano/configuration/null_filter.rb +9 -0
  48. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  49. data/lib/capistrano/configuration/question.rb +76 -0
  50. data/lib/capistrano/configuration/role_filter.rb +29 -0
  51. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  52. data/lib/capistrano/configuration/server.rb +137 -0
  53. data/lib/capistrano/configuration/servers.rb +56 -96
  54. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  55. data/lib/capistrano/configuration/variables.rb +79 -94
  56. data/lib/capistrano/configuration.rb +178 -33
  57. data/lib/capistrano/console.rb +1 -0
  58. data/lib/capistrano/defaults.rb +36 -0
  59. data/lib/capistrano/deploy.rb +3 -0
  60. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  61. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  62. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  63. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  64. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  65. data/lib/capistrano/doctor.rb +6 -0
  66. data/lib/capistrano/dotfile.rb +2 -0
  67. data/lib/capistrano/dsl/env.rb +43 -0
  68. data/lib/capistrano/dsl/paths.rb +89 -0
  69. data/lib/capistrano/dsl/stages.rb +31 -0
  70. data/lib/capistrano/dsl/task_enhancements.rb +61 -0
  71. data/lib/capistrano/dsl.rb +95 -0
  72. data/lib/capistrano/framework.rb +2 -0
  73. data/lib/capistrano/i18n.rb +46 -0
  74. data/lib/capistrano/immutable_task.rb +30 -0
  75. data/lib/capistrano/install.rb +1 -0
  76. data/lib/capistrano/plugin.rb +95 -0
  77. data/lib/capistrano/proc_helpers.rb +13 -0
  78. data/lib/capistrano/scm/git.rb +105 -0
  79. data/lib/capistrano/scm/hg.rb +55 -0
  80. data/lib/capistrano/scm/plugin.rb +13 -0
  81. data/lib/capistrano/scm/svn.rb +56 -0
  82. data/lib/capistrano/scm/tasks/git.rake +84 -0
  83. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  84. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  85. data/lib/capistrano/scm.rb +115 -0
  86. data/lib/capistrano/setup.rb +36 -0
  87. data/lib/capistrano/tasks/console.rake +25 -0
  88. data/lib/capistrano/tasks/deploy.rake +280 -0
  89. data/lib/capistrano/tasks/doctor.rake +24 -0
  90. data/lib/capistrano/tasks/framework.rake +67 -0
  91. data/lib/capistrano/tasks/install.rake +41 -0
  92. data/lib/capistrano/templates/Capfile +38 -0
  93. data/lib/capistrano/templates/deploy.rb.erb +39 -0
  94. data/lib/capistrano/templates/stage.rb.erb +61 -0
  95. data/lib/capistrano/upload_task.rb +9 -0
  96. data/lib/capistrano/version.rb +1 -14
  97. data/lib/capistrano/version_validator.rb +32 -0
  98. data/lib/capistrano.rb +0 -3
  99. data/spec/integration/dsl_spec.rb +632 -0
  100. data/spec/integration_spec_helper.rb +5 -0
  101. data/spec/lib/capistrano/application_spec.rb +60 -0
  102. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  103. data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
  104. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  105. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  106. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  107. data/spec/lib/capistrano/configuration/question_spec.rb +92 -0
  108. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  109. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
  110. data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
  111. data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
  112. data/spec/lib/capistrano/configuration_spec.rb +357 -0
  113. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  114. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  115. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  116. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  117. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  118. data/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
  119. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
  120. data/spec/lib/capistrano/dsl_spec.rb +125 -0
  121. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  122. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  123. data/spec/lib/capistrano/scm/git_spec.rb +194 -0
  124. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  125. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  126. data/spec/lib/capistrano/scm_spec.rb +103 -0
  127. data/spec/lib/capistrano/upload_task_spec.rb +19 -0
  128. data/spec/lib/capistrano/version_validator_spec.rb +118 -0
  129. data/spec/lib/capistrano_spec.rb +7 -0
  130. data/spec/spec_helper.rb +29 -0
  131. data/spec/support/matchers.rb +5 -0
  132. data/spec/support/tasks/database.rake +11 -0
  133. data/spec/support/tasks/fail.rake +8 -0
  134. data/spec/support/tasks/failed.rake +5 -0
  135. data/spec/support/tasks/plugin.rake +6 -0
  136. data/spec/support/tasks/root.rake +11 -0
  137. data/spec/support/test_app.rb +205 -0
  138. metadata +234 -208
  139. data/.rvmrc +0 -1
  140. data/CHANGELOG +0 -954
  141. data/README.mdown +0 -76
  142. data/lib/capistrano/callback.rb +0 -45
  143. data/lib/capistrano/cli/execute.rb +0 -85
  144. data/lib/capistrano/cli/help.rb +0 -125
  145. data/lib/capistrano/cli/help.txt +0 -81
  146. data/lib/capistrano/cli/options.rb +0 -243
  147. data/lib/capistrano/cli/ui.rb +0 -40
  148. data/lib/capistrano/cli.rb +0 -47
  149. data/lib/capistrano/command.rb +0 -286
  150. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
  151. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  152. data/lib/capistrano/configuration/actions/invocation.rb +0 -298
  153. data/lib/capistrano/configuration/callbacks.rb +0 -148
  154. data/lib/capistrano/configuration/connections.rb +0 -230
  155. data/lib/capistrano/configuration/execution.rb +0 -143
  156. data/lib/capistrano/configuration/loading.rb +0 -197
  157. data/lib/capistrano/configuration/namespaces.rb +0 -197
  158. data/lib/capistrano/configuration/roles.rb +0 -73
  159. data/lib/capistrano/errors.rb +0 -19
  160. data/lib/capistrano/ext/string.rb +0 -5
  161. data/lib/capistrano/extensions.rb +0 -57
  162. data/lib/capistrano/logger.rb +0 -59
  163. data/lib/capistrano/processable.rb +0 -53
  164. data/lib/capistrano/recipes/compat.rb +0 -32
  165. data/lib/capistrano/recipes/deploy/assets.rb +0 -57
  166. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  167. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
  168. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
  169. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  170. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
  171. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  172. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
  173. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
  174. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
  175. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
  176. data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
  177. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
  178. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
  179. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  180. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
  181. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  182. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
  183. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  184. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  185. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
  186. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  187. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  188. data/lib/capistrano/recipes/deploy.rb +0 -568
  189. data/lib/capistrano/recipes/standard.rb +0 -37
  190. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  191. data/lib/capistrano/role.rb +0 -102
  192. data/lib/capistrano/server_definition.rb +0 -56
  193. data/lib/capistrano/shell.rb +0 -260
  194. data/lib/capistrano/ssh.rb +0 -101
  195. data/lib/capistrano/task_definition.rb +0 -75
  196. data/lib/capistrano/transfer.rb +0 -216
  197. data/rvmrc.sample +0 -1
  198. data/test/cli/execute_test.rb +0 -132
  199. data/test/cli/help_test.rb +0 -165
  200. data/test/cli/options_test.rb +0 -329
  201. data/test/cli/ui_test.rb +0 -28
  202. data/test/cli_test.rb +0 -17
  203. data/test/command_test.rb +0 -289
  204. data/test/configuration/actions/file_transfer_test.rb +0 -61
  205. data/test/configuration/actions/inspect_test.rb +0 -65
  206. data/test/configuration/actions/invocation_test.rb +0 -247
  207. data/test/configuration/callbacks_test.rb +0 -220
  208. data/test/configuration/connections_test.rb +0 -420
  209. data/test/configuration/execution_test.rb +0 -175
  210. data/test/configuration/loading_test.rb +0 -132
  211. data/test/configuration/namespace_dsl_test.rb +0 -311
  212. data/test/configuration/roles_test.rb +0 -144
  213. data/test/configuration/servers_test.rb +0 -183
  214. data/test/configuration/variables_test.rb +0 -190
  215. data/test/configuration_test.rb +0 -88
  216. data/test/deploy/local_dependency_test.rb +0 -76
  217. data/test/deploy/remote_dependency_test.rb +0 -135
  218. data/test/deploy/scm/accurev_test.rb +0 -23
  219. data/test/deploy/scm/base_test.rb +0 -55
  220. data/test/deploy/scm/bzr_test.rb +0 -51
  221. data/test/deploy/scm/darcs_test.rb +0 -37
  222. data/test/deploy/scm/git_test.rb +0 -184
  223. data/test/deploy/scm/mercurial_test.rb +0 -134
  224. data/test/deploy/scm/none_test.rb +0 -35
  225. data/test/deploy/scm/subversion_test.rb +0 -32
  226. data/test/deploy/strategy/copy_test.rb +0 -321
  227. data/test/extensions_test.rb +0 -69
  228. data/test/fixtures/cli_integration.rb +0 -5
  229. data/test/fixtures/config.rb +0 -5
  230. data/test/fixtures/custom.rb +0 -3
  231. data/test/logger_test.rb +0 -123
  232. data/test/recipes_test.rb +0 -25
  233. data/test/role_test.rb +0 -11
  234. data/test/server_definition_test.rb +0 -121
  235. data/test/shell_test.rb +0 -90
  236. data/test/ssh_test.rb +0 -113
  237. data/test/task_definition_test.rb +0 -116
  238. data/test/transfer_test.rb +0 -160
  239. data/test/utils.rb +0 -37
@@ -0,0 +1,309 @@
1
+ require "spec_helper"
2
+
3
+ module Capistrano
4
+ class Configuration
5
+ describe Server do
6
+ let(:server) { Server.new("root@hostname:1234") }
7
+
8
+ describe "adding a role" do
9
+ subject { server.add_role(:test) }
10
+ it "adds the role" do
11
+ expect { subject }.to change { server.roles.size }.from(0).to(1)
12
+ end
13
+ end
14
+
15
+ describe "adding roles" do
16
+ subject { server.add_roles(%i(things stuff)) }
17
+ it "adds the roles" do
18
+ expect { subject }.to change { server.roles.size }.from(0).to(2)
19
+ end
20
+ end
21
+
22
+ describe "checking roles" do
23
+ subject { server.has_role?(:test) }
24
+
25
+ before do
26
+ server.add_role(:test)
27
+ end
28
+
29
+ it "adds the role" do
30
+ expect(subject).to be_truthy
31
+ end
32
+ end
33
+
34
+ describe "comparing identity" do
35
+ subject { server.hostname == Server[hostname].hostname }
36
+
37
+ context "with the same user, hostname and port" do
38
+ let(:hostname) { "root@hostname:1234" }
39
+ it { expect(subject).to be_truthy }
40
+ end
41
+
42
+ context "with a different user" do
43
+ let(:hostname) { "deployer@hostname:1234" }
44
+ it { expect(subject).to be_truthy }
45
+ end
46
+
47
+ context "with a different port" do
48
+ let(:hostname) { "root@hostname:5678" }
49
+ it { expect(subject).to be_truthy }
50
+ end
51
+
52
+ context "with a different hostname" do
53
+ let(:hostname) { "root@otherserver:1234" }
54
+ it { expect(subject).to be_falsey }
55
+ end
56
+ end
57
+
58
+ describe "identifying as primary" do
59
+ subject { server.primary }
60
+ context "server is primary" do
61
+ before do
62
+ server.set(:primary, true)
63
+ end
64
+ it "returns self" do
65
+ expect(subject).to eq server
66
+ end
67
+ end
68
+
69
+ context "server is not primary" do
70
+ it "is falesy" do
71
+ expect(subject).to be_falsey
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "assigning properties" do
77
+ before do
78
+ server.with(properties)
79
+ end
80
+
81
+ context "properties contains roles" do
82
+ let(:properties) { { roles: [:clouds] } }
83
+
84
+ it "adds the roles" do
85
+ expect(server.roles.first).to eq :clouds
86
+ end
87
+ end
88
+
89
+ context "properties contains user" do
90
+ let(:properties) { { user: "tomc" } }
91
+
92
+ it "sets the user" do
93
+ expect(server.user).to eq "tomc"
94
+ end
95
+
96
+ it "sets the netssh_options user" do
97
+ expect(server.netssh_options[:user]).to eq "tomc"
98
+ end
99
+ end
100
+
101
+ context "properties contains port" do
102
+ let(:properties) { { port: 2222 } }
103
+
104
+ it "sets the port" do
105
+ expect(server.port).to eq 2222
106
+ end
107
+ end
108
+
109
+ context "properties contains key" do
110
+ let(:properties) { { key: "/key" } }
111
+
112
+ it "adds the key" do
113
+ expect(server.keys).to include "/key"
114
+ end
115
+ end
116
+
117
+ context "properties contains password" do
118
+ let(:properties) { { password: "supersecret" } }
119
+
120
+ it "adds the key" do
121
+ expect(server.password).to eq "supersecret"
122
+ end
123
+ end
124
+
125
+ context "new properties" do
126
+ let(:properties) { { webscales: 5 } }
127
+
128
+ it "adds the properties" do
129
+ expect(server.properties.webscales).to eq 5
130
+ end
131
+ end
132
+
133
+ context "existing properties" do
134
+ let(:properties) { { webscales: 6 } }
135
+
136
+ it "keeps the existing properties" do
137
+ expect(server.properties.webscales).to eq 6
138
+ server.properties.webscales = 5
139
+ expect(server.properties.webscales).to eq 5
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#include?" do
145
+ let(:options) { {} }
146
+
147
+ subject { server.select?(options) }
148
+
149
+ before do
150
+ server.properties.active = true
151
+ end
152
+
153
+ context "options are empty" do
154
+ it { expect(subject).to be_truthy }
155
+ end
156
+
157
+ context "value is a symbol" do
158
+ context "value matches server property" do
159
+ context "with :filter" do
160
+ let(:options) { { filter: :active } }
161
+ it { expect(subject).to be_truthy }
162
+ end
163
+
164
+ context "with :select" do
165
+ let(:options) { { select: :active } }
166
+ it { expect(subject).to be_truthy }
167
+ end
168
+
169
+ context "with :exclude" do
170
+ let(:options) { { exclude: :active } }
171
+ it { expect(subject).to be_falsey }
172
+ end
173
+ end
174
+
175
+ context "value does not match server properly" do
176
+ context "with :active true" do
177
+ let(:options) { { active: true } }
178
+ it { expect(subject).to be_truthy }
179
+ end
180
+
181
+ context "with :active false" do
182
+ let(:options) { { active: false } }
183
+ it { expect(subject).to be_falsey }
184
+ end
185
+ end
186
+
187
+ context "value does not match server properly" do
188
+ context "with :filter" do
189
+ let(:options) { { filter: :inactive } }
190
+ it { expect(subject).to be_falsey }
191
+ end
192
+
193
+ context "with :select" do
194
+ let(:options) { { select: :inactive } }
195
+ it { expect(subject).to be_falsey }
196
+ end
197
+
198
+ context "with :exclude" do
199
+ let(:options) { { exclude: :inactive } }
200
+ it { expect(subject).to be_truthy }
201
+ end
202
+ end
203
+ end
204
+
205
+ context "key is a property" do
206
+ context "with :active true" do
207
+ let(:options) { { active: true } }
208
+ it { expect(subject).to be_truthy }
209
+ end
210
+
211
+ context "with :active false" do
212
+ let(:options) { { active: false } }
213
+ it { expect(subject).to be_falsey }
214
+ end
215
+ end
216
+
217
+ context "value is a proc" do
218
+ context "value matches server property" do
219
+ context "with :filter" do
220
+ let(:options) { { filter: ->(s) { s.properties.active } } }
221
+ it { expect(subject).to be_truthy }
222
+ end
223
+
224
+ context "with :select" do
225
+ let(:options) { { select: ->(s) { s.properties.active } } }
226
+ it { expect(subject).to be_truthy }
227
+ end
228
+
229
+ context "with :exclude" do
230
+ let(:options) { { exclude: ->(s) { s.properties.active } } }
231
+ it { expect(subject).to be_falsey }
232
+ end
233
+ end
234
+
235
+ context "value does not match server properly" do
236
+ context "with :filter" do
237
+ let(:options) { { filter: ->(s) { s.properties.inactive } } }
238
+ it { expect(subject).to be_falsey }
239
+ end
240
+
241
+ context "with :select" do
242
+ let(:options) { { select: ->(s) { s.properties.inactive } } }
243
+ it { expect(subject).to be_falsey }
244
+ end
245
+
246
+ context "with :exclude" do
247
+ let(:options) { { exclude: ->(s) { s.properties.inactive } } }
248
+ it { expect(subject).to be_truthy }
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ describe "assign ssh_options" do
255
+ let(:server) { Server.new("user_name@hostname") }
256
+
257
+ context "defaults" do
258
+ it "forward agent" do
259
+ expect(server.netssh_options[:forward_agent]).to eq true
260
+ end
261
+ it "contains user" do
262
+ expect(server.netssh_options[:user]).to eq "user_name"
263
+ end
264
+ end
265
+
266
+ context "custom" do
267
+ let(:properties) do
268
+ { ssh_options: {
269
+ user: "another_user",
270
+ keys: %w(/home/another_user/.ssh/id_rsa),
271
+ forward_agent: false,
272
+ auth_methods: %w(publickey password)
273
+ } }
274
+ end
275
+
276
+ before do
277
+ server.with(properties)
278
+ end
279
+
280
+ it "not forward agent" do
281
+ expect(server.netssh_options[:forward_agent]).to eq false
282
+ end
283
+ it "contains correct user" do
284
+ expect(server.netssh_options[:user]).to eq "another_user"
285
+ end
286
+ it "does not affect server user in host" do
287
+ expect(server.user).to eq "user_name"
288
+ end
289
+ it "contains keys" do
290
+ expect(server.netssh_options[:keys]).to eq %w(/home/another_user/.ssh/id_rsa)
291
+ end
292
+ it "contains auth_methods" do
293
+ expect(server.netssh_options[:auth_methods]).to eq %w(publickey password)
294
+ end
295
+ end
296
+ end
297
+
298
+ describe ".[]" do
299
+ it "creates a server if its argument is not already a server" do
300
+ expect(Server["hostname:1234"]).to be_a Server
301
+ end
302
+
303
+ it "returns its argument if it is already a server" do
304
+ expect(Server[server]).to be server
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
@@ -0,0 +1,331 @@
1
+ require "spec_helper"
2
+
3
+ module Capistrano
4
+ class Configuration
5
+ describe Servers do
6
+ let(:servers) { Servers.new }
7
+
8
+ describe "adding a role" do
9
+ it "adds two new server instances" do
10
+ expect { servers.add_role(:app, %w{1 2}) }
11
+ .to change { servers.count }.from(0).to(2)
12
+ end
13
+
14
+ it "handles de-duplification within roles" do
15
+ servers.add_role(:app, %w{1})
16
+ servers.add_role(:app, %w{1})
17
+ expect(servers.count).to eq 1
18
+ end
19
+
20
+ it "handles de-duplification within roles with users" do
21
+ servers.add_role(:app, %w{1}, user: "nick")
22
+ servers.add_role(:app, %w{1}, user: "fred")
23
+ expect(servers.count).to eq 1
24
+ end
25
+
26
+ it "accepts instances of server objects" do
27
+ servers.add_role(:app, [Capistrano::Configuration::Server.new("example.net"), "example.com"])
28
+ expect(servers.roles_for([:app]).length).to eq 2
29
+ end
30
+
31
+ it "accepts non-enumerable types" do
32
+ servers.add_role(:app, "1")
33
+ expect(servers.roles_for([:app]).count).to eq 1
34
+ end
35
+
36
+ it "creates distinct server properties" do
37
+ servers.add_role(:db, %w{1 2}, db: { port: 1234 })
38
+ servers.add_host("1", db: { master: true })
39
+ expect(servers.count).to eq(2)
40
+ expect(servers.roles_for([:db]).count).to eq 2
41
+ expect(servers.find { |s| s.hostname == "1" }.properties.db).to eq(port: 1234, master: true)
42
+ expect(servers.find { |s| s.hostname == "2" }.properties.db).to eq(port: 1234)
43
+ end
44
+ end
45
+
46
+ describe "adding a role to an existing server" do
47
+ before do
48
+ servers.add_role(:web, %w{1 2})
49
+ servers.add_role(:app, %w{1 2})
50
+ end
51
+
52
+ it "adds new roles to existing servers" do
53
+ expect(servers.count).to eq 2
54
+ end
55
+ end
56
+
57
+ describe "collecting server roles" do
58
+ let(:app) { Set.new([:app]) }
59
+ let(:web_app) { Set.new(%i(web app)) }
60
+ let(:web) { Set.new([:web]) }
61
+
62
+ before do
63
+ servers.add_role(:app, %w{1 2 3})
64
+ servers.add_role(:web, %w{2 3 4})
65
+ end
66
+
67
+ it "returns an array of the roles" do
68
+ expect(servers.roles_for([:app]).collect(&:roles)).to eq [app, web_app, web_app]
69
+ expect(servers.roles_for([:web]).collect(&:roles)).to eq [web_app, web_app, web]
70
+ end
71
+ end
72
+
73
+ describe "finding the primary server" do
74
+ after do
75
+ Configuration.reset!
76
+ end
77
+ it "takes the first server if none have the primary property" do
78
+ servers.add_role(:app, %w{1 2})
79
+ expect(servers.fetch_primary(:app).hostname).to eq("1")
80
+ end
81
+
82
+ it "takes the first server with the primary have the primary flag" do
83
+ servers.add_role(:app, %w{1 2})
84
+ servers.add_host("2", primary: true)
85
+ expect(servers.fetch_primary(:app).hostname).to eq("2")
86
+ end
87
+
88
+ it "ignores any on_filters" do
89
+ Configuration.env.set :filter, host: "1"
90
+ servers.add_role(:app, %w{1 2})
91
+ servers.add_host("2", primary: true)
92
+ expect(servers.fetch_primary(:app).hostname).to eq("2")
93
+ end
94
+ end
95
+
96
+ describe "fetching servers" do
97
+ before do
98
+ servers.add_role(:app, %w{1 2})
99
+ servers.add_role(:web, %w{2 3})
100
+ end
101
+
102
+ it "returns the correct app servers" do
103
+ expect(servers.roles_for([:app]).map(&:hostname)).to eq %w{1 2}
104
+ end
105
+
106
+ it "returns the correct web servers" do
107
+ expect(servers.roles_for([:web]).map(&:hostname)).to eq %w{2 3}
108
+ end
109
+
110
+ it "returns the correct app and web servers" do
111
+ expect(servers.roles_for(%i(app web)).map(&:hostname)).to eq %w{1 2 3}
112
+ end
113
+
114
+ it "returns all servers" do
115
+ expect(servers.roles_for([:all]).map(&:hostname)).to eq %w{1 2 3}
116
+ end
117
+ end
118
+
119
+ describe "adding a server" do
120
+ before do
121
+ servers.add_host("1", roles: [:app, "web"], test: :value)
122
+ end
123
+
124
+ it "can create a server with properties" do
125
+ expect(servers.roles_for([:app]).first.hostname).to eq "1"
126
+ expect(servers.roles_for([:web]).first.hostname).to eq "1"
127
+ expect(servers.roles_for([:all]).first.properties.test).to eq :value
128
+ expect(servers.roles_for([:all]).first.properties.keys).to eq [:test]
129
+ end
130
+
131
+ it "can accept multiple servers with the same hostname but different ports or users" do
132
+ servers.add_host("1", roles: [:app, "web"], test: :value, port: 12)
133
+ expect(servers.count).to eq(2)
134
+ servers.add_host("1", roles: [:app, "web"], test: :value, port: 34)
135
+ servers.add_host("1", roles: [:app, "web"], test: :value, user: "root")
136
+ servers.add_host("1", roles: [:app, "web"], test: :value, user: "deployer")
137
+ servers.add_host("1", roles: [:app, "web"], test: :value, user: "root", port: 34)
138
+ servers.add_host("1", roles: [:app, "web"], test: :value, user: "deployer", port: 34)
139
+ servers.add_host("1", roles: [:app, "web"], test: :value, user: "deployer", port: 56)
140
+ expect(servers.count).to eq(4)
141
+ end
142
+
143
+ describe "with a :user property" do
144
+ it "sets the server ssh username" do
145
+ servers.add_host("1", roles: [:app, "web"], user: "nick")
146
+ expect(servers.count).to eq(1)
147
+ expect(servers.roles_for([:all]).first.user).to eq "nick"
148
+ end
149
+
150
+ it "overwrites the value of a user specified in the hostname" do
151
+ servers.add_host("brian@1", roles: [:app, "web"], user: "nick")
152
+ expect(servers.count).to eq(1)
153
+ expect(servers.roles_for([:all]).first.user).to eq "nick"
154
+ end
155
+ end
156
+
157
+ it "overwrites the value of a previously defined scalar property" do
158
+ servers.add_host("1", roles: [:app, "web"], test: :volatile)
159
+ expect(servers.count).to eq(1)
160
+ expect(servers.roles_for([:all]).first.properties.test).to eq :volatile
161
+ end
162
+
163
+ it "merges previously defined hash properties" do
164
+ servers.add_host("1", roles: [:b], db: { port: 1234 })
165
+ servers.add_host("1", roles: [:b], db: { master: true })
166
+ expect(servers.count).to eq(1)
167
+ expect(servers.roles_for([:b]).first.properties.db).to eq(port: 1234, master: true)
168
+ end
169
+
170
+ it "concatenates previously defined array properties" do
171
+ servers.add_host("1", roles: [:b], steps: [1, 3, 5])
172
+ servers.add_host("1", roles: [:b], steps: [1, 9])
173
+ expect(servers.count).to eq(1)
174
+ expect(servers.roles_for([:b]).first.properties.steps).to eq([1, 3, 5, 1, 9])
175
+ end
176
+
177
+ it "merges previously defined set properties" do
178
+ servers.add_host("1", roles: [:b], endpoints: Set[123, 333])
179
+ servers.add_host("1", roles: [:b], endpoints: Set[222, 333])
180
+ expect(servers.count).to eq(1)
181
+ expect(servers.roles_for([:b]).first.properties.endpoints).to eq(Set[123, 222, 333])
182
+ end
183
+
184
+ it "adds array property value only ones for a new host" do
185
+ servers.add_host("2", roles: [:array_test], array_property: [1, 2])
186
+ expect(servers.roles_for([:array_test]).first.properties.array_property).to eq [1, 2]
187
+ end
188
+
189
+ it "updates roles when custom user defined" do
190
+ servers.add_host("1", roles: ["foo"], user: "custom")
191
+ servers.add_host("1", roles: ["bar"], user: "custom")
192
+ expect(servers.roles_for([:foo]).first.hostname).to eq "1"
193
+ expect(servers.roles_for([:bar]).first.hostname).to eq "1"
194
+ end
195
+
196
+ it "updates roles when custom port defined" do
197
+ servers.add_host("1", roles: ["foo"], port: 1234)
198
+ servers.add_host("1", roles: ["bar"], port: 1234)
199
+ expect(servers.roles_for([:foo]).first.hostname).to eq "1"
200
+ expect(servers.roles_for([:bar]).first.hostname).to eq "1"
201
+ end
202
+ end
203
+
204
+ describe "selecting roles" do
205
+ before do
206
+ servers.add_host("1", roles: :app, active: true)
207
+ servers.add_host("2", roles: :app)
208
+ end
209
+
210
+ it "is empty if the filter would remove all matching hosts" do
211
+ expect(servers.roles_for([:app, select: :inactive])).to be_empty
212
+ end
213
+
214
+ it "can filter hosts by properties on the host object using symbol as shorthand" do
215
+ expect(servers.roles_for([:app, filter: :active]).length).to eq 1
216
+ end
217
+
218
+ it "can select hosts by properties on the host object using symbol as shorthand" do
219
+ expect(servers.roles_for([:app, select: :active]).length).to eq 1
220
+ end
221
+
222
+ it "can filter hosts by properties on the host using a regular proc" do
223
+ expect(servers.roles_for([:app, filter: ->(h) { h.properties.active }]).length).to eq 1
224
+ end
225
+
226
+ it "can select hosts by properties on the host using a regular proc" do
227
+ expect(servers.roles_for([:app, select: ->(h) { h.properties.active }]).length).to eq 1
228
+ end
229
+
230
+ it "is empty if the regular proc filter would remove all matching hosts" do
231
+ expect(servers.roles_for([:app, select: ->(h) { h.properties.inactive }])).to be_empty
232
+ end
233
+ end
234
+
235
+ describe "excluding by property" do
236
+ before do
237
+ servers.add_host("1", roles: :app, active: true)
238
+ servers.add_host("2", roles: :app, active: true, no_release: true)
239
+ end
240
+
241
+ it "is empty if the filter would remove all matching hosts" do
242
+ hosts = servers.roles_for([:app, exclude: :active])
243
+ expect(hosts.map(&:hostname)).to be_empty
244
+ end
245
+
246
+ it "returns the servers without the attributes specified" do
247
+ hosts = servers.roles_for([:app, exclude: :no_release])
248
+ expect(hosts.map(&:hostname)).to eq %w{1}
249
+ end
250
+
251
+ it "can exclude hosts by properties on the host using a regular proc" do
252
+ hosts = servers.roles_for([:app, exclude: ->(h) { h.properties.no_release }])
253
+ expect(hosts.map(&:hostname)).to eq %w{1}
254
+ end
255
+
256
+ it "is empty if the regular proc filter would remove all matching hosts" do
257
+ hosts = servers.roles_for([:app, exclude: ->(h) { h.properties.active }])
258
+ expect(hosts.map(&:hostname)).to be_empty
259
+ end
260
+ end
261
+
262
+ describe "filtering roles internally" do
263
+ before do
264
+ servers.add_host("1", roles: :app, active: true)
265
+ servers.add_host("2", roles: :app)
266
+ servers.add_host("3", roles: :web)
267
+ servers.add_host("4", roles: :web)
268
+ servers.add_host("5", roles: :db)
269
+ end
270
+
271
+ subject { servers.roles_for(roles).map(&:hostname) }
272
+
273
+ context "with the ROLES environment variable set" do
274
+ before do
275
+ ENV.stubs(:[]).with("ROLES").returns("web,db")
276
+ ENV.stubs(:[]).with("HOSTS").returns(nil)
277
+ end
278
+
279
+ context "when selecting all roles" do
280
+ let(:roles) { [:all] }
281
+ it "ignores it" do
282
+ expect(subject).to eq %w{1 2 3 4 5}
283
+ end
284
+ end
285
+
286
+ context "when selecting specific roles" do
287
+ let(:roles) { %i(app web) }
288
+ it "ignores it" do
289
+ expect(subject).to eq %w{1 2 3 4}
290
+ end
291
+ end
292
+
293
+ context "when selecting roles not included in ROLE" do
294
+ let(:roles) { [:app] }
295
+ it "ignores it" do
296
+ expect(subject).to eq %w{1 2}
297
+ end
298
+ end
299
+ end
300
+
301
+ context "with the HOSTS environment variable set" do
302
+ before do
303
+ ENV.stubs(:[]).with("ROLES").returns(nil)
304
+ ENV.stubs(:[]).with("HOSTS").returns("3,5")
305
+ end
306
+
307
+ context "when selecting all roles" do
308
+ let(:roles) { [:all] }
309
+ it "ignores it" do
310
+ expect(subject).to eq %w{1 2 3 4 5}
311
+ end
312
+ end
313
+
314
+ context "when selecting specific roles" do
315
+ let(:roles) { %i(app web) }
316
+ it "ignores it" do
317
+ expect(subject).to eq %w{1 2 3 4}
318
+ end
319
+ end
320
+
321
+ context "when selecting no roles" do
322
+ let(:roles) { [] }
323
+ it "ignores it" do
324
+ expect(subject).to be_empty
325
+ end
326
+ end
327
+ end
328
+ end
329
+ end
330
+ end
331
+ end