foreman 0.57.0-java → 0.61.0-java
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/foreman-runner +3 -3
- data/data/export/launchd/launchd.plist.erb +12 -1
- data/lib/foreman.rb +2 -2
- data/lib/foreman/capistrano.rb +54 -0
- data/lib/foreman/cli.rb +13 -2
- data/lib/foreman/engine.rb +14 -6
- data/lib/foreman/engine/cli.rb +4 -4
- data/lib/foreman/env.rb +4 -2
- data/lib/foreman/export/base.rb +2 -2
- data/lib/foreman/export/inittab.rb +10 -1
- data/lib/foreman/export/launchd.rb +2 -0
- data/lib/foreman/process.rb +33 -9
- data/lib/foreman/procfile.rb +1 -1
- data/lib/foreman/version.rb +1 -1
- data/man/foreman.1 +2 -2
- data/spec/foreman/cli_spec.rb +9 -0
- data/spec/foreman/engine_spec.rb +8 -0
- data/spec/foreman/export/launchd_spec.rb +10 -0
- data/spec/foreman/export/upstart_spec.rb +1 -1
- data/spec/resources/export/inittab/inittab.concurrency +2 -2
- data/spec/resources/export/inittab/inittab.default +2 -2
- data/spec/resources/export/launchd/launchd-a.default +7 -0
- data/spec/resources/export/launchd/launchd-b.default +7 -0
- data/spec/resources/export/launchd/launchd-c.default +30 -0
- data/spec/resources/export/supervisord/app-alpha-1.conf +2 -2
- data/spec/resources/export/supervisord/app-alpha-2.conf +2 -2
- data/spec/spec_helper.rb +6 -2
- metadata +10 -7
data/bin/foreman-runner
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/
|
|
1
|
+
#!/bin/sh
|
|
2
2
|
#
|
|
3
3
|
#/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...]
|
|
4
4
|
#/
|
|
@@ -32,9 +32,9 @@ shift $((OPTIND-1))
|
|
|
32
32
|
|
|
33
33
|
[ -z "$1" ] && usage
|
|
34
34
|
|
|
35
|
-
if [ "$read_profile"
|
|
35
|
+
if [ "$read_profile" = "1" ]; then
|
|
36
36
|
if [ -f .profile ]; then
|
|
37
|
-
|
|
37
|
+
. .profile
|
|
38
38
|
fi
|
|
39
39
|
fi
|
|
40
40
|
|
|
@@ -4,14 +4,25 @@
|
|
|
4
4
|
<dict>
|
|
5
5
|
<key>Label</key>
|
|
6
6
|
<string><%= "#{app}-#{name}-#{num}" %></string>
|
|
7
|
+
<key>EnvironmentVariables</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
|
|
10
|
+
<key><%= var.upcase %></key>
|
|
11
|
+
<string><%= env %></string>
|
|
12
|
+
<%- end -%>
|
|
13
|
+
</dict>
|
|
7
14
|
<key>ProgramArguments</key>
|
|
8
15
|
<array>
|
|
9
|
-
|
|
16
|
+
<%- command_args.each do |command| -%>
|
|
17
|
+
<string><%= command %></string>
|
|
18
|
+
<%- end -%>
|
|
10
19
|
</array>
|
|
11
20
|
<key>KeepAlive</key>
|
|
12
21
|
<true/>
|
|
13
22
|
<key>RunAtLoad</key>
|
|
14
23
|
<true/>
|
|
24
|
+
<key>StandardOutPath</key>
|
|
25
|
+
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
|
|
15
26
|
<key>StandardErrorPath</key>
|
|
16
27
|
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
|
|
17
28
|
<key>UserName</key>
|
data/lib/foreman.rb
CHANGED
|
@@ -8,8 +8,8 @@ module Foreman
|
|
|
8
8
|
File.expand_path("../../bin/foreman-runner", __FILE__)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def self.
|
|
12
|
-
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
|
|
11
|
+
def self.jruby_18?
|
|
12
|
+
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java" and ruby_18?
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def self.ruby_18?
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
if defined?(Capistrano)
|
|
2
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
|
3
|
+
|
|
4
|
+
namespace :foreman do
|
|
5
|
+
desc <<-DESC
|
|
6
|
+
Export the Procfile to upstart. Will use sudo if available.
|
|
7
|
+
|
|
8
|
+
You can override any of these defaults by setting the variables shown below.
|
|
9
|
+
|
|
10
|
+
set :foreman_format, "upstart"
|
|
11
|
+
set :foreman_location, "/etc/init"
|
|
12
|
+
set :foreman_procfile, "Procfile"
|
|
13
|
+
set :foreman_app, application
|
|
14
|
+
set :foreman_user, user
|
|
15
|
+
set :foreman_log, 'shared_path/log'
|
|
16
|
+
set :foreman_concurrency, false
|
|
17
|
+
DESC
|
|
18
|
+
task :export, :roles => :app do
|
|
19
|
+
bundle_cmd = fetch(:bundle_cmd, "bundle")
|
|
20
|
+
foreman_format = fetch(:foreman_format, "upstart")
|
|
21
|
+
foreman_location = fetch(:foreman_location, "/etc/init")
|
|
22
|
+
foreman_procfile = fetch(:foreman_procfile, "Procfile")
|
|
23
|
+
foreman_app = fetch(:foreman_app, application)
|
|
24
|
+
foreman_user = fetch(:foreman_user, user)
|
|
25
|
+
foreman_log = fetch(:foreman_log, "#{shared_path}/log")
|
|
26
|
+
foreman_concurrency = fetch(:foreman_concurrency, false)
|
|
27
|
+
|
|
28
|
+
args = ["#{foreman_format} #{foreman_location}"]
|
|
29
|
+
args << "-f #{foreman_procfile}"
|
|
30
|
+
args << "-a #{foreman_app}"
|
|
31
|
+
args << "-u #{foreman_user}"
|
|
32
|
+
args << "-l #{foreman_log}"
|
|
33
|
+
args << "-c #{foreman_concurrency}" if foreman_concurrency
|
|
34
|
+
run "cd #{release_path} && #{sudo} #{bundle_cmd} exec foreman export #{args.join(' ')}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc "Start the application services"
|
|
38
|
+
task :start, :roles => :app do
|
|
39
|
+
run "#{sudo} start #{application}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "Stop the application services"
|
|
43
|
+
task :stop, :roles => :app do
|
|
44
|
+
run "#{sudo} stop #{application}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc "Restart the application services"
|
|
48
|
+
task :restart, :roles => :app do
|
|
49
|
+
run "#{sudo} start #{application} || #{sudo} restart #{application}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/foreman/cli.rb
CHANGED
|
@@ -23,6 +23,7 @@ class Foreman::CLI < Thor
|
|
|
23
23
|
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
|
24
24
|
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
|
|
25
25
|
method_option :port, :type => :numeric, :aliases => "-p"
|
|
26
|
+
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shudown gracefully before receiving a SIGKILL, defaults to 5."
|
|
26
27
|
|
|
27
28
|
class << self
|
|
28
29
|
# Hackery. Take the run method away from Thor so that we can redefine it.
|
|
@@ -75,10 +76,19 @@ class Foreman::CLI < Thor
|
|
|
75
76
|
|
|
76
77
|
def run(*args)
|
|
77
78
|
load_environment!
|
|
79
|
+
|
|
80
|
+
if File.exist?(procfile)
|
|
81
|
+
engine.load_procfile(procfile)
|
|
82
|
+
end
|
|
83
|
+
|
|
78
84
|
pid = fork do
|
|
79
85
|
begin
|
|
80
86
|
engine.env.each { |k,v| ENV[k] = v }
|
|
81
|
-
|
|
87
|
+
if args.size == 1 && process = engine.process(args.first)
|
|
88
|
+
process.exec(:env => engine.env)
|
|
89
|
+
else
|
|
90
|
+
exec args.shelljoin
|
|
91
|
+
end
|
|
82
92
|
rescue Errno::EACCES
|
|
83
93
|
error "not executable: #{args.first}"
|
|
84
94
|
rescue Errno::ENOENT
|
|
@@ -86,6 +96,7 @@ class Foreman::CLI < Thor
|
|
|
86
96
|
end
|
|
87
97
|
end
|
|
88
98
|
Process.wait(pid)
|
|
99
|
+
exit $?.exitstatus
|
|
89
100
|
end
|
|
90
101
|
|
|
91
102
|
desc "version", "Display Foreman gem version"
|
|
@@ -129,7 +140,7 @@ private ######################################################################
|
|
|
129
140
|
def procfile
|
|
130
141
|
case
|
|
131
142
|
when options[:procfile] then options[:procfile]
|
|
132
|
-
when options[:root] then File.expand_path(File.join(options[:
|
|
143
|
+
when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
|
|
133
144
|
else "Procfile"
|
|
134
145
|
end
|
|
135
146
|
end
|
data/lib/foreman/engine.rb
CHANGED
|
@@ -25,6 +25,7 @@ class Foreman::Engine
|
|
|
25
25
|
@options = options.dup
|
|
26
26
|
|
|
27
27
|
@options[:formation] ||= (options[:concurrency] || "all=1")
|
|
28
|
+
@options[:timeout] ||= 5
|
|
28
29
|
|
|
29
30
|
@env = {}
|
|
30
31
|
@mutex = Mutex.new
|
|
@@ -37,6 +38,9 @@ class Foreman::Engine
|
|
|
37
38
|
# Start the processes registered to this +Engine+
|
|
38
39
|
#
|
|
39
40
|
def start
|
|
41
|
+
# Make sure foreman is the process group leader.
|
|
42
|
+
Process.setpgrp unless Foreman.windows?
|
|
43
|
+
|
|
40
44
|
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
|
|
41
45
|
trap("INT") { puts "SIGINT received"; terminate_gracefully }
|
|
42
46
|
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP'
|
|
@@ -109,7 +113,7 @@ class Foreman::Engine
|
|
|
109
113
|
end
|
|
110
114
|
else
|
|
111
115
|
begin
|
|
112
|
-
Process.kill "-#{signal}", Process.
|
|
116
|
+
Process.kill "-#{signal}", Process.getpgrp
|
|
113
117
|
rescue Errno::ESRCH, Errno::EPERM
|
|
114
118
|
end
|
|
115
119
|
end
|
|
@@ -257,7 +261,6 @@ private
|
|
|
257
261
|
reader, writer = create_pipe
|
|
258
262
|
begin
|
|
259
263
|
pid = process.run(:output => writer, :env => {
|
|
260
|
-
"HOME" => process.cwd,
|
|
261
264
|
"PORT" => port_for(process, n).to_s
|
|
262
265
|
})
|
|
263
266
|
writer.puts "started with pid #{pid}"
|
|
@@ -274,9 +277,14 @@ private
|
|
|
274
277
|
Thread.new do
|
|
275
278
|
begin
|
|
276
279
|
loop do
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
+
io = IO.select(@readers.values, nil, nil, 30)
|
|
281
|
+
(io.nil? ? [] : io.first).each do |reader|
|
|
282
|
+
if reader.eof?
|
|
283
|
+
@readers.delete_if { |key, value| value == reader }
|
|
284
|
+
else
|
|
285
|
+
data = reader.gets
|
|
286
|
+
output_with_mutex name_for(@readers.invert[reader]), data
|
|
287
|
+
end
|
|
280
288
|
end
|
|
281
289
|
end
|
|
282
290
|
rescue Exception => ex
|
|
@@ -305,7 +313,7 @@ private
|
|
|
305
313
|
system "sending SIGTERM to all processes"
|
|
306
314
|
killall "SIGTERM"
|
|
307
315
|
end
|
|
308
|
-
Timeout.timeout(
|
|
316
|
+
Timeout.timeout(options[:timeout]) do
|
|
309
317
|
watch_for_termination while @running.length > 0
|
|
310
318
|
end
|
|
311
319
|
rescue Timeout::Error
|
data/lib/foreman/engine/cli.rb
CHANGED
|
@@ -44,8 +44,8 @@ class Foreman::Engine::CLI < Foreman::Engine
|
|
|
44
44
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
FOREMAN_COLORS = %w( cyan yellow green magenta red blue
|
|
48
|
-
|
|
47
|
+
FOREMAN_COLORS = %w( cyan yellow green magenta red blue bright_cyan bright_yellow
|
|
48
|
+
bright_green bright_magenta bright_red bright_blue )
|
|
49
49
|
|
|
50
50
|
def startup
|
|
51
51
|
@colors = map_colors
|
|
@@ -54,7 +54,7 @@ class Foreman::Engine::CLI < Foreman::Engine
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def output(name, data)
|
|
57
|
-
data.to_s.
|
|
57
|
+
data.to_s.lines.map(&:chomp).each do |message|
|
|
58
58
|
output = ""
|
|
59
59
|
output += $stdout.color(@colors[name.split(".").first].to_sym)
|
|
60
60
|
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
|
@@ -89,7 +89,7 @@ private
|
|
|
89
89
|
@names.values.each_with_index do |name, index|
|
|
90
90
|
colors[name] = FOREMAN_COLORS[index % FOREMAN_COLORS.length]
|
|
91
91
|
end
|
|
92
|
-
colors["system"] = "
|
|
92
|
+
colors["system"] = "bright_white"
|
|
93
93
|
colors
|
|
94
94
|
end
|
|
95
95
|
|
data/lib/foreman/env.rb
CHANGED
|
@@ -5,12 +5,14 @@ class Foreman::Env
|
|
|
5
5
|
attr_reader :entries
|
|
6
6
|
|
|
7
7
|
def initialize(filename)
|
|
8
|
-
@entries = File.read(filename).split("\n").inject({}) do |ax, line|
|
|
8
|
+
@entries = File.read(filename).gsub("\r\n","\n").split("\n").inject({}) do |ax, line|
|
|
9
9
|
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
|
|
10
10
|
key = $1
|
|
11
11
|
case val = $2
|
|
12
|
+
# Remove single quotes
|
|
12
13
|
when /\A'(.*)'\z/ then ax[key] = $1
|
|
13
|
-
|
|
14
|
+
# Remove double quotes and unescape string preserving newline characters
|
|
15
|
+
when /\A"(.*)"\z/ then ax[key] = $1.gsub('\n', "\n").gsub(/\\(.)/, '\1')
|
|
14
16
|
else ax[key] = val
|
|
15
17
|
end
|
|
16
18
|
end
|
data/lib/foreman/export/base.rb
CHANGED
|
@@ -91,7 +91,7 @@ private ######################################################################
|
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def shell_quote(value)
|
|
94
|
-
|
|
94
|
+
Shellwords.escape(value)
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# deprecated
|
|
@@ -119,7 +119,7 @@ private ######################################################################
|
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def write_template(name, target, binding)
|
|
122
|
-
compiled = ERB.new(export_template(name)).result(binding)
|
|
122
|
+
compiled = ERB.new(export_template(name), nil, '-').result(binding)
|
|
123
123
|
write_file target, compiled
|
|
124
124
|
end
|
|
125
125
|
|
|
@@ -13,7 +13,16 @@ class Foreman::Export::Inittab < Foreman::Export::Base
|
|
|
13
13
|
1.upto(engine.formation[name]) do |num|
|
|
14
14
|
id = app.slice(0, 2).upcase + sprintf("%02d", index)
|
|
15
15
|
port = engine.port_for(process, num)
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
commands = []
|
|
18
|
+
commands << "cd #{engine.root}"
|
|
19
|
+
commands << "export PORT=#{port}"
|
|
20
|
+
engine.env.each_pair do |var, env|
|
|
21
|
+
commands << "export #{var.upcase}=#{shell_quote(env)}"
|
|
22
|
+
end
|
|
23
|
+
commands << "#{process.command} >> #{log}/#{name}-#{num}.log 2>&1"
|
|
24
|
+
|
|
25
|
+
inittab << "#{id}:4:respawn:/bin/su - #{user} -c '#{commands.join(";")}'"
|
|
17
26
|
index += 1
|
|
18
27
|
end
|
|
19
28
|
end
|
|
@@ -7,6 +7,8 @@ class Foreman::Export::Launchd < Foreman::Export::Base
|
|
|
7
7
|
super
|
|
8
8
|
engine.each_process do |name, process|
|
|
9
9
|
1.upto(engine.formation[name]) do |num|
|
|
10
|
+
port = engine.port_for(process, num)
|
|
11
|
+
command_args = process.command.split(" ")
|
|
10
12
|
write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding
|
|
11
13
|
end
|
|
12
14
|
end
|
data/lib/foreman/process.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require "foreman"
|
|
2
|
-
require "rubygems"
|
|
3
2
|
|
|
4
3
|
class Foreman::Process
|
|
5
4
|
|
|
@@ -21,6 +20,21 @@ class Foreman::Process
|
|
|
21
20
|
@options[:env] ||= {}
|
|
22
21
|
end
|
|
23
22
|
|
|
23
|
+
# Get environment-expanded command for a +Process+
|
|
24
|
+
#
|
|
25
|
+
# @param [Hash] custom_env ({}) Environment variables to merge with defaults
|
|
26
|
+
#
|
|
27
|
+
# @return [String] The expanded command
|
|
28
|
+
#
|
|
29
|
+
def expanded_command(custom_env={})
|
|
30
|
+
env = @options[:env].merge(custom_env)
|
|
31
|
+
expanded_command = command.dup
|
|
32
|
+
env.each do |key, val|
|
|
33
|
+
expanded_command.gsub!("$#{key}", val)
|
|
34
|
+
end
|
|
35
|
+
expanded_command
|
|
36
|
+
end
|
|
37
|
+
|
|
24
38
|
# Run a +Process+
|
|
25
39
|
#
|
|
26
40
|
# @param [Hash] options
|
|
@@ -31,18 +45,14 @@ class Foreman::Process
|
|
|
31
45
|
# @returns [Fixnum] pid The +pid+ of the process
|
|
32
46
|
#
|
|
33
47
|
def run(options={})
|
|
34
|
-
env =
|
|
48
|
+
env = @options[:env].merge(options[:env] || {})
|
|
35
49
|
output = options[:output] || $stdout
|
|
36
50
|
|
|
37
51
|
if Foreman.windows?
|
|
38
52
|
Dir.chdir(cwd) do
|
|
39
|
-
expanded_command
|
|
40
|
-
env.each do |key, val|
|
|
41
|
-
expanded_command.gsub!("$#{key}", val)
|
|
42
|
-
end
|
|
43
|
-
Process.spawn env, expanded_command, :out => output, :err => output
|
|
53
|
+
Process.spawn env, expanded_command(env), :out => output, :err => output
|
|
44
54
|
end
|
|
45
|
-
elsif Foreman.
|
|
55
|
+
elsif Foreman.jruby_18?
|
|
46
56
|
require "posix/spawn"
|
|
47
57
|
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
|
48
58
|
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
|
|
@@ -52,7 +62,7 @@ class Foreman::Process
|
|
|
52
62
|
$stderr.reopen output
|
|
53
63
|
env.each { |k,v| ENV[k] = v }
|
|
54
64
|
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
|
55
|
-
exec wrapped_command
|
|
65
|
+
Kernel.exec wrapped_command
|
|
56
66
|
end
|
|
57
67
|
else
|
|
58
68
|
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
|
@@ -60,6 +70,20 @@ class Foreman::Process
|
|
|
60
70
|
end
|
|
61
71
|
end
|
|
62
72
|
|
|
73
|
+
# Exec a +Process+
|
|
74
|
+
#
|
|
75
|
+
# @param [Hash] options
|
|
76
|
+
#
|
|
77
|
+
# @option options :env ({}) Environment variables to set for this execution
|
|
78
|
+
#
|
|
79
|
+
# @return Does not return
|
|
80
|
+
def exec(options={})
|
|
81
|
+
env = @options[:env].merge(options[:env] || {})
|
|
82
|
+
env.each { |k, v| ENV[k] = v }
|
|
83
|
+
Dir.chdir(cwd)
|
|
84
|
+
Kernel.exec expanded_command(env)
|
|
85
|
+
end
|
|
86
|
+
|
|
63
87
|
# Send a signal to this +Process+
|
|
64
88
|
#
|
|
65
89
|
# @param [String] signal The signal to send
|
data/lib/foreman/procfile.rb
CHANGED
data/lib/foreman/version.rb
CHANGED
data/man/foreman.1
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
|
3
3
|
.
|
|
4
|
-
.TH "FOREMAN" "1" "
|
|
4
|
+
.TH "FOREMAN" "1" "January 2013" "Foreman 0.61.0" "Foreman Manual"
|
|
5
5
|
.
|
|
6
6
|
.SH "NAME"
|
|
7
7
|
\fBforeman\fR \- manage Procfile\-based applications
|
|
@@ -90,7 +90,7 @@ Specify the user the application should be run as\. Defaults to the app name
|
|
|
90
90
|
These options control all modes of foreman\'s operation\.
|
|
91
91
|
.
|
|
92
92
|
.TP
|
|
93
|
-
\fB\-d\fR, \fB\-\-
|
|
93
|
+
\fB\-d\fR, \fB\-\-root\fR
|
|
94
94
|
Specify an alternate application root\. This defaults to the directory containing the Procfile\.
|
|
95
95
|
.
|
|
96
96
|
.TP
|
data/spec/foreman/cli_spec.rb
CHANGED
|
@@ -72,6 +72,15 @@ describe "Foreman::CLI", :fakefs do
|
|
|
72
72
|
it "includes the environment" do
|
|
73
73
|
forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
it "can run a command from the Procfile" do
|
|
77
|
+
forked_foreman("run -f #{resource_path("Procfile")} test").should == "testing\n"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "exits with the same exit code as the command" do
|
|
81
|
+
fork_and_get_exitstatus("run echo 1").should == 0
|
|
82
|
+
fork_and_get_exitstatus("run date 'invalid_date'").should == 1
|
|
83
|
+
end
|
|
75
84
|
end
|
|
76
85
|
|
|
77
86
|
describe "version" do
|
data/spec/foreman/engine_spec.rb
CHANGED
|
@@ -90,6 +90,14 @@ describe "Foreman::Engine", :fakefs do
|
|
|
90
90
|
subject.env["OTHER"].should == 'escaped"quote'
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
it "should handle multiline strings" do
|
|
94
|
+
File.open("/tmp/env", "w") do |f|
|
|
95
|
+
f.puts 'FOO="bar\nbaz"'
|
|
96
|
+
end
|
|
97
|
+
subject.load_env "/tmp/env"
|
|
98
|
+
subject.env["FOO"].should == "bar\nbaz"
|
|
99
|
+
end
|
|
100
|
+
|
|
93
101
|
it "should fail if specified and doesnt exist" do
|
|
94
102
|
lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT)
|
|
95
103
|
end
|
|
@@ -18,4 +18,14 @@ describe Foreman::Export::Launchd, :fakefs do
|
|
|
18
18
|
File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default")
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
context "with multiple command arguments" do
|
|
22
|
+
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", "charlie") }
|
|
23
|
+
|
|
24
|
+
it "splits each command argument" do
|
|
25
|
+
launchd.export
|
|
26
|
+
File.read("/tmp/init/app-alpha-1.plist").should == example_export_file("launchd/launchd-c.default")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
21
31
|
end
|
|
@@ -38,7 +38,7 @@ describe Foreman::Export::Upstart, :fakefs do
|
|
|
38
38
|
engine.env['KEY'] = 'd"\|d'
|
|
39
39
|
upstart.export
|
|
40
40
|
"foobarfoo".should include "bar"
|
|
41
|
-
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY=
|
|
41
|
+
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY=d\\"\\\\\\\|d/
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
context "with a formation" do
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# ----- foreman app processes -----
|
|
2
|
-
AP01:4:respawn:/bin/su - app -c 'PORT=5000
|
|
3
|
-
AP02:4:respawn:/bin/su - app -c 'PORT=5001
|
|
2
|
+
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
|
|
3
|
+
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5001;./alpha >> /var/log/app/alpha-2.log 2>&1'
|
|
4
4
|
# ----- end foreman app processes -----
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# ----- foreman app processes -----
|
|
2
|
-
AP01:4:respawn:/bin/su - app -c 'PORT=5000
|
|
3
|
-
AP02:4:respawn:/bin/su - app -c 'PORT=5100
|
|
2
|
+
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
|
|
3
|
+
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5100;./bravo >> /var/log/app/bravo-1.log 2>&1'
|
|
4
4
|
# ----- end foreman app processes -----
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
<dict>
|
|
5
5
|
<key>Label</key>
|
|
6
6
|
<string>app-alpha-1</string>
|
|
7
|
+
<key>EnvironmentVariables</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>PORT</key>
|
|
10
|
+
<string>5000</string>
|
|
11
|
+
</dict>
|
|
7
12
|
<key>ProgramArguments</key>
|
|
8
13
|
<array>
|
|
9
14
|
<string>./alpha</string>
|
|
@@ -12,6 +17,8 @@
|
|
|
12
17
|
<true/>
|
|
13
18
|
<key>RunAtLoad</key>
|
|
14
19
|
<true/>
|
|
20
|
+
<key>StandardOutPath</key>
|
|
21
|
+
<string>/var/log/app/app-alpha-1.log</string>
|
|
15
22
|
<key>StandardErrorPath</key>
|
|
16
23
|
<string>/var/log/app/app-alpha-1.log</string>
|
|
17
24
|
<key>UserName</key>
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
<dict>
|
|
5
5
|
<key>Label</key>
|
|
6
6
|
<string>app-bravo-1</string>
|
|
7
|
+
<key>EnvironmentVariables</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>PORT</key>
|
|
10
|
+
<string>5100</string>
|
|
11
|
+
</dict>
|
|
7
12
|
<key>ProgramArguments</key>
|
|
8
13
|
<array>
|
|
9
14
|
<string>./bravo</string>
|
|
@@ -12,6 +17,8 @@
|
|
|
12
17
|
<true/>
|
|
13
18
|
<key>RunAtLoad</key>
|
|
14
19
|
<true/>
|
|
20
|
+
<key>StandardOutPath</key>
|
|
21
|
+
<string>/var/log/app/app-bravo-1.log</string>
|
|
15
22
|
<key>StandardErrorPath</key>
|
|
16
23
|
<string>/var/log/app/app-bravo-1.log</string>
|
|
17
24
|
<key>UserName</key>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string>app-alpha-1</string>
|
|
7
|
+
<key>EnvironmentVariables</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>PORT</key>
|
|
10
|
+
<string>5000</string>
|
|
11
|
+
</dict>
|
|
12
|
+
<key>ProgramArguments</key>
|
|
13
|
+
<array>
|
|
14
|
+
<string>./alpha</string>
|
|
15
|
+
<string>charlie</string>
|
|
16
|
+
</array>
|
|
17
|
+
<key>KeepAlive</key>
|
|
18
|
+
<true/>
|
|
19
|
+
<key>RunAtLoad</key>
|
|
20
|
+
<true/>
|
|
21
|
+
<key>StandardOutPath</key>
|
|
22
|
+
<string>/var/log/app/app-alpha-1.log</string>
|
|
23
|
+
<key>StandardErrorPath</key>
|
|
24
|
+
<string>/var/log/app/app-alpha-1.log</string>
|
|
25
|
+
<key>UserName</key>
|
|
26
|
+
<string>app</string>
|
|
27
|
+
<key>WorkingDirectory</key>
|
|
28
|
+
<string>/tmp/app</string>
|
|
29
|
+
</dict>
|
|
30
|
+
</plist>
|
|
@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
|
|
|
8
8
|
stderr_logfile=/var/log/app/alpha-1.error.log
|
|
9
9
|
user=app
|
|
10
10
|
directory=/tmp/app
|
|
11
|
-
environment=PORT=
|
|
11
|
+
environment=PORT=5000
|
|
12
12
|
[program:app-bravo-1]
|
|
13
13
|
command=./bravo
|
|
14
14
|
autostart=true
|
|
@@ -18,7 +18,7 @@ stdout_logfile=/var/log/app/bravo-1.log
|
|
|
18
18
|
stderr_logfile=/var/log/app/bravo-1.error.log
|
|
19
19
|
user=app
|
|
20
20
|
directory=/tmp/app
|
|
21
|
-
environment=PORT=
|
|
21
|
+
environment=PORT=5100
|
|
22
22
|
|
|
23
23
|
[group:app]
|
|
24
24
|
programs=app-alpha-1,app-bravo-1
|
|
@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
|
|
|
8
8
|
stderr_logfile=/var/log/app/alpha-1.error.log
|
|
9
9
|
user=app
|
|
10
10
|
directory=/tmp/app
|
|
11
|
-
environment=PORT=
|
|
11
|
+
environment=PORT=5000
|
|
12
12
|
[program:app-alpha-2]
|
|
13
13
|
command=./alpha
|
|
14
14
|
autostart=true
|
|
@@ -18,7 +18,7 @@ stdout_logfile=/var/log/app/alpha-2.log
|
|
|
18
18
|
stderr_logfile=/var/log/app/alpha-2.error.log
|
|
19
19
|
user=app
|
|
20
20
|
directory=/tmp/app
|
|
21
|
-
environment=PORT=
|
|
21
|
+
environment=PORT=5001
|
|
22
22
|
|
|
23
23
|
[group:app]
|
|
24
24
|
programs=app-alpha-1,app-alpha-2
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require "rubygems"
|
|
2
|
-
|
|
3
1
|
require "simplecov"
|
|
4
2
|
SimpleCov.start do
|
|
5
3
|
add_filter "/spec/"
|
|
@@ -58,6 +56,12 @@ def fork_and_capture(&blk)
|
|
|
58
56
|
end
|
|
59
57
|
end
|
|
60
58
|
|
|
59
|
+
def fork_and_get_exitstatus(args)
|
|
60
|
+
pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
|
|
61
|
+
Process.wait(pid)
|
|
62
|
+
$?.exitstatus
|
|
63
|
+
end
|
|
64
|
+
|
|
61
65
|
def mock_exit(&block)
|
|
62
66
|
block.should raise_error(SystemExit)
|
|
63
67
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.61.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: java
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2013-01-14 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: thor
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70341187029940 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,10 +21,10 @@ dependencies:
|
|
|
21
21
|
version: 0.13.6
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70341187029940
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: posix-spawn
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70341187029340 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ~>
|
|
@@ -32,7 +32,7 @@ dependencies:
|
|
|
32
32
|
version: 0.3.6
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70341187029340
|
|
36
36
|
description: Process manager for applications with multiple components
|
|
37
37
|
email: ddollar@gmail.com
|
|
38
38
|
executables:
|
|
@@ -59,6 +59,7 @@ files:
|
|
|
59
59
|
- data/export/upstart/master.conf.erb
|
|
60
60
|
- data/export/upstart/process.conf.erb
|
|
61
61
|
- data/export/upstart/process_master.conf.erb
|
|
62
|
+
- lib/foreman/capistrano.rb
|
|
62
63
|
- lib/foreman/cli.rb
|
|
63
64
|
- lib/foreman/distribution.rb
|
|
64
65
|
- lib/foreman/engine/cli.rb
|
|
@@ -103,6 +104,7 @@ files:
|
|
|
103
104
|
- spec/resources/export/inittab/inittab.default
|
|
104
105
|
- spec/resources/export/launchd/launchd-a.default
|
|
105
106
|
- spec/resources/export/launchd/launchd-b.default
|
|
107
|
+
- spec/resources/export/launchd/launchd-c.default
|
|
106
108
|
- spec/resources/export/runit/app-alpha-1/log/run
|
|
107
109
|
- spec/resources/export/runit/app-alpha-1/run
|
|
108
110
|
- spec/resources/export/runit/app-alpha-2/log/run
|
|
@@ -121,7 +123,8 @@ files:
|
|
|
121
123
|
- spec/spec_helper.rb
|
|
122
124
|
- man/foreman.1
|
|
123
125
|
homepage: http://github.com/ddollar/foreman
|
|
124
|
-
licenses:
|
|
126
|
+
licenses:
|
|
127
|
+
- MIT
|
|
125
128
|
post_install_message:
|
|
126
129
|
rdoc_options: []
|
|
127
130
|
require_paths:
|