capistrano-runit-tasks 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,17 @@
1
+ *0.2.0* (March 23rd 2006)
2
+
3
+ * Added RunitServiceHelper which adds service.add to allow easy creation of
4
+ services. Refactored other code to use new functionality.
5
+
6
+ * Made runner.create handle file based templates, changed it's API slightly
7
+
8
+ * Added RunitCommandHelper, which adds an sv command to send signals to
9
+ services e.g. sv.up. Can set :sv_command to :sv or :runsvctrl to choose
10
+ which binary to run on there server
11
+
12
+ * Changed default master_service_dir to ~/service to match the defendem.com
13
+ instructions
14
+
15
+ * Changed default fcgi_listener_base_port to 9000
16
+
17
+ * Added tests for 0.1.0
data/README CHANGED
@@ -10,12 +10,10 @@ make it easy to add other services in your deploy.rb.
10
10
 
11
11
  == Status
12
12
 
13
- capistrano-runit-tests 0.1.0 (known as cap-runit from now on) is the first
13
+ capistrano-runit-tests 0.2.0 (known as cap-runit from now on) is the second
14
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.
15
+ uses runit. It supports both the sv and runsvctrl/runsvstat versions of runit.
16
+ Support for daemontools svc command will be added at a later date.
19
17
 
20
18
  The current version assumes you have a runit setup similar to the one created
21
19
  in http://www.defendem.com/read/chapter/5#page6, i.e. a supervised directory
@@ -30,7 +28,7 @@ Install the package via gems or .tgz / .zip and setup.rb.
30
28
 
31
29
  Include it in your deploy.rb with:
32
30
 
33
- require 'capistrano-runit-tasks'
31
+ require "capistrano-runit-tasks"
34
32
 
35
33
  Then run:
36
34
 
@@ -42,8 +40,8 @@ and point your webserver at the new listener.
42
40
 
43
41
  == Usage
44
42
 
45
- When you require 'runit-tasks' it replaces the following cap tasks with runit
46
- versions:
43
+ When you require "capistrano-runit-tasks" it replaces the following cap tasks
44
+ with runit versions:
47
45
 
48
46
  * cold_deploy
49
47
  * restart
@@ -72,7 +70,13 @@ Then adds the following tasks, helpers and variables:
72
70
  (Default: 1)
73
71
 
74
72
  [fcgi_listener_base_port] The base port number to use for the fcgi listeners.
75
- (Default: 8000)
73
+ (Default: 9000)
74
+
75
+ [sv_command] Either :sv or :runsvctrl
76
+ (Default: sv)
77
+
78
+ [runner_template_path] The path to search for custom templates.
79
+ (Default: templates/runit)
76
80
 
77
81
  cap-runit creates a directory for each listener you ask for. At the moment the
78
82
  directories are created by setup_service_dirs. Later versions should allow for
@@ -93,36 +97,48 @@ in deploy.rb you'll get foo-8500, foo-8501 etc.
93
97
  fcgi_count to yield each of the fcgi port numbers back to
94
98
  the calling block
95
99
 
96
- [runner.create] Creates runner scripts, see the rdoc or comments above
97
- the method for how it's used.
100
+ [fcgi_listener_dirs] Returns an array containing the path to each of the fcgi
101
+ listener dirs. This is useful when sending commands using
102
+ sv as it accepts an array of directories as an argument
103
+
104
+ [service.add] Adds a new service to the application, see the
105
+ documentation in RunitServiceHelper for more
106
+
107
+ [sv.<signal>] Sends the signal given to services you choose. See the
108
+ documentation in RunitCommandHelper for more details.
109
+
110
+ [runner.create] Creates runner scripts, see the documentation in
111
+ RunitRunnerHelper method for how it's used.
98
112
 
99
113
  == Logging
100
114
 
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.
115
+ The default tasks create a log directory under each service directory. You can
116
+ override the default log template as described below if you need something
117
+ different.
118
+
119
+ == Overriding the default templates
120
+
121
+ The directory pointed to by the runner_template_path variable is searched
122
+ before the directory containing the default templates. If you want to override
123
+ the default templates, create default_fcgi_runner.rhtml and/or
124
+ default_log_runner.rhtml and cap-runit will pick your custom versions first.
105
125
 
106
126
  == Adding your own services
107
127
 
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:
128
+ The example below assumes you are creating a service called mailer.
111
129
 
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"
130
+ To add your own service directories and run scripts, add a template to
131
+ templates/runit called mailer_runner with contents:
116
132
 
117
- mailer_run_template = <<-TEMPLATE
118
133
  #!/bin/sh -e
119
134
  export RAILS_ENV=production
120
135
  exec 2>&1 /usr/bin/env ruby <%= application_dir %>/current/script/mailer
121
- TEMPLATE
122
136
 
123
- runner.create :runner, mailer_service_dir,
124
- mailer_run_template, :application_dir => deploy_to
125
- runner.create :log, mailer_service_dir
137
+ Then, in your deploy.rb create after_setup_service_dirs, after_spinner and
138
+ after_restart tasks that look something like these:
139
+
140
+ task :after_setup_service_dirs do
141
+ service.add 'mailer'
126
142
  end
127
143
 
128
144
  task :after_spinner do
@@ -138,12 +154,10 @@ deploy.rb that look something like these:
138
154
 
139
155
  So the process is:
140
156
 
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.
157
+ * create the runner template (and logger if you need, see docs)
158
+ * add the service
159
+ * add a spinner task to get runit to start supervising
160
+ * add the tasks to stop and start as needed
147
161
 
148
162
  == Switching from spinner/spawner/reaper
149
163
 
@@ -160,12 +174,12 @@ This again should be automated, the manual steps I used were:
160
174
 
161
175
  == TODO
162
176
 
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
177
  * Allow add_service to create more than one directory to be supervised
171
- * Add task to automate switching from spinner
178
+ * Add task to automate switching from spinner
179
+ * Make which servers the code runs on configurable
180
+ * Make the rails env configurable
181
+ * Allow creation of other files such as log/config
182
+ * Add support for daemontools svc command
183
+ * Make the RAILS_ENV configurable
184
+ * Add helper methods to make linking the services into the master service
185
+ directory easier
@@ -0,0 +1,3 @@
1
+ #!/bin/sh -e
2
+ export RAILS_ENV=production
3
+ exec 2>&1 /usr/bin/env spawn-fcgi -n -f <%= deploy_to %>/current/public/dispatch.fcgi -p <%= fcgi_port %>
@@ -0,0 +1,2 @@
1
+ #!/bin/sh -e
2
+ exec svlogd -t ./main
@@ -1,10 +1,14 @@
1
1
  require 'runit_runner_helper'
2
+ require 'runit_command_helper'
3
+ require 'runit_service_helper'
2
4
 
3
5
  Capistrano.configuration(:must_exist).load do
4
6
  set :service_dir, 'service'
5
7
  set :fcgi_count, 1
6
- set :master_service_dir, '~/services'
7
- set :fcgi_listener_base_port, 8000
8
+ set :master_service_dir, '~/service'
9
+ set :fcgi_listener_base_port, 9000
10
+ set :sv_command, :sv # can be :sv or :runsvctrl
11
+ set :runner_template_path, File.join('templates', 'runit')
8
12
 
9
13
  # We need our own task for this as the default cold_deploy
10
14
  # calls restart, which won't work until we've setup the
@@ -21,15 +25,11 @@ Capistrano.configuration(:must_exist).load do
21
25
 
22
26
  desc "Sets up services directories for supervising fcgi using runit"
23
27
  task :setup_service_dirs do
24
- puts 'Creating service directories'
25
28
  application_service_dir = "#{deploy_to}/#{service_dir}"
26
29
  run "mkdir -p #{application_service_dir}"
27
30
 
28
31
  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
32
+ service.add fcgi_listener_port, :template => :fcgi, :fcgi_port => fcgi_listener_port
33
33
  end
34
34
  end
35
35
 
@@ -43,12 +43,7 @@ Capistrano.configuration(:must_exist).load do
43
43
 
44
44
  desc "restart task for runit supervised fcgis"
45
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
46
+ sv.usr2 fcgi_listener_dirs
52
47
  end
53
48
 
54
49
  desc "Hook into after setup to create the runit service directory"
@@ -61,4 +56,10 @@ Capistrano.configuration(:must_exist).load do
61
56
  yield fcgi_listener_port
62
57
  end
63
58
  end
59
+
60
+ def fcgi_listener_dirs
61
+ dirs = []
62
+ each_fcgi_listener { |port| dirs << "#{deploy_to}/#{service_dir}/#{port}" }
63
+ dirs
64
+ end
64
65
  end
@@ -0,0 +1,52 @@
1
+ begin
2
+ require 'capistrano'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'capistrano'
6
+ end
7
+
8
+ # This module provides a facade to allow signals to be set to runit managed
9
+ # service directories from Capistrano. It uses the <tt>sv_command</tt> variable to decide
10
+ # which command to run on the server and currently supports both <tt>sv</tt> and <tt>runsvctrl</tt>.
11
+ #
12
+ # The <tt>:sv_command</tt> variable can be set to <tt>:sv</tt> or <tt>:runsvctrl</tt> to choose.
13
+ #
14
+ # The supported signals are shown in the <tt>SIGNALS</tt> constant below.
15
+ #
16
+ # Usage examples:
17
+ # * <tt>sv.usr2 "/path/to/service/dir"</tt>
18
+ # * <tt>sv.down ["foo1", "foo2"]</tt>
19
+ #
20
+ # As daemontools is very similar, support for that will be added at a later date.
21
+ #
22
+ # The methods are available through sv.<method name> in your deploy.rb
23
+ module RunitCommandHelper
24
+ SIGNALS = %w(up down once pause cont hup alarm interrupt quit usr1 usr2 term kill status)
25
+
26
+ SIGNALS.each do |signal|
27
+ if signal =~ /usr([1|2])/ then
28
+ cmd = $1
29
+ else
30
+ cmd = signal
31
+ end
32
+
33
+ define_method(signal) do |service_dirs|
34
+ service_dirs = service_dirs.join(" ") if service_dirs.is_a? Array
35
+ run "#{get_command(signal, cmd)} #{service_dirs}"
36
+ end
37
+ end
38
+
39
+ protected
40
+ def get_command(signal, cmd)
41
+ case configuration.sv_command
42
+ when :sv
43
+ "sv #{cmd}"
44
+ when :runsvctrl
45
+ signal == 'status' ? 'runsvstat' : "runsvctrl #{cmd}"
46
+ else
47
+ raise "Error: sv_command setting of #{configuration.sv_command} is unsupported"
48
+ end
49
+ end
50
+ end
51
+
52
+ Capistrano.plugin :sv, RunitCommandHelper
@@ -1,32 +1,79 @@
1
- require 'capistrano'
1
+ begin
2
+ require 'capistrano'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'capistrano'
6
+ end
2
7
 
8
+ # This module provides methods to ease creating run scripts in service directories.
9
+ #
10
+ # The methods are available through runner.<method name> in your deploy.rb
3
11
  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
12
+ # Creates a runner from a template, puts it on the server at the given
13
+ # path and sets file permissions to 0700.
14
+ #
15
+ # * service_dir should be the path to your service directory, it should not
16
+ # include run or log/run, these are added by create.
17
+ # * template can be :log, :fcgi, the name of a file or a string.
18
+ # :log and :fcgi create the standard logger/fcgi templates,
19
+ # see get_template below for a list of places searched for template files.
20
+ # * If you're making a custom log runner, include :log_runner => true in the
21
+ # options so create knows to put the contents in service_dir/log/run, you
22
+ # don't need this if you're using the standard :log template.
23
+ # * options except for :log_runner are assumed to be for the template and
24
+ # are passed through to render.
25
+ def create(service_dir, template, options = {})
26
+ case template
22
27
  when :log
23
- template = LOG_TEMPLATE
24
- else
25
- template = FCGI_TEMPLATE if template == :fcgi
28
+ template = 'default_log_runner'
29
+ options.merge!(:log_runner => true)
30
+ when :fcgi
31
+ template = 'default_fcgi_runner'
26
32
  end
27
33
 
28
- put render(options.merge(:template => template)), runner_path, :mode => 0700
34
+ path = "#{service_dir}/#{options[:log_runner] ? 'log/run' : 'run'}"
35
+ options.delete(:log_runner)
36
+
37
+ options = add_default_options(options)
38
+
39
+ runner = render options.merge(:template => get_template(template))
40
+
41
+ put runner, path, :mode => 0700
29
42
  end
43
+
44
+ # Works out whether the given template is a file or string containing rhtml.
45
+ #
46
+ # Checks:
47
+ # * current directory
48
+ # * runner_templates path (defaults to templates/runit)
49
+ # * capistrano-runit-tasks-templates dir where cappy-runit is installed
50
+ # (the standard templates are here)
51
+ #
52
+ # If it can't find the file it assumes it's a one line string template and
53
+ # returns that
54
+ def get_template(template)
55
+ if template =~ /<%/ or template =~ /\n/
56
+ template
57
+ else
58
+ [ ".",
59
+ configuration.runner_template_path,
60
+ File.join(File.dirname(__FILE__), 'capistrano-runit-tasks-templates')
61
+ ].each do |dir|
62
+ if File.file?(File.join(dir, template))
63
+ return File.read(File.join(dir, template))
64
+ elsif File.file?(File.join(dir, template + ".rhtml"))
65
+ @file_template_full_path = File.join(dir, template + ".rhtml")
66
+ return File.read(File.join(dir, template + ".rhtml"))
67
+ end
68
+ end
69
+ end
70
+ template
71
+ end
72
+
73
+ protected
74
+ def add_default_options(options)
75
+ {:deploy_to => configuration.deploy_to}.merge(options)
76
+ end
30
77
  end
31
78
 
32
79
  Capistrano.plugin :runner, RunitRunnerHelper
@@ -0,0 +1,65 @@
1
+ begin
2
+ require 'capistrano'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'capistrano'
6
+ end
7
+
8
+ require 'runit_runner_helper'
9
+
10
+ # This module provides an easy method to create service directories in your application and have them
11
+ # populated with runner scripts.
12
+ #
13
+ # The methods are available through service.<method name> in your deploy.rb
14
+ module RunitServiceHelper
15
+ # Adds a service to the applications service directory and creates run and log/run scripts
16
+ #
17
+ # If no runner or logger options are passed, looks for a runner template called <service_name>_runner
18
+ # and a log runner template called <service_name>_log_runner. These should be in the templates directory set
19
+ # with runner_template_path in your deploy.rb.
20
+ #
21
+ # * If the runner template does not exist an exception will be raised
22
+ # * If the logger template does not exist the standard logger template will be used.
23
+ #
24
+ # If you want to use your own template or a string containing rhtml pass a :template option to the appropriate
25
+ # options hash.
26
+ #
27
+ # The default options will be passed through to the template as described in RunitRunnerHelper#create
28
+ def add(service_name, runner_options = {}, logger_options = {})
29
+ make_service_dir service_name
30
+ create_service(service_name, runner_options)
31
+ create_service(service_name, logger_options.merge(:log_runner => true))
32
+ end
33
+
34
+ # Returns the full path to the service directory given a service name.
35
+ # Doesn't check the service name is valid.
36
+ def service_dir(service_name)
37
+ "#{configuration.deploy_to}/#{configuration.service_dir}/#{service_name}"
38
+ end
39
+
40
+ protected
41
+ def create_service(service_name, options)
42
+ if options[:template].nil?
43
+ runner_template_path = options[:log_runner] ? "#{service_name.to_s}_log_runner" : "#{service_name.to_s}_runner"
44
+ runner_template = runner.get_template(runner_template_path)
45
+ if runner_template == runner_template_path # didn't find a template
46
+ if options[:log_runner]
47
+ # Just use the standard template
48
+ runner_template = :log
49
+ else
50
+ raise "Couldn't find runner template #{runner_template_path} and no runner template provided"
51
+ end
52
+ end
53
+ else
54
+ runner_template = options[:template]
55
+ end
56
+ options.delete(:template)
57
+ runner.create service_dir(service_name), runner_template, options
58
+ end
59
+
60
+ def make_service_dir(service_name)
61
+ run "mkdir -p #{service_dir(service_name)}/log/main"
62
+ end
63
+ end
64
+
65
+ Capistrano.plugin :service, RunitServiceHelper
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: capistrano-runit-tasks
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2006-03-18 00:00:00 +00:00
6
+ version: 0.2.0
7
+ date: 2006-03-23 00:00:00 +00:00
8
8
  summary: Adds tasks to capistrano for use with the runit supervision scheme.
9
9
  require_paths:
10
10
  - lib
@@ -29,9 +29,15 @@ cert_chain:
29
29
  authors:
30
30
  - Chris McGrath
31
31
  files:
32
+ - lib/capistrano-runit-tasks-templates
32
33
  - lib/capistrano-runit-tasks.rb
34
+ - lib/runit_command_helper.rb
33
35
  - lib/runit_runner_helper.rb
36
+ - lib/runit_service_helper.rb
37
+ - lib/capistrano-runit-tasks-templates/default_fcgi_runner.rhtml
38
+ - lib/capistrano-runit-tasks-templates/default_log_runner.rhtml
34
39
  - README
40
+ - ChangeLog
35
41
  test_files: []
36
42
  rdoc_options:
37
43
  - "--title"
@@ -40,6 +46,7 @@ rdoc_options:
40
46
  - README
41
47
  extra_rdoc_files:
42
48
  - README
49
+ - ChangeLog
43
50
  executables: []
44
51
  extensions: []
45
52
  requirements: []