capistrano 2.8.0 → 3.19.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 (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