centostrano 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 (121) hide show
  1. data/CHANGELOG +215 -0
  2. data/COPYING +19 -0
  3. data/LICENSE +339 -0
  4. data/README +166 -0
  5. data/THANKS +5 -0
  6. data/bin/centify +137 -0
  7. data/docs/ANNOUNCE.deprec2 +47 -0
  8. data/docs/README.install +88 -0
  9. data/docs/README.nagios +28 -0
  10. data/docs/README.rails +20 -0
  11. data/docs/README.svn +31 -0
  12. data/docs/ROADMAP.txt +74 -0
  13. data/docs/deprec-1.x/deprec-1.x.quickstart +50 -0
  14. data/docs/deprec-1.x/notes.txt +12 -0
  15. data/docs/deprec_banner.gif +0 -0
  16. data/lib/centostrano.rb +9 -0
  17. data/lib/deprec/capistrano_extensions.rb +391 -0
  18. data/lib/deprec/centostrano.rb +46 -0
  19. data/lib/deprec/recipes/apache.rb +188 -0
  20. data/lib/deprec/recipes/canonical.rb +57 -0
  21. data/lib/deprec/recipes/deprec.rb +188 -0
  22. data/lib/deprec/recipes/deprecated.rb +71 -0
  23. data/lib/deprec/recipes/example.rb +115 -0
  24. data/lib/deprec/recipes/git.rb +106 -0
  25. data/lib/deprec/recipes/gitosis.rb +134 -0
  26. data/lib/deprec/recipes/logrotate.rb +54 -0
  27. data/lib/deprec/recipes/memcache.rb +53 -0
  28. data/lib/deprec/recipes/merb.rb +57 -0
  29. data/lib/deprec/recipes/mongrel.rb +220 -0
  30. data/lib/deprec/recipes/monit.rb +139 -0
  31. data/lib/deprec/recipes/mysql.rb +147 -0
  32. data/lib/deprec/recipes/nginx.rb +172 -0
  33. data/lib/deprec/recipes/postgresql.rb +132 -0
  34. data/lib/deprec/recipes/rails.rb +297 -0
  35. data/lib/deprec/recipes/ruby.rb +71 -0
  36. data/lib/deprec/recipes/sphinx.rb +89 -0
  37. data/lib/deprec/recipes/ssh.rb +93 -0
  38. data/lib/deprec/recipes/svn.rb +167 -0
  39. data/lib/deprec/recipes/users.rb +90 -0
  40. data/lib/deprec/recipes.rb +33 -0
  41. data/lib/deprec/templates/aoe/aoe-init +55 -0
  42. data/lib/deprec/templates/aoe/fence_aoemask +351 -0
  43. data/lib/deprec/templates/apache/httpd-vhost-app.conf.erb +144 -0
  44. data/lib/deprec/templates/apache/httpd.conf +465 -0
  45. data/lib/deprec/templates/apache/index.html.erb +37 -0
  46. data/lib/deprec/templates/apache/master.css +72 -0
  47. data/lib/deprec/templates/centos/repository.erb +6 -0
  48. data/lib/deprec/templates/coraid/aoe-init +55 -0
  49. data/lib/deprec/templates/deprec/caprc.erb +14 -0
  50. data/lib/deprec/templates/heartbeat/authkeys.erb +2 -0
  51. data/lib/deprec/templates/heartbeat/ha.cf.erb +15 -0
  52. data/lib/deprec/templates/heartbeat/haresources.erb +1 -0
  53. data/lib/deprec/templates/logrotate/logrotate.conf.erb +32 -0
  54. data/lib/deprec/templates/mongrel/logrotate.conf.erb +11 -0
  55. data/lib/deprec/templates/mongrel/logrotate.erb +0 -0
  56. data/lib/deprec/templates/mongrel/mongrel_cluster-init-script +54 -0
  57. data/lib/deprec/templates/mongrel/mongrel_cluster.logrotate.d +14 -0
  58. data/lib/deprec/templates/mongrel/mongrel_cluster.yml.erb +10 -0
  59. data/lib/deprec/templates/mongrel/monit.conf.erb +17 -0
  60. data/lib/deprec/templates/monit/monit-init-script +104 -0
  61. data/lib/deprec/templates/monit/monitrc.erb +227 -0
  62. data/lib/deprec/templates/monit/nothing +0 -0
  63. data/lib/deprec/templates/mysql/create_databases.sql +20 -0
  64. data/lib/deprec/templates/mysql/database.yml.prod +6 -0
  65. data/lib/deprec/templates/mysql/database.yml.stage +6 -0
  66. data/lib/deprec/templates/mysql/my.cnf.erb +140 -0
  67. data/lib/deprec/templates/mysql/sphinx.conf.prod +542 -0
  68. data/lib/deprec/templates/mysql/sphinx.conf.stage +542 -0
  69. data/lib/deprec/templates/nagios/cgi.cfg.erb +321 -0
  70. data/lib/deprec/templates/nagios/commands.cfg.erb +240 -0
  71. data/lib/deprec/templates/nagios/contacts.cfg.erb +57 -0
  72. data/lib/deprec/templates/nagios/hosts.cfg.erb +143 -0
  73. data/lib/deprec/templates/nagios/htpasswd.users +1 -0
  74. data/lib/deprec/templates/nagios/localhost.cfg.erb +157 -0
  75. data/lib/deprec/templates/nagios/nagios.cfg.erb +1274 -0
  76. data/lib/deprec/templates/nagios/nagios_apache_vhost.conf.erb +45 -0
  77. data/lib/deprec/templates/nagios/nrpe.cfg.erb +210 -0
  78. data/lib/deprec/templates/nagios/nrpe.xinetd.erb +16 -0
  79. data/lib/deprec/templates/nagios/resource.cfg.erb +34 -0
  80. data/lib/deprec/templates/nagios/services.cfg.erb +79 -0
  81. data/lib/deprec/templates/nagios/templates.cfg.erb +9 -0
  82. data/lib/deprec/templates/nagios/timeperiods.cfg.erb +94 -0
  83. data/lib/deprec/templates/network/hostname.erb +1 -0
  84. data/lib/deprec/templates/network/hosts.erb +2 -0
  85. data/lib/deprec/templates/network/interfaces.erb +22 -0
  86. data/lib/deprec/templates/nginx/logrotate.conf.erb +13 -0
  87. data/lib/deprec/templates/nginx/logrotate.erb +0 -0
  88. data/lib/deprec/templates/nginx/mime.types.erb +70 -0
  89. data/lib/deprec/templates/nginx/nginx-init-script +109 -0
  90. data/lib/deprec/templates/nginx/nginx.conf.erb +120 -0
  91. data/lib/deprec/templates/nginx/nginx.logrotate.d +12 -0
  92. data/lib/deprec/templates/nginx/nothing.conf +1 -0
  93. data/lib/deprec/templates/nginx/rails_nginx_vhost.conf.erb +41 -0
  94. data/lib/deprec/templates/ntp/ntp.conf.erb +42 -0
  95. data/lib/deprec/templates/postfix/aliases.erb +3 -0
  96. data/lib/deprec/templates/postfix/dynamicmaps.cf.erb +8 -0
  97. data/lib/deprec/templates/postfix/main.cf.erb +41 -0
  98. data/lib/deprec/templates/postfix/master.cf.erb +77 -0
  99. data/lib/deprec/templates/postgresql/pg_hba.conf.erb +76 -0
  100. data/lib/deprec/templates/sphinx/monit.conf.erb +5 -0
  101. data/lib/deprec/templates/ssh/ssh_config.erb +50 -0
  102. data/lib/deprec/templates/ssh/sshd_config.erb +78 -0
  103. data/lib/deprec/templates/subversion/svn.apache.vhost.erb +43 -0
  104. data/lib/deprec/templates/trac/apache_vhost.conf.erb +24 -0
  105. data/lib/deprec/templates/trac/trac.ini.erb +106 -0
  106. data/lib/deprec/templates/trac/trac_deprec.png +0 -0
  107. data/lib/deprec/templates/trac/tracd-init.erb +43 -0
  108. data/lib/deprec/templates/xen/15-disable-hwclock +40 -0
  109. data/lib/deprec/templates/xen/network-bridge-wrapper +3 -0
  110. data/lib/deprec/templates/xen/xen-tools.conf.erb +220 -0
  111. data/lib/deprec/templates/xen/xend-config.sxp.erb +195 -0
  112. data/lib/deprec/templates/xen/xend-init.erb +69 -0
  113. data/lib/deprec/templates/xen/xendomains.erb +137 -0
  114. data/lib/deprec/templates/xen/xm.tmpl.erb +85 -0
  115. data/lib/deprec_cmd_completion.sh +26 -0
  116. data/lib/vmbuilder_plugins/all.rb +20 -0
  117. data/lib/vmbuilder_plugins/apt.rb +93 -0
  118. data/lib/vmbuilder_plugins/emerge.rb +76 -0
  119. data/lib/vmbuilder_plugins/gem.rb +90 -0
  120. data/lib/vmbuilder_plugins/std.rb +203 -0
  121. metadata +207 -0
@@ -0,0 +1,28 @@
1
+ deprec: Install and configure Nagios on Ubuntu 7.10 (gutsy)
2
+ ===========================================================
3
+ by Mike Bailey
4
+ * Quickstart
5
+
6
+ # You need the following items defined (in config/deploy.rb)
7
+ set :application, 'nagios'
8
+ set :domain, 'nagios.host.name'
9
+ role :nagios, domain
10
+ role :app, 'nagios'
11
+ role :web, nil # must be defined but content not important
12
+
13
+ # Run the following on your workstation
14
+ export HOSTS=nagios.domain.name # replace with desired domain
15
+ cap deprec:apache:install
16
+ cap deprec:apache:activate
17
+ cap deprec:nagios:install
18
+ cap deprec:nagios:activate
19
+ cap deprec:nagios_plugins:install
20
+ cap deprec:nagios:config_gen
21
+ cap deprec:nagios:htpass # create web logins
22
+ cap deprec:nagios:config
23
+ cap deprec:apache:restart
24
+
25
+
26
+ * The detail
27
+
28
+ TBC
data/docs/README.rails ADDED
@@ -0,0 +1,20 @@
1
+ deprec: Install Ruby on Rails app on fresh Ubuntu 7.10 (gutsy)
2
+ ==============================================================
3
+ by Mike Bailey
4
+
5
+ * Quickstart
6
+
7
+ cd /rails/project/root
8
+ depify .
9
+ # edit config/deploy.rb
10
+ cap deprec:rails:install_stack
11
+ cap deploy:setup
12
+ cap deploy
13
+ cap deprec:db:create
14
+ cap deprec:db:migrate
15
+ cap deprec:nginx:restart
16
+
17
+
18
+ * The detail
19
+
20
+ TBC
data/docs/README.svn ADDED
@@ -0,0 +1,31 @@
1
+ == svn
2
+
3
+ # Add the following to your deploy.rb (or ~/.caprc if always the same)
4
+ set :scm, 'your.svn.server'
5
+
6
+ # The run the following from the root the project you wish to import
7
+ cap deprec:svn:install
8
+ cap deprec:svn:setup
9
+
10
+
11
+ # XXX Not tested on deprec2
12
+ #
13
+ #
14
+ # Installs subversion and trac software on server.
15
+ # Creates subversion repository on server and imports project.
16
+ # Sets up trac installation for project.
17
+ #
18
+ # role :scm, 'deptest.deprecated.org'
19
+ #
20
+ # # install packages
21
+ # cap apache_install svn_install trac_install
22
+ #
23
+ # # import project
24
+ # cap svn_import_project
25
+ # cap trac_init
26
+ # cap trac_start
27
+ #
28
+ # # your project will be viewable at http://yourdomain:8000/
29
+ # # you can add other users with 'cap trac_user_add'
30
+
31
+
data/docs/ROADMAP.txt ADDED
@@ -0,0 +1,74 @@
1
+ deprec 2.0 roadmap
2
+
3
+ # expectations/constraints
4
+
5
+ - all tasks should be re-runnable
6
+ - all install_ tasks should install required dependancies
7
+ - users should expect that standard cap commands will work
8
+
9
+
10
+ # interactive tools
11
+
12
+ deprec should make it easy to perform commonly use sysadmin tasks.
13
+ While automation brings great power it's still often quicker to
14
+ run 'semi automated' tasks that require some interactive input.
15
+
16
+ For example, adding a user account to a number of servers could be
17
+ made easier with a general purpose interactive recipe:
18
+
19
+ cap add_user
20
+ > username for new user? : fred
21
+ > password for new user? : ******
22
+ > retype password : ******
23
+ > user type for new user?
24
+ 1. default
25
+ 2. admin
26
+ ?: 2
27
+ creating...
28
+ server01 - created user 'fred' of type 'admin'
29
+ server02 - created user 'fred' of type 'admin'
30
+ server03 - created user 'fred' of type 'admin'
31
+ server04 - user 'fred' exists. Set type to 'admin'
32
+
33
+ * Note that the servers above were all servers mentioned in deploy.rb
34
+ for a project however there are many ways to get this list.
35
+
36
+
37
+ Plugin support for different distro's was too ambitious. I've tried other
38
+ distros and didn't like them much. I'm happy with Ubuntu at the moment and
39
+ # # plugin based support different distros, versions (and possibly OS's)
40
+ #
41
+ # While deprec was built to work with Ubuntu 6.06, some people have shown interest
42
+ # in using it with other distro's. I plan to move all of the Ubuntu specific code
43
+ # into a separate gem 'deprec_ubuntu' which deprec will load by default. This will
44
+ # mean anyone else can create and maintain plugins that allow the use of other linux
45
+ # distros (and perhaps other OS's).
46
+ #
47
+ # All platform dependent functions will be:
48
+ #
49
+ # - cap extensions, not tasks
50
+ # - plugins, not part of the deprec itself
51
+ # - loaded using gemplugins http://mongrel.rubyforge.org/gem_plugin_rdoc/index.html
52
+ #
53
+ # I'd like 'cap -T' to show the distros supported for each command when not arch independant.
54
+
55
+
56
+ # add lots more useful tasks
57
+
58
+ I'd like to extend deprec beyond just getting your rails app up and running.
59
+ Anything I need that takes some time to do right will go in. If you've got
60
+ something you want added then write it and let me know.
61
+
62
+ install and configure the following package groups:
63
+ - source control (svn, trac)
64
+ - mail (postfix, imap, mutt, mailx)
65
+
66
+
67
+ # don't rely on third party servers to be available when installing software
68
+
69
+ As I write, www.apache.org is serving at a crawling pace. I'd like to make it easy for
70
+ users to download and cache all required third party apps, gems, etc and have deprec
71
+ use these.
72
+
73
+ Currently you can drop the tarballs into /usr/local/src on the target server and
74
+ they'll get picked up automatically. I haven't looked at a simple way to cache the gems yet.
@@ -0,0 +1,50 @@
1
+ #
2
+ # Old notes - YMMV
3
+ #
4
+
5
+ == deprec quickstart (with svn, trac and deployment to apache/mongrel/mysql)
6
+
7
+ Here are instructions that will take a fresh install of Ubuntu Dapper (6.06.1 server), create a working rails app, create an SVN repository and trac installation for it and deploy it using apache, mongrel and mysql.
8
+
9
+ All commands below are run on your local host. You will *never* be requested
10
+ to log into the remote server manually. Capistrano does all the work.
11
+
12
+ - Mike
13
+
14
+ # Install deprec on workstation
15
+ sudo gem install deprec --include-dependencies
16
+ echo 'require "deprec/recipes"' >> ~/.caprc
17
+ echo "ssh_options[:keys] = %w(${HOME}/.ssh/id_dsa)" >> ~/.caprc
18
+ echo 'ssh_options[:paranoid] = false' >> ~/.caprc
19
+ echo 'ssh_options[:forward_agent] = true' >> ~/.caprc
20
+
21
+ # Create rails project on workstation and configure for deprec
22
+ # (alternatively use an existing project)
23
+ rails example
24
+ cd example
25
+ ./script/generate scaffold_resource person name:string age:integer
26
+ deprec --apply-to . --name example --domain www.example.com
27
+
28
+ # NOTE! Use following two commands if you only have 'root' account on server
29
+ # Some VPS services provide you with this when you sign up
30
+ cap change_root_password_as_root # '_as_root' means run this as 'root' user
31
+ cap setup_admin_account_as_root
32
+
33
+ # Copy your ssh keys to remote server to avoid having to type passwords
34
+ cap setup_ssh_keys
35
+
36
+ # Install all required software on remote server
37
+ cap install_rails_stack svn_install trac_install
38
+
39
+ # Import application into subversion respository and setup trac
40
+ cap svn_setup
41
+ cap trac_setup
42
+ cap trac_user_add # this command allows you to create other trac users
43
+ cap trac_start # trac is now available on http://www.example.com:9000/
44
+ cap trac_stop # if you had the need
45
+
46
+ # Deploy application
47
+ cap setup
48
+ cap deploy_with_migrations
49
+ cap apache_restart
50
+ # application is now running on http://www.example.com/people
@@ -0,0 +1,12 @@
1
+ # update timezone on gutsy
2
+ # dpkg-reconfigure tzdata
3
+
4
+
5
+ # Building Edge Capistrano
6
+ You can build an edge gem by cd'ing to that directory and doing:
7
+
8
+ 1. svn info. Find the line that says "Revision:" and mark the revision number.
9
+ 2. rake PKG_BUILD=<rev> gem. Replace <rev> with the revision number.
10
+ 3. Look in the pkg subdirectory. Install that gem file via "gem install pkg/<gem file>"
11
+
12
+ - Jamis
Binary file
@@ -0,0 +1,9 @@
1
+ unless Capistrano::Configuration.respond_to?(:instance)
2
+ abort "Centostrano requires Capistrano 2"
3
+ end
4
+
5
+ require "#{File.dirname(__FILE__)}/deprec/capistrano_extensions"
6
+ require "#{File.dirname(__FILE__)}/deprec/centostrano"
7
+ require "#{File.dirname(__FILE__)}/vmbuilder_plugins/all"
8
+ require "#{File.dirname(__FILE__)}/deprec/recipes"
9
+
@@ -0,0 +1,391 @@
1
+ # Copyright 2006-2008 by Mike Bailey. All rights reserved.
2
+ require 'capistrano'
3
+ require 'fileutils'
4
+
5
+ module Deprec2
6
+
7
+ # Temporarly set ROLES to something different
8
+ def for_roles(roles)
9
+ old_roles = ENV['ROLES']
10
+ ENV['ROLES'] = roles
11
+ yield
12
+ ENV['ROLES'] = old_roles
13
+ end
14
+
15
+ DEPREC_TEMPLATES_BASE = File.join(File.dirname(__FILE__), 'templates')
16
+
17
+ # Render template (usually a config file)
18
+ #
19
+ # Usually we render it to a file on the local filesystem.
20
+ # This way, we keep a copy of the config file under source control.
21
+ # We can make manual changes if required and push to new hosts.
22
+ #
23
+ # If the options hash contains :path then it's written to that path.
24
+ # If it contains :remote => true, the file will instead be written to remote targets
25
+ # If options[:path] and options[:remote] are missing, it just returns the rendered
26
+ # template as a string (good for debugging).
27
+ #
28
+ # XXX I would like to get rid of :render_template_to_file
29
+ # XXX Perhaps pass an option to this function to write to remote
30
+ #
31
+ def render_template(app, options={})
32
+ template = options[:template]
33
+ path = options[:path] || nil
34
+ remote = options[:remote] || false
35
+ mode = options[:mode] || 0755
36
+ owner = options[:owner] || nil
37
+
38
+ # replace this with a check for the file
39
+ if ! template
40
+ puts "render_template() requires a value for the template!"
41
+ return false
42
+ end
43
+
44
+ # If local copies of deprec templates exist they will be used
45
+ # If you don't specify the location with the local_template_dir option
46
+ # it defaults to config/templates.
47
+ # e.g. config/templates/nginx/nginx.conf.erb
48
+ local_template = File.join(local_template_dir, app.to_s, template)
49
+ if File.exists?(local_template)
50
+ puts
51
+ puts "Using local template (#{local_template})"
52
+ template = ERB.new(IO.read(local_template), nil, '-')
53
+ else
54
+ template = ERB.new(IO.read(File.join(DEPREC_TEMPLATES_BASE, app.to_s, template)), nil, '-')
55
+ end
56
+ rendered_template = template.result(binding)
57
+
58
+ if remote
59
+ # render to remote machine
60
+ puts 'You need to specify a path to render the template to!' unless path
61
+ exit unless path
62
+ sudo "test -d #{File.dirname(path)} || sudo mkdir -p #{File.dirname(path)}"
63
+ std.su_put rendered_template, path, '/tmp/', :mode => mode
64
+ sudo "chown #{owner} #{path}" if defined?(owner)
65
+ elsif path
66
+ # render to local file
67
+ full_path = File.join('config', app.to_s, path)
68
+ path_dir = File.dirname(full_path)
69
+ if File.exists?(full_path)
70
+ if IO.read(full_path) == rendered_template
71
+ puts "[skip] File exists and is identical (#{full_path})."
72
+ return false
73
+ elsif overwrite?(full_path, rendered_template)
74
+ File.delete(full_path)
75
+ else
76
+ puts "[skip] Not overwriting #{full_path}"
77
+ return false
78
+ end
79
+ end
80
+ FileUtils.mkdir_p "#{path_dir}" if ! File.directory?(path_dir)
81
+ # added line above to make windows compatible
82
+ # system "mkdir -p #{path_dir}" if ! File.directory?(path_dir)
83
+ File.open(full_path, 'w'){|f| f.write rendered_template }
84
+ puts "[done] #{full_path} written"
85
+ else
86
+ # render to string
87
+ return rendered_template
88
+ end
89
+ end
90
+
91
+ def overwrite?(full_path, rendered_template)
92
+ if defined?(overwrite_all)
93
+ if overwrite_all == true
94
+ return true
95
+ else
96
+ return false
97
+ end
98
+ end
99
+
100
+ # XXX add :always and :never later - not sure how to set persistent value from here
101
+ # response = Capistrano::CLI.ui.ask "File exists. Overwrite? ([y]es, [n]o, [a]lways, n[e]ver)" do |q|
102
+ puts
103
+ response = Capistrano::CLI.ui.ask "File exists (#{full_path}).
104
+ Overwrite? ([y]es, [n]o, [d]iff)" do |q|
105
+ q.default = 'n'
106
+ end
107
+
108
+ case response
109
+ when 'y'
110
+ return true
111
+ when 'n'
112
+ return false
113
+ when 'd'
114
+ require 'tempfile'
115
+ tf = Tempfile.new("deprec_diff")
116
+ tf.puts(rendered_template)
117
+ tf.close
118
+ puts
119
+ puts "Running diff -u current_file new_file_if_you_overwrite"
120
+ puts
121
+ system "diff -u #{full_path} #{tf.path} | less"
122
+ puts
123
+ overwrite?(full_path, rendered_template)
124
+ # XXX add :always and :never later - not sure how to set persistent value from here
125
+ # when 'a'
126
+ # set :overwrite_all, true
127
+ # when 'e'
128
+ # set :overwrite_all, false
129
+ end
130
+
131
+ end
132
+
133
+ def render_template_to_file(template_name, destination_file_name, templates_dir = DEPREC_TEMPLATES_BASE)
134
+ template_name += '.conf' if File.extname(template_name) == '' # XXX this to be removed
135
+
136
+ file = File.join(templates_dir, template_name)
137
+ buffer = render :template => File.read(file)
138
+
139
+ temporary_location = "/tmp/#{template_name}"
140
+ put buffer, temporary_location
141
+ sudo "cp #{temporary_location} #{destination_file_name}"
142
+ delete temporary_location
143
+ end
144
+
145
+ # Copy configs to server(s). Note there is no :pull task. No changes should
146
+ # be made to configs on the servers so why would you need to pull them back?
147
+ def push_configs(app, files)
148
+ app = app.to_s
149
+ files.each do |file|
150
+ # If the file path is relative we will prepend a path to this projects
151
+ # own config directory for this service.
152
+ if file[:path][0,1] != '/'
153
+ full_remote_path = File.join(deploy_to, app, file[:path])
154
+ else
155
+ full_remote_path = file[:path]
156
+ end
157
+ full_local_path = File.join('config', app, file[:path])
158
+ sudo "test -d #{File.dirname(full_remote_path)} || sudo mkdir -p #{File.dirname(full_remote_path)}"
159
+ #
160
+ # XXX work this in to check for per-host variants of config files
161
+ #
162
+ # if any variants of this file exist for this host (they have -hostname at end)
163
+ # servers = find_servers_for_task(current_task)
164
+ # servers.each do |server|
165
+ # puts server(..., :hosts => server) # XXX find a way to restrict su_put to one host
166
+ # end
167
+ # else
168
+ # # just send them the normal way, it's quicker in parallel
169
+ std.su_put File.read(full_local_path), full_remote_path, '/tmp/', :mode=>file[:mode]
170
+ # end
171
+ #
172
+ sudo "chown #{file[:owner]} #{full_remote_path}"
173
+ end
174
+ end
175
+
176
+ def teardown_connections
177
+ sessions.keys.each do |server|
178
+ sessions[server].close
179
+ sessions.delete(server)
180
+ end
181
+ end
182
+
183
+ def append_to_file_if_missing(filename, value, options={})
184
+ # XXX sort out single quotes in 'value' - they'l break command!
185
+ # XXX if options[:requires_sudo] and :use_sudo then use sudo
186
+ sudo <<-END
187
+ sh -c '
188
+ grep -F "#{value}" #{filename} > /dev/null 2>&1 ||
189
+ echo "#{value}" >> #{filename}
190
+ '
191
+ END
192
+ end
193
+
194
+ # create new user account on target system
195
+ def useradd(user, options={})
196
+ options[:shell] ||= '/bin/bash' # new accounts on ubuntu 6.06.1 have been getting /bin/sh
197
+ switches = ''
198
+ switches += " -s #{options[:shell]} " if options[:shell]
199
+ switches += ' -M ' if options[:homedir] == false
200
+ switches += " -g #{options[:group]} " unless options[:group].nil?
201
+ invoke_command "grep '^#{user}:' /etc/passwd || sudo /usr/sbin/useradd #{switches} #{user}",
202
+ :via => run_method
203
+ end
204
+
205
+ # create a new group on target system
206
+ def groupadd(group, options={})
207
+ via = options.delete(:via) || run_method
208
+ # XXX I don't like specifying the path to groupadd - need to sort out paths before long
209
+ invoke_command "grep '#{group}:' /etc/group || sudo /usr/sbin/groupadd #{group}", :via => via
210
+ end
211
+
212
+ # add group to the list of groups this user belongs to
213
+ def add_user_to_group(user, group)
214
+ invoke_command "groups #{user} | grep ' #{group} ' || sudo /usr/sbin/usermod -G #{group} -a #{user}",
215
+ :via => run_method
216
+ end
217
+
218
+ # create directory if it doesn't already exist
219
+ # set permissions and ownership
220
+ # XXX move mode, path and
221
+ def mkdir(path, options={})
222
+ via = options.delete(:via) || :run
223
+ # XXX need to make sudo commands wrap the whole command (sh -c ?)
224
+ # XXX removed the extra 'sudo' from after the '||' - need something else
225
+ invoke_command "test -d #{path} || #{sudo if via == :sudo} mkdir -p #{path}"
226
+ invoke_command "chmod #{sprintf("%3o",options[:mode]||0755)} #{path}", :via => via if options[:mode]
227
+ invoke_command "chown -R #{options[:owner]} #{path}", :via => via if options[:owner]
228
+ groupadd(options[:group], :via => via) if options[:group]
229
+ invoke_command "chgrp -R #{options[:group]} #{path}", :via => via if options[:group]
230
+ end
231
+
232
+ def create_src_dir
233
+ mkdir(src_dir, :mode => 0775, :group => group_src, :via => :sudo)
234
+ end
235
+
236
+ # download source package if we don't already have it
237
+ def download_src(src_package, src_dir)
238
+ set_package_defaults(src_package)
239
+ create_src_dir
240
+ # check if file exists and if we have an MD5 hash or bytecount to compare
241
+ # against if so, compare and decide if we need to download again
242
+ if defined?(src_package[:md5sum])
243
+ md5_clause = " && echo '#{src_package[:md5sum]}' | md5sum -c - "
244
+ end
245
+ apt.install( {:base => %w(wget)}, :stable )
246
+ # XXX replace with invoke_command
247
+ run "cd #{src_dir} && test -f #{src_package[:filename]} #{md5_clause} || #{sudo} wget --quiet --timestamping #{src_package[:url]}"
248
+ end
249
+
250
+ # unpack src and make it writable by the group
251
+ def unpack_src(src_package, src_dir)
252
+ set_package_defaults(src_package)
253
+ package_dir = File.join(src_dir, src_package[:dir])
254
+ # XXX replace with invoke_command
255
+ sudo <<-EOF
256
+ bash -c '
257
+ cd #{src_dir};
258
+ test -d #{package_dir}.old && rm -fr #{package_dir}.old;
259
+ test -d #{package_dir} && mv #{package_dir} #{package_dir}.old;
260
+ #{src_package[:unpack]}
261
+ chgrp -R #{group} #{package_dir};
262
+ chmod -R g+w #{package_dir};
263
+ '
264
+ EOF
265
+ end
266
+
267
+ def set_package_defaults(pkg)
268
+ pkg[:filename] ||= File.basename(pkg[:url])
269
+ pkg[:dir] ||= File.basename(pkg[:url], '.tar.gz')
270
+ pkg[:unpack] ||= "tar zxf #{pkg[:filename]};"
271
+ pkg[:configure] ||= './configure ;'
272
+ pkg[:make] ||= 'make;'
273
+ pkg[:install] ||= 'make install;'
274
+ end
275
+
276
+ # install package from source
277
+ def install_from_src(src_package, src_dir)
278
+ package_dir = File.join(src_dir, src_package[:dir])
279
+ unpack_src(src_package, src_dir)
280
+ apt.install( {:base => %w(gcc gcc-c++ make)}, :stable )
281
+ # XXX replace with invoke_command
282
+ sudo <<-SUDO
283
+ sh -c '
284
+ cd #{package_dir};
285
+ #{src_package[:configure]}
286
+ #{src_package[:make]}
287
+ #{src_package[:install]}
288
+ #{src_package[:post_install]}
289
+ '
290
+ SUDO
291
+ end
292
+
293
+
294
+ ##
295
+ # Run a command and ask for input when input_query is seen.
296
+ # Sends the response back to the server.
297
+ #
298
+ # +input_query+ is a regular expression that defaults to /^Password/.
299
+ #
300
+ # Can be used where +run+ would otherwise be used.
301
+ #
302
+ # run_with_input 'ssh-keygen ...', /^Are you sure you want to overwrite\?/
303
+
304
+ def run_with_input(shell_command, input_query=/^Password/, response=nil)
305
+ handle_command_with_input(:run, shell_command, input_query, response)
306
+ end
307
+
308
+ ##
309
+ # Run a command using sudo and ask for input when a regular expression is seen.
310
+ # Sends the response back to the server.
311
+ #
312
+ # See also +run_with_input+
313
+ #
314
+ # +input_query+ is a regular expression
315
+
316
+ def sudo_with_input(shell_command, input_query=/^Password/, response=nil)
317
+ handle_command_with_input(:sudo, shell_command, input_query, response)
318
+ end
319
+
320
+ def invoke_with_input(shell_command, input_query=/^Password/, response=nil)
321
+ handle_command_with_input(run_method, shell_command, input_query, response)
322
+ end
323
+
324
+ ##
325
+ # Run a command using sudo and continuously pipe the results back to the console.
326
+ #
327
+ # Similar to the built-in +stream+, but for privileged users.
328
+
329
+ def sudo_stream(command)
330
+ sudo(command) do |ch, stream, out|
331
+ puts out if stream == :out
332
+ if stream == :err
333
+ puts "[err : #{ch[:host]}] #{out}"
334
+ break
335
+ end
336
+ end
337
+ end
338
+
339
+ # We don't need this. Put 'USER=root' on the command line instead.
340
+ #
341
+ # XXX Not working in deprec2
342
+ # ##
343
+ # # Run a command using the root account.
344
+ # #
345
+ # # Some linux distros/VPS providers only give you a root login when you install.
346
+ #
347
+ # def run_as_root(shell_command)
348
+ # std.connect_as_root do |tempuser|
349
+ # run shell_command
350
+ # end
351
+ # end
352
+ #
353
+ # ##
354
+ # # Run a task using root account.
355
+ # #
356
+ # # Some linux distros/VPS providers only give you a root login when you install.
357
+ # #
358
+ # # tempuser: contains the value replaced by 'root' for the duration of this call
359
+ #
360
+ # def as_root()
361
+ # std.connect_as_root do |tempuser|
362
+ # yield tempuser
363
+ # end
364
+ # end
365
+
366
+ private
367
+
368
+ ##
369
+ # Does the actual capturing of the input and streaming of the output.
370
+ #
371
+ # local_run_method: run or sudo
372
+ # shell_command: The command to run
373
+ # input_query: A regular expression matching a request for input: /^Please enter your password/
374
+
375
+ def handle_command_with_input(local_run_method, shell_command, input_query, response=nil)
376
+ send(local_run_method, shell_command) do |channel, stream, data|
377
+ logger.info data, channel[:host]
378
+ if data =~ input_query
379
+ if response
380
+ channel.send_data "#{response}\n"
381
+ else
382
+ response = ::Capistrano::CLI.password_prompt "#{data}"
383
+ channel.send_data "#{response}\n"
384
+ end
385
+ end
386
+ end
387
+ end
388
+
389
+ end
390
+
391
+ Capistrano.plugin :deprec2, Deprec2