calas-capitate 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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,105 @@
|
|
1
|
+
# Patch to add ability to clear sessions/connections.
|
2
|
+
module Capitate
|
3
|
+
module CapExt
|
4
|
+
module Connections
|
5
|
+
|
6
|
+
# Set the user to something new (but save the old user; reset_user will set it back).
|
7
|
+
# Takes care of invalidating current connections. Will force a re-login.
|
8
|
+
#
|
9
|
+
# ==== Options
|
10
|
+
# +new_user+:: User to become
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
# set_user("nginx")
|
14
|
+
# # Do something as user nginx
|
15
|
+
#
|
16
|
+
def set_user(new_user)
|
17
|
+
previous_user = fetch(:user)
|
18
|
+
|
19
|
+
return if previous_user == new_user
|
20
|
+
set :previous_user, previous_user
|
21
|
+
|
22
|
+
set :user, new_user
|
23
|
+
clear_sessions
|
24
|
+
end
|
25
|
+
|
26
|
+
# Reset to the old user.
|
27
|
+
# Takes care of invalidating current connections. Will force a re-login.
|
28
|
+
#
|
29
|
+
# ==== Examples
|
30
|
+
# # User is "root"
|
31
|
+
# set_user("nginx")
|
32
|
+
# # Do something as user nginx
|
33
|
+
# reset_user
|
34
|
+
# # User is now root
|
35
|
+
#
|
36
|
+
def reset_user
|
37
|
+
return unless exists?(:previous_user)
|
38
|
+
set :user, fetch(:previous_user)
|
39
|
+
unset :previous_user
|
40
|
+
clear_sessions
|
41
|
+
end
|
42
|
+
|
43
|
+
# Perform action as a different user. Yields the previous user to the block.
|
44
|
+
#
|
45
|
+
# ==== Options
|
46
|
+
# +new_user+:: User to become
|
47
|
+
#
|
48
|
+
# ==== Examples
|
49
|
+
# new_user("nginx") do |old_user|
|
50
|
+
# # Do something as user nginx
|
51
|
+
# end
|
52
|
+
# # Now as user old_user
|
53
|
+
#
|
54
|
+
def with_user(new_user, &block)
|
55
|
+
begin
|
56
|
+
set_user(new_user)
|
57
|
+
yield exists?(:previous_user) ? fetch(:previous_user) : nil
|
58
|
+
ensure
|
59
|
+
reset_user
|
60
|
+
end
|
61
|
+
|
62
|
+
clear_sessions
|
63
|
+
end
|
64
|
+
|
65
|
+
# Close all open sessions, and will force user to re-login.
|
66
|
+
def clear_sessions
|
67
|
+
sessions.each do |key, session|
|
68
|
+
logger.info "Closing: #{key}"
|
69
|
+
session.close
|
70
|
+
end
|
71
|
+
sessions.clear
|
72
|
+
reset_password
|
73
|
+
end
|
74
|
+
|
75
|
+
# Reset the password.
|
76
|
+
# Display the current user that is asking for the password.
|
77
|
+
def reset_password
|
78
|
+
set :password, Proc.new {
|
79
|
+
Capistrano::CLI.password_prompt("Password (for user: #{user}): ")
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Debug connections
|
88
|
+
class Capistrano::SSH
|
89
|
+
|
90
|
+
class << self
|
91
|
+
|
92
|
+
def connect_with_logging(server, options={}, &block)
|
93
|
+
@connect_mutex ||= Mutex.new
|
94
|
+
|
95
|
+
@connect_mutex.synchronize do
|
96
|
+
puts "--- Connecting to #{server} with user: #{server.user || options[:user]}"
|
97
|
+
end
|
98
|
+
|
99
|
+
connect_without_logging(server, options, &block)
|
100
|
+
end
|
101
|
+
|
102
|
+
alias_method_chain :connect, :logging
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Capitate
|
2
|
+
|
3
|
+
module CapExt
|
4
|
+
|
5
|
+
module Docs
|
6
|
+
|
7
|
+
# Get link to github source, so we can refer to recipe code.
|
8
|
+
#
|
9
|
+
# ==== Options
|
10
|
+
# +recipe+:: Recipe path, probably use __FILE__
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
# # In a lib/recipes/foo/foo.rb
|
14
|
+
# link_to_source(__FILE__) => "http://github.com/gabriel/capitate/tree/master/lib/recipes/foo/foo.rb"
|
15
|
+
#
|
16
|
+
def link_to_source(recipe_path)
|
17
|
+
full_path = File.expand_path(recipe_path)
|
18
|
+
project_path = File.expand_path(File.dirname(__FILE__) + "/../../../")
|
19
|
+
"http://github.com/gabriel/capitate/tree/master#{full_path.sub(project_path, "")}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Capitate
|
2
|
+
|
3
|
+
module CapExt
|
4
|
+
|
5
|
+
module Namespace
|
6
|
+
|
7
|
+
def self.included(base) #:nodoc:
|
8
|
+
unless base.method_defined?(:task_without_capitate)
|
9
|
+
base.send :alias_method, :task_without_capitate, :task
|
10
|
+
base.send :alias_method, :task, :task_with_capitate
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def task_arg(name, desc, options = {})
|
15
|
+
@next_task_arguments ||= []
|
16
|
+
@next_task_arguments << options.merge({ :name => name, :desc => desc })
|
17
|
+
end
|
18
|
+
|
19
|
+
def task_with_capitate(name, options={}, &block)
|
20
|
+
task_without_capitate(name, options) do
|
21
|
+
find_task(name).setup_defaults
|
22
|
+
block.call
|
23
|
+
end
|
24
|
+
task_def = find_task(name)
|
25
|
+
task_def.arguments = @next_task_arguments
|
26
|
+
@next_task_arguments = nil
|
27
|
+
task_def
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Capitate::CapExt::RunVia
|
2
|
+
|
3
|
+
# Invoke command with current run_method setting.
|
4
|
+
#
|
5
|
+
# Chooses +sudo+ or +run+ based on <tt>:run_method</tt> setting.
|
6
|
+
#
|
7
|
+
# ==== Options
|
8
|
+
# +cmd+:: Command to run
|
9
|
+
# +options+:: Options (see invoke_command options)
|
10
|
+
#
|
11
|
+
def run_via(cmd, options = {}, &block)
|
12
|
+
options[:via] = fetch(:run_method, :sudo) unless options.has_key?(:via)
|
13
|
+
invoke_command(cmd, options, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Capitate
|
2
|
+
|
3
|
+
module CapExt
|
4
|
+
|
5
|
+
module TaskDefinition
|
6
|
+
|
7
|
+
attr_accessor :arguments
|
8
|
+
|
9
|
+
def setup_defaults
|
10
|
+
return if arguments.blank?
|
11
|
+
|
12
|
+
arguments.each do |arg|
|
13
|
+
namespace.fetch_or_default(arg[:name], arg[:default]) if arg.has_key?(:default)
|
14
|
+
namespace.fetch_or_set(arg[:name], arg[:set]) if arg.has_key?(:set)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Capitate
|
2
|
+
module CapExt
|
3
|
+
module Variables
|
4
|
+
|
5
|
+
def self.included(base) #:nodoc:
|
6
|
+
base.send :alias_method, :fetch_without_capitate, :fetch
|
7
|
+
base.send :alias_method, :fetch, :fetch_with_capitate
|
8
|
+
end
|
9
|
+
|
10
|
+
# Fetch.
|
11
|
+
# Displays usage message from recipe docs if variable not found.
|
12
|
+
#
|
13
|
+
# See capistrano fetch for usage info.
|
14
|
+
#
|
15
|
+
def fetch_with_capitate(variable, *args)
|
16
|
+
begin
|
17
|
+
fetch_without_capitate(variable, *args)
|
18
|
+
rescue IndexError
|
19
|
+
message = capitate.usage(variable)
|
20
|
+
|
21
|
+
if message.blank?
|
22
|
+
message = <<-EOS
|
23
|
+
|
24
|
+
Please set :#{variable} variable in your Capfile or deploy.rb
|
25
|
+
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
|
29
|
+
raise IndexError, "\n#{message}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fetch or set and return default.
|
34
|
+
#
|
35
|
+
# ==== Options
|
36
|
+
# +variable+:: Variable to fetch
|
37
|
+
# +default+:: Default value if not set
|
38
|
+
# +args+:: ?
|
39
|
+
#
|
40
|
+
# ==== Examples
|
41
|
+
# fetch_or_default(:memcached_port, 11211) => 11211
|
42
|
+
# # Any calls to fetch(memcached_port) in the future will return this value 11211 (unless overriden)
|
43
|
+
#
|
44
|
+
def fetch_or_default(variable, default, *args)
|
45
|
+
if exists?(variable)
|
46
|
+
fetch(variable, *args)
|
47
|
+
else
|
48
|
+
set variable, default
|
49
|
+
default
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Fetch or set and fetch any default variable listed.
|
54
|
+
#
|
55
|
+
# ==== Options
|
56
|
+
# +variable+:: Variable to fetch
|
57
|
+
# +variables+:: List if variables to try in order
|
58
|
+
#
|
59
|
+
# ==== Examples
|
60
|
+
# fetch_or_set(:sphinx_db_host, :db_host)
|
61
|
+
#
|
62
|
+
def fetch_or_set(variable, *default_variables)
|
63
|
+
return fetch(variable) if exists?(variable)
|
64
|
+
|
65
|
+
default_variables.each do |default_variable|
|
66
|
+
if exists?(default_variable)
|
67
|
+
value = fetch(default_variable)
|
68
|
+
set variable, value
|
69
|
+
return value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Fetch roles with name and options.
|
76
|
+
# I don't actually use this.
|
77
|
+
#
|
78
|
+
# ==== Options
|
79
|
+
# +name+:: Role name to look for
|
80
|
+
# +options+:: Options to match on, e.g. :primary => true
|
81
|
+
#
|
82
|
+
# ==== Examples
|
83
|
+
# fetch_roles(:db) => [ "10.0.6.71", "10.0.6.72" ]
|
84
|
+
# fetch_roles(:db, :primary => true) => [ "10.0.6.71" ]
|
85
|
+
#
|
86
|
+
def fetch_roles(name, options = {})
|
87
|
+
matched_roles = Set.new
|
88
|
+
|
89
|
+
roles.each do |role_info|
|
90
|
+
role_name = role_info.first
|
91
|
+
|
92
|
+
next unless role_name == name
|
93
|
+
|
94
|
+
role = role_info.last
|
95
|
+
role.each do |server|
|
96
|
+
|
97
|
+
abort = false
|
98
|
+
options.each do |k, v|
|
99
|
+
unless server.options[k] == v
|
100
|
+
abort = true
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
next if abort
|
105
|
+
|
106
|
+
matched_roles << server
|
107
|
+
end
|
108
|
+
end
|
109
|
+
matched_roles.to_a
|
110
|
+
end
|
111
|
+
|
112
|
+
# Fetch first role with name and options.
|
113
|
+
#
|
114
|
+
# ==== Options
|
115
|
+
# +name+:: Role name to look for
|
116
|
+
# +options+:: Options to match on, e.g. :primary => true
|
117
|
+
#
|
118
|
+
# ==== Examples
|
119
|
+
# fetch_roles(:db) => [ "10.0.6.71", "10.0.6.72" ]
|
120
|
+
# fetch_roles(:db, :primary => true) => [ "10.0.6.71" ]
|
121
|
+
#
|
122
|
+
def fetch_role(name, options = {})
|
123
|
+
matched = fetch_roles(name, options)
|
124
|
+
return matched.first if matched
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
# Capitate base capistrano plugin
|
5
|
+
module Capitate::Plugins::Base
|
6
|
+
|
7
|
+
# Project root. Fetch from :project_root, or fall back to RAILS_ROOT.
|
8
|
+
def root
|
9
|
+
return fetch(:project_root) if exists?(:project_root)
|
10
|
+
RAILS_ROOT
|
11
|
+
end
|
12
|
+
|
13
|
+
# Path relative to project root.
|
14
|
+
#
|
15
|
+
# To set the project root:
|
16
|
+
#
|
17
|
+
# set :project_root, "path/to/project" in Capfile.
|
18
|
+
#
|
19
|
+
# ==== Options
|
20
|
+
# +path+:: Relative path
|
21
|
+
# +check_exist+:: Whether to check its existence and throw error if not found
|
22
|
+
#
|
23
|
+
# ==== Examples
|
24
|
+
# relative_to_root("config/foo.yml") => "path/to/project/config/foo.yml"
|
25
|
+
#
|
26
|
+
def relative_to_root(path = nil, check_exist = false)
|
27
|
+
if path
|
28
|
+
root_path = File.join(root, path)
|
29
|
+
else
|
30
|
+
root_path = root
|
31
|
+
end
|
32
|
+
|
33
|
+
# Check for file existance
|
34
|
+
if check_exist and !File.exist?(root_path)
|
35
|
+
raise <<-EOS
|
36
|
+
|
37
|
+
File not found: #{File.expand_path(root_path)}
|
38
|
+
|
39
|
+
This is loaded for the capitate plugin. View the README in:
|
40
|
+
#{File.expand_path(File.dirname(__FILE__) + "/../doc/README")}
|
41
|
+
EOS
|
42
|
+
end
|
43
|
+
|
44
|
+
root_path
|
45
|
+
end
|
46
|
+
|
47
|
+
# Usage for current task.
|
48
|
+
#
|
49
|
+
# ==== Options
|
50
|
+
# +variable+:: Missing variable setting (to display as not set)
|
51
|
+
#
|
52
|
+
# ==== Examples
|
53
|
+
# usage(:gem_list) => "Description from task definition."
|
54
|
+
#
|
55
|
+
def usage(variable = nil)
|
56
|
+
message = ""
|
57
|
+
|
58
|
+
if variable
|
59
|
+
message += <<-EOS
|
60
|
+
|
61
|
+
Error: :#{variable} not set.
|
62
|
+
EOS
|
63
|
+
end
|
64
|
+
|
65
|
+
if current_task
|
66
|
+
message += <<-EOS
|
67
|
+
|
68
|
+
Usage:
|
69
|
+
|
70
|
+
#{indent_doc(current_task.desc)}
|
71
|
+
|
72
|
+
EOS
|
73
|
+
end
|
74
|
+
message
|
75
|
+
end
|
76
|
+
|
77
|
+
# Indent string block.
|
78
|
+
#
|
79
|
+
# ==== Options
|
80
|
+
# +s+:: String block
|
81
|
+
# +amount+:: Amount to indent
|
82
|
+
#
|
83
|
+
def indent_doc(s, amount = 4)
|
84
|
+
return nil if s.blank?
|
85
|
+
indentation = (0..amount).collect { |n| " " }.join
|
86
|
+
s.split("\n").collect { |sp| "#{indentation}#{sp}"}.join("\n")
|
87
|
+
end
|
88
|
+
|
89
|
+
# Unindent.
|
90
|
+
#
|
91
|
+
# Lifted from capistrano bin/capify
|
92
|
+
#
|
93
|
+
# ==== Options
|
94
|
+
# +string+:: String to unindent
|
95
|
+
#
|
96
|
+
def unindent(string)
|
97
|
+
return "" if string.blank?
|
98
|
+
if string =~ /\A(\s*)/
|
99
|
+
amount = $1.length
|
100
|
+
return string.strip.gsub(/^#{$1}/, "")
|
101
|
+
end
|
102
|
+
string
|
103
|
+
end
|
104
|
+
|
105
|
+
# Load all tasks into an array.
|
106
|
+
def load_all_tasks
|
107
|
+
tasks = []
|
108
|
+
top.namespaces.each do |namespace|
|
109
|
+
load_tasks(namespace, tasks)
|
110
|
+
end
|
111
|
+
tasks
|
112
|
+
end
|
113
|
+
|
114
|
+
# Build a task tree, consisting of task nodes.
|
115
|
+
def task_tree
|
116
|
+
top_node = Capitate::TaskNode.new("top")
|
117
|
+
|
118
|
+
load_all_tasks.each do |task|
|
119
|
+
Capitate::TaskNode.populate_with_task(top_node, task)
|
120
|
+
end
|
121
|
+
top_node
|
122
|
+
end
|
123
|
+
|
124
|
+
protected
|
125
|
+
|
126
|
+
def load_tasks(namespace, tasks = [])
|
127
|
+
recipe = namespace.last
|
128
|
+
|
129
|
+
recipe.namespaces.each do |nested_namespace|
|
130
|
+
load_tasks(nested_namespace, tasks)
|
131
|
+
end
|
132
|
+
|
133
|
+
recipe.task_list.each do |task|
|
134
|
+
tasks << task
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
Capistrano.plugin :capitate, Capitate::Plugins::Base
|