capistrano-runit-tasks 0.1.0

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 ADDED
@@ -0,0 +1,171 @@
1
+ = Capistrano runit tasks
2
+
3
+ Adds tasks to Capistrano for use with the runit supervision scheme.
4
+
5
+ This library extends Capistrano to allow processes to be supervised using the
6
+ runit package. It replaces some of the standard tasks with runit versions and
7
+ includes tasks and helpers to create the service directory layout and populate
8
+ it with run scripts. It currently only supports fcgi listeners, but tries to
9
+ make it easy to add other services in your deploy.rb.
10
+
11
+ == Status
12
+
13
+ capistrano-runit-tests 0.1.0 (known as cap-runit from now on) is the first
14
+ release of the library. It will need more work to be useful to everybody who
15
+ uses runit. The intention of releasing it now is to find out which areas need
16
+ improvement first and get working on them. It's was developed and tested with
17
+ the Debian sarge version of runit, 1.0.5 so currently uses runsvctrl rather
18
+ than sv.
19
+
20
+ The current version assumes you have a runit setup similar to the one created
21
+ in http://www.defendem.com/read/chapter/5#page6, i.e. a supervised directory
22
+ where links can be created to get tasks monitored.
23
+
24
+ == Quick Start
25
+
26
+ This assumes you're creating a fresh install, not migrating an app from
27
+ spinner/spawner/reaper.
28
+
29
+ Install the package via gems or .tgz / .zip and setup.rb.
30
+
31
+ Include it in your deploy.rb with:
32
+
33
+ require 'capistrano-runit-tasks'
34
+
35
+ Then run:
36
+
37
+ * cap setup
38
+ * cap cold_deploy
39
+
40
+ This sets up one fcgi listener on port 8000. Make sure your database is setup
41
+ and point your webserver at the new listener.
42
+
43
+ == Usage
44
+
45
+ When you require 'runit-tasks' it replaces the following cap tasks with runit
46
+ versions:
47
+
48
+ * cold_deploy
49
+ * restart
50
+ * spinner
51
+
52
+ Then adds the following tasks, helpers and variables:
53
+
54
+ === Tasks
55
+
56
+ [setup_service_dirs] Creates the skeleton directory structure for the services
57
+
58
+ [after_setup] Calls setup_service_dirs so they're created as part of
59
+ the standard cap setup
60
+
61
+ === Variables
62
+
63
+ [service_dir] Change this if you want to change the name
64
+ of the service directory in the app on the server(s).
65
+ (Default: service)
66
+
67
+ [master_service_dir] Supervised directory where cap-runit will link the
68
+ service directories to to start the service.
69
+ (Default: ~/services)
70
+
71
+ [fcgi_count] Number of fcgi listener service dirs to create.
72
+ (Default: 1)
73
+
74
+ [fcgi_listener_base_port] The base port number to use for the fcgi listeners.
75
+ (Default: 8000)
76
+
77
+ cap-runit creates a directory for each listener you ask for. At the moment the
78
+ directories are created by setup_service_dirs. Later versions should allow for
79
+ dynamic creation / deletion.
80
+
81
+ The directories are named after the port number the fcgi listener will run on.
82
+ If you specified 8500 for the base port and 3 for the fcgi_count then
83
+ service/8500, service/8501 and service/8502 directories will be created and
84
+ populated with run scripts that launch the fcgis on the corresponding port.
85
+
86
+ When the service directories are linked into the master service dir to run,
87
+ they are named <application>-<port number>. So if :application is set to "foo"
88
+ in deploy.rb you'll get foo-8500, foo-8501 etc.
89
+
90
+ === Helpers
91
+
92
+ [each_fcgi_listener] Uses the values for fcgi_listener_base_port and
93
+ fcgi_count to yield each of the fcgi port numbers back to
94
+ the calling block
95
+
96
+ [runner.create] Creates runner scripts, see the rdoc or comments above
97
+ the method for how it's used.
98
+
99
+ == Logging
100
+
101
+ The default tasks create a log directory under each service directory. For
102
+ your own services, this has do be done manually for now. The intention
103
+ is to make it automatic and then allow the generic template to be overridden
104
+ easily.
105
+
106
+ == Adding your own services
107
+
108
+ To add your own service directories and run scripts, add
109
+ after_setup_service_dirs, after_spinner and after_restart tasks to your
110
+ deploy.rb that look something like these:
111
+
112
+ task :after_setup_service_dirs do
113
+ puts 'Creating mailer service directory'
114
+ mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
115
+ run "mkdir -p #{mailer_service_dir}/log/main"
116
+
117
+ mailer_run_template = <<-TEMPLATE
118
+ #!/bin/sh -e
119
+ export RAILS_ENV=production
120
+ exec 2>&1 /usr/bin/env ruby <%= application_dir %>/current/script/mailer
121
+ TEMPLATE
122
+
123
+ runner.create :runner, mailer_service_dir,
124
+ mailer_run_template, :application_dir => deploy_to
125
+ runner.create :log, mailer_service_dir
126
+ end
127
+
128
+ task :after_spinner do
129
+ mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
130
+ run "ln -sf #{mailer_service_dir} #{master_service_dir}/#{application}-mailer"
131
+ end
132
+
133
+ task :after_restart do
134
+ mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
135
+ run "runsvctrl down #{mailer_service_dir}"
136
+ run "runsvctrl up #{mailer_service_dir}"
137
+ end
138
+
139
+ So the process is:
140
+
141
+ * make the service directory
142
+ * create a rhtml template for your runner (string only for now, sorry)
143
+ * create a runner from the template
144
+ * create the logger
145
+
146
+ This is will be wrapped in a helper function at the earliest opportunity.
147
+
148
+ == Switching from spinner/spawner/reaper
149
+
150
+ This again should be automated, the manual steps I used were:
151
+
152
+ * Modify deploy.rb and do a test deploy to a new directory on a different port
153
+ * Check the deploy worked ok
154
+ * Revert deploy.rb
155
+ * cap setup_service_dirs to create the structure (Won't touch what's running)
156
+ * Kill the spinner process
157
+ * use script/process/reaper to kill the running fcgis
158
+ * cap cold_deploy to start the service
159
+ * Check everything is running OK
160
+
161
+ == TODO
162
+
163
+ * Make runner.create use file based templates
164
+ * Intead of run "runsvctrl ..." have an sv helper method like sv :up, svc_dir
165
+ * Setting for sv program to use, runsvctrl or sv
166
+ * Automatically create log directories with custom templates
167
+ * add_service(path, runner, logger = nil) helper function
168
+ e.g. add_service(path, {:template => 'my_runner', :port => 1234})
169
+ Which would set a custom runner and a standard logger
170
+ * Allow add_service to create more than one directory to be supervised
171
+ * Add task to automate switching from spinner
@@ -0,0 +1,64 @@
1
+ require 'runit_runner_helper'
2
+
3
+ Capistrano.configuration(:must_exist).load do
4
+ set :service_dir, 'service'
5
+ set :fcgi_count, 1
6
+ set :master_service_dir, '~/services'
7
+ set :fcgi_listener_base_port, 8000
8
+
9
+ # We need our own task for this as the default cold_deploy
10
+ # calls restart, which won't work until we've setup the
11
+ # symlink, perhaps we could add a test to restart to check if the
12
+ # link exists, but that's beyond my current (very bad) shell-foo
13
+ desc "Used only for deploying when the services haven't been setup"
14
+ task :cold_deploy do
15
+ transaction do
16
+ update_code
17
+ symlink
18
+ end
19
+ spinner
20
+ end
21
+
22
+ desc "Sets up services directories for supervising fcgi using runit"
23
+ task :setup_service_dirs do
24
+ puts 'Creating service directories'
25
+ application_service_dir = "#{deploy_to}/#{service_dir}"
26
+ run "mkdir -p #{application_service_dir}"
27
+
28
+ each_fcgi_listener do |fcgi_listener_port|
29
+ fcgi_service_dir = "#{application_service_dir}/#{fcgi_listener_port}"
30
+ run "mkdir -p #{fcgi_service_dir}/log/main"
31
+ runner.create :runner, fcgi_service_dir, :fcgi, :application_dir => deploy_to, :fcgi_port => fcgi_listener_port
32
+ runner.create :log, fcgi_service_dir
33
+ end
34
+ end
35
+
36
+ desc "Links created service dir into master service dir so runit starts the fcgi"
37
+ task :spinner do
38
+ each_fcgi_listener do |fcgi_listener_port|
39
+ fcgi_service_dir = "#{deploy_to}/#{service_dir}/#{fcgi_listener_port}"
40
+ run "ln -sf #{fcgi_service_dir} #{master_service_dir}/#{application}-#{fcgi_listener_port}"
41
+ end
42
+ end
43
+
44
+ desc "restart task for runit supervised fcgis"
45
+ task :restart do
46
+ each_fcgi_listener do |fcgi_listener_port|
47
+ fcgi_service_dir = "#{deploy_to}/#{service_dir}/#{fcgi_listener_port}"
48
+
49
+ # Signal USR2 is what reaper does
50
+ run "runsvctrl 2 #{fcgi_service_dir}"
51
+ end
52
+ end
53
+
54
+ desc "Hook into after setup to create the runit service directory"
55
+ task :after_setup do
56
+ setup_service_dirs
57
+ end
58
+
59
+ def each_fcgi_listener
60
+ fcgi_listener_base_port.upto(fcgi_listener_base_port + fcgi_count - 1) do |fcgi_listener_port|
61
+ yield fcgi_listener_port
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,32 @@
1
+ require 'capistrano'
2
+
3
+ module RunitRunnerHelper
4
+ FCGI_TEMPLATE = <<-TEMPLATE
5
+ #!/bin/sh -e
6
+ export RAILS_ENV=production
7
+ exec 2>&1 /usr/bin/env spawn-fcgi -n -f <%= application_dir %>/current/public/dispatch.fcgi -p <%= fcgi_port %>
8
+ TEMPLATE
9
+
10
+ LOG_TEMPLATE = <<-TEMPLATE
11
+ #!/bin/sh -e
12
+ exec svlogd -t ./main
13
+ TEMPLATE
14
+
15
+ # Wrapper to render a file from a string template (file template not supported yet)
16
+ # and put it on the server at the given path. The file permissions are set to 0700.
17
+ # options are passed through to the call to render.
18
+ # runner_type can be :log or :runner
19
+ def create(runner_type, path, template = nil, options = {})
20
+ runner_path = "#{path}#{runner_type == :log ? '/log/run' : '/run'}"
21
+ case runner_type
22
+ when :log
23
+ template = LOG_TEMPLATE
24
+ else
25
+ template = FCGI_TEMPLATE if template == :fcgi
26
+ end
27
+
28
+ put render(options.merge(:template => template)), runner_path, :mode => 0700
29
+ end
30
+ end
31
+
32
+ Capistrano.plugin :runner, RunitRunnerHelper
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: capistrano-runit-tasks
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-03-18 00:00:00 +00:00
8
+ summary: Adds tasks to capistrano for use with the runit supervision scheme.
9
+ require_paths:
10
+ - lib
11
+ email: chris@octopod.info
12
+ homepage: http://cappy-runit.rubyforge.org
13
+ rubyforge_project: cappy-runit
14
+ description:
15
+ autorequire: capistrano-runit-tasks
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Chris McGrath
31
+ files:
32
+ - lib/capistrano-runit-tasks.rb
33
+ - lib/runit_runner_helper.rb
34
+ - README
35
+ test_files: []
36
+ rdoc_options:
37
+ - "--title"
38
+ - Capistrano runit tasks documentation
39
+ - "--main"
40
+ - README
41
+ extra_rdoc_files:
42
+ - README
43
+ executables: []
44
+ extensions: []
45
+ requirements: []
46
+ dependencies:
47
+ - !ruby/object:Gem::Dependency
48
+ name: capistrano
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Version::Requirement
51
+ requirements:
52
+ -
53
+ - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 1.1.0
56
+ version: