capistrano 2.1.0 → 3.0.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.
- 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
|