foreman 0.27.0 → 0.28.0.pre1
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/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
|