capistrano-scope 0.0.1

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 (3) hide show
  1. data/README +337 -0
  2. data/lib/capistrano/scope.rb +112 -0
  3. metadata +85 -0
data/README ADDED
@@ -0,0 +1,337 @@
1
+
2
+
3
+
4
+ # -------------------------------------------------------------------------
5
+ # clientx.rb capistrano config file
6
+
7
+ # The order you specify servers or roles doesn't matter, you can define
8
+ # scope.role for a server before you define scope.server or visa versa.
9
+ # You can give servers any name you like but they are broken into logical
10
+ # groups by using the ":" separator.
11
+
12
+ scope.server 'clienta:projectx:staging:lb:1', '123.456.567.1'
13
+ scope.server 'clienta:projectx:staging:lb:2', '123.456.567.2'
14
+ scope.server 'clienta:projectx:staging:app:1', '123.456.567.3'
15
+ scope.server 'clienta:projectx:staging:app:2', '123.456.567.4'
16
+ scope.server 'clienta:projectx:staging:db:1', '123.456.567.5'
17
+ scope.server 'clienta:projectx:staging:db:2', '123.456.567.6'
18
+
19
+ scope.server 'clienta:projectx:production:lb:1', '123.456.567.7'
20
+ scope.server 'clienta:projectx:production:lb:2', '123.456.567.8'
21
+ scope.server 'clienta:projectx:production:app:1', '123.456.567.9'
22
+ scope.server 'clienta:projectx:production:app:2', '123.456.567.10'
23
+ scope.server 'clienta:projectx:production:db:1', '123.456.567.12'
24
+ scope.server 'clienta:projectx:production:db:2', '123.456.567.13'
25
+
26
+ scope.server 'clienta:projecty:staging:lb:1', '123.456.567.1'
27
+ scope.server 'clienta:projecty:staging:lb:2', '123.456.567.2'
28
+ scope.server 'clienta:projecty:staging:app:1', '123.456.567.3'
29
+ scope.server 'clienta:projecty:staging:app:2', '123.456.567.4'
30
+ scope.server 'clienta:projecty:staging:db:1', '123.456.567.5'
31
+ scope.server 'clienta:projecty:staging:db:2', '123.456.567.6'
32
+
33
+ scope.server 'clienta:projecty:production:lb:1', '123.456.567.7'
34
+ scope.server 'clienta:projecty:production:lb:2', '123.456.567.8'
35
+ scope.server 'clienta:projecty:production:app:1', '123.456.567.9'
36
+ scope.server 'clienta:projecty:production:app:2', '123.456.567.10'
37
+ scope.server 'clienta:projecty:production:db:1', '123.456.567.12'
38
+ scope.server 'clienta:projecty:production:db:2', '123.456.567.13'
39
+
40
+
41
+ scope.role :server, 'clienta:projectx:staging:lb:1'
42
+ scope.role :server, 'clienta:projectx:staging:lb:2'
43
+ scope.role :server, 'clienta:projectx:staging:app:1'
44
+ scope.role :server, 'clienta:projectx:staging:app:2'
45
+ scope.role :server, 'clienta:projectx:staging:db:1'
46
+ scope.role :server, 'clienta:projectx:staging:db:2'
47
+ scope.role :server, 'clienta:projectx:production:lb:1'
48
+ scope.role :server, 'clienta:projectx:production:lb:2'
49
+ scope.role :server, 'clienta:projectx:production:app:1'
50
+ scope.role :server, 'clienta:projectx:production:app:2'
51
+ scope.role :server, 'clienta:projectx:production:db:1'
52
+ scope.role :server, 'clienta:projectx:production:db:2'
53
+ scope.role :server, 'clienta:projecty:staging:lb:1'
54
+ scope.role :server, 'clienta:projecty:staging:lb:2'
55
+ scope.role :server, 'clienta:projecty:staging:app:1'
56
+ scope.role :server, 'clienta:projecty:staging:app:2'
57
+ scope.role :server, 'clienta:projecty:staging:db:1'
58
+ scope.role :server, 'clienta:projecty:staging:db:2'
59
+ scope.role :server, 'clienta:projecty:production:lb:1'
60
+ scope.role :server, 'clienta:projecty:production:lb:2'
61
+ scope.role :server, 'clienta:projecty:production:app:1'
62
+ scope.role :server, 'clienta:projecty:production:app:2'
63
+ scope.role :server, 'clienta:projecty:production:db:1'
64
+ scope.role :server, 'clienta:projecty:production:db:2'
65
+
66
+ scope.role :load_balancer, 'clienta:projectx:staging:lb:1'
67
+ scope.role :load_balancer, 'clienta:projectx:staging:lb:2'
68
+ scope.role :load_balancer, 'clienta:projectx:production:lb:1'
69
+ scope.role :load_balancer, 'clienta:projectx:production:lb:2'
70
+ scope.role :load_balancer, 'clienta:projecty:staging:lb:1'
71
+ scope.role :load_balancer, 'clienta:projecty:staging:lb:2'
72
+ scope.role :load_balancer, 'clienta:projecty:production:lb:1'
73
+ scope.role :load_balancer, 'clienta:projecty:production:lb:2'
74
+
75
+ scope.role :app, 'clienta:projectx:staging:app:1'
76
+ scope.role :app, 'clienta:projectx:staging:app:2'
77
+ scope.role :app, 'clienta:projectx:production:app:1'
78
+ scope.role :app, 'clienta:projectx:production:app:2'
79
+ scope.role :app, 'clienta:projecty:staging:app:1'
80
+ scope.role :app, 'clienta:projecty:staging:app:2'
81
+ scope.role :app, 'clienta:projecty:production:app:1'
82
+ scope.role :app, 'clienta:projecty:production:app:2'
83
+
84
+ scope.role :db, 'clienta:projectx:staging:db:1', :primary => true
85
+ scope.role :db, 'clienta:projectx:staging:db:2'
86
+ scope.role :db, 'clienta:projectx:production:db:1', :primary => true
87
+ scope.role :db, 'clienta:projectx:production:db:2'
88
+ scope.role :db, 'clienta:projecty:staging:db:1', :primary => true
89
+ scope.role :db, 'clienta:projecty:staging:db:2'
90
+ scope.role :db, 'clienta:projecty:production:db:1', :primary => true
91
+ scope.role :db, 'clienta:projecty:production:db:2'
92
+
93
+ # end of clientx.rb
94
+ # -------------------------------------------------------------------------
95
+
96
+
97
+
98
+
99
+ # For the sake of demonstration lets assume we also have the following tasks
100
+ # defined and included from somewhere else.
101
+ # -------------------------------------------------------------------------
102
+ # recipes.rb
103
+
104
+ namespace :server do
105
+ desc "Concatenate Keys and upload new authorized_keys file to the server."
106
+ task :authorized_keys, :roles => :server do
107
+ ...
108
+ end
109
+
110
+ desc "Install Subversion"
111
+ task :install_subversion, :roles => :server do
112
+ ...
113
+ end
114
+ end
115
+
116
+ namespace :mysql do
117
+ desc "Backup Database"
118
+ task :backup, :roles => :db do
119
+ ...
120
+ end
121
+ end
122
+
123
+ namespace :app do
124
+ desc "Install bundler"
125
+ task :install_bundler, :roles => :app do
126
+ ...
127
+ end
128
+
129
+ desc "Install nginx"
130
+ task :install_nginx, :roles => :app do
131
+ ...
132
+ end
133
+
134
+ desc "Install imagemagick"
135
+ task :install_imagemagick, :roles => :app do
136
+ ...
137
+ end
138
+ end
139
+
140
+ namespace :nagios do
141
+ desc "Update nagios config on the admin server and restart nagios service"
142
+ task :deploy, :roles => :admin do
143
+ ...
144
+ end
145
+
146
+ desc "Restart the nagios SMF Service"
147
+ task :restart, :roles => :admin do
148
+ ...
149
+ end
150
+
151
+ namespace :nrpe do
152
+ desc "Install NRPE"
153
+ task :install, :roles => :server do
154
+ ...
155
+ end
156
+
157
+ desc "Update NRPE Configuration"
158
+ task :deploy, :roles => :server do
159
+ ...
160
+ end
161
+ end
162
+
163
+ namespace :plugins do
164
+ desc "Copy plugins to servers"
165
+ task :deploy, :roles => :server do
166
+ ...
167
+ end
168
+ end
169
+ end
170
+
171
+ # end of recipes.rb
172
+ # -------------------------------------------------------------------------
173
+
174
+
175
+
176
+ # Now on the command line you can see the tasks that you normally would
177
+ # by listing out tasks with descriptions.
178
+
179
+ $ cap -T
180
+
181
+ cap @:all # Scope all defined servers
182
+ cap @:show # Show the roles and servers ...
183
+ cap app:install_bundler
184
+ cap app:install_nginx
185
+ cap app:install_image_magick
186
+ cap mysql:backup
187
+ cap nagios:deploy
188
+ cap nagios:restart
189
+ cap nagios:nrpe:install
190
+ cap nagios:nrpe:deploy
191
+ cap nagios:plugins:deploy
192
+ cap server:authorized_keys
193
+ cap server:install_subversion
194
+
195
+
196
+
197
+ # And if you want to see a list of all the server scopes that you have
198
+ # defined use the verbose flag. Since we used the '@' as the top level
199
+ # namespace for our scoping tasks they should all sort to the top of the
200
+ # list and then be followed by your normal capistrano tasks.
201
+
202
+ $ cap -vT
203
+
204
+ cap @:all # Scope all defined servers
205
+ cap @:clienta:all #
206
+ cap @:clienta:projectx:all #
207
+ cap @:clienta:projectx:production:all #
208
+ cap @:clienta:projectx:production:app:1 #
209
+ cap @:clienta:projectx:production:app:2 #
210
+ cap @:clienta:projectx:production:app:all #
211
+ cap @:clienta:projectx:production:db:1 #
212
+ cap @:clienta:projectx:production:db:2 #
213
+ cap @:clienta:projectx:production:db:all #
214
+ cap @:clienta:projectx:production:lb:1 #
215
+ cap @:clienta:projectx:production:lb:2 #
216
+ cap @:clienta:projectx:production:lb:all #
217
+ cap @:clienta:projectx:staging:all #
218
+ cap @:clienta:projectx:staging:app:1 #
219
+ cap @:clienta:projectx:staging:app:2 #
220
+ cap @:clienta:projectx:staging:app:all #
221
+ cap @:clienta:projectx:staging:db:1 #
222
+ cap @:clienta:projectx:staging:db:2 #
223
+ cap @:clienta:projectx:staging:db:all #
224
+ cap @:clienta:projectx:staging:lb:1 #
225
+ cap @:clienta:projectx:staging:lb:2 #
226
+ cap @:clienta:projectx:staging:lb:all #
227
+ cap @:clienta:projecty:all #
228
+ cap @:clienta:projecty:production:all #
229
+ cap @:clienta:projecty:production:app:1 #
230
+ cap @:clienta:projecty:production:app:2 #
231
+ cap @:clienta:projecty:production:app:all #
232
+ cap @:clienta:projecty:production:db:1 #
233
+ cap @:clienta:projecty:production:db:2 #
234
+ cap @:clienta:projecty:production:db:all #
235
+ cap @:clienta:projecty:production:lb:1 #
236
+ cap @:clienta:projecty:production:lb:2 #
237
+ cap @:clienta:projecty:production:lb:all #
238
+ cap @:clienta:projecty:staging:all #
239
+ cap @:clienta:projecty:staging:app:1 #
240
+ cap @:clienta:projecty:staging:app:2 #
241
+ cap @:clienta:projecty:staging:app:all #
242
+ cap @:clienta:projecty:staging:db:1 #
243
+ cap @:clienta:projecty:staging:db:2 #
244
+ cap @:clienta:projecty:staging:db:all #
245
+ cap @:clienta:projecty:staging:lb:1 #
246
+ cap @:clienta:projecty:staging:lb:2 #
247
+ cap @:clienta:projecty:staging:lb:all #
248
+ cap @:create_role_tasks #
249
+ cap @:show # Show the roles and servers ...
250
+ cap app:install_bundler
251
+ cap app:install_nginx
252
+ cap app:install_image_magick
253
+ cap mysql:backup
254
+ cap nagios:deploy
255
+ cap nagios:restart
256
+ cap nagios:nrpe:install
257
+ cap nagios:nrpe:deploy
258
+ cap nagios:plugins:deploy
259
+ cap server:authorized_keys
260
+ cap server:install_subversion
261
+
262
+
263
+
264
+
265
+ # Now to execute a task on a single server you can precede the task with the
266
+ # scope task for that server.
267
+
268
+ $ cap @:clienta:projectx:production:app:1 app:install_bundler
269
+
270
+
271
+ # Or if you want to execute that task on a group of servers you can use the
272
+ # all task that is defined for you at each level.
273
+
274
+ $ cap @:clienta:projectx:production:app:all
275
+
276
+
277
+ # Since we have added roles to our tasks and servers we can still execute
278
+ # tasks on larger groups of servers that include servers that we don't want
279
+ # the command to run on. Because the task is role based it will only execute
280
+ # the task on the correct servers. For example if we wanted to install nginx
281
+ # on all app servers of clientx but not clienty we could do this:
282
+
283
+ $ cap @:clientx:all app:install_nginx
284
+
285
+ # And if we really wanted to go global we can execute something across all
286
+ # servers with the @:all scope. Lets say we want to deploy they updated
287
+ # nrpe config file and a new plugin we wrote to all our servers.
288
+
289
+ $ cap @:all nagios:nrpe:deploy nagios:plugins:deploy
290
+
291
+
292
+ # Included with this package is a @:show task that will list out all the
293
+ # servers and roles that are defined for a given scope.
294
+
295
+ $ cap @:clienta:projectx:all @:show
296
+
297
+ triggering load callbacks
298
+ * executing `@:create_role_tasks'
299
+ * executing `@:clienta:projectx:all'
300
+ * executing `@:show'
301
+ Roles:
302
+ app
303
+ db
304
+ load_balancer
305
+ server
306
+ Servers:
307
+ clienta:projectx:production:app:1
308
+ clienta:projectx:production:app:2
309
+ clienta:projectx:production:db:1
310
+ clienta:projectx:production:db:2
311
+ clienta:projectx:staging:app:1
312
+ clienta:projectx:staging:app:2
313
+ clienta:projectx:staging:db:2
314
+ clienta:projecty:production:lb:1
315
+ clienta:projecty:production:lb:2
316
+ clienta:projecty:staging:db:1
317
+ clienta:projecty:staging:lb:1
318
+ clienta:projecty:staging:lb:2
319
+
320
+
321
+
322
+
323
+ $ cap @:clienta:projectx:staging:db:all @:show
324
+
325
+ triggering load callbacks
326
+ * executing `@:create_role_tasks'
327
+ * executing `@:clienta:projectx:staging:db:all'
328
+ * executing `@:show'
329
+ Roles:
330
+ db
331
+ server
332
+ Servers:
333
+ clienta:projectx:staging:db:2
334
+ clienta:projecty:staging:db:1
335
+
336
+
337
+
@@ -0,0 +1,112 @@
1
+ # require 'capistrano'
2
+ # unless Capistrano::Configuration.respond_to?(:instance)
3
+ # abort "scope requires requires Capistrano 2"
4
+ # end
5
+
6
+
7
+ module Scope
8
+ @@servers = Hash.new {|h,k| h[k] = {:ip_address => nil, :roles => [] } }
9
+
10
+ def role(role, server_name, options={})
11
+ @@servers[server_name][:roles] << {:name => role, :options => options}
12
+ end
13
+
14
+ def server(server_name, ip_address)
15
+ @@servers[server_name][:ip_address] = ip_address
16
+ end
17
+
18
+ def create_task(name, pattern, ns)
19
+ ns.task(name) do
20
+ keys = @@servers.keys.grep(/^#{pattern}/)
21
+
22
+ keys.each do |key|
23
+ ip_address = @@servers[key][:ip_address]
24
+ @@servers[key][:roles].each do |role|
25
+ top.role(role[:name], ip_address, role[:options])
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def namespace_task(namespace_list, ns)
32
+ name = namespace_list.pop
33
+ pattern = "#{ns.fully_qualified_name}:#{name}".sub('@:','')
34
+
35
+ if namespace_list.empty?
36
+ create_task name, pattern, ns
37
+ else
38
+ ns.namespace name.to_sym do
39
+ end
40
+ create_task 'all', pattern, ns.namespaces[name.to_sym]
41
+ namespace_task namespace_list, ns.namespaces[name.to_sym]
42
+ end
43
+ end
44
+
45
+ # Execution starts here.
46
+ def create_role_tasks(ns)
47
+ @@servers.keys.each do |name|
48
+ namespace_task name.split(':').reverse, ns
49
+ end
50
+ end
51
+
52
+ def all(ns)
53
+ @@servers.each_value do |scope_server|
54
+ scope_server[:roles].each do |role|
55
+ ns.top.role(role[:name], scope_server[:ip_address], role[:options])
56
+ end
57
+ end
58
+ end
59
+
60
+ def defined_roles(ns)
61
+ ns.top.roles.keys.collect {|r| r.to_s }.sort {|a,b| a <=> b }
62
+ end
63
+
64
+ def defined_servers(ns)
65
+ ip_to_name = @@servers.keys.inject({}) do |h,key|
66
+ h[@@servers[key][:ip_address]] = key
67
+ h
68
+ end
69
+ defined_servers = []
70
+ ns.top.roles.each_value do |defined_role|
71
+ defined_role.servers.each do |server|
72
+ unless defined_servers.include? ip_to_name[server.host]
73
+ defined_servers << ip_to_name[server.host]
74
+ end
75
+ end
76
+ end
77
+
78
+ return defined_servers.sort
79
+ end
80
+ end
81
+ Capistrano.plugin :scope, Scope
82
+
83
+
84
+ Capistrano::Configuration.instance.load do
85
+ namespace '@'.to_sym do
86
+
87
+ task :create_role_tasks do
88
+ scope.create_role_tasks self
89
+ end
90
+
91
+ desc "Scope all defined servers"
92
+ task :all do
93
+ scope.all self
94
+ end
95
+
96
+ desc "Show the roles and servers defined by this scope."
97
+ task :show do
98
+ puts "Roles:"
99
+ scope.defined_roles(self).each do |defined_role|
100
+ puts " #{defined_role}"
101
+ end
102
+ puts "Servers:"
103
+ scope.defined_servers(self).each do |defined_server|
104
+ puts " #{defined_server}"
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ on :load, '@:create_role_tasks'
111
+ end
112
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-scope
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Kirt Fitzpatrick
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-17 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: capistrano
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 63
30
+ segments:
31
+ - 2
32
+ - 5
33
+ - 18
34
+ version: 2.5.18
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Adds the ability to restrict the set of servers that capistrano acts on via the command line.
38
+ email: kirt.fitzpatrick@akqa.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - README
47
+ - lib/capistrano/scope.rb
48
+ has_rdoc: true
49
+ homepage:
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 59
63
+ segments:
64
+ - 1
65
+ - 8
66
+ - 6
67
+ version: 1.8.6
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Scoping system for capistrano servers.
84
+ test_files: []
85
+