deprec-core 3.1.0 → 3.1.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.
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ deprec-core
2
+ ===========
3
+
4
+ Extracted from the deprec-gem, deprec core is a task free set of tools
5
+ to make publishing your own Capistrano/Rake task gems simpler.
6
+
7
+ To be continued...
@@ -0,0 +1,418 @@
1
+ # Copyright 2006-2008 by Mike Bailey. All rights reserved.
2
+ require 'capistrano'
3
+ require 'fileutils'
4
+
5
+ module Deprec2
6
+
7
+ # Temporarily modify ROLES if HOSTS not set
8
+ # Capistrano's default behaviour is for HOSTS to override ROLES
9
+ def for_roles(roles)
10
+ old_roles = ENV['ROLES']
11
+ ENV['ROLES'] = roles.to_s unless ENV['HOSTS']
12
+ yield
13
+ ENV['ROLES'] = old_roles.to_s unless ENV['HOSTS']
14
+ end
15
+
16
+
17
+ # Temporarily ignore ROLES and HOSTS
18
+ def ignoring_roles_and_hosts
19
+ old_roles = ENV['ROLES']
20
+ old_hosts = ENV['HOSTS']
21
+ ENV['ROLES'] = nil
22
+ ENV['HOSTS'] = nil
23
+ yield
24
+ ENV['ROLES'] = old_roles
25
+ ENV['HOSTS'] = old_hosts
26
+ end
27
+
28
+ DEPREC_TEMPLATES_BASE = File.join(File.dirname(__FILE__), 'templates')
29
+
30
+ # Render template (usually a config file)
31
+ #
32
+ # Usually we render it to a file on the local filesystem.
33
+ # This way, we keep a copy of the config file under source control.
34
+ # We can make manual changes if required and push to new hosts.
35
+ #
36
+ # If the options hash contains :path then it's written to that path.
37
+ # If it contains :remote => true, the file will instead be written to remote targets
38
+ # If options[:path] and options[:remote] are missing, it just returns the rendered
39
+ # template as a string (good for debugging).
40
+ #
41
+ # XXX I would like to get rid of :render_template_to_file
42
+ # XXX Perhaps pass an option to this function to write to remote
43
+ #
44
+ def render_template(app, options={})
45
+ template = options[:template]
46
+ path = options[:path] || nil
47
+ remote = options[:remote] || false
48
+ mode = options[:mode] || 0755
49
+ owner = options[:owner] || nil
50
+ stage = exists?(:stage) ? fetch(:stage).to_s : ''
51
+ # replace this with a check for the file
52
+ if ! template
53
+ puts "render_template() requires a value for the template!"
54
+ return false
55
+ end
56
+
57
+ # If local copies of deprec templates exist they will be used
58
+ # If you don't specify the location with the local_template_dir option
59
+ # it defaults to config/templates.
60
+ # e.g. config/templates/nginx/nginx.conf.erb
61
+ local_template = File.join(local_template_dir, app.to_s, template)
62
+ if File.exists?(local_template)
63
+ puts
64
+ puts "Using local template (#{local_template})"
65
+ template = ERB.new(IO.read(local_template), nil, '-')
66
+ else
67
+ template = ERB.new(IO.read(File.join(DEPREC_TEMPLATES_BASE, app.to_s, template)), nil, '-')
68
+ end
69
+ rendered_template = template.result(binding)
70
+
71
+ if remote
72
+ # render to remote machine
73
+ puts 'You need to specify a path to render the template to!' unless path
74
+ exit unless path
75
+ sudo "test -d #{File.dirname(path)} || #{sudo} mkdir -p #{File.dirname(path)}"
76
+ std.su_put rendered_template, path, '/tmp/', :mode => mode
77
+ sudo "chown #{owner} #{path}" if defined?(owner)
78
+ elsif path
79
+ # render to local file
80
+ full_path = File.join('config', stage, app.to_s, path)
81
+ path_dir = File.dirname(File.expand_path(full_path))
82
+ if File.exists?(full_path)
83
+ if IO.read(full_path) == rendered_template
84
+ puts "[skip] Identical file exists (#{full_path})."
85
+ return false
86
+ elsif overwrite?(full_path, rendered_template)
87
+ File.delete(full_path)
88
+ else
89
+ puts "[skip] Not overwriting #{full_path}"
90
+ return false
91
+ end
92
+ end
93
+ FileUtils.mkdir_p "#{path_dir}" if ! File.directory?(path_dir)
94
+ # added line above to make windows compatible
95
+ # system "mkdir -p #{path_dir}" if ! File.directory?(path_dir)
96
+ File.open(File.expand_path(full_path), 'w'){|f| f.write rendered_template }
97
+ puts "[done] #{full_path} written"
98
+ else
99
+ # render to string
100
+ return rendered_template
101
+ end
102
+ end
103
+
104
+ def overwrite?(full_path, rendered_template)
105
+ if defined?(overwrite_all)
106
+ if overwrite_all == true
107
+ return true
108
+ else
109
+ return false
110
+ end
111
+ end
112
+
113
+ # XXX add :always and :never later - not sure how to set persistent value from here
114
+ # response = Capistrano::CLI.ui.ask "File exists. Overwrite? ([y]es, [n]o, [a]lways, n[e]ver)" do |q|
115
+ puts
116
+ response = Capistrano::CLI.ui.ask "File exists (#{full_path}).
117
+ Overwrite? ([y]es, [n]o, [d]iff)" do |q|
118
+ q.default = 'n'
119
+ end
120
+
121
+ case response
122
+ when 'y'
123
+ return true
124
+ when 'n'
125
+ return false
126
+ when 'd'
127
+ require 'tempfile'
128
+ tf = Tempfile.new("deprec_diff")
129
+ tf.puts(rendered_template)
130
+ tf.close
131
+ puts
132
+ puts "Running diff -u current_file new_file_if_you_overwrite"
133
+ puts
134
+ system "diff -u #{full_path} #{tf.path} | less"
135
+ puts
136
+ overwrite?(full_path, rendered_template)
137
+ # XXX add :always and :never later - not sure how to set persistent value from here
138
+ # when 'a'
139
+ # set :overwrite_all, true
140
+ # when 'e'
141
+ # set :overwrite_all, false
142
+ end
143
+
144
+ end
145
+
146
+ def render_template_to_file(template_name, destination_file_name, templates_dir = DEPREC_TEMPLATES_BASE)
147
+ template_name += '.conf' if File.extname(template_name) == '' # XXX this to be removed
148
+
149
+ file = File.join(templates_dir, template_name)
150
+ buffer = render :template => File.read(file)
151
+
152
+ temporary_location = "/tmp/#{template_name}"
153
+ put buffer, temporary_location
154
+ sudo "cp #{temporary_location} #{destination_file_name}"
155
+ delete temporary_location
156
+ end
157
+
158
+ # Copy configs to server(s). Note there is no :pull task. No changes should
159
+ # be made to configs on the servers so why would you need to pull them back?
160
+ def push_configs(app, files)
161
+ app = app.to_s
162
+ stage = exists?(:stage) ? fetch(:stage).to_s : ''
163
+
164
+ files.each do |file|
165
+ full_local_path = File.join('config', stage, app, file[:path])
166
+ if File.exists?(full_local_path)
167
+ # If the file path is relative we will prepend a path to this projects
168
+ # own config directory for this service.
169
+ if file[:path][0,1] != '/'
170
+ full_remote_path = File.join(deploy_to, app, file[:path])
171
+ else
172
+ full_remote_path = file[:path]
173
+ end
174
+ sudo "test -d #{File.dirname(full_remote_path)} || #{sudo} mkdir -p #{File.dirname(full_remote_path)}"
175
+ std.su_put File.read(full_local_path), full_remote_path, '/tmp/', :mode=>file[:mode]
176
+ sudo "chown #{file[:owner]} #{full_remote_path}"
177
+ else
178
+ # Render directly to remote host.
179
+ render_template(app, file.merge(:remote => true))
180
+ end
181
+ end
182
+ end
183
+
184
+ def teardown_connections
185
+ sessions.keys.each do |server|
186
+ sessions[server].close
187
+ sessions.delete(server)
188
+ end
189
+ end
190
+
191
+ def append_to_file_if_missing(filename, value, options={})
192
+ # XXX sort out single quotes in 'value' - they'l break command!
193
+ # XXX if options[:requires_sudo] and :use_sudo then use sudo
194
+ sudo <<-END
195
+ sh -c '
196
+ grep -F "#{value}" #{filename} > /dev/null 2>&1 ||
197
+ echo "#{value}" >> #{filename}
198
+ '
199
+ END
200
+ end
201
+
202
+ # create new user account on target system
203
+ def useradd(user, options={})
204
+ options[:shell] ||= '/bin/bash' # new accounts on ubuntu 6.06.1 have been getting /bin/sh
205
+ switches = ''
206
+ switches += " --shell=#{options[:shell]} " if options[:shell]
207
+ switches += ' --create-home ' unless options[:homedir] == false
208
+ switches += " --gid #{options[:group]} " unless options[:group].nil?
209
+ invoke_command "grep '^#{user}:' /etc/passwd || #{sudo} /usr/sbin/useradd #{switches} #{user}",
210
+ :via => run_method
211
+ end
212
+
213
+ # create a new group on target system
214
+ def groupadd(group, options={})
215
+ via = options.delete(:via) || run_method
216
+ # XXX I don't like specifying the path to groupadd - need to sort out paths before long
217
+ invoke_command "grep '#{group}:' /etc/group || #{sudo} /usr/sbin/groupadd #{group}", :via => via
218
+ end
219
+
220
+ # add group to the list of groups this user belongs to
221
+ def add_user_to_group(user, group)
222
+ invoke_command "groups #{user} | grep ' #{group} ' || #{sudo} /usr/sbin/usermod -G #{group} -a #{user}",
223
+ :via => run_method
224
+ end
225
+
226
+ # create directory if it doesn't already exist
227
+ # set permissions and ownership
228
+ # XXX move mode, path and
229
+ def mkdir(path, options={})
230
+ via = options.delete(:via) || :run
231
+ # XXX need to make sudo commands wrap the whole command (sh -c ?)
232
+ # XXX removed the extra 'sudo' from after the '||' - need something else
233
+ invoke_command "test -d #{path} || #{sudo if via == :sudo} mkdir -p #{path}"
234
+ invoke_command "chmod #{sprintf("%3o",options[:mode]||0755)} #{path}", :via => via if options[:mode]
235
+ invoke_command "chown -R #{options[:owner]} #{path}", :via => via if options[:owner]
236
+ groupadd(options[:group], :via => via) if options[:group]
237
+ invoke_command "chgrp -R #{options[:group]} #{path}", :via => via if options[:group]
238
+ end
239
+
240
+ def create_src_dir
241
+ mkdir(src_dir, :mode => 0775, :group => group_src, :via => :sudo)
242
+ end
243
+
244
+ # download source pkg if we don't already have it
245
+ def download_src(src_pkg, src_dir=src_dir)
246
+ set_pkg_defaults(src_pkg)
247
+ create_src_dir
248
+ # check if file exists and if we have an MD5 hash or bytecount to compare
249
+ # against if so, compare and decide if we need to download again
250
+ if defined?(src_pkg[:md5sum])
251
+ md5_clause = " && echo '#{src_pkg[:md5sum]}' | md5sum -c - "
252
+ end
253
+ case src_pkg[:download_method]
254
+ # when getting source with git
255
+ when :git
256
+ # ensure git is installed
257
+ apt.install( {:base => %w(git-core)}, :stable) #TODO fix this to test ubuntu version <hardy might need specific git version for full git submodules support
258
+ pkg_dir = File.join(src_dir, src_pkg[:dir])
259
+ run "if [ -d #{pkg_dir} ]; then cd #{pkg_dir} && #{sudo} git checkout master && #{sudo} git pull && #{sudo} git submodule init && #{sudo} git submodule update; else #{sudo} git clone #{src_pkg[:url]} #{pkg_dir} && cd #{pkg_dir} && #{sudo} git submodule init && #{sudo} git submodule update ; fi"
260
+ # Checkout the revision wanted if defined
261
+ if src_pkg[:version]
262
+ run "cd #{pkg_dir} && git branch | grep '#{src_pkg[:version]}$' && #{sudo} git branch -D '#{src_pkg[:version]}'; exit 0"
263
+ run "cd #{pkg_dir} && #{sudo} git checkout -b #{src_pkg[:version]} #{src_pkg[:version]}"
264
+ end
265
+
266
+ # when getting source with wget
267
+ when :http
268
+ # ensure wget is installed
269
+ apt.install( {:base => %w(wget)}, :stable )
270
+ # XXX replace with invoke_command
271
+ run "cd #{src_dir} && test -f #{src_pkg[:filename]} #{md5_clause} || #{sudo} wget --quiet --timestamping #{src_pkg[:url]}"
272
+
273
+ when :deb
274
+ run "cd #{src_dir} && test -f #{src_pkg[:filename]} #{md5_clause} || #{sudo} wget --quiet --timestamping #{src_pkg[:url]}"
275
+
276
+ else
277
+ puts "DOWNLOAD SRC: Download method not recognised. src_pkg[:download_method]: #{src_pkg[:download_method]}"
278
+ end
279
+ end
280
+
281
+ # unpack src and make it writable by the group
282
+ def unpack_src(src_pkg, src_dir=src_dir)
283
+ set_pkg_defaults(src_pkg)
284
+ pkg_dir = File.join([src_dir, src_pkg[:dir]].compact)
285
+ case src_pkg[:download_method]
286
+ # when unpacking git sources - nothing to do
287
+ when :deb
288
+ puts "UNPACK SRC: nothing to do for deb installs"
289
+ when :git
290
+ puts "UNPACK SRC: nothing to do for git installs"
291
+ when :http
292
+ run "test -d #{pkg_dir}.old && #{sudo} rm -fr #{pkg_dir}.old; exit 0"
293
+ run "test -d #{pkg_dir} && #{sudo} mv #{pkg_dir} #{pkg_dir}.old; exit 0"
294
+ run "cd #{src_dir} && #{sudo} #{src_pkg[:unpack]}" if src_pkg[:unpack] != ''
295
+ run "#{sudo} chgrp -R #{group} #{pkg_dir}"
296
+ run "#{sudo} chmod -R g+w #{pkg_dir}"
297
+ else
298
+ puts "UNPACK SRC: Download method not recognised. src_pkg[:download_method]: #{src_pkg[:download_method]} "
299
+ end
300
+ end
301
+
302
+ def set_pkg_defaults(pkg)
303
+ pkg[:filename] ||= File.basename(pkg[:url])
304
+ pkg[:download_method] ||= :http
305
+ pkg[:post_install] ||= ''
306
+ case pkg[:download_method]
307
+ when :http
308
+ pkg[:dir] ||= pkg[:filename].sub(/(\.tgz|\.tar\.gz)/,'')
309
+ pkg[:unpack] ||= "tar zxf #{pkg[:filename]};"
310
+ pkg[:configure] ||= './configure ;'
311
+ pkg[:make] ||= 'make;'
312
+ pkg[:install] ||= 'make install;'
313
+ when :deb
314
+ pkg[:dir] ||= ''
315
+ pkg[:unpack] ||= ''
316
+ pkg[:configure] ||= ''
317
+ pkg[:make] ||= ''
318
+ pkg[:install] ||= "dpkg -i #{pkg[:filename]}"
319
+ end
320
+ end
321
+
322
+ # install pkg from source
323
+ def install_from_src(src_pkg, src_dir=src_dir)
324
+ install_deps(src_pkg[:deps])
325
+ set_pkg_defaults(src_pkg)
326
+ pkg_dir = File.join([src_dir, src_pkg[:dir]].compact)
327
+ unpack_src(src_pkg, src_dir)
328
+ apt.install( {:base => %w(build-essential)}, :stable )
329
+ run "cd #{pkg_dir} && #{sudo} #{src_pkg[:configure]}" if src_pkg[:configure] != ''
330
+ run "cd #{pkg_dir} && #{sudo} #{src_pkg[:make]}" if src_pkg[:make] != ''
331
+ run "cd #{pkg_dir} && #{sudo} #{src_pkg[:install]}" if src_pkg[:install] != ''
332
+ run "cd #{pkg_dir} && #{sudo} #{src_pkg[:post_install]}" if src_pkg[:post_install] != ''
333
+ end
334
+
335
+ def install_deps(packages=[])
336
+ apt.install({:base => Array(packages)}, :stable)
337
+ end
338
+
339
+ def read_database_yml
340
+ stage = exists?(:stage) ? fetch(:stage).to_s : ''
341
+ db_config = YAML.load_file(File.join('config', stage, 'database.yml'))
342
+ set :db_user, db_config[rails_env]["username"]
343
+ set :db_password, db_config[rails_env]["password"]
344
+ set :db_name, db_config[rails_env]["database"]
345
+ end
346
+
347
+
348
+ ##
349
+ # Run a command and ask for input when input_query is seen.
350
+ # Sends the response back to the server.
351
+ #
352
+ # +input_query+ is a regular expression that defaults to /^Password/.
353
+ #
354
+ # Can be used where +run+ would otherwise be used.
355
+ #
356
+ # run_with_input 'ssh-keygen ...', /^Are you sure you want to overwrite\?/
357
+
358
+ def run_with_input(shell_command, input_query=/^Password/, response=nil)
359
+ handle_command_with_input(:run, shell_command, input_query, response)
360
+ end
361
+
362
+ ##
363
+ # Run a command using sudo and ask for input when a regular expression is seen.
364
+ # Sends the response back to the server.
365
+ #
366
+ # See also +run_with_input+
367
+ #
368
+ # +input_query+ is a regular expression
369
+
370
+ def sudo_with_input(shell_command, input_query=/^Password/, response=nil)
371
+ handle_command_with_input(:sudo, shell_command, input_query, response)
372
+ end
373
+
374
+ def invoke_with_input(shell_command, input_query=/^Password/, response=nil)
375
+ handle_command_with_input(run_method, shell_command, input_query, response)
376
+ end
377
+
378
+ ##
379
+ # Run a command using sudo and continuously pipe the results back to the console.
380
+ #
381
+ # Similar to the built-in +stream+, but for privileged users.
382
+
383
+ def sudo_stream(command)
384
+ sudo(command) do |ch, stream, out|
385
+ puts out if stream == :out
386
+ if stream == :err
387
+ puts "[err : #{ch[:host]}] #{out}"
388
+ break
389
+ end
390
+ end
391
+ end
392
+
393
+ private
394
+
395
+ ##
396
+ # Does the actual capturing of the input and streaming of the output.
397
+ #
398
+ # local_run_method: run or sudo
399
+ # shell_command: The command to run
400
+ # input_query: A regular expression matching a request for input: /^Please enter your password/
401
+
402
+ def handle_command_with_input(local_run_method, shell_command, input_query, response=nil)
403
+ send(local_run_method, shell_command) do |channel, stream, data|
404
+ logger.info data, channel[:host]
405
+ if data =~ input_query
406
+ if response
407
+ channel.send_data "#{response}\n"
408
+ else
409
+ response = ::Capistrano::CLI.password_prompt "#{data}"
410
+ channel.send_data "#{response}\n"
411
+ end
412
+ end
413
+ end
414
+ end
415
+
416
+ end
417
+
418
+ Capistrano.plugin :deprec2, Deprec2
@@ -1,5 +1,5 @@
1
1
  module Deprec
2
2
  module Core
3
- VERSION = "3.1.0"
3
+ VERSION = "3.1.1"
4
4
  end
5
5
  end
@@ -0,0 +1,20 @@
1
+ # =all.rb: Load all the Capistrano Plugins in the directory.
2
+ #
3
+ # Require all other ruby files in the directory.
4
+ #
5
+ # ----
6
+ # Copyright (c) 2007 Neil Wilson, Aldur Systems Ltd
7
+ #
8
+ # Licensed under the GNU Public License v2. No warranty is provided.
9
+ # ----
10
+ # = Usage
11
+ #
12
+ # require 'vmbuilder_plugins/all'
13
+
14
+ # Splitting and joining __FILE__ deals with the current directory case
15
+ # properly
16
+ Dir[File.join( File.dirname(__FILE__), '*.rb')].each do |plugin_name|
17
+ unless plugin_name == File.join(File.dirname(__FILE__), File.basename(__FILE__))
18
+ require plugin_name
19
+ end
20
+ end
@@ -0,0 +1,93 @@
1
+ # =apt.rb: Debian 'apt' Installer library
2
+ # Capistrano plugin module to install and manage apt packages
3
+ #
4
+ # ----
5
+ # Copyright (c) 2007 Neil Wilson, Aldur Systems Ltd
6
+ #
7
+ # Licensed under the GNU Public License v2. No warranty is provided.
8
+
9
+ require 'capistrano'
10
+
11
+ # = Purpose
12
+ # Apt is a Capistrano plugin module providing a set of methods
13
+ # that invoke the *apt* package manager (as used in Debian and Ubuntu)
14
+ #
15
+ # Installs within Capistrano as the plugin _apt_.
16
+ #
17
+ # =Usage
18
+ #
19
+ # require 'vmbuilder_plugins/apt'
20
+ #
21
+ # Prefix all calls to the library with <tt>apt.</tt>
22
+ #
23
+ module Apt
24
+
25
+ # Default apt-get command - reduces any interactivity to the minimum.
26
+ APT_GET="DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive apt-get"
27
+
28
+ # Run the apt install program across the package list in 'packages'.
29
+ # Select those packages referenced by <tt>:base</tt> and the +version+
30
+ # of the distribution you want to use.
31
+ def install(packages, version, options={})
32
+ update
33
+ special_options="--allow-unauthenticated" if version != :stable
34
+ send(run_method, %{
35
+ sh -c "#{APT_GET} -qyu --force-yes #{special_options.to_s} install #{package_list(packages, version)}"
36
+ }, options)
37
+ end
38
+
39
+ # Run an apt clean
40
+ def clean(options={})
41
+ send(run_method, %{sh -c "#{APT_GET} -qy clean"}, options)
42
+ end
43
+
44
+ # Run an apt autoclean
45
+ def autoclean(options={})
46
+ send(run_method, %{sh -c "#{APT_GET} -qy autoclean"}, options)
47
+ end
48
+
49
+ # Run an apt distribution upgrade
50
+ def dist_upgrade(options={})
51
+ update
52
+ send(run_method, %{sh -c "#{APT_GET} -qy dist-upgrade"}, options)
53
+ end
54
+
55
+ # Run an apt upgrade. Use dist_upgrade instead if you want to upgrade
56
+ # the critical base packages.
57
+ def upgrade(options={})
58
+ update
59
+ send(run_method, %{sh -c "#{APT_GET} -qy upgrade"}, options)
60
+ end
61
+
62
+ # Run an apt update.
63
+ def update(options={})
64
+ send(run_method, %{sh -c "#{APT_GET} -qy update"}, options)
65
+ end
66
+
67
+ # RPM package install via alien
68
+ def rpm_install(packages, options={})
69
+ install({:base => %w(wget alien) }, :base)
70
+ send(run_method, "wget -Ncq #{packages.join(' ')}", options)
71
+ files=packages.collect { |package| File.basename(package) }
72
+ send(run_method, "alien -i #{files.join(' ')}", options)
73
+ end
74
+
75
+ # Clear the source list and package cache
76
+ def clear_cache(options={})
77
+ clean
78
+ cmd="rm -f /var/cache/apt/*.bin /var/lib/apt/lists/*_* /var/lib/apt/lists/partial/*"
79
+ send(run_method, cmd, options)
80
+ end
81
+
82
+ private
83
+
84
+ # Provides a string containing all the package names in the base
85
+ #list plus those in +version+.
86
+ def package_list(packages, version)
87
+ Array(packages[:base]).join(' ') + ' ' + Array(packages[version]).join(' ')
88
+ end
89
+
90
+ end
91
+
92
+ Capistrano.plugin :apt, Apt
93
+ # vim: nowrap sw=2 sts=2 ts=8 ff=unix ft=ruby:
@@ -0,0 +1,76 @@
1
+ # =emerge.rb: Gentoo 'emerge' Installer library
2
+ # Capistrano task library to install and manage portage packages
3
+ #
4
+ # Copyright (c) 2007 monki(Wesley Beary)
5
+ #
6
+ # inspiration: vmbuilder by Neil Wilson, Aldur Systems Ltd
7
+ #
8
+ # Licenced under the GNU Public License v2. No warranty is provided.
9
+
10
+ require 'capistrano'
11
+
12
+ # =Purpose
13
+ # emerge is a Capistrano plugin module providing a set of methods
14
+ # that invoke the portage package manage (as used in Gentoo)
15
+ #
16
+ # Installs within Capistrano as the plugin _emerge_.
17
+ #
18
+ # =Usage
19
+ #
20
+ # require 'marshall/plugins/emerge'
21
+ #
22
+ # Prefix all calls to the library with <tt>emerge.</tt>
23
+ #
24
+ module Emerge
25
+ # Default emerge command - reduce interactivity to the minimum
26
+ EMERGE="emerge -q"
27
+
28
+ # Emerge a new package or packages
29
+ def install(packages, options={})
30
+ cmd = <<-CMD
31
+ sh -c "#{EMERGE} #{packages.join(" ")}"
32
+ CMD
33
+ sudo(cmd, options)
34
+ end
35
+
36
+ # Run clean old/unused packages
37
+ def clean(options={})
38
+ cmd = <<-CMD
39
+ sh -c "#{EMERGE} -clean"
40
+ CMD
41
+ sudo(cmd, options)
42
+ end
43
+
44
+ # Upgrade installed package list
45
+ def upgrade(options={})
46
+ cmd = <<-CMD
47
+ sh -c "#{EMERGE} --sync"
48
+ CMD
49
+ sudo(cmd, options)
50
+ end
51
+
52
+ # Update portage
53
+ def update_system(options={})
54
+ cmd = <<-CMD
55
+ sh -c "#{EMERGE} portage"
56
+ CMD
57
+ sudo(cmd, options)
58
+ end
59
+
60
+ # Update all installed packages
61
+ def update(options={})
62
+ cmd = <<-CMD
63
+ sh -c "#{EMERGE} --update --deep --newuse world"
64
+ CMD
65
+ sudo(cmd, options)
66
+ end
67
+
68
+ # Boot script manipulation command
69
+ def rc_update(packages, setting)
70
+ packages.each do |service|
71
+ sudo "rc_update add #{service} #{setting}"
72
+ end
73
+ end
74
+ end
75
+
76
+ Capistrano.plugin :emerge, Emerge
@@ -0,0 +1,90 @@
1
+ # =gem.rb: Gem Installer library
2
+ # Capistrano library to install and manage Ruby Gems.
3
+ #
4
+ # ----
5
+ # Copyright (c) 2007 Neil Wilson, Aldur Systems Ltd
6
+ #
7
+ # Licensed under the GNU Public License v2. No warranty is provided.
8
+
9
+ require 'capistrano'
10
+
11
+ # = Purpose
12
+ # Gem is a Capistrano plugin module providing a set of methods
13
+ # that invoke the *gem* package manager.
14
+ #
15
+ # Installs within Capistrano as the plugin _gem_.
16
+ #
17
+ # =Usage
18
+ #
19
+ # require 'vmbuilder_plugins/gem'
20
+ #
21
+ # Prefix all calls to the library with <tt>gem.</tt>
22
+ #
23
+ module Gem
24
+
25
+ # Default install command
26
+ #
27
+ # * doesn't install documentation
28
+ # * installs all required dependencies automatically.
29
+ #
30
+ GEM_INSTALL="gem install --no-rdoc --no-ri"
31
+ GEM_UPDATE=GEM_INSTALL.sub("install", "update")
32
+
33
+ # Upgrade the *gem* system to the latest version. Runs via *sudo*
34
+ def update_system
35
+ send(run_method, "#{GEM_UPDATE} --system")
36
+ end
37
+
38
+ # Updates all the installed gems to the latest version. Runs via *sudo*.
39
+ # Don't use this command if any of the gems require a version selection.
40
+ def upgrade
41
+ send(run_method, GEM_UPDATE)
42
+ end
43
+
44
+ # Removes old versions of gems from installation area.
45
+ def cleanup
46
+ send(run_method, "gem cleanup")
47
+ end
48
+
49
+ # Installs the gems detailed in +packages+, selecting version +version+ if
50
+ # specified.
51
+ #
52
+ # +packages+ can be a single string or an array of strings.
53
+ #
54
+ def install(packages, version=nil)
55
+ send(run_method,"#{GEM_INSTALL} #{if version then '-v '+version.to_s end} #{Array(packages).join(' ')}")
56
+ end
57
+
58
+ # Auto selects a gem from a list and installs it.
59
+ #
60
+ # *gem* has no mechanism on the command line of disambiguating builds for
61
+ # different platforms, and instead asks the user. This method has the necessary
62
+ # conversation to select the +version+ relevant to +platform+ (or the one nearest
63
+ # the top of the list if you don't specify +version+).
64
+ def select(package, version=nil, platform='ruby')
65
+ selections={}
66
+ cmd="#{GEM_INSTALL} #{if version then '-v '+version.to_s end} #{package}"
67
+ send run_method, cmd do |channel, stream, data|
68
+ data.each_line do | line |
69
+ case line
70
+ when /\s(\d+).*\(#{platform}\)/
71
+ if selections[channel[:host]].nil?
72
+ selections[channel[:host]]=$1.dup+"\n"
73
+ logger.info "Selecting #$&", "#{stream} :: #{channel[:host]}"
74
+ end
75
+ when /\s\d+\./
76
+ # Discard other selections from data stream
77
+ when /^>/
78
+ channel.send_data selections[channel[:host]]
79
+ logger.debug line, "#{stream} :: #{channel[:host]}"
80
+ else
81
+ logger.info line, "#{stream} :: #{channel[:host]}"
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ Capistrano.plugin :gem2, Gem
90
+ # vim: nowrap sw=2 sts=2 ts=8 ff=unix ft=ruby:
@@ -0,0 +1,203 @@
1
+ # =std.rb: Capistrano Standard Methods
2
+ # Standard library of procedures and functions that you can use with Capistrano.
3
+ #
4
+ # ----
5
+ # Copyright (c) 2007 Neil Wilson, Aldur Systems Ltd
6
+ #
7
+ # Licensed under the GNU Public License v2. No warranty is provided.
8
+
9
+ require 'capistrano'
10
+
11
+ # = Purpose
12
+ # Std is a Capistrano plugin that provides a set of standard methods refactored
13
+ # out of several Capistrano task libraries.
14
+ #
15
+ # Installs within Capistrano as the plugin _std_
16
+ #
17
+ # = Usage
18
+ #
19
+ # require 'vmbuilder_plugins/std'
20
+ #
21
+ # Prefix all calls to the library with <tt>std.</tt>
22
+ module Std
23
+
24
+ begin
25
+ # Use the Mmap class if it is available
26
+ # http://moulon.inra.fr/ruby/mmap.html
27
+ require 'mmap'
28
+ MMAP=true #:nodoc:
29
+ rescue LoadError
30
+ # no MMAP class, use normal reads instead
31
+ MMAP=false #:nodoc:
32
+ end
33
+
34
+ # Copies the files specified by +file_pattern+ to +destination+
35
+ #
36
+ # Error checking is minimal - a pattern onto a single file will result in +destination+
37
+ # containing the data from the last file only.
38
+ #
39
+ # Installs via *sudo*, +options+ are as for *put*.
40
+ def fput(file_pattern, destination, options={})
41
+ logger.info file_pattern
42
+ Dir.glob(file_pattern) do |fname|
43
+ if File.readable?(fname) then
44
+ if MMAP
45
+ logger.debug "Using Memory Mapped File Upload"
46
+ fdata=Mmap.new(fname,"r", Mmap::MAP_SHARED, :advice => Mmap::MADV_SEQUENTIAL)
47
+ else
48
+ fdata=File.open(fname).read
49
+ end
50
+ su_put(fdata, destination, File.join('/tmp',File.basename(fname)), options)
51
+ else
52
+ logger.error "Unable to read file #{fname}"
53
+ end
54
+ end
55
+ end
56
+
57
+ # Upload +data+ to +temporary_area+ before installing it in
58
+ # +destination+ using sudo.
59
+ #
60
+ # +options+ are as for *put*
61
+ #
62
+ def su_put(data, destination, temporary_area='/tmp', options={})
63
+ temporary_area = File.join(temporary_area,"#{File.basename(destination)}-$CAPISTRANO:HOST$")
64
+ put(data, temporary_area, options)
65
+ send run_method, <<-CMD
66
+ sh -c "install -m#{sprintf("%3o",options[:mode]||0755)} #{temporary_area} #{destination} &&
67
+ rm -f #{temporary_area}"
68
+ CMD
69
+ end
70
+
71
+ # Copies the +file_pattern+, which is assumed to be a tar
72
+ # file of some description (gzipped or plain), and unpacks it into
73
+ # +destination+.
74
+ def unzip(file_pattern, destination, options={})
75
+ Dir.glob(file_pattern) do |fname|
76
+ if File.readable?(fname) then
77
+ target="/tmp/#{File.basename(fname)}"
78
+ if MMAP
79
+ logger.debug "Using Memory Mapped File Upload"
80
+ fdata=Mmap.new(fname,"r", Mmap::MAP_SHARED, :advice => Mmap::MADV_SEQUENTIAL)
81
+ else
82
+ fdata=File.open(fname).read
83
+ end
84
+ put(fdata, target, options)
85
+ send run_method, <<-CMD
86
+ sh -c "cd #{destination} &&
87
+ zcat -f #{target} | tar xvf - &&
88
+ rm -f #{target}"
89
+ CMD
90
+ end
91
+ end
92
+ end
93
+
94
+ # Wrap this around your task calls to catch the no servers error and
95
+ # ignore it
96
+ #
97
+ # std.ignore_no_servers_error do
98
+ # activate_mysql
99
+ # end
100
+ #
101
+ def ignore_no_servers_error (&block)
102
+ begin
103
+ yield
104
+ rescue RuntimeError => failure
105
+ if failure.message =~ /no servers matched/
106
+ logger.debug "Ignoring 'no servers matched' error in task #{current_task.name}"
107
+ else
108
+ raise
109
+ end
110
+ end
111
+ end
112
+
113
+ # Wrap this around your task to force a connection as root.
114
+ # Flushes the session cache before and after the connection.
115
+ #
116
+ # std.connect_as_root do
117
+ # install_sudo
118
+ # end
119
+ #
120
+ def connect_as_root (&block)
121
+ begin
122
+ tempuser = user
123
+ set :user, "root"
124
+ actor.sessions.delete_if { true }
125
+ yield tempuser
126
+ ensure
127
+ set :user, tempuser if tempuser
128
+ actor.sessions.delete_if { true }
129
+ end
130
+ end
131
+
132
+ #Returns a random string of alphanumeric characters of size +size+
133
+ #Useful for passwords, usernames and the like.
134
+ def random_string(size=10)
135
+ s = ""
136
+ size.times { s << (i = rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
137
+ s
138
+ end
139
+
140
+
141
+ # Return a relative path from the destination directory +from_str+
142
+ # to the target file/directory +to_str+. Used to create relative
143
+ # symbolic link paths.
144
+ def relative_path (from_str, to_str)
145
+ require 'pathname'
146
+ Pathname.new(to_str).relative_path_from(Pathname.new(from_str)).to_s
147
+ end
148
+
149
+ # Run a ruby command file on the servers
150
+ #
151
+ def ruby(cmd, options={}, &block)
152
+ temp_name = random_string + ".rb"
153
+ begin
154
+ put(cmd, temp_name, :mode => 0700)
155
+ send(run_method, "ruby #{temp_name}", options, &block)
156
+ ensure
157
+ delete temp_name
158
+ end
159
+ end
160
+
161
+ # Run a patchfile on the servers
162
+ # Ignores reverses and rejects.
163
+ #
164
+ def patch(patchfile, level = '0', where = '/')
165
+ temp_name = random_string
166
+ begin
167
+ fput(patchfile, temp_name, :mode => 0600)
168
+ send(run_method, %{
169
+ patch -p#{level} -tNd #{where} -r /dev/null < #{temp_name} || true
170
+ })
171
+ ensure
172
+ delete temp_name
173
+ end
174
+ end
175
+
176
+ # Deletes the given file(s) from all servers targetted by the current
177
+ # task, but runs the +delete+ command according to the current setting
178
+ # of <tt>:use_sudo</tt>.
179
+ #
180
+ # If <tt>:recursive => true</tt> is specified, it may be used to remove
181
+ # directories.
182
+ def su_delete(path, options={})
183
+ cmd = "rm -%sf #{path}" % (options[:recursive] ? "r" : "")
184
+ send(run_method, cmd, options)
185
+ end
186
+
187
+ # Render a template file and upload it to the servers
188
+ #
189
+ def put_template(template, destination, options={})
190
+ if MMAP
191
+ logger.debug "Using Memory Mapped File Upload"
192
+ fdata=Mmap.new(template,"r", Mmap::MAP_SHARED, :advice => Mmap::MADV_SEQUENTIAL)
193
+ else
194
+ fdata=File.read(template)
195
+ end
196
+ put(render(:template => fdata), destination, options)
197
+ end
198
+
199
+ end
200
+
201
+ Capistrano.plugin :std, Std
202
+ #
203
+ # vim: nowrap sw=2 sts=2 ts=8 ff=unix ft=ruby:
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: deprec-core
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 3.1.0
5
+ version: 3.1.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mike Bailey
@@ -25,10 +25,17 @@ extra_rdoc_files: []
25
25
  files:
26
26
  - .gitignore
27
27
  - Gemfile
28
+ - README.md
28
29
  - Rakefile
29
30
  - deprec-core.gemspec
30
31
  - lib/deprec-core.rb
32
+ - lib/deprec-core/capistrano_extensions.rb
31
33
  - lib/deprec-core/version.rb
34
+ - lib/vmbuilder_plugins/all.rb
35
+ - lib/vmbuilder_plugins/apt.rb
36
+ - lib/vmbuilder_plugins/emerge.rb
37
+ - lib/vmbuilder_plugins/gem.rb
38
+ - lib/vmbuilder_plugins/std.rb
32
39
  homepage: ""
33
40
  licenses: []
34
41