fujin-mongrel_runit 0.2.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.
- data/CHANGELOG.txt +8 -0
- data/History.txt +0 -0
- data/LICENSE +339 -0
- data/Manifest.txt +11 -0
- data/README.txt +123 -0
- data/Rakefile +58 -0
- data/bin/mongrel_runit +9 -0
- data/lib/mongrel_runit/base.rb +58 -0
- data/lib/mongrel_runit/cli.rb +60 -0
- data/lib/mongrel_runit/config.rb +184 -0
- data/lib/mongrel_runit/service.rb +253 -0
- data/lib/mongrel_runit/servicerunner.rb +91 -0
- data/lib/mongrel_runit/version.rb +9 -0
- data/lib/mongrel_runit.rb +25 -0
- data/test/config/mongrel_runit.yml +21 -0
- data/test/config/mongrel_runit_service.yml +12 -0
- data/test/tc_config.rb +93 -0
- data/test/tc_service.rb +153 -0
- data/test/tc_servicerunner.rb +74 -0
- data/test/test_helper.rb +2 -0
- data/test/test_mongrel_runit.rb +9 -0
- metadata +78 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
# Author:: Adam Jacob (<adam@hjksolutions.com>)
|
2
|
+
# Copyright:: Copyright (c) 2007 HJK Solutions, LLC
|
3
|
+
# License:: GNU General Public License version 2
|
4
|
+
#---
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License version 2
|
7
|
+
# as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License along
|
15
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
16
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
17
|
+
#+++
|
18
|
+
|
19
|
+
require 'yaml'
|
20
|
+
require 'optparse'
|
21
|
+
require 'mongrel_runit/base'
|
22
|
+
|
23
|
+
module MongrelRunit
|
24
|
+
|
25
|
+
# Takes a YAML config file and a list of command line arguments, and
|
26
|
+
# populates itself with the resulting combined configuration.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# config = MongrelRunit::Config('monkey', '/etc/sv/monkey.yml', ARGV)
|
31
|
+
# puts config["application_name"] # monkey
|
32
|
+
#
|
33
|
+
class Config < Base
|
34
|
+
attr_accessor :config, :command, :verbose
|
35
|
+
|
36
|
+
# Takes an application name, a YAML file, and command line arguments
|
37
|
+
# and spits out a working configuration. The YAML file and arguments
|
38
|
+
# can optionally be nil.
|
39
|
+
#
|
40
|
+
# Unless otherwise specified, the following default values are
|
41
|
+
# set:
|
42
|
+
#
|
43
|
+
# environment: ENV["RAILS_ENV"] or development
|
44
|
+
# port: 3000
|
45
|
+
# servers: 2
|
46
|
+
# runit_svdir: /etc/sv
|
47
|
+
# runit_service_dir: /var/service
|
48
|
+
def initialize(appname, yamlfile, args)
|
49
|
+
@config = Hash.new
|
50
|
+
load_args(args) if args
|
51
|
+
load_yaml(yamlfile) if yamlfile
|
52
|
+
@config["environment"] ||= ENV["RAILS_ENV"] || 'development'
|
53
|
+
@config["port"] ||= "3000"
|
54
|
+
@config["servers"] ||= 2
|
55
|
+
@config["application_name"] ||= appname
|
56
|
+
@config["runit_svdir"] ||= '/etc/sv'
|
57
|
+
@config["runit_service_dir"] ||= '/var/service'
|
58
|
+
@config["address"] ||= '127.0.0.1'
|
59
|
+
|
60
|
+
raise ArgumentError, "Must supply an application_name!" unless @config["application_name"]
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the value from the config hash.
|
65
|
+
def [](arg)
|
66
|
+
@config[arg]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Load options from a config file alone
|
70
|
+
def Config.load_file(yamlfile)
|
71
|
+
MongrelRunit::Config.new(nil, yamlfile, nil)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Load options from command line arguments alone
|
75
|
+
def Config.load_args(*args)
|
76
|
+
MongrelRunit::Config.new(nil, nil, *args)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def load_yaml(yamlfile)
|
82
|
+
@config = YAML.load_file(File.expand_path(yamlfile))
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_from_path(path)
|
86
|
+
path.strip!
|
87
|
+
epath = File.expand_path(path)
|
88
|
+
@path = epath
|
89
|
+
mr_conf = File.expand_path(File.join(epath, "config", "mongrel_runit.yml"))
|
90
|
+
mc_conf = File.expand_path(File.join(epath, "config", "mongrel_cluster.yml"))
|
91
|
+
if File.file?(mr_conf)
|
92
|
+
load_yaml(mr_conf)
|
93
|
+
elsif File.file?(mc_conf)
|
94
|
+
load_yaml(mc_conf)
|
95
|
+
else
|
96
|
+
puts "#{path} must have a ./config/mongrel_runit.yml or ./config/mongrel_cluster.yml"
|
97
|
+
return nil
|
98
|
+
end
|
99
|
+
return true
|
100
|
+
end
|
101
|
+
|
102
|
+
def load_args(args)
|
103
|
+
|
104
|
+
loaded_config = nil
|
105
|
+
|
106
|
+
opts = OptionParser.new do |opts|
|
107
|
+
opts.banner = "Usage: #{$0} (options) (#{ALLOWEDCOMMANDS.join('|')})"
|
108
|
+
|
109
|
+
opts.on("-p PATH", "--path PATH", "Path to a Rails app to start") do |p|
|
110
|
+
loaded_config = load_from_path(p)
|
111
|
+
end
|
112
|
+
|
113
|
+
opts.on("-a NAME", "--application NAME", "The name of your Application. (Used for the service directories)") do |a|
|
114
|
+
@config["application_name"] = a
|
115
|
+
end
|
116
|
+
|
117
|
+
opts.on("-c FILE", "--config FILE", "A mongrel_runit.yml config file") do |c|
|
118
|
+
c.strip!
|
119
|
+
file = File.expand_path(c)
|
120
|
+
if File.file?(file)
|
121
|
+
load_yaml(file)
|
122
|
+
loaded_config = true
|
123
|
+
else
|
124
|
+
puts "I could not find config file: #{file}"
|
125
|
+
exit 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
opts.on_tail("-v", "--verbose", "Be verbose") do
|
130
|
+
@verbose = true
|
131
|
+
end
|
132
|
+
|
133
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
134
|
+
puts opts
|
135
|
+
exit
|
136
|
+
end
|
137
|
+
end
|
138
|
+
opts.parse!(args)
|
139
|
+
|
140
|
+
unless loaded_config
|
141
|
+
path = Dir.getwd
|
142
|
+
loaded_config = load_from_path(path)
|
143
|
+
end
|
144
|
+
|
145
|
+
if loaded_config && ! @config["application_name"]
|
146
|
+
if @path
|
147
|
+
appname = File.basename(@path)
|
148
|
+
@config["application_name"] = appname
|
149
|
+
else
|
150
|
+
puts "You need application_name defined in your config!"
|
151
|
+
YAML.dump @config
|
152
|
+
exit 1
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
unless loaded_config
|
157
|
+
puts "Configuration Dump:\n\n"
|
158
|
+
puts YAML.dump(@config)
|
159
|
+
puts "I could not find a way to configure myself properly!\n"
|
160
|
+
puts opts.help
|
161
|
+
exit 1
|
162
|
+
end
|
163
|
+
|
164
|
+
if args.length > 1
|
165
|
+
puts "You specified more command line arguments than I can handle:"
|
166
|
+
puts args.join(" ")
|
167
|
+
puts opts.help
|
168
|
+
exit 1
|
169
|
+
end
|
170
|
+
|
171
|
+
if self.has_command?(args[0]) || args[0] == "create"
|
172
|
+
@command = args[0]
|
173
|
+
else
|
174
|
+
if args[0]
|
175
|
+
puts "#{args[0]} is not an allowed command"
|
176
|
+
else
|
177
|
+
puts "You must provide a command!"
|
178
|
+
end
|
179
|
+
puts opts.help
|
180
|
+
exit 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
# Created by Adam Jacob on 2007-03-21.
|
2
|
+
# Copyright (c) 2007. All rights reserved.
|
3
|
+
|
4
|
+
require 'mongrel_runit/base'
|
5
|
+
|
6
|
+
module MongrelRunit
|
7
|
+
|
8
|
+
# Represents a runit service directory for a particular mongrel.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# service = MongrelRunit::Service.new(config)
|
13
|
+
# service.stop
|
14
|
+
# service.start
|
15
|
+
# service.create
|
16
|
+
#
|
17
|
+
|
18
|
+
class Service < Base
|
19
|
+
attr_reader :runfile, :logrunfile, :logconfig, :checkfile, :svdir, :config
|
20
|
+
|
21
|
+
# Takes a configuration hash as it's argument, ensures the
|
22
|
+
# runit_service_dir exists, and creates the runit_sv_dir.
|
23
|
+
def initialize(config)
|
24
|
+
@config = config
|
25
|
+
|
26
|
+
raise ArgumentError, "Must have an application_name!" unless @config.has_key?("application_name")
|
27
|
+
raise ArgumentError, "Must have a port!" unless @config.has_key?("port")
|
28
|
+
raise ArgumentError, "Must have a runit_sv_dir!" unless @config.has_key?("runit_sv_dir")
|
29
|
+
raise ArgumentError, "Must have a runit_service_dir!" unless @config.has_key?("runit_service_dir")
|
30
|
+
|
31
|
+
check_service_dir
|
32
|
+
make_sv_dir
|
33
|
+
end
|
34
|
+
|
35
|
+
# Catch-all for the common service commands. See MongrelRunit::Base for
|
36
|
+
# a list.
|
37
|
+
def method_missing(status)
|
38
|
+
if self.has_command?(status.id2name)
|
39
|
+
run(status.id2name)
|
40
|
+
else
|
41
|
+
Kernel.method_missing
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns true if the process is running, nil if it's not.
|
46
|
+
def is_running?
|
47
|
+
output, success = run("status")
|
48
|
+
output =~ /^run:/ ? true : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# Run a given command through sv.
|
52
|
+
def run(status)
|
53
|
+
cmd = "sv "
|
54
|
+
cmd += " -w #{@config['svwait']}" if @config.has_key?('svwait')
|
55
|
+
cmd += " #{status} #{@svdir}"
|
56
|
+
output = `#{cmd}`
|
57
|
+
return output, $?.success?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create the service directory for this mongrel. This includes the
|
61
|
+
# run script, log script, check script, and log config file. This
|
62
|
+
# should run any time there is a change to the configruation.
|
63
|
+
def create
|
64
|
+
make_run
|
65
|
+
make_check
|
66
|
+
make_log
|
67
|
+
make_log_config
|
68
|
+
link = make_service_link
|
69
|
+
return link, true
|
70
|
+
end
|
71
|
+
|
72
|
+
# Raises an exception if the runit_service_dir does not exist.
|
73
|
+
def check_service_dir
|
74
|
+
dir_exists = File.directory?(@config["runit_service_dir"])
|
75
|
+
raise ArgumentError, "runit_service_dir does not exist: #{@config["runit_service_dir"]}" unless dir_exists
|
76
|
+
dir_exists
|
77
|
+
end
|
78
|
+
|
79
|
+
# Creates the symlink between the mongrel's sv directory and the
|
80
|
+
# runit_service_dir.
|
81
|
+
def make_service_link
|
82
|
+
servicename = File.basename(@svdir)
|
83
|
+
link = File.expand_path(File.join(@config["runit_service_dir"], servicename))
|
84
|
+
unless File.symlink?(link)
|
85
|
+
`ln -s #{@svdir} #{@config["runit_service_dir"]}`
|
86
|
+
end
|
87
|
+
link
|
88
|
+
end
|
89
|
+
|
90
|
+
# Populates the check file, either with the contents of the checkfile
|
91
|
+
# configuration option, or:
|
92
|
+
#
|
93
|
+
# #!/usr/bin/env ruby
|
94
|
+
#
|
95
|
+
# require 'net/http'
|
96
|
+
#
|
97
|
+
# http = Net::HTTP.new('#{address}', #{@config["port"].to_i})
|
98
|
+
# begin
|
99
|
+
# response = http.options('/')
|
100
|
+
# if response = Net::HTTPSuccess
|
101
|
+
# exit 0
|
102
|
+
# else
|
103
|
+
# exit 1
|
104
|
+
# end
|
105
|
+
# rescue Errno::ECONNREFUSED
|
106
|
+
# exit 1
|
107
|
+
# end
|
108
|
+
def make_check
|
109
|
+
if @config.has_key?("checkfile")
|
110
|
+
@checkfile = interpret_line(@config["checkfile"])
|
111
|
+
else
|
112
|
+
@checkfile = <<EOH
|
113
|
+
#!/usr/bin/env ruby
|
114
|
+
|
115
|
+
require 'net/http'
|
116
|
+
|
117
|
+
http = Net::HTTP.new('#{@config['address']}', #{@config["port"].to_i})
|
118
|
+
begin
|
119
|
+
response = http.options('/')
|
120
|
+
if response = Net::HTTPSuccess
|
121
|
+
exit 0
|
122
|
+
else
|
123
|
+
exit 1
|
124
|
+
end
|
125
|
+
rescue Errno::ECONNREFUSED
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
EOH
|
129
|
+
end
|
130
|
+
path_to_checkfile = File.expand_path(File.join(@svdir, "check"))
|
131
|
+
create_or_update_file(path_to_checkfile, @checkfile)
|
132
|
+
File.chmod(0755, path_to_checkfile)
|
133
|
+
path_to_checkfile
|
134
|
+
end
|
135
|
+
|
136
|
+
# Creates the sv direrectory for this mongrel. (From runit_sv_dir)
|
137
|
+
def make_sv_dir
|
138
|
+
@svdir = File.expand_path(File.join(
|
139
|
+
@config["runit_sv_dir"],
|
140
|
+
"mongrel-#{@config["application_name"]}-#{@config["port"]}"
|
141
|
+
))
|
142
|
+
@svlogdir = File.expand_path(File.join(
|
143
|
+
@svdir, "log"
|
144
|
+
))
|
145
|
+
`mkdir -p #{@svlogdir}`
|
146
|
+
raise "Cannot create #{@svlogdir}" unless $?.success?
|
147
|
+
@svlogdir
|
148
|
+
end
|
149
|
+
|
150
|
+
# If svlogd_config is defined, creates the log config file.
|
151
|
+
def make_log_config
|
152
|
+
path_to_file = nil
|
153
|
+
if @config.has_key?("svlogd_config")
|
154
|
+
path_to_file = File.expand_path(File.join(@svlogdir, "config"))
|
155
|
+
@logconfig = @config["svlogd_config"]
|
156
|
+
create_or_update_file(path_to_file, @logconfig)
|
157
|
+
end
|
158
|
+
path_to_file
|
159
|
+
end
|
160
|
+
|
161
|
+
# Makes the log run script.
|
162
|
+
def make_log
|
163
|
+
logdir = File.expand_path(File.join(@svlogdir, "main"))
|
164
|
+
if @config.has_key?("base_log_directory")
|
165
|
+
logdir = File.expand_path(File.join(
|
166
|
+
@config["base_log_directory"],
|
167
|
+
"#{@config[application_name]}-#{@config[port]}"
|
168
|
+
))
|
169
|
+
end
|
170
|
+
`mkdir -p #{logdir}`
|
171
|
+
raise "Cannot create #{logdir}" unless $?.success?
|
172
|
+
@logrunfile = "#!/bin/sh\n"
|
173
|
+
@logrunfile << "exec svlogd -tt #{logdir}"
|
174
|
+
path_to_logrunfile = File.expand_path(File.join(@svlogdir, "run"))
|
175
|
+
create_or_update_file(path_to_logrunfile, @logrunfile)
|
176
|
+
File.chmod(0755, path_to_logrunfile)
|
177
|
+
path_to_logrunfile
|
178
|
+
end
|
179
|
+
|
180
|
+
# Makes the run script, which calls mongrel directly. The command
|
181
|
+
# line assembly code for mongrel_rails is taken verbatim from mongrel_cluster.
|
182
|
+
def make_run
|
183
|
+
cmd = if @config["command_line"]
|
184
|
+
interpret_line(@config["command_line"])
|
185
|
+
else
|
186
|
+
argv = [ "mongrel_rails" ]
|
187
|
+
argv << "start"
|
188
|
+
argv << "-e #{@config["environment"]}" if @config["environment"]
|
189
|
+
argv << "-p #{@config["port"]}"
|
190
|
+
argv << "-a #{@config["address"]}" if @config["address"]
|
191
|
+
argv << "-l #{@config["log_file"]}" if @config["log_file"]
|
192
|
+
argv << "-c #{File.expand_path(@config["cwd"])}" if @config["cwd"]
|
193
|
+
argv << "-t #{@config["timeout"]}" if @config["timeout"]
|
194
|
+
argv << "-m #{@config["mime_map"]}" if @config["mime_map"]
|
195
|
+
argv << "-r #{@config["docroot"]}" if @config["docroot"]
|
196
|
+
argv << "-n #{@config["num_procs"]}" if @config["num_procs"]
|
197
|
+
argv << "-B" if @config["debug"]
|
198
|
+
argv << "-S #{@config["config_script"]}" if @config["config_script"]
|
199
|
+
argv << "--user #{@config["user"]}" if @config["user"]
|
200
|
+
argv << "--group #{@config["group"]}" if @config["group"]
|
201
|
+
argv << "--prefix #{@config["prefix"]}" if @config["prefix"]
|
202
|
+
argv.join(" ")
|
203
|
+
end
|
204
|
+
env = nil
|
205
|
+
if @config.has_key?("env_vars")
|
206
|
+
env = "env"
|
207
|
+
@config["env_vars"].each do |key, value|
|
208
|
+
env << " #{key.upcase}=#{value}"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
chpst = nil
|
212
|
+
if @config.has_key?("chpst")
|
213
|
+
chpst_command = `which chpst`.chomp
|
214
|
+
chpst = "#{chpst_command} #{@config['chpst']}"
|
215
|
+
end
|
216
|
+
@runfile = "#!/bin/sh\n"
|
217
|
+
@runfile << "exec \\\n"
|
218
|
+
@runfile << " #{env} \\\n" if env
|
219
|
+
@runfile << " #{chpst} \\\n" if chpst
|
220
|
+
@runfile << " #{cmd} 2>&1\n"
|
221
|
+
|
222
|
+
path_to_runfile = File.expand_path(File.join(@svdir, "run"))
|
223
|
+
create_or_update_file(path_to_runfile, @runfile)
|
224
|
+
File.chmod(0755, path_to_runfile)
|
225
|
+
path_to_runfile
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def interpret_line(cmd)
|
231
|
+
begin
|
232
|
+
eval("\"#{cmd}\"")
|
233
|
+
rescue SyntaxError
|
234
|
+
puts "You have a syntax error in your string; perhaps you included a double quote without escaping it?"
|
235
|
+
raise
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def create_or_update_file(file, new_contents)
|
240
|
+
write = 1
|
241
|
+
if File.file?(file)
|
242
|
+
current_contents = IO.read(file)
|
243
|
+
if current_contents == new_contents
|
244
|
+
write = nil
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
File.open(file, "w") do |file|
|
249
|
+
file.print(new_contents)
|
250
|
+
end if write
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'mongrel_runit/base'
|
2
|
+
require 'mongrel_runit/service'
|
3
|
+
require 'find'
|
4
|
+
|
5
|
+
module MongrelRunit
|
6
|
+
class ServiceRunner < Base
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
@mongrel_services = {}
|
12
|
+
@mongrel_names = []
|
13
|
+
|
14
|
+
raise ArgumentError, "Must have an application_name!" unless @config.has_key?("application_name")
|
15
|
+
raise ArgumentError, "Must have a port!" unless @config.has_key?("port")
|
16
|
+
raise ArgumentError, "Must have a servers option!" unless @config.has_key?("servers")
|
17
|
+
|
18
|
+
start_port = @config["port"].to_i
|
19
|
+
port_end = start_port + @config["servers"].to_i - 1
|
20
|
+
start_port.upto(port_end) do |port|
|
21
|
+
local_config = config.dup
|
22
|
+
local_config["port"] = port
|
23
|
+
@mongrel_services[port] = MongrelRunit::Service.new(local_config)
|
24
|
+
@mongrel_names << "mongrel-#{@config["application_name"]}-#{port}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(method)
|
29
|
+
if self.has_command?(method.id2name) || method.id2name == "create"
|
30
|
+
run(method.id2name)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(method)
|
37
|
+
return self.create if method == "create"
|
38
|
+
threads = []
|
39
|
+
response = {}
|
40
|
+
final_status = true
|
41
|
+
self.each do |svc|
|
42
|
+
threads << Thread.new(svc) do |s|
|
43
|
+
output, status = s.send(:run, method)
|
44
|
+
response[svc.config["port"]] = [ output, status ]
|
45
|
+
final_status = status if status == false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
threads.each { |t| t.join }
|
49
|
+
return response, final_status
|
50
|
+
end
|
51
|
+
|
52
|
+
def create
|
53
|
+
|
54
|
+
response = {}
|
55
|
+
final_status = true
|
56
|
+
self.each do |svc|
|
57
|
+
output, status = svc.create
|
58
|
+
response[svc.config["port"]] = [ output, status ]
|
59
|
+
final_status = status if status == false
|
60
|
+
end
|
61
|
+
|
62
|
+
service_path = File.expand_path(@config["runit_service_dir"])
|
63
|
+
sv_path = File.expand_path(@config["runit_sv_dir"])
|
64
|
+
Find.find(sv_path, service_path) do |file|
|
65
|
+
if File.directory?(file) || File.symlink?(file)
|
66
|
+
if file =~ /mongrel-#{@config["application_name"]}-(\d+)$/
|
67
|
+
safe = @mongrel_names.detect { |cm| cm =~ /#{File.basename(file)}$/ }
|
68
|
+
if ! safe
|
69
|
+
output = `rm -r #{file}`
|
70
|
+
raise "Cannot remove stale mongrel config" unless $?.success?
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
return response, final_status
|
76
|
+
end
|
77
|
+
|
78
|
+
def [](port)
|
79
|
+
@mongrel_services[port]
|
80
|
+
end
|
81
|
+
|
82
|
+
def length
|
83
|
+
@mongrel_services.length
|
84
|
+
end
|
85
|
+
|
86
|
+
def each
|
87
|
+
@mongrel_services.each_value { |value| yield value }
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Mongrel Runit takes a yaml config file and automatically sets up a
|
3
|
+
# group of mongrels for you. It is functionally equivilant to
|
4
|
+
# mongrel_cluster, but relies on runit for the fairly complex daemon
|
5
|
+
# management tasks.
|
6
|
+
#
|
7
|
+
# Author:: Adam Jacob (<adam@hjksolutions.com>)
|
8
|
+
# Copyright:: Copyright (c) 2007 HJK Solutions, LLC
|
9
|
+
# License:: GNU General Public License version 2.1
|
10
|
+
#
|
11
|
+
# This program is free software; you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License version 2
|
13
|
+
# as published by the Free Software Foundation.
|
14
|
+
#
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
18
|
+
# GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License along
|
21
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
22
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
23
|
+
|
24
|
+
|
25
|
+
Dir[File.join(File.dirname(__FILE__), 'mongrel_runit/**/*.rb')].sort.each { |lib| require lib }
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
port: 3000
|
3
|
+
address: 127.0.0.1
|
4
|
+
pid_file: log/mongrel.pid
|
5
|
+
servers: 2
|
6
|
+
log_file: foo.log
|
7
|
+
environment: production
|
8
|
+
cwd: /Users/adam/src/sandbox/mongrel_runit
|
9
|
+
timeout: 100
|
10
|
+
mime_map: log/mime.map
|
11
|
+
docroot: htdocs
|
12
|
+
num_procs: 1024
|
13
|
+
debug: true
|
14
|
+
config_path: /foo/bar/config
|
15
|
+
config_script: /foo/bar/config/yml
|
16
|
+
user: www-data
|
17
|
+
group: www-data
|
18
|
+
prefix: /monkey
|
19
|
+
runit_sv_dir: /etc/sv
|
20
|
+
runit_service_dir: /var/service
|
21
|
+
application_name: monkey
|
data/test/tc_config.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
require "mongrel_runit/config"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
class TestMongrelRunitConfig < Test::Unit::TestCase
|
7
|
+
YAMLFILE = File.dirname(__FILE__) + "/config/mongrel_runit.yml"
|
8
|
+
ARGS = " -e PRODUCTION"
|
9
|
+
ARGS << " -p 8000"
|
10
|
+
ARGS << " -a 127.0.0.1"
|
11
|
+
ARGS << " -l log/file.log"
|
12
|
+
ARGS << " -P log/file.pid"
|
13
|
+
ARGS << " -n 1024"
|
14
|
+
ARGS << " -m mime-types.conf"
|
15
|
+
ARGS << " -c /tmp"
|
16
|
+
ARGS << " -r /tmp"
|
17
|
+
ARGS << " --debug"
|
18
|
+
ARGS << " -C /conf/path"
|
19
|
+
ARGS << " -S /conf/path/script"
|
20
|
+
ARGS << " --user www-data"
|
21
|
+
ARGS << " --group www-data"
|
22
|
+
|
23
|
+
def setup
|
24
|
+
@file_template = {
|
25
|
+
:port => 3000,
|
26
|
+
:address => '127.0.0.1',
|
27
|
+
:pid_file => 'log/mongrel.pid',
|
28
|
+
:servers => 2,
|
29
|
+
:log_file => 'foo.log',
|
30
|
+
:environment => "production",
|
31
|
+
:cwd => "/Users/adam/src/sandbox/mongrel_runit",
|
32
|
+
:timeout => 100,
|
33
|
+
:mime_map => "log/mime.map",
|
34
|
+
:docroot => "htdocs",
|
35
|
+
:num_procs => 1024,
|
36
|
+
:debug => true,
|
37
|
+
:config_path => "/foo/bar/config",
|
38
|
+
:config_script => "/foo/bar/config/yml",
|
39
|
+
:user => "www-data",
|
40
|
+
:group => "www-data",
|
41
|
+
:prefix => "/monkey",
|
42
|
+
:runit_sv_dir => "/etc/sv",
|
43
|
+
:runit_service_dir => "/var/service",
|
44
|
+
:application_name => "monkey",
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_file
|
49
|
+
@from_file = MongrelRunit::Config.load_file(YAMLFILE)
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_args(args)
|
53
|
+
config = MongrelRunit::Config.load_args(args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_load_args
|
57
|
+
args = [ "-c#{File.expand_path('./config/mongrel_runit.yml')}", "status" ]
|
58
|
+
config = load_args(args)
|
59
|
+
@file_template.each do |key, value|
|
60
|
+
assert_equal(value, config["#{key}"], "#{key} has proper value")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_load_appname_args
|
65
|
+
args = [
|
66
|
+
"-c#{File.expand_path('./config/mongrel_runit.yml')}",
|
67
|
+
"-amoo",
|
68
|
+
"status",
|
69
|
+
]
|
70
|
+
config = load_args(args)
|
71
|
+
@file_template[:application_name] = "moo"
|
72
|
+
@file_template.each do |key, value|
|
73
|
+
assert_equal(value, config["#{key}"], "#{key} has proper value")
|
74
|
+
end
|
75
|
+
assert_equal("status", config.command, "Command is correct")
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_load_nothing
|
79
|
+
args = [ "status" ]
|
80
|
+
config = load_args(args)
|
81
|
+
@file_template.each do |key, value|
|
82
|
+
assert_equal(value, config["#{key}"], "#{key} has proper value")
|
83
|
+
end
|
84
|
+
assert_equal("status", config.command, "Command is correct")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_load_file
|
88
|
+
load_file
|
89
|
+
@file_template.each do |key, value|
|
90
|
+
assert_equal(value, @from_file["#{key}"], "#{key} has proper value")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|