capistrano 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +89 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +674 -0
- data/README.md +226 -0
- data/Rakefile +5 -0
- data/bin/cap +2 -3
- data/bin/capify +7 -77
- data/capistrano-public_cert.pem +22 -0
- data/capistrano.gemspec +35 -0
- data/features/deploy.feature +52 -0
- data/features/installation.feature +16 -0
- data/features/remote_file_task.feature +14 -0
- data/features/step_definitions/assertions.rb +90 -0
- data/features/step_definitions/cap_commands.rb +8 -0
- data/features/step_definitions/setup.rb +25 -0
- data/features/support/env.rb +12 -0
- data/features/support/remote_command_helpers.rb +20 -0
- data/lib/Capfile +3 -0
- data/lib/capistrano/all.rb +16 -0
- data/lib/capistrano/application.rb +60 -0
- data/lib/capistrano/configuration/question.rb +42 -0
- data/lib/capistrano/configuration/server.rb +133 -0
- data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
- data/lib/capistrano/configuration/servers.rb +53 -58
- data/lib/capistrano/configuration.rb +84 -30
- data/lib/capistrano/console.rb +1 -0
- data/lib/capistrano/defaults.rb +13 -0
- data/lib/capistrano/deploy.rb +3 -0
- data/lib/capistrano/dotfile.rb +3 -0
- data/lib/capistrano/dsl/env.rb +64 -0
- data/lib/capistrano/dsl/paths.rb +94 -0
- data/lib/capistrano/dsl/stages.rb +15 -0
- data/lib/capistrano/dsl/task_enhancements.rb +53 -0
- data/lib/capistrano/dsl.rb +48 -0
- data/lib/capistrano/git.rb +1 -0
- data/lib/capistrano/hg.rb +1 -0
- data/lib/capistrano/i18n.rb +34 -0
- data/lib/capistrano/install.rb +1 -0
- data/lib/capistrano/setup.rb +21 -0
- data/lib/capistrano/tasks/console.rake +21 -0
- data/lib/capistrano/tasks/deploy.rake +204 -0
- data/lib/capistrano/tasks/framework.rake +67 -0
- data/lib/capistrano/tasks/git.rake +62 -0
- data/lib/capistrano/tasks/hg.rake +39 -0
- data/lib/capistrano/tasks/install.rake +39 -0
- data/lib/capistrano/templates/Capfile +26 -0
- data/lib/capistrano/templates/deploy.rb.erb +40 -0
- data/lib/capistrano/templates/stage.rb.erb +42 -0
- data/lib/capistrano/version.rb +1 -20
- data/lib/capistrano/version_validator.rb +37 -0
- data/lib/capistrano.rb +0 -2
- data/spec/integration/dsl_spec.rb +344 -0
- data/spec/integration_spec_helper.rb +7 -0
- data/spec/lib/capistrano/application_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +249 -0
- data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +184 -0
- data/spec/lib/capistrano/configuration_spec.rb +101 -0
- data/spec/lib/capistrano/dsl/env_spec.rb +10 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
- data/spec/lib/capistrano/dsl_spec.rb +63 -0
- data/spec/lib/capistrano/version_validator_spec.rb +103 -0
- data/spec/lib/capistrano_spec.rb +8 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/.gitignore +1 -0
- data/spec/support/Vagrantfile +13 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/support/tasks/database.cap +11 -0
- data/spec/support/test_app.rb +138 -0
- metadata +251 -179
- data/CHANGELOG +0 -512
- data/MIT-LICENSE +0 -20
- data/README +0 -43
- data/examples/sample.rb +0 -14
- data/lib/capistrano/callback.rb +0 -45
- data/lib/capistrano/cli/execute.rb +0 -82
- data/lib/capistrano/cli/help.rb +0 -102
- data/lib/capistrano/cli/help.txt +0 -53
- data/lib/capistrano/cli/options.rb +0 -183
- data/lib/capistrano/cli/ui.rb +0 -28
- data/lib/capistrano/cli.rb +0 -47
- data/lib/capistrano/command.rb +0 -161
- data/lib/capistrano/configuration/actions/file_transfer.rb +0 -35
- data/lib/capistrano/configuration/actions/inspect.rb +0 -46
- data/lib/capistrano/configuration/actions/invocation.rb +0 -134
- data/lib/capistrano/configuration/callbacks.rb +0 -148
- data/lib/capistrano/configuration/connections.rb +0 -159
- data/lib/capistrano/configuration/execution.rb +0 -126
- data/lib/capistrano/configuration/loading.rb +0 -198
- data/lib/capistrano/configuration/namespaces.rb +0 -196
- data/lib/capistrano/configuration/roles.rb +0 -51
- data/lib/capistrano/configuration/variables.rb +0 -127
- data/lib/capistrano/errors.rb +0 -15
- data/lib/capistrano/extensions.rb +0 -57
- data/lib/capistrano/gateway.rb +0 -131
- data/lib/capistrano/logger.rb +0 -59
- data/lib/capistrano/recipes/compat.rb +0 -32
- data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
- data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -46
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -96
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
- data/lib/capistrano/recipes/deploy/scm/base.rb +0 -192
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -151
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -85
- data/lib/capistrano/recipes/deploy/scm/git.rb +0 -191
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -129
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -126
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -114
- data/lib/capistrano/recipes/deploy/scm.rb +0 -19
- data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -64
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -144
- data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -47
- data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/deploy.rb +0 -494
- data/lib/capistrano/recipes/standard.rb +0 -37
- data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/upgrade.rb +0 -33
- data/lib/capistrano/server_definition.rb +0 -51
- data/lib/capistrano/shell.rb +0 -256
- data/lib/capistrano/ssh.rb +0 -109
- data/lib/capistrano/task_definition.rb +0 -69
- data/lib/capistrano/upload.rb +0 -146
- data/test/cli/execute_test.rb +0 -132
- data/test/cli/help_test.rb +0 -139
- data/test/cli/options_test.rb +0 -226
- data/test/cli/ui_test.rb +0 -28
- data/test/cli_test.rb +0 -17
- data/test/command_test.rb +0 -309
- data/test/configuration/actions/file_transfer_test.rb +0 -40
- data/test/configuration/actions/inspect_test.rb +0 -62
- data/test/configuration/actions/invocation_test.rb +0 -202
- data/test/configuration/callbacks_test.rb +0 -206
- data/test/configuration/connections_test.rb +0 -288
- data/test/configuration/execution_test.rb +0 -159
- data/test/configuration/loading_test.rb +0 -127
- data/test/configuration/namespace_dsl_test.rb +0 -297
- data/test/configuration/roles_test.rb +0 -47
- data/test/configuration/servers_test.rb +0 -90
- data/test/configuration/variables_test.rb +0 -180
- data/test/configuration_test.rb +0 -81
- data/test/deploy/scm/accurev_test.rb +0 -23
- data/test/deploy/scm/base_test.rb +0 -55
- data/test/deploy/scm/git_test.rb +0 -112
- data/test/deploy/strategy/copy_test.rb +0 -147
- data/test/extensions_test.rb +0 -69
- data/test/fixtures/cli_integration.rb +0 -5
- data/test/fixtures/config.rb +0 -5
- data/test/fixtures/custom.rb +0 -3
- data/test/gateway_test.rb +0 -167
- data/test/logger_test.rb +0 -123
- data/test/server_definition_test.rb +0 -108
- data/test/shell_test.rb +0 -64
- data/test/ssh_test.rb +0 -97
- data/test/task_definition_test.rb +0 -101
- data/test/upload_test.rb +0 -131
- data/test/utils.rb +0 -42
- data/test/version_test.rb +0 -24
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
describe Server do
|
6
|
+
let(:server) { Server.new('hostname') }
|
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([: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
|
+
|
23
|
+
describe 'checking roles' do
|
24
|
+
subject { server.has_role?(:test) }
|
25
|
+
|
26
|
+
before do
|
27
|
+
server.add_role(:test)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'adds the role' do
|
31
|
+
expect{subject}.to be_true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'comparing identity' do
|
36
|
+
subject { server.matches? hostname }
|
37
|
+
|
38
|
+
context 'with the same hostname' do
|
39
|
+
let(:hostname) { 'hostname' }
|
40
|
+
it { should be_true }
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with the same hostname and a user' do
|
44
|
+
let(:hostname) { 'user@hostname' }
|
45
|
+
it { should be_true }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with a different hostname' do
|
49
|
+
let(:hostname) { 'otherserver' }
|
50
|
+
it { should be_false }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'identifying as primary' do
|
55
|
+
subject { server.primary }
|
56
|
+
context 'server is primary' do
|
57
|
+
before do
|
58
|
+
server.set(:primary, true)
|
59
|
+
end
|
60
|
+
it 'returns self' do
|
61
|
+
expect(subject).to eq server
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'server is not primary' do
|
66
|
+
it 'is falesy' do
|
67
|
+
expect(subject).to be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'assigning properties' do
|
73
|
+
|
74
|
+
before do
|
75
|
+
server.with(properties)
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'properties contains roles' do
|
79
|
+
let(:properties) { {roles: [:clouds]} }
|
80
|
+
|
81
|
+
it 'adds the roles' do
|
82
|
+
expect(server.roles.first).to eq :clouds
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'properties contains user' do
|
87
|
+
let(:properties) { {user: 'tomc'} }
|
88
|
+
|
89
|
+
it 'sets the user' do
|
90
|
+
expect(server.user).to eq 'tomc'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'properties contains port' do
|
95
|
+
let(:properties) { {port: 2222} }
|
96
|
+
|
97
|
+
it 'sets the port' do
|
98
|
+
expect(server.port).to eq 2222
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'properties contains key' do
|
103
|
+
let(:properties) { {key: '/key'} }
|
104
|
+
|
105
|
+
it 'adds the key' do
|
106
|
+
expect(server.keys).to include '/key'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'properties contains password' do
|
111
|
+
let(:properties) { {password: 'supersecret'} }
|
112
|
+
|
113
|
+
it 'adds the key' do
|
114
|
+
expect(server.password).to eq 'supersecret'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'new properties' do
|
119
|
+
let(:properties) { { webscales: 5 } }
|
120
|
+
|
121
|
+
it 'adds the properties' do
|
122
|
+
expect(server.properties.webscales).to eq 5
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'existing properties' do
|
127
|
+
let(:properties) { { webscales: 6 } }
|
128
|
+
|
129
|
+
it 'keeps the existing properties' do
|
130
|
+
expect(server.properties.webscales).to eq 6
|
131
|
+
server.properties.webscales = 5
|
132
|
+
expect(server.properties.webscales).to eq 5
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#include?' do
|
138
|
+
let(:options) { {} }
|
139
|
+
|
140
|
+
subject { server.select?(options) }
|
141
|
+
|
142
|
+
before do
|
143
|
+
server.properties.active = true
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'options are empty' do
|
147
|
+
it { should be_true }
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'value is a symbol' do
|
151
|
+
context 'value matches server property' do
|
152
|
+
|
153
|
+
context 'with :filter' do
|
154
|
+
let(:options) { { filter: :active }}
|
155
|
+
it { should be_true }
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'with :select' do
|
159
|
+
let(:options) { { select: :active }}
|
160
|
+
it { should be_true }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'value does not match server properly' do
|
165
|
+
context 'with :filter' do
|
166
|
+
let(:options) { { filter: :inactive }}
|
167
|
+
it { should be_false }
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'with :select' do
|
171
|
+
let(:options) { { select: :inactive }}
|
172
|
+
it { should be_false }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'value is a proc' do
|
178
|
+
context 'value matches server property' do
|
179
|
+
|
180
|
+
context 'with :filter' do
|
181
|
+
let(:options) { { filter: ->(s) { s.properties.active } } }
|
182
|
+
it { should be_true }
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'with :select' do
|
186
|
+
let(:options) { { select: ->(s) { s.properties.active } } }
|
187
|
+
it { should be_true }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'value does not match server properly' do
|
192
|
+
context 'with :filter' do
|
193
|
+
let(:options) { { filter: ->(s) { s.properties.inactive } } }
|
194
|
+
it { should be_false }
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'with :select' do
|
198
|
+
let(:options) { { select: ->(s) { s.properties.inactive } } }
|
199
|
+
it { should be_false }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
describe 'assign ssh_options' do
|
207
|
+
let(:server) { Server.new('user_name@hostname') }
|
208
|
+
|
209
|
+
context 'defaults' do
|
210
|
+
it 'forward agent' do
|
211
|
+
expect(server.netssh_options[:forward_agent]).to eq true
|
212
|
+
end
|
213
|
+
it 'contains user' do
|
214
|
+
expect(server.netssh_options[:user]).to eq 'user_name'
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context 'custom' do
|
219
|
+
let(:properties) do
|
220
|
+
{ ssh_options: {
|
221
|
+
user: 'another_user',
|
222
|
+
keys: %w(/home/another_user/.ssh/id_rsa),
|
223
|
+
forward_agent: false,
|
224
|
+
auth_methods: %w(publickey password) } }
|
225
|
+
end
|
226
|
+
|
227
|
+
before do
|
228
|
+
server.with(properties)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'not forward agent' do
|
232
|
+
expect(server.netssh_options[:forward_agent]).to eq false
|
233
|
+
end
|
234
|
+
it 'contains correct user' do
|
235
|
+
expect(server.netssh_options[:user]).to eq 'another_user'
|
236
|
+
end
|
237
|
+
it 'contains keys' do
|
238
|
+
expect(server.netssh_options[:keys]).to eq %w(/home/another_user/.ssh/id_rsa)
|
239
|
+
end
|
240
|
+
it 'contains auth_methods' do
|
241
|
+
expect(server.netssh_options[:auth_methods]).to eq %w(publickey password)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
class Servers
|
6
|
+
|
7
|
+
describe RoleFilter do
|
8
|
+
let(:role_filter) { RoleFilter.new(required, available) }
|
9
|
+
let(:required) { [] }
|
10
|
+
let(:available) { [:web, :app, :db] }
|
11
|
+
|
12
|
+
describe '#new' do
|
13
|
+
it 'takes two arrays of role names' do
|
14
|
+
expect(role_filter)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.for' do
|
19
|
+
|
20
|
+
subject { RoleFilter.for(required, available) }
|
21
|
+
|
22
|
+
context 'without env vars' do
|
23
|
+
context ':all required' do
|
24
|
+
let(:required) { [:all] }
|
25
|
+
|
26
|
+
it 'returns all available names' do
|
27
|
+
expect(subject).to eq available
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'role names required' do
|
32
|
+
let(:required) { [:web, :app] }
|
33
|
+
it 'returns all required names' do
|
34
|
+
expect(subject).to eq required
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with ENV vars' do
|
40
|
+
before do
|
41
|
+
ENV.stubs(:[]).with('ROLES').returns('app,web')
|
42
|
+
end
|
43
|
+
|
44
|
+
context ':all required' do
|
45
|
+
let(:required) { [:all] }
|
46
|
+
|
47
|
+
it 'returns available names defined in ROLES' do
|
48
|
+
expect(subject).to eq [:app, :web]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'role names required' do
|
53
|
+
let(:required) { [:web, :db] }
|
54
|
+
it 'returns all required names defined in ROLES' do
|
55
|
+
expect(subject).to eq [:web]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with configuration filters' do
|
61
|
+
before do
|
62
|
+
Configuration.env.set(:filter, roles: %w{app web})
|
63
|
+
end
|
64
|
+
|
65
|
+
context ':all required' do
|
66
|
+
let(:required) { [:all] }
|
67
|
+
|
68
|
+
it 'returns available names defined in the filter' do
|
69
|
+
expect(subject).to eq [:app, :web]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'role names required' do
|
74
|
+
let(:required) { [:web, :db] }
|
75
|
+
it 'returns all required names defined in the filter' do
|
76
|
+
expect(subject).to eq [:web]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
after do
|
81
|
+
Configuration.env.delete(:filter)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a single configuration filter' do
|
86
|
+
before do
|
87
|
+
Configuration.env.set(:filter, roles: 'web')
|
88
|
+
end
|
89
|
+
|
90
|
+
context ':all required' do
|
91
|
+
let(:required) { [:all] }
|
92
|
+
|
93
|
+
it 'returns available names defined in the filter' do
|
94
|
+
expect(subject).to eq [:web]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'role names required' do
|
99
|
+
let(:required) { [:web, :db] }
|
100
|
+
it 'returns all required names defined in the filter' do
|
101
|
+
expect(subject).to eq [:web]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
after do
|
106
|
+
Configuration.env.delete(:filter)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with configuration filters and ENV vars' do
|
111
|
+
before do
|
112
|
+
Configuration.env.set(:filter, roles: %w{app})
|
113
|
+
ENV.stubs(:[]).with('ROLES').returns('web')
|
114
|
+
end
|
115
|
+
|
116
|
+
context ':all required' do
|
117
|
+
let(:required) { [:all] }
|
118
|
+
|
119
|
+
it 'returns available names defined in the filter' do
|
120
|
+
expect(subject).to eq [:web, :app]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'role names required' do
|
125
|
+
let(:required) { [:web, :db] }
|
126
|
+
it 'returns all required names defined in the filter' do
|
127
|
+
expect(subject).to eq [:web]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
after do
|
132
|
+
Configuration.env.delete(:filter)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,184 @@
|
|
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
|
+
|
10
|
+
it 'adds two new server instances' do
|
11
|
+
expect{servers.add_role(:app, %w{1 2})}.
|
12
|
+
to change{servers.count}.from(0).to(2)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'handles de-duplification within roles' do
|
16
|
+
servers.add_role(:app, %w{1})
|
17
|
+
servers.add_role(:app, %w{1})
|
18
|
+
expect(servers.count).to eq 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'accepts instances of server objects' do
|
22
|
+
servers.add_role(:app, [Capistrano::Configuration::Server.new('example.net'), 'example.com'])
|
23
|
+
expect(servers.roles_for([:app]).length).to eq 2
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'accepts non-enumerable types' do
|
27
|
+
servers.add_role(:app, '1')
|
28
|
+
expect(servers.roles_for([:app]).count).to eq 1
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'adding a role to an existing server' do
|
34
|
+
before do
|
35
|
+
servers.add_role(:web, %w{1 2})
|
36
|
+
servers.add_role(:app, %w{1 2})
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'adds new roles to existing servers' do
|
40
|
+
expect(servers.count).to eq 2
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'collecting server roles' do
|
46
|
+
let(:app) { Set.new([:app]) }
|
47
|
+
let(:web_app) { Set.new([:web, :app]) }
|
48
|
+
let(:web) { Set.new([:web]) }
|
49
|
+
|
50
|
+
before do
|
51
|
+
servers.add_role(:app, %w{1 2 3})
|
52
|
+
servers.add_role(:web, %w{2 3 4})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns an array of the roles' do
|
56
|
+
expect(servers.roles_for([:app]).collect(&:roles)).to eq [app, web_app, web_app]
|
57
|
+
expect(servers.roles_for([:web]).collect(&:roles)).to eq [web_app, web_app, web]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'finding the primary server' do
|
62
|
+
it 'takes the first server if none have the primary property' do
|
63
|
+
servers.add_role(:app, %w{1 2})
|
64
|
+
servers.fetch_primary(:app).hostname.should == '1'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'takes the first server with the primary have the primary flag' do
|
68
|
+
servers.add_role(:app, %w{1 2})
|
69
|
+
servers.add_host('2', primary: true)
|
70
|
+
servers.fetch_primary(:app).hostname.should == '2'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'fetching servers' do
|
75
|
+
before do
|
76
|
+
servers.add_role(:app, %w{1 2})
|
77
|
+
servers.add_role(:web, %w{2 3})
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns the correct app servers' do
|
81
|
+
expect(servers.roles_for([:app]).map(&:hostname)).to eq %w{1 2}
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns the correct web servers' do
|
85
|
+
expect(servers.roles_for([:web]).map(&:hostname)).to eq %w{2 3}
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'returns the correct app and web servers' do
|
89
|
+
expect(servers.roles_for([:app, :web]).map(&:hostname)).to eq %w{1 2 3}
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns all servers' do
|
93
|
+
expect(servers.roles_for([:all]).map(&:hostname)).to eq %w{1 2 3}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'adding a server' do
|
98
|
+
|
99
|
+
before do
|
100
|
+
servers.add_host('1', roles: [:app, 'web'], test: :value)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'can create a server with properties' do
|
104
|
+
expect(servers.roles_for([:app]).first.hostname).to eq '1'
|
105
|
+
expect(servers.roles_for([:web]).first.hostname).to eq '1'
|
106
|
+
expect(servers.roles_for([:all]).first.properties.test).to eq :value
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'selecting roles' do
|
112
|
+
|
113
|
+
before do
|
114
|
+
servers.add_host('1', roles: :app, active: true)
|
115
|
+
servers.add_host('2', roles: :app)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'is empty if the filter would remove all matching hosts' do
|
119
|
+
expect(servers.roles_for([:app, select: :inactive])).to be_empty
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'can filter hosts by properties on the host object using symbol as shorthand' do
|
123
|
+
expect(servers.roles_for([:app, filter: :active]).length).to eq 1
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'can select hosts by properties on the host object using symbol as shorthand' do
|
127
|
+
expect(servers.roles_for([:app, select: :active]).length).to eq 1
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'can filter hosts by properties on the host using a regular proc' do
|
131
|
+
expect(servers.roles_for([:app, filter: ->(h) { h.properties.active }]).length).to eq 1
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'can select hosts by properties on the host using a regular proc' do
|
135
|
+
expect(servers.roles_for([:app, select: ->(h) { h.properties.active }]).length).to eq 1
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'is empty if the regular proc filter would remove all matching hosts' do
|
139
|
+
expect(servers.roles_for([:app, select: ->(h) { h.properties.inactive }])).to be_empty
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
describe 'filtering roles' do
|
145
|
+
|
146
|
+
before do
|
147
|
+
ENV.stubs(:[]).with('ROLES').returns('web,db')
|
148
|
+
servers.add_host('1', roles: :app, active: true)
|
149
|
+
servers.add_host('2', roles: :app)
|
150
|
+
servers.add_host('3', roles: :web)
|
151
|
+
servers.add_host('4', roles: :web)
|
152
|
+
servers.add_host('5', roles: :db)
|
153
|
+
end
|
154
|
+
|
155
|
+
subject { servers.roles_for(roles).map(&:hostname) }
|
156
|
+
|
157
|
+
context 'when selecting all roles' do
|
158
|
+
let(:roles) { [:all] }
|
159
|
+
|
160
|
+
it 'returns the roles specified by ROLE' do
|
161
|
+
expect(subject).to eq %w{3 4 5}
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'when selecting roles included in ROLE' do
|
166
|
+
let(:roles) { [:app, :web] }
|
167
|
+
|
168
|
+
it 'returns only roles that match ROLE' do
|
169
|
+
expect(subject).to eq %w{3 4}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when selecting roles not included in ROLE' do
|
174
|
+
let(:roles) { [:app] }
|
175
|
+
|
176
|
+
it 'is empty' do
|
177
|
+
expect(subject).to be_empty
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
describe Configuration do
|
5
|
+
let(:config) { Configuration.new }
|
6
|
+
let(:servers) { stub }
|
7
|
+
|
8
|
+
describe '.env' do
|
9
|
+
it 'is a global accessor to a single instance' do
|
10
|
+
Configuration.env.set(:test, true)
|
11
|
+
expect(Configuration.env.fetch(:test)).to be_true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'roles' do
|
16
|
+
context 'adding a role' do
|
17
|
+
subject { config.role(:app, %w{server1 server2}) }
|
18
|
+
|
19
|
+
before do
|
20
|
+
Configuration::Servers.expects(:new).returns(servers)
|
21
|
+
servers.expects(:add_role).with(:app, %w{server1 server2}, {})
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'adds the role' do
|
25
|
+
expect(subject)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'setting and fetching' do
|
31
|
+
subject { config.fetch(:key, :default) }
|
32
|
+
|
33
|
+
context 'value is set' do
|
34
|
+
before do
|
35
|
+
config.set(:key, :value)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns the set value' do
|
39
|
+
expect(subject).to eq :value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'value is not set' do
|
44
|
+
it 'returns the default value' do
|
45
|
+
expect(subject).to eq :default
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'value is a proc' do
|
50
|
+
subject { config.fetch(:key, Proc.new { :proc } ) }
|
51
|
+
it 'calls the proc' do
|
52
|
+
expect(subject).to eq :proc
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'block is passed to fetch' do
|
57
|
+
subject { config.fetch(:key, :default) { fail 'we need this!' } }
|
58
|
+
|
59
|
+
it 'returns the block value' do
|
60
|
+
expect { subject }.to raise_error
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'deleting' do
|
66
|
+
before do
|
67
|
+
config.set(:key, :value)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'deletes the value' do
|
71
|
+
config.delete(:key)
|
72
|
+
expect(config.fetch(:key)).to be_nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'asking' do
|
77
|
+
let(:question) { stub }
|
78
|
+
|
79
|
+
before do
|
80
|
+
Configuration::Question.expects(:new).with(config, :branch, :default).
|
81
|
+
returns(question)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'prompts for the value when fetching' do
|
85
|
+
config.ask(:branch, :default)
|
86
|
+
expect(config.fetch(:branch)).to eq question
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'setting the backend' do
|
91
|
+
it 'by default, is SSHKit' do
|
92
|
+
expect(config.backend).to eq SSHKit
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'can be set to another class' do
|
96
|
+
config.backend = :test
|
97
|
+
expect(config.backend).to eq :test
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|