foreman 0.27.0 → 0.28.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/runner +2 -0
- data/data/export/bluepill/master.pill.erb +2 -2
- data/lib/foreman.rb +5 -0
- data/lib/foreman/cli.rb +5 -10
- data/lib/foreman/engine.rb +69 -65
- data/lib/foreman/export/inittab.rb +1 -1
- data/lib/foreman/export/runit.rb +16 -16
- data/lib/foreman/export/upstart.rb +1 -1
- data/lib/foreman/process.rb +51 -6
- data/lib/foreman/procfile.rb +8 -7
- data/lib/foreman/procfile_entry.rb +22 -0
- data/lib/foreman/version.rb +1 -1
- data/spec/foreman/engine_spec.rb +12 -25
- data/spec/foreman/export/bluepill_spec.rb +1 -2
- data/spec/resources/export/bluepill/app.pill +3 -3
- metadata +12 -13
data/bin/runner
ADDED
@@ -3,7 +3,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
|
|
3
3
|
app.uid = "<%= user %>"
|
4
4
|
app.gid = "<%= user %>"
|
5
5
|
|
6
|
-
<% engine.
|
6
|
+
<% engine.procfile.entries.each do |process| %>
|
7
7
|
<% 1.upto(concurrency[process.name]) do |num| %>
|
8
8
|
<% port = engine.port_for(process, num, options[:port]) %>
|
9
9
|
app.process("<%= process.name %>-<%=num%>") do |process|
|
@@ -19,7 +19,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
|
|
19
19
|
process.monitor_children do |children|
|
20
20
|
children.stop_command "kill -QUIT {{PID}}"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
process.group = "<%= app %>-<%= process.name %>"
|
24
24
|
end
|
25
25
|
<% end %>
|
data/lib/foreman.rb
CHANGED
data/lib/foreman/cli.rb
CHANGED
@@ -8,20 +8,15 @@ class Foreman::CLI < Thor
|
|
8
8
|
|
9
9
|
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
10
10
|
|
11
|
-
desc "start
|
11
|
+
desc "start", "Start the application"
|
12
12
|
|
13
13
|
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
14
14
|
method_option :port, :type => :numeric, :aliases => "-p"
|
15
15
|
method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
|
16
16
|
|
17
|
-
def start
|
17
|
+
def start
|
18
18
|
check_procfile!
|
19
|
-
|
20
|
-
if process
|
21
|
-
engine.execute(process)
|
22
|
-
else
|
23
|
-
engine.start
|
24
|
-
end
|
19
|
+
engine.start
|
25
20
|
end
|
26
21
|
|
27
22
|
desc "export FORMAT LOCATION", "Export the application to another process management format"
|
@@ -55,8 +50,8 @@ class Foreman::CLI < Thor
|
|
55
50
|
desc "check", "Validate your application's Procfile"
|
56
51
|
|
57
52
|
def check
|
58
|
-
error "no processes defined" unless engine.
|
59
|
-
display "valid procfile detected (#{engine.
|
53
|
+
error "no processes defined" unless engine.procfile.entries.length > 0
|
54
|
+
display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
|
60
55
|
end
|
61
56
|
|
62
57
|
private ######################################################################
|
data/lib/foreman/engine.rb
CHANGED
@@ -23,6 +23,7 @@ class Foreman::Engine
|
|
23
23
|
@directory = File.expand_path(File.dirname(procfile))
|
24
24
|
@options = options
|
25
25
|
@environment = read_environment_files(options[:env])
|
26
|
+
@output_mutex = Mutex.new
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.load_env!(env_file)
|
@@ -32,34 +33,17 @@ class Foreman::Engine
|
|
32
33
|
|
33
34
|
def start
|
34
35
|
proctitle "ruby: foreman master"
|
35
|
-
termtitle "#{File.basename(@directory)} - foreman
|
36
|
-
|
37
|
-
processes.each do |process|
|
38
|
-
process.color = next_color
|
39
|
-
fork process
|
40
|
-
end
|
41
|
-
|
42
|
-
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
|
43
|
-
trap("INT") { puts "SIGINT received"; terminate_gracefully }
|
44
|
-
|
45
|
-
watch_for_termination
|
46
|
-
end
|
47
|
-
|
48
|
-
def execute(name)
|
49
|
-
error "no such process: #{name}" unless process = procfile[name]
|
50
|
-
process.color = next_color
|
51
|
-
fork process
|
36
|
+
termtitle "#{File.basename(@directory)} - foreman"
|
52
37
|
|
53
38
|
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
|
54
39
|
trap("INT") { puts "SIGINT received"; terminate_gracefully }
|
55
40
|
|
41
|
+
assign_colors
|
42
|
+
spawn_processes
|
43
|
+
watch_for_output
|
56
44
|
watch_for_termination
|
57
45
|
end
|
58
46
|
|
59
|
-
def processes
|
60
|
-
procfile.processes
|
61
|
-
end
|
62
|
-
|
63
47
|
def port_for(process, num, base_port=nil)
|
64
48
|
base_port ||= 5000
|
65
49
|
offset = procfile.process_names.index(process.name) * 100
|
@@ -68,47 +52,20 @@ class Foreman::Engine
|
|
68
52
|
|
69
53
|
private ######################################################################
|
70
54
|
|
71
|
-
def
|
55
|
+
def spawn_processes
|
72
56
|
concurrency = Foreman::Utils.parse_concurrency(@options[:concurrency])
|
73
57
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
apply_environment!
|
81
|
-
|
82
|
-
ENV["PORT"] = port.to_s
|
83
|
-
ENV["PS"] = "#{process.name}.#{num}"
|
84
|
-
|
85
|
-
pid = Process.fork do
|
86
|
-
run(process)
|
58
|
+
procfile.entries.each do |entry|
|
59
|
+
reader, writer = IO.pipe
|
60
|
+
entry.spawn(concurrency[entry.name], writer, @directory, @environment, base_port).each do |process|
|
61
|
+
running_processes[process.pid] = process
|
62
|
+
readers[process] = reader
|
63
|
+
end
|
87
64
|
end
|
88
|
-
|
89
|
-
info "started with pid #{pid}", process
|
90
|
-
running_processes[pid] = process
|
91
65
|
end
|
92
66
|
|
93
|
-
def
|
94
|
-
|
95
|
-
trap("SIGINT", "IGNORE")
|
96
|
-
|
97
|
-
begin
|
98
|
-
Dir.chdir directory do
|
99
|
-
PTY.spawn(process.command) do |stdin, stdout, pid|
|
100
|
-
trap("SIGTERM") { Process.kill("SIGTERM", pid) }
|
101
|
-
until stdin.eof?
|
102
|
-
info stdin.gets, process
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
rescue PTY::ChildExited, Interrupt, Errno::EIO, Errno::ENOENT
|
107
|
-
begin
|
108
|
-
info "process exiting", process
|
109
|
-
rescue Interrupt
|
110
|
-
end
|
111
|
-
end
|
67
|
+
def base_port
|
68
|
+
options[:port] || 5000
|
112
69
|
end
|
113
70
|
|
114
71
|
def kill_all(signal="SIGTERM")
|
@@ -120,29 +77,59 @@ private ######################################################################
|
|
120
77
|
def terminate_gracefully
|
121
78
|
info "sending SIGTERM to all processes"
|
122
79
|
kill_all "SIGTERM"
|
123
|
-
Timeout.timeout(
|
80
|
+
Timeout.timeout(5) { Process.waitall }
|
124
81
|
rescue Timeout::Error
|
125
82
|
info "sending SIGKILL to all processes"
|
126
83
|
kill_all "SIGKILL"
|
127
84
|
end
|
128
85
|
|
86
|
+
def watch_for_output
|
87
|
+
Thread.new do
|
88
|
+
begin
|
89
|
+
loop do
|
90
|
+
rs, ws = IO.select(readers.values, [], [], 1)
|
91
|
+
(rs || []).each do |r|
|
92
|
+
ps, message = r.gets.split(",", 2)
|
93
|
+
color = colors[ps.split(".").first]
|
94
|
+
info message, ps, color
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue Exception => ex
|
98
|
+
puts ex.message
|
99
|
+
puts ex.backtrace
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
129
104
|
def watch_for_termination
|
130
105
|
pid, status = Process.wait2
|
131
106
|
process = running_processes.delete(pid)
|
132
|
-
info "process terminated", process
|
107
|
+
info "process terminated", process.name
|
133
108
|
terminate_gracefully
|
134
109
|
kill_all
|
135
110
|
rescue Errno::ECHILD
|
136
111
|
end
|
137
112
|
|
138
|
-
def info(message,
|
139
|
-
print
|
140
|
-
print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(
|
113
|
+
def info(message, name="system", color=Term::ANSIColor.white)
|
114
|
+
print color
|
115
|
+
print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
141
116
|
print Term::ANSIColor.reset
|
142
117
|
print message.chomp
|
143
118
|
puts
|
144
119
|
end
|
145
120
|
|
121
|
+
def print(message=nil)
|
122
|
+
@output_mutex.synchronize do
|
123
|
+
$stdout.print message
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def puts(message=nil)
|
128
|
+
@output_mutex.synchronize do
|
129
|
+
$stdout.puts message
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
146
133
|
def error(message)
|
147
134
|
puts "ERROR: #{message}"
|
148
135
|
exit 1
|
@@ -156,9 +143,8 @@ private ######################################################################
|
|
156
143
|
end
|
157
144
|
end
|
158
145
|
|
159
|
-
def pad_process_name(
|
160
|
-
name
|
161
|
-
name.ljust(longest_process_name + 3) # add 3 for process number padding
|
146
|
+
def pad_process_name(name="system")
|
147
|
+
name.to_s.ljust(longest_process_name + 3) # add 3 for process number padding
|
162
148
|
end
|
163
149
|
|
164
150
|
def proctitle(title)
|
@@ -173,6 +159,24 @@ private ######################################################################
|
|
173
159
|
@running_processes ||= {}
|
174
160
|
end
|
175
161
|
|
162
|
+
def readers
|
163
|
+
@readers ||= {}
|
164
|
+
end
|
165
|
+
|
166
|
+
def colors
|
167
|
+
@colors ||= {}
|
168
|
+
end
|
169
|
+
|
170
|
+
def assign_colors
|
171
|
+
procfile.entries.each do |entry|
|
172
|
+
colors[entry.name] = next_color
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def process_by_reader(reader)
|
177
|
+
readers.invert[reader]
|
178
|
+
end
|
179
|
+
|
176
180
|
def next_color
|
177
181
|
@current_color ||= -1
|
178
182
|
@current_color += 1
|
@@ -12,7 +12,7 @@ class Foreman::Export::Inittab < Foreman::Export::Base
|
|
12
12
|
inittab = []
|
13
13
|
inittab << "# ----- foreman #{app} processes -----"
|
14
14
|
|
15
|
-
engine.
|
15
|
+
engine.procfile.entries.inject(1) do |index, process|
|
16
16
|
1.upto(concurrency[process.name]) do |num|
|
17
17
|
id = app.slice(0, 2).upcase + sprintf("%02d", index)
|
18
18
|
port = engine.port_for(process, num, options[:port])
|
data/lib/foreman/export/runit.rb
CHANGED
@@ -3,58 +3,58 @@ require "foreman/export"
|
|
3
3
|
|
4
4
|
class Foreman::Export::Runit < Foreman::Export::Base
|
5
5
|
ENV_VARIABLE_REGEX = /([a-zA-Z_]+[a-zA-Z0-9_]*)=(\S+)/
|
6
|
-
|
6
|
+
|
7
7
|
def export(location, options={})
|
8
8
|
error("Must specify a location") unless location
|
9
|
-
|
9
|
+
|
10
10
|
app = options[:app] || File.basename(engine.directory)
|
11
11
|
user = options[:user] || app
|
12
12
|
log_root = options[:log] || "/var/log/#{app}"
|
13
13
|
template_root = options[:template]
|
14
|
-
|
14
|
+
|
15
15
|
concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
|
16
|
-
|
16
|
+
|
17
17
|
run_template = export_template('runit', 'run.erb', template_root)
|
18
18
|
log_run_template = export_template('runit', 'log_run.erb', template_root)
|
19
19
|
|
20
|
-
engine.
|
20
|
+
engine.procfile.entries.each do |process|
|
21
21
|
1.upto(concurrency[process.name]) do |num|
|
22
22
|
process_directory = "#{location}/#{app}-#{process.name}-#{num}"
|
23
23
|
process_env_directory = "#{process_directory}/env"
|
24
24
|
process_log_directory = "#{process_directory}/log"
|
25
|
-
|
25
|
+
|
26
26
|
create_directory process_directory
|
27
27
|
create_directory process_env_directory
|
28
28
|
create_directory process_log_directory
|
29
|
-
|
29
|
+
|
30
30
|
run = ERB.new(run_template).result(binding)
|
31
31
|
write_file "#{process_directory}/run", run
|
32
|
-
|
32
|
+
|
33
33
|
port = engine.port_for(process, num, options[:port])
|
34
34
|
environment_variables = {'PORT' => port}.
|
35
35
|
merge(engine.environment).
|
36
36
|
merge(inline_variables(process.command))
|
37
|
-
|
37
|
+
|
38
38
|
environment_variables.each_pair do |var, env|
|
39
39
|
write_file "#{process_env_directory}/#{var.upcase}", env
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
log_run = ERB.new(log_run_template).result(binding)
|
43
43
|
write_file "#{process_log_directory}/run", log_run
|
44
|
-
|
44
|
+
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
private
|
51
51
|
def create_directory(location)
|
52
52
|
say "creating: #{location}"
|
53
53
|
FileUtils.mkdir(location)
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def inline_variables(command)
|
57
|
-
variable_name_regex =
|
57
|
+
variable_name_regex =
|
58
58
|
Hash[*command.scan(ENV_VARIABLE_REGEX).flatten]
|
59
59
|
end
|
60
|
-
end
|
60
|
+
end
|
@@ -26,7 +26,7 @@ class Foreman::Export::Upstart < Foreman::Export::Base
|
|
26
26
|
|
27
27
|
process_template = export_template("upstart", "process.conf.erb", template_root)
|
28
28
|
|
29
|
-
engine.
|
29
|
+
engine.procfile.entries.each do |process|
|
30
30
|
next if (conc = concurrency[process.name]) < 1
|
31
31
|
process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
|
32
32
|
process_master_config = ERB.new(process_master_template).result(binding)
|
data/lib/foreman/process.rb
CHANGED
@@ -2,13 +2,58 @@ require "foreman"
|
|
2
2
|
|
3
3
|
class Foreman::Process
|
4
4
|
|
5
|
-
attr_reader :
|
6
|
-
attr_reader :
|
7
|
-
|
5
|
+
attr_reader :entry
|
6
|
+
attr_reader :num
|
7
|
+
attr_reader :pid
|
8
|
+
attr_reader :port
|
8
9
|
|
9
|
-
def initialize(
|
10
|
-
@
|
11
|
-
@
|
10
|
+
def initialize(entry, num, port)
|
11
|
+
@entry = entry
|
12
|
+
@num = num
|
13
|
+
@port = port
|
14
|
+
end
|
15
|
+
|
16
|
+
def run(pipe, basedir, environment)
|
17
|
+
Dir.chdir(basedir) do
|
18
|
+
with_environment(environment.merge("PORT" => port.to_s)) do
|
19
|
+
run_process entry.command
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def name
|
25
|
+
"%s.%s" % [ entry.name, num ]
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def run_process(command)
|
31
|
+
io = IO.popen([Foreman.runner, replace_command_env(command)], "w+")
|
32
|
+
@pid = io.pid
|
33
|
+
trap("SIGTERM") { "got sigterm for %d" % @pid }
|
34
|
+
output pipe, "started with pid %d" % @pid
|
35
|
+
Thread.new do
|
36
|
+
until io.eof?
|
37
|
+
output pipe, io.gets
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def output(pipe, message)
|
43
|
+
pipe.puts "%s,%s" % [ name, message ]
|
44
|
+
end
|
45
|
+
|
46
|
+
def replace_command_env(command)
|
47
|
+
command.gsub(/\$(\w+)/) { |e| ENV[e[1..-1]] }
|
48
|
+
end
|
49
|
+
|
50
|
+
def with_environment(environment)
|
51
|
+
old_env = ENV.each_pair.inject({}) { |h,(k,v)| h.update(k => v) }
|
52
|
+
environment.each { |k,v| ENV[k] = v }
|
53
|
+
ret = yield
|
54
|
+
ENV.clear
|
55
|
+
old_env.each { |k,v| ENV[k] = v}
|
56
|
+
ret
|
12
57
|
end
|
13
58
|
|
14
59
|
end
|
data/lib/foreman/procfile.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "foreman"
|
2
|
+
require "foreman/procfile_entry"
|
2
3
|
|
3
4
|
# A valid Procfile entry is captured by this regex.
|
4
5
|
# All other lines are ignored.
|
@@ -10,18 +11,18 @@ require "foreman"
|
|
10
11
|
#
|
11
12
|
class Foreman::Procfile
|
12
13
|
|
13
|
-
attr_reader :
|
14
|
+
attr_reader :entries
|
14
15
|
|
15
16
|
def initialize(filename)
|
16
|
-
@
|
17
|
+
@entries = parse_procfile(filename)
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
|
20
|
+
def [](name)
|
21
|
+
entries.detect { |entry| entry.name == name }
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
24
|
+
def process_names
|
25
|
+
entries.map(&:name)
|
25
26
|
end
|
26
27
|
|
27
28
|
private
|
@@ -29,7 +30,7 @@ private
|
|
29
30
|
def parse_procfile(filename)
|
30
31
|
File.read(filename).split("\n").map do |line|
|
31
32
|
if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
|
32
|
-
Foreman::
|
33
|
+
Foreman::ProcfileEntry.new($1, $2)
|
33
34
|
end
|
34
35
|
end.compact
|
35
36
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "foreman"
|
2
|
+
|
3
|
+
class Foreman::ProcfileEntry
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :command
|
7
|
+
attr_accessor :color
|
8
|
+
|
9
|
+
def initialize(name, command)
|
10
|
+
@name = name
|
11
|
+
@command = command
|
12
|
+
end
|
13
|
+
|
14
|
+
def spawn(num, pipe, basedir, environment, base_port)
|
15
|
+
(1..num).to_a.map do |n|
|
16
|
+
process = Foreman::Process.new(self, n, base_port + (n-1))
|
17
|
+
process.run(pipe, basedir, environment)
|
18
|
+
process
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/foreman/version.rb
CHANGED
data/spec/foreman/engine_spec.rb
CHANGED
@@ -24,8 +24,9 @@ describe "Foreman::Engine" do
|
|
24
24
|
describe "start" do
|
25
25
|
it "forks the processes" do
|
26
26
|
write_procfile
|
27
|
-
mock(
|
28
|
-
mock(
|
27
|
+
mock.instance_of(Foreman::Process).run_process("./alpha")
|
28
|
+
mock.instance_of(Foreman::Process).run_process("./bravo")
|
29
|
+
mock(subject).watch_for_output
|
29
30
|
mock(subject).watch_for_termination
|
30
31
|
subject.start
|
31
32
|
end
|
@@ -33,29 +34,14 @@ describe "Foreman::Engine" do
|
|
33
34
|
it "handles concurrency" do
|
34
35
|
write_procfile
|
35
36
|
engine = Foreman::Engine.new("Procfile",:concurrency => "alpha=2")
|
36
|
-
mock(
|
37
|
-
mock(
|
38
|
-
mock(engine).
|
37
|
+
mock.instance_of(Foreman::Process).run_process("./alpha").twice
|
38
|
+
mock.instance_of(Foreman::Process).run_process("./bravo")
|
39
|
+
mock(engine).watch_for_output
|
39
40
|
mock(engine).watch_for_termination
|
40
41
|
engine.start
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
describe "execute" do
|
45
|
-
it "runs the processes" do
|
46
|
-
write_procfile
|
47
|
-
mock(subject).fork(subject.procfile["alpha"])
|
48
|
-
mock(subject).watch_for_termination
|
49
|
-
subject.execute("alpha")
|
50
|
-
end
|
51
|
-
|
52
|
-
it "shows an error running a process that doesnt exist" do
|
53
|
-
write_procfile
|
54
|
-
mock(subject).puts("ERROR: no such process: foo")
|
55
|
-
lambda { subject.execute("foo") }.should raise_error(SystemExit)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
45
|
describe "environment" do
|
60
46
|
before(:each) do
|
61
47
|
write_procfile
|
@@ -66,9 +52,10 @@ describe "Foreman::Engine" do
|
|
66
52
|
File.open("/tmp/env", "w") { |f| f.puts("FOO=baz") }
|
67
53
|
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
|
68
54
|
stub(engine).info
|
55
|
+
mock(engine).spawn_processes
|
69
56
|
mock(engine).watch_for_termination
|
70
57
|
engine.environment.should == {"FOO"=>"baz"}
|
71
|
-
engine.
|
58
|
+
engine.start
|
72
59
|
end
|
73
60
|
|
74
61
|
it "should read more than one if specified" do
|
@@ -76,9 +63,10 @@ describe "Foreman::Engine" do
|
|
76
63
|
File.open("/tmp/env2", "w") { |f| f.puts("BAZ=qux") }
|
77
64
|
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env1,/tmp/env2")
|
78
65
|
stub(engine).info
|
66
|
+
mock(engine).spawn_processes
|
79
67
|
mock(engine).watch_for_termination
|
80
68
|
engine.environment.should == { "FOO"=>"bar", "BAZ"=>"qux" }
|
81
|
-
engine.
|
69
|
+
engine.start
|
82
70
|
end
|
83
71
|
|
84
72
|
it "should fail if specified and doesnt exist" do
|
@@ -89,11 +77,10 @@ describe "Foreman::Engine" do
|
|
89
77
|
it "should read .env if none specified" do
|
90
78
|
File.open(".env", "w") { |f| f.puts("FOO=qoo") }
|
91
79
|
engine = Foreman::Engine.new("Procfile")
|
92
|
-
|
80
|
+
mock(engine).spawn_processes
|
93
81
|
mock(engine).watch_for_termination
|
94
|
-
mock(engine).fork_individual(anything, anything, anything)
|
95
82
|
engine.environment.should == {"FOO"=>"qoo"}
|
96
|
-
engine.
|
83
|
+
engine.start
|
97
84
|
end
|
98
85
|
end
|
99
86
|
end
|
@@ -19,7 +19,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
19
19
|
process.monitor_children do |children|
|
20
20
|
children.stop_command "kill -QUIT {{PID}}"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
process.group = "app-alpha"
|
24
24
|
end
|
25
25
|
|
@@ -37,7 +37,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
37
37
|
process.monitor_children do |children|
|
38
38
|
children.stop_command "kill -QUIT {{PID}}"
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
process.group = "app-alpha"
|
42
42
|
end
|
43
43
|
|
@@ -57,7 +57,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
|
|
57
57
|
process.monitor_children do |children|
|
58
58
|
children.stop_command "kill -QUIT {{PID}}"
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
process.group = "app-bravo"
|
62
62
|
end
|
63
63
|
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.28.0.pre1
|
5
|
+
prerelease: 7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Dollar
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-09 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: term-ansicolor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70324999098260 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70324999098260
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: thor
|
27
|
-
requirement: &
|
27
|
+
requirement: &70324999097620 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 0.13.6
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70324999097620
|
36
36
|
description: Process manager for applications with multiple components
|
37
37
|
email: ddollar@gmail.com
|
38
38
|
executables:
|
@@ -41,6 +41,7 @@ extensions: []
|
|
41
41
|
extra_rdoc_files: []
|
42
42
|
files:
|
43
43
|
- bin/foreman
|
44
|
+
- bin/runner
|
44
45
|
- data/example/error
|
45
46
|
- data/example/log/neverdie.log
|
46
47
|
- data/example/Procfile
|
@@ -63,6 +64,7 @@ files:
|
|
63
64
|
- lib/foreman/export.rb
|
64
65
|
- lib/foreman/process.rb
|
65
66
|
- lib/foreman/procfile.rb
|
67
|
+
- lib/foreman/procfile_entry.rb
|
66
68
|
- lib/foreman/utils.rb
|
67
69
|
- lib/foreman/version.rb
|
68
70
|
- lib/foreman.rb
|
@@ -104,16 +106,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
106
|
version: '0'
|
105
107
|
segments:
|
106
108
|
- 0
|
107
|
-
hash:
|
109
|
+
hash: 710611056517005467
|
108
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
111
|
none: false
|
110
112
|
requirements:
|
111
|
-
- - ! '
|
113
|
+
- - ! '>'
|
112
114
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
114
|
-
segments:
|
115
|
-
- 0
|
116
|
-
hash: -3613490576676930257
|
115
|
+
version: 1.3.1
|
117
116
|
requirements: []
|
118
117
|
rubyforge_project:
|
119
118
|
rubygems_version: 1.8.10
|