calas-capitate 0.3.6
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/Capfile +13 -0
- data/History.txt +167 -0
- data/License.txt +20 -0
- data/Manifest.txt +121 -0
- data/README.txt +8 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +72 -0
- data/config/requirements.rb +17 -0
- data/lib/capitate.rb +56 -0
- data/lib/capitate/cap_ext/connections.rb +105 -0
- data/lib/capitate/cap_ext/docs.rb +26 -0
- data/lib/capitate/cap_ext/namespace.rb +34 -0
- data/lib/capitate/cap_ext/run_via.rb +16 -0
- data/lib/capitate/cap_ext/task_definition.rb +22 -0
- data/lib/capitate/cap_ext/variables.rb +132 -0
- data/lib/capitate/plugins/base.rb +140 -0
- data/lib/capitate/plugins/build.rb +71 -0
- data/lib/capitate/plugins/gem.rb +24 -0
- data/lib/capitate/plugins/prompt.rb +109 -0
- data/lib/capitate/plugins/rake.rb +25 -0
- data/lib/capitate/plugins/script.rb +96 -0
- data/lib/capitate/plugins/templates.rb +113 -0
- data/lib/capitate/plugins/utils.rb +151 -0
- data/lib/capitate/plugins/yum.rb +76 -0
- data/lib/capitate/recipes.rb +5 -0
- data/lib/capitate/task_node.rb +262 -0
- data/lib/capitate/version.rb +9 -0
- data/lib/deployment/centos-5.1-64-web/install.rb +196 -0
- data/lib/recipes/active_record.rb +36 -0
- data/lib/recipes/apache.rb +47 -0
- data/lib/recipes/backgroundrb.rb +29 -0
- data/lib/recipes/centos/backgroundjob.rb +27 -0
- data/lib/recipes/centos/backgroundrb.rb +23 -0
- data/lib/recipes/centos/centos.rb +45 -0
- data/lib/recipes/centos/imagemagick.rb +29 -0
- data/lib/recipes/centos/memcached.rb +45 -0
- data/lib/recipes/centos/merb.rb +23 -0
- data/lib/recipes/centos/mongrel_cluster.rb +54 -0
- data/lib/recipes/centos/monit.rb +62 -0
- data/lib/recipes/centos/mysql.rb +25 -0
- data/lib/recipes/centos/nginx.rb +64 -0
- data/lib/recipes/centos/ruby.rb +40 -0
- data/lib/recipes/centos/sphinx.rb +59 -0
- data/lib/recipes/docs.rb +24 -0
- data/lib/recipes/logrotate/backgroundjob.rb +26 -0
- data/lib/recipes/logrotate/backgroundrb.rb +26 -0
- data/lib/recipes/logrotate/merb.rb +25 -0
- data/lib/recipes/logrotate/mongrel_cluster.rb +29 -0
- data/lib/recipes/logrotate/monit.rb +28 -0
- data/lib/recipes/logrotate/mysql.rb +26 -0
- data/lib/recipes/logrotate/nginx.rb +37 -0
- data/lib/recipes/logrotate/rails.rb +21 -0
- data/lib/recipes/logrotate/sphinx.rb +21 -0
- data/lib/recipes/logrotated.rb +61 -0
- data/lib/recipes/memcached.rb +26 -0
- data/lib/recipes/merb.rb +32 -0
- data/lib/recipes/monit.rb +35 -0
- data/lib/recipes/monit/backgroundjob.rb +38 -0
- data/lib/recipes/monit/backgroundrb.rb +38 -0
- data/lib/recipes/monit/database.rb +25 -0
- data/lib/recipes/monit/memcached.rb +22 -0
- data/lib/recipes/monit/merb.rb +58 -0
- data/lib/recipes/monit/mongrel_cluster.rb +85 -0
- data/lib/recipes/monit/mysql.rb +20 -0
- data/lib/recipes/monit/nginx.rb +37 -0
- data/lib/recipes/monit/sphinx.rb +38 -0
- data/lib/recipes/monit/sshd.rb +27 -0
- data/lib/recipes/mysql.rb +42 -0
- data/lib/recipes/nginx.rb +29 -0
- data/lib/recipes/rails.rb +71 -0
- data/lib/recipes/redmine.rb +38 -0
- data/lib/recipes/sphinx.rb +60 -0
- data/lib/recipes/sshd.rb +47 -0
- data/lib/recipes/syslogd.rb +21 -0
- data/lib/templates/apache/vhost.mongrel_cluster.conf.erb +46 -0
- data/lib/templates/backgroundjob/backgroundjob.initd.centos.erb +54 -0
- data/lib/templates/backgroundjob/backgroundjob.monitrc.erb +3 -0
- data/lib/templates/backgroundrb/backgroundrb.initd.centos.erb +58 -0
- data/lib/templates/backgroundrb/backgroundrb.monitrc.erb +3 -0
- data/lib/templates/backgroundrb/backgroundrb.yml.erb +14 -0
- data/lib/templates/capistrano/Capfile +22 -0
- data/lib/templates/logrotated/conf.erb +3 -0
- data/lib/templates/memcached/memcached.initd.centos.erb +58 -0
- data/lib/templates/memcached/memcached.monitrc.erb +4 -0
- data/lib/templates/memcached/memcached.yml.erb +14 -0
- data/lib/templates/merb/merb-no-http.monitrc.erb +13 -0
- data/lib/templates/merb/merb.initd.centos.erb +123 -0
- data/lib/templates/merb/merb.monitrc.erb +15 -0
- data/lib/templates/mongrel/mongrel_cluster.initd.centos.erb +94 -0
- data/lib/templates/mongrel/mongrel_cluster.monitrc.erb +15 -0
- data/lib/templates/mongrel/mongrel_cluster.yml.erb +11 -0
- data/lib/templates/monit/monit.cnf +34 -0
- data/lib/templates/monit/monit.initd.centos.erb +68 -0
- data/lib/templates/monit/monitrc.erb +18 -0
- data/lib/templates/mysql/install_db.sql.erb +6 -0
- data/lib/templates/mysql/my.cnf.innodb_1024.erb +122 -0
- data/lib/templates/mysql/my.cnf.innodb_512.erb +127 -0
- data/lib/templates/mysql/mysql.monitrc.erb +6 -0
- data/lib/templates/nginx/nginx.conf.erb +97 -0
- data/lib/templates/nginx/nginx.initd.centos.erb +69 -0
- data/lib/templates/nginx/nginx.monitrc.erb +4 -0
- data/lib/templates/nginx/nginx_vhost.conf.erb +101 -0
- data/lib/templates/nginx/nginx_vhost_generic.conf.erb +99 -0
- data/lib/templates/rails/database.yml.erb +7 -0
- data/lib/templates/redmine/email.yml.erb +10 -0
- data/lib/templates/ruby/fix_openssl.sh +12 -0
- data/lib/templates/sphinx/sphinx.conf.erb +157 -0
- data/lib/templates/sphinx/sphinx.monitrc.erb +4 -0
- data/lib/templates/sphinx/sphinx_app.initd.centos.erb +90 -0
- data/lib/templates/sshd/sshd.monitrc.erb +5 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +80 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +23 -0
- data/test/test_helper.rb +2 -0
- data/test/test_plugin_upload.rb +32 -0
- data/test/test_recipes.rb +37 -0
- data/test/test_templates.rb +29 -0
- metadata +198 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Capitate::Plugins::Build
|
|
2
|
+
|
|
3
|
+
# Configure, make, make install.
|
|
4
|
+
#
|
|
5
|
+
# ==== Options
|
|
6
|
+
# +name+:: Name for app
|
|
7
|
+
# +options+:: Options (See Make install options)
|
|
8
|
+
#
|
|
9
|
+
# ==== Make install options
|
|
10
|
+
# +build_dest+:: Place to build from, ex. /usr/src, defaults to /tmp/name
|
|
11
|
+
# +url+:: URL to download package from
|
|
12
|
+
# +configure_options+:: Options for ./configure
|
|
13
|
+
# +symlink+:: After install, list of source, dest pairs to symlink
|
|
14
|
+
# [ { "/usr/local/sphinx-0.9.8-rc1" => "/usr/local/sphinx" }, ... ]
|
|
15
|
+
# ln -s /usr/local/sphinx-0.9.8-rc1 /usr/local/sphinx
|
|
16
|
+
# +unpack_dir+:: Directory that is unpacked from tgz (if not matching the file name)
|
|
17
|
+
# +to_log+:: If specified, will redirect output to this path
|
|
18
|
+
#
|
|
19
|
+
# ==== Examples (in capistrano task)
|
|
20
|
+
# build.make_install("nginx", { :url => "http://sysoev.ru/nginx/nginx-0.5.35.tar.gz", ... })
|
|
21
|
+
#
|
|
22
|
+
def make_install(name, options)
|
|
23
|
+
install(name, options) do |dir|
|
|
24
|
+
configure_options = options[:configure_options] || ""
|
|
25
|
+
|
|
26
|
+
# Whether to capture build output
|
|
27
|
+
unless options.has_key?(:to_log)
|
|
28
|
+
to_log = ">> debug.log 2>&1"
|
|
29
|
+
else
|
|
30
|
+
to_log = ""
|
|
31
|
+
to_log = ">> #{options[:to_log]}" unless options[:to_log].blank?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
script.run_all <<-CMDS
|
|
35
|
+
sh -c "cd #{dir} && ./configure #{configure_options} #{to_log}"
|
|
36
|
+
sh -c "cd #{dir} && make #{to_log}"
|
|
37
|
+
sh -c "cd #{dir} && make install #{to_log}"
|
|
38
|
+
CMDS
|
|
39
|
+
|
|
40
|
+
utils.ln(options[:symlink]) unless options[:symlink].blank?
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Download, unpack and yield (unpacked source director).
|
|
45
|
+
#
|
|
46
|
+
# ==== Options
|
|
47
|
+
# +name+:: Name for app
|
|
48
|
+
# +options+:: Options (see Install options)
|
|
49
|
+
#
|
|
50
|
+
# ==== Install options
|
|
51
|
+
# +build_dest+:: Place to build from, ex. /usr/src, defaults to /tmp/name
|
|
52
|
+
# +url+:: URL to download package from
|
|
53
|
+
#
|
|
54
|
+
# ==== Examples (in capistrano task)
|
|
55
|
+
# script.make("rubygems", { :url => :url => "http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz" }) do |dir|
|
|
56
|
+
# sudo "echo 'Running setup...' && cd #{dir} && ruby #{dir}/setup.rb"
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
def install(name, options, &block)
|
|
60
|
+
build_dest = options[:build_dest]
|
|
61
|
+
build_dest ||= "/tmp/#{name}"
|
|
62
|
+
url = options[:url]
|
|
63
|
+
|
|
64
|
+
script.unpack(url, build_dest, options) do |dir|
|
|
65
|
+
yield(dir) if block_given?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Capistrano.plugin :build, Capitate::Plugins::Build
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Capitate::Plugins::Gem
|
|
2
|
+
|
|
3
|
+
# Install a gem.
|
|
4
|
+
#
|
|
5
|
+
# ==== Options
|
|
6
|
+
# +gems+:: List of gem names, or a single gem
|
|
7
|
+
#
|
|
8
|
+
# ==== Examples (in capistrano task)
|
|
9
|
+
# gems.install("raspell")
|
|
10
|
+
# gems.install([ "raspell", "foo" ])
|
|
11
|
+
#
|
|
12
|
+
def install(gems)
|
|
13
|
+
# If a single object, wrap in array
|
|
14
|
+
gems = [ gems ] unless gems.is_a?(Array)
|
|
15
|
+
|
|
16
|
+
# Install one at a time because we may need to pass install args (e.g. mysql)
|
|
17
|
+
gems.each do |gem|
|
|
18
|
+
run_via "gem install --no-rdoc --no-ri --no-verbose #{gem}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Capistrano.plugin :gems, Capitate::Plugins::Gem
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require 'md5'
|
|
2
|
+
|
|
3
|
+
module Capitate::Plugins::Prompt
|
|
4
|
+
|
|
5
|
+
# Prompt.
|
|
6
|
+
#
|
|
7
|
+
# ==== Options
|
|
8
|
+
# :label<String>:: Label
|
|
9
|
+
# :options<Hash>:: An options hash (see below)
|
|
10
|
+
#
|
|
11
|
+
def ask(label, options = {}, &block)
|
|
12
|
+
Capistrano::CLI.ui.ask(label, &block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Prompt for password.
|
|
16
|
+
#
|
|
17
|
+
# ==== Options (options)
|
|
18
|
+
# :label<String>:: Label
|
|
19
|
+
# :options<Hash>:: An options hash (see below)
|
|
20
|
+
#
|
|
21
|
+
# ==== Password options
|
|
22
|
+
# :verify<bool>:: If true, prompt twice and verify
|
|
23
|
+
# :lazy<bool>:: If true, returns a Proc. _Defaults to true_
|
|
24
|
+
# :check_hash<String>:: If present, checks that md5 is same as password md5
|
|
25
|
+
# :max_attempts<Integer>:: Number of attempts to retry. _Defaults to 3_
|
|
26
|
+
#
|
|
27
|
+
def password(label, options = {})
|
|
28
|
+
|
|
29
|
+
verify = options[:verify]
|
|
30
|
+
lazy = options[:lazy].nil? ? true : options[:lazy]
|
|
31
|
+
check_hash = options[:check_hash]
|
|
32
|
+
max_attempts = options[:max_attempts] || 3
|
|
33
|
+
|
|
34
|
+
# Lazy
|
|
35
|
+
password_prompt = Proc.new {
|
|
36
|
+
|
|
37
|
+
attempts = 0
|
|
38
|
+
password = nil
|
|
39
|
+
success = true
|
|
40
|
+
|
|
41
|
+
loop do
|
|
42
|
+
password = Capistrano::CLI.password_prompt(label)
|
|
43
|
+
attempts += 1
|
|
44
|
+
|
|
45
|
+
if verify
|
|
46
|
+
password_verify = Capistrano::CLI.password_prompt("[VERIFY] #{label}")
|
|
47
|
+
if password != password_verify
|
|
48
|
+
logger.important "Passwords do not match"
|
|
49
|
+
success = false
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if check_hash
|
|
54
|
+
if MD5.md5(password).hexdigest != check_hash
|
|
55
|
+
logger.important "Invalid password, try again."
|
|
56
|
+
success = false
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
break if success
|
|
61
|
+
break if attempts >= max_attempts
|
|
62
|
+
|
|
63
|
+
# Reset success
|
|
64
|
+
success = true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
raise "Invalid password, too many tries" unless success
|
|
68
|
+
|
|
69
|
+
password
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return password_prompt if lazy
|
|
73
|
+
password_prompt.call
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Preview variables, and re-set them if asked to.
|
|
77
|
+
# Uses highline menus. Is not very intelligent.
|
|
78
|
+
#
|
|
79
|
+
# ==== Options
|
|
80
|
+
# :variables<Array>:: List of variables to show and verify
|
|
81
|
+
# :header<String>:: Menu header
|
|
82
|
+
# :prompt<String>:: Menu prompt
|
|
83
|
+
#
|
|
84
|
+
def preview_variables(variables, header = "Verify your settings", prompt = "Choose: ")
|
|
85
|
+
hl = Capistrano::CLI.ui
|
|
86
|
+
|
|
87
|
+
confirmed = false
|
|
88
|
+
while not confirmed do
|
|
89
|
+
hl.choose do |menu|
|
|
90
|
+
menu.header = header
|
|
91
|
+
menu.prompt = prompt
|
|
92
|
+
|
|
93
|
+
menu.choice("<Continue>") do
|
|
94
|
+
confirmed = true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
variables.each do |variable|
|
|
98
|
+
menu.choice("#{variable}: #{fetch(variable)}") do
|
|
99
|
+
new_setting = ask("Set #{variable}: ") { |q| q.default = fetch(variable) }
|
|
100
|
+
set variable, new_setting
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
Capistrano.plugin :prompt, Capitate::Plugins::Prompt
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Capitate::Plugins::Rake
|
|
2
|
+
|
|
3
|
+
# Execute rake tasks.
|
|
4
|
+
#
|
|
5
|
+
# ==== Options
|
|
6
|
+
# +tasks+:: List of task names, or a single task
|
|
7
|
+
#
|
|
8
|
+
# ==== Examples (in capistrano task)
|
|
9
|
+
# rake.run("db:migrate")
|
|
10
|
+
# rake.run([ "db:create", "db:migrate" ])
|
|
11
|
+
# rake.run("db:bootstrap AUTO_ACCEPT=true")
|
|
12
|
+
#
|
|
13
|
+
def run(tasks)
|
|
14
|
+
# If a single object, wrap in array
|
|
15
|
+
tasks = [ tasks ] unless tasks.is_a?(Array)
|
|
16
|
+
|
|
17
|
+
# Install one at a time because we may need to pass install args (e.g. AUTO_ACCEPT=true)
|
|
18
|
+
tasks.each do |task|
|
|
19
|
+
run_via "/usr/bin/env rake RAILS_ENV=#{rails_env} #{task}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Capistrano.plugin :rake, Capitate::Plugins::Rake
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Capitate::Plugins::Script
|
|
2
|
+
|
|
3
|
+
# Run (sh) script. If script has .erb extension it will evaluate it.
|
|
4
|
+
#
|
|
5
|
+
# ==== Options
|
|
6
|
+
# +script+:: Name of sh file (relative to templates dir)
|
|
7
|
+
# +override_binding++:: Binding to override, otherwise defaults to current (task) context
|
|
8
|
+
#
|
|
9
|
+
# ==== Examples
|
|
10
|
+
# script.sh("ruby/openssl_fix.sh")
|
|
11
|
+
#
|
|
12
|
+
def sh(script, override_binding = nil)
|
|
13
|
+
|
|
14
|
+
if File.extname(script) == ".erb"
|
|
15
|
+
name = script[0...script.length-4]
|
|
16
|
+
dest = "/tmp/cap/#{name}"
|
|
17
|
+
run_via "mkdir -p #{File.dirname(dest)}"
|
|
18
|
+
put template.load(script, override_binding || binding), dest
|
|
19
|
+
else
|
|
20
|
+
name = script
|
|
21
|
+
dest = "/tmp/cap/#{name}"
|
|
22
|
+
run_via "mkdir -p #{File.dirname(dest)}"
|
|
23
|
+
put template.load(script), dest
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# If want verbose, -v
|
|
27
|
+
run_all <<-CMDS
|
|
28
|
+
sh -v #{dest}
|
|
29
|
+
rm -rf #{File.dirname(dest)}
|
|
30
|
+
CMDS
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Download and unpack URL.
|
|
34
|
+
# Yields path to unpacked source.
|
|
35
|
+
#
|
|
36
|
+
# ==== Options
|
|
37
|
+
# +url+:: URL to download
|
|
38
|
+
# +dest+:: Destination directory
|
|
39
|
+
# +options+:: Options (see Unpack options)
|
|
40
|
+
#
|
|
41
|
+
# ==== Unpack options
|
|
42
|
+
# +clean+:: If true will remove the unpacked directory. _Defaults to true_
|
|
43
|
+
# +unpack_dir+:: Directory that is unpacked from tgz (if not matching the file name)
|
|
44
|
+
#
|
|
45
|
+
# ==== Examples
|
|
46
|
+
# script.unpack("http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz", "/tmp/rubygems") do
|
|
47
|
+
# sudo "ruby setup.rb"
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
def unpack(url, dest, options, &block)
|
|
51
|
+
file = url.split("/").last
|
|
52
|
+
|
|
53
|
+
# TODO: Support other types
|
|
54
|
+
if file !~ /\.tar\.gz\Z|\.tgz\Z/
|
|
55
|
+
raise "Can't unpack this file: #{file}; only support tar.gz and tgz formats"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
options[:clean] = true if options[:clean].nil?
|
|
59
|
+
unpack_dir = options[:unpack_dir]
|
|
60
|
+
clean = options[:clean]
|
|
61
|
+
|
|
62
|
+
unpack_dir ||= file.gsub(/\.tar\.gz|\.tgz/, "")
|
|
63
|
+
|
|
64
|
+
http_get_method = fetch(:http_get_method, "wget -nv")
|
|
65
|
+
|
|
66
|
+
run_all <<-CMDS
|
|
67
|
+
sh -c "mkdir -p #{dest} && cd #{dest} && #{http_get_method} #{url}"
|
|
68
|
+
sh -c "cd #{dest} && tar zxf #{file}"
|
|
69
|
+
CMDS
|
|
70
|
+
|
|
71
|
+
if block_given?
|
|
72
|
+
yield("#{dest}/#{unpack_dir}")
|
|
73
|
+
run_via "rm -f #{dest}/#{file}"
|
|
74
|
+
run_via "rm -rf #{dest}" if clean
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Run all commands (separated by newlines).
|
|
79
|
+
#
|
|
80
|
+
# Uses run_via to execute, so will use <tt>run</tt> or <tt>sudo</tt>
|
|
81
|
+
# depending on the current <tt>:run_method</tt>
|
|
82
|
+
#
|
|
83
|
+
# ==== Options
|
|
84
|
+
# +cmds+:: Commands (separated by newlines)
|
|
85
|
+
# +options+:: See Capistrano invoke_command options
|
|
86
|
+
#
|
|
87
|
+
def run_all(cmds, options = {}, &block)
|
|
88
|
+
cmds.split("\n").each do |cmd|
|
|
89
|
+
cmd = cmd.gsub(/^\s+/, "")
|
|
90
|
+
run_via(cmd, options, &block)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
Capistrano.plugin :script, Capitate::Plugins::Script
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Capitate::Plugins::Templates
|
|
2
|
+
|
|
3
|
+
# Load template. If the extension is .erb will be evaluated with binding.
|
|
4
|
+
#
|
|
5
|
+
# You can add to the list of places we search for templates by setting:
|
|
6
|
+
#
|
|
7
|
+
# set :templates_dirs, [ "path/to/templates1", "/path/to/templates2" ]
|
|
8
|
+
#
|
|
9
|
+
# It looks for the template from:
|
|
10
|
+
# * the <tt>:templates_dirs</tt> setting (if set)
|
|
11
|
+
# * the current directory
|
|
12
|
+
# * the <tt>:project_root</tt> setting (if set)
|
|
13
|
+
# * the gem templates path
|
|
14
|
+
#
|
|
15
|
+
# ==== Options
|
|
16
|
+
# +path+:: If starts with '/', absolute path, otherwise relative path to templates dir
|
|
17
|
+
# +override_binding+:: Binding to override, otherwise uses current (task) binding
|
|
18
|
+
#
|
|
19
|
+
# ==== Examples
|
|
20
|
+
# template.load("memcached/memcached.monitrc.erb") => "This is the text of eval'ed template found at ..."
|
|
21
|
+
#
|
|
22
|
+
# put template.load("memcached/memcached.monitrc.erb"), "/tmp/memcached.monitrc" # Uploads eval'ed template to remote /tmp/ directory
|
|
23
|
+
#
|
|
24
|
+
def load(path, override_binding = nil)
|
|
25
|
+
template_dirs_found = template_dirs.select { |dir| File.exist?("#{dir}/#{path}") }
|
|
26
|
+
|
|
27
|
+
# Not found anywhere, throw error
|
|
28
|
+
if template_dirs_found.empty?
|
|
29
|
+
raise "\n\nTemplate not found: #{path}\n\n"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Use first
|
|
33
|
+
template_path = template_dirs_found.first + "/#{path}"
|
|
34
|
+
|
|
35
|
+
logger.info "reading #{template_path}"
|
|
36
|
+
template_data = IO.read(template_path)
|
|
37
|
+
|
|
38
|
+
if File.extname(template_path) == ".erb"
|
|
39
|
+
template = ERB.new(template_data)
|
|
40
|
+
logger.info "evaluating #{template_path}"
|
|
41
|
+
template_data = template.result(override_binding || binding)
|
|
42
|
+
end
|
|
43
|
+
template_data
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Write template at (relative path) with binding to LOCAL destination path.
|
|
47
|
+
#
|
|
48
|
+
# ==== Options
|
|
49
|
+
# +template_path+:: Path to template relative to templates path
|
|
50
|
+
# +dest_path+:: Local destination path to write to
|
|
51
|
+
# +overwrite_binding+:: Binding
|
|
52
|
+
# +overwrite+:: Force overwrite
|
|
53
|
+
# +verbose+:: Verbose output
|
|
54
|
+
#
|
|
55
|
+
# ==== Examples
|
|
56
|
+
# template.write("config/templates/sphinx.conf.erb", "config/sphinx.conf")
|
|
57
|
+
#
|
|
58
|
+
def write(template_path, dest_path, override_binding = nil, overwrite = false, verbose = true)
|
|
59
|
+
# This is gnarly!
|
|
60
|
+
relative_dest_path = Pathname.new(File.expand_path(dest_path)).relative_path_from(Pathname.new(File.expand_path(".")))
|
|
61
|
+
|
|
62
|
+
if !overwrite && File.exist?(dest_path)
|
|
63
|
+
puts "%10s %-40s (skipped)" % [ "create", relative_dest_path ] if verbose
|
|
64
|
+
return
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
puts "%10s %-40s" % [ "create", relative_dest_path ] if verbose
|
|
68
|
+
template_data = load(template_path, override_binding)
|
|
69
|
+
File.open(dest_path, "w") { |file| file.puts(load(template_path, override_binding)) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
protected
|
|
74
|
+
|
|
75
|
+
# Load all possible places for templates.
|
|
76
|
+
#
|
|
77
|
+
# Returns:
|
|
78
|
+
# * the <tt>:templates_dirs</tt> setting (if set)
|
|
79
|
+
# * the current directory
|
|
80
|
+
# * the <tt>:project_root</tt> setting (if set)
|
|
81
|
+
# * the gem templates path
|
|
82
|
+
#
|
|
83
|
+
def template_dirs
|
|
84
|
+
@template_dirs ||= begin
|
|
85
|
+
template_dirs = []
|
|
86
|
+
template_dirs += fetch(:templates_dirs) if exists?(:templates_dirs)
|
|
87
|
+
template_dirs << "."
|
|
88
|
+
template_dirs << project_root if exists?(:project_root)
|
|
89
|
+
template_dirs << gem_templates_root
|
|
90
|
+
template_dirs
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Get the absolute base templates path.
|
|
95
|
+
def gem_templates_root
|
|
96
|
+
File.expand_path(File.dirname(__FILE__) + "/../../templates")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Get full template path from relative path.
|
|
100
|
+
#
|
|
101
|
+
# ==== Options
|
|
102
|
+
# +template_path+:: Relative path
|
|
103
|
+
#
|
|
104
|
+
# ==== Examples
|
|
105
|
+
# gem_template_path("monit/monit.cnf") => /usr/lib/..../capitate/lib/templates/monit/monit.cnf
|
|
106
|
+
#
|
|
107
|
+
def gem_template_path(template_path)
|
|
108
|
+
File.join(gem_templates_root, template_path)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
Capistrano.plugin :template, Capitate::Plugins::Templates
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
module Capitate::Plugins::Utils
|
|
2
|
+
|
|
3
|
+
# Symlink source to dest
|
|
4
|
+
#
|
|
5
|
+
# ==== Options
|
|
6
|
+
# +args+:: Arguments. If argument is hash, then key is symlinked to value.
|
|
7
|
+
#
|
|
8
|
+
# ==== Examples
|
|
9
|
+
# utils.ln("src/foo" => "dest/foo") # Run: ln -nfs src/foo dest/foo
|
|
10
|
+
# utils.ln("src/foo" => "dest/foo", "src/bar" => "dest/bar") # Links both
|
|
11
|
+
#
|
|
12
|
+
def ln(*args)
|
|
13
|
+
args.each do |arg|
|
|
14
|
+
if arg.is_a?(Hash)
|
|
15
|
+
arg.each do |src, dest|
|
|
16
|
+
run_via "ln -nfs #{src} #{dest}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Delete file.
|
|
23
|
+
#
|
|
24
|
+
# ==== Options
|
|
25
|
+
# +path+:: Path to delete
|
|
26
|
+
#
|
|
27
|
+
def rm(path)
|
|
28
|
+
run_via "rm #{path}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Delete file (recursive/force)
|
|
32
|
+
#
|
|
33
|
+
# ==== Options
|
|
34
|
+
# +path+:: Path to delete
|
|
35
|
+
#
|
|
36
|
+
def rm_rf(path)
|
|
37
|
+
run_via "rm -rf #{path}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Load template and install it.
|
|
41
|
+
# Removes temporary files during transfer and ensures desination directory is created before install.
|
|
42
|
+
#
|
|
43
|
+
# See template plugin for where template paths are loaded from.
|
|
44
|
+
#
|
|
45
|
+
# ==== Options
|
|
46
|
+
# +template_path+:: Path to template
|
|
47
|
+
# +destination+:: Remote path to evaluated template
|
|
48
|
+
# +options+:: Options (see Install template options)
|
|
49
|
+
#
|
|
50
|
+
# ==== Install template options
|
|
51
|
+
# +user+:: User to install (-o). Defaults to *root*.
|
|
52
|
+
# +mode+:: Mode to install file (-m)
|
|
53
|
+
#
|
|
54
|
+
# ==== Example
|
|
55
|
+
# utils.install_template("monit/memcached.monitrc.erb", "/etc/monit/memcached.monitrc", :user => "root", :mode => "600")
|
|
56
|
+
#
|
|
57
|
+
def install_template(template_path, destination, options = {})
|
|
58
|
+
# Truncate extension
|
|
59
|
+
tmp_file_path = template_path.gsub("/", "_").gsub(/.erb$/, "")
|
|
60
|
+
tmp_path = "/tmp/#{tmp_file_path}"
|
|
61
|
+
|
|
62
|
+
options[:user] ||= "root"
|
|
63
|
+
|
|
64
|
+
install_options = []
|
|
65
|
+
install_options << "-o #{options[:user]}"
|
|
66
|
+
install_options << "-m #{options[:mode]}" if options.has_key?(:mode)
|
|
67
|
+
|
|
68
|
+
put template.load(template_path), tmp_path
|
|
69
|
+
# TOOD: Ensure directory exists? mkdir -p #{File.dirname(destination)}
|
|
70
|
+
run_via "install #{install_options.join(" ")} #{tmp_path} #{destination} && rm -f #{tmp_path}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Grep file for regex. Returns true if found, false otherwise.
|
|
74
|
+
#
|
|
75
|
+
# ==== Options
|
|
76
|
+
# +grep+:: Regular expression
|
|
77
|
+
# +path+:: Path to file
|
|
78
|
+
#
|
|
79
|
+
# ==== Example
|
|
80
|
+
# utils.egrep("^mail.\\*", "/etc/syslog.conf") => true
|
|
81
|
+
#
|
|
82
|
+
def egrep(grep, path)
|
|
83
|
+
found = true
|
|
84
|
+
run_via %{egrep '#{grep}' #{path} || echo $?} do |channel, stream, data|
|
|
85
|
+
if data =~ /^(\d+)/
|
|
86
|
+
if $1.to_i > 0
|
|
87
|
+
logger.trace "Not found"
|
|
88
|
+
found = false
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
found
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Check if file exists.
|
|
96
|
+
#
|
|
97
|
+
# ==== Options
|
|
98
|
+
# +path+:: Path to file
|
|
99
|
+
#
|
|
100
|
+
def exist?(path)
|
|
101
|
+
found = true
|
|
102
|
+
run_via "head -1 #{path} >/dev/null 2>&1 || echo $?" do |channel, stream, data|
|
|
103
|
+
if data =~ /^(\d+)/
|
|
104
|
+
if $1.to_i > 0
|
|
105
|
+
logger.trace "Not found"
|
|
106
|
+
found = false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
found
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Get the hostname of the remote server
|
|
114
|
+
#
|
|
115
|
+
# ==== Example
|
|
116
|
+
# utils.hostname => "localhost.localdomain"
|
|
117
|
+
#
|
|
118
|
+
def hostname
|
|
119
|
+
hostname = nil
|
|
120
|
+
run "hostname" do |channel, stream, data|
|
|
121
|
+
hostname = data.chomp
|
|
122
|
+
end
|
|
123
|
+
hostname
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Append data to a file.
|
|
127
|
+
# Optionally check that it exists before adding.
|
|
128
|
+
#
|
|
129
|
+
# ==== Options
|
|
130
|
+
# +path+:: Path to file to append to
|
|
131
|
+
# +data+:: String data to append
|
|
132
|
+
# +check+:: If not nil, will check to see if egrep matches this regex and will not re-append
|
|
133
|
+
# +left_strip+:: If true (default), remove whitespace before lines
|
|
134
|
+
# +should_exist+:: If true (default), raise error if file does not exist
|
|
135
|
+
#
|
|
136
|
+
def append_to(path, data, check = nil, left_strip = true, should_exist = true)
|
|
137
|
+
# If checking and found expression then abort append
|
|
138
|
+
return if check and egrep(check, path)
|
|
139
|
+
|
|
140
|
+
# If should exist and doesn't then abort append
|
|
141
|
+
raise "Can't append to file. File should exist: #{path}" if should_exist and !exist?(path)
|
|
142
|
+
|
|
143
|
+
data.split("\n").each do |line|
|
|
144
|
+
line = line.gsub(/^\s+/, "") if left_strip
|
|
145
|
+
run_via "echo '#{line}' >> #{path}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
Capistrano.plugin :utils, Capitate::Plugins::Utils
|