foreman 0.50.0-mingw32 → 0.61.0-mingw32
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 +11 -2
- data/data/export/launchd/launchd.plist.erb +12 -1
- data/data/export/upstart/master.conf.erb +8 -0
- data/lib/foreman.rb +2 -2
- data/lib/foreman/capistrano.rb +54 -0
- data/lib/foreman/cli.rb +22 -7
- data/lib/foreman/engine.rb +17 -6
- data/lib/foreman/engine/cli.rb +7 -8
- 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 +48 -25
- 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/resources/export/upstart/app.conf +8 -0
- data/spec/spec_helper.rb +6 -2
- metadata +10 -7
data/bin/foreman-runner
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
#
|
3
|
-
#/ Usage: foreman-runner [-d <dir>] <command> [<args>...]
|
3
|
+
#/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...]
|
4
4
|
#/
|
5
5
|
#/ Run a command with exec, optionally changing directory first
|
6
6
|
|
@@ -16,9 +16,12 @@ usage() {
|
|
16
16
|
exit
|
17
17
|
}
|
18
18
|
|
19
|
-
|
19
|
+
read_profile=""
|
20
|
+
|
21
|
+
while getopts ":hd:p" OPT; do
|
20
22
|
case $OPT in
|
21
23
|
d) cd "$OPTARG" ;;
|
24
|
+
p) read_profile="1" ;;
|
22
25
|
h) usage ;;
|
23
26
|
\?) error "invalid option: -$OPTARG" ;;
|
24
27
|
:) error "option -$OPTARG requires an argument" ;;
|
@@ -29,4 +32,10 @@ shift $((OPTIND-1))
|
|
29
32
|
|
30
33
|
[ -z "$1" ] && usage
|
31
34
|
|
35
|
+
if [ "$read_profile" = "1" ]; then
|
36
|
+
if [ -f .profile ]; then
|
37
|
+
. .profile
|
38
|
+
fi
|
39
|
+
fi
|
40
|
+
|
32
41
|
exec "$@"
|
@@ -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,13 +76,27 @@ class Foreman::CLI < Thor
|
|
75
76
|
|
76
77
|
def run(*args)
|
77
78
|
load_environment!
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
|
80
|
+
if File.exist?(procfile)
|
81
|
+
engine.load_procfile(procfile)
|
82
|
+
end
|
83
|
+
|
84
|
+
pid = fork do
|
85
|
+
begin
|
86
|
+
engine.env.each { |k,v| ENV[k] = v }
|
87
|
+
if args.size == 1 && process = engine.process(args.first)
|
88
|
+
process.exec(:env => engine.env)
|
89
|
+
else
|
90
|
+
exec args.shelljoin
|
91
|
+
end
|
92
|
+
rescue Errno::EACCES
|
93
|
+
error "not executable: #{args.first}"
|
94
|
+
rescue Errno::ENOENT
|
95
|
+
error "command not found: #{args.first}"
|
96
|
+
end
|
84
97
|
end
|
98
|
+
Process.wait(pid)
|
99
|
+
exit $?.exitstatus
|
85
100
|
end
|
86
101
|
|
87
102
|
desc "version", "Display Foreman gem version"
|
@@ -125,7 +140,7 @@ private ######################################################################
|
|
125
140
|
def procfile
|
126
141
|
case
|
127
142
|
when options[:procfile] then options[:procfile]
|
128
|
-
when options[:root] then File.expand_path(File.join(options[:
|
143
|
+
when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
|
129
144
|
else "Procfile"
|
130
145
|
end
|
131
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
|
@@ -256,7 +260,9 @@ private
|
|
256
260
|
1.upto(formation[@names[process]]) do |n|
|
257
261
|
reader, writer = create_pipe
|
258
262
|
begin
|
259
|
-
pid = process.run(:output => writer, :env => {
|
263
|
+
pid = process.run(:output => writer, :env => {
|
264
|
+
"PORT" => port_for(process, n).to_s
|
265
|
+
})
|
260
266
|
writer.puts "started with pid #{pid}"
|
261
267
|
rescue Errno::ENOENT
|
262
268
|
writer.puts "unknown command: #{process.command}"
|
@@ -271,9 +277,14 @@ private
|
|
271
277
|
Thread.new do
|
272
278
|
begin
|
273
279
|
loop do
|
274
|
-
|
275
|
-
|
276
|
-
|
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
|
277
288
|
end
|
278
289
|
end
|
279
290
|
rescue Exception => ex
|
@@ -302,7 +313,7 @@ private
|
|
302
313
|
system "sending SIGTERM to all processes"
|
303
314
|
killall "SIGTERM"
|
304
315
|
end
|
305
|
-
Timeout.timeout(
|
316
|
+
Timeout.timeout(options[:timeout]) do
|
306
317
|
watch_for_termination while @running.length > 0
|
307
318
|
end
|
308
319
|
rescue Timeout::Error
|
data/lib/foreman/engine/cli.rb
CHANGED
@@ -31,7 +31,7 @@ class Foreman::Engine::CLI < Foreman::Engine
|
|
31
31
|
|
32
32
|
def color?
|
33
33
|
return true if @@color_force
|
34
|
-
return
|
34
|
+
return false if Foreman.windows?
|
35
35
|
return false unless self.respond_to?(:isatty)
|
36
36
|
self.isatty && ENV["TERM"]
|
37
37
|
end
|
@@ -44,18 +44,17 @@ 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
|
52
|
-
proctitle "foreman: master"
|
53
|
-
|
54
|
-
Color.enable($stdout, options[:color]) unless $stdout.respond_to?(:color?)
|
52
|
+
proctitle "foreman: master" unless Foreman.windows?
|
53
|
+
Color.enable($stdout, options[:color])
|
55
54
|
end
|
56
55
|
|
57
56
|
def output(name, data)
|
58
|
-
data.to_s.
|
57
|
+
data.to_s.lines.map(&:chomp).each do |message|
|
59
58
|
output = ""
|
60
59
|
output += $stdout.color(@colors[name.split(".").first].to_sym)
|
61
60
|
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
@@ -90,7 +89,7 @@ private
|
|
90
89
|
@names.values.each_with_index do |name, index|
|
91
90
|
colors[name] = FOREMAN_COLORS[index % FOREMAN_COLORS.length]
|
92
91
|
end
|
93
|
-
colors["system"] = "
|
92
|
+
colors["system"] = "bright_white"
|
94
93
|
colors
|
95
94
|
end
|
96
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,38 +45,45 @@ 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
|
44
|
-
end
|
45
|
-
elsif Foreman.jruby?
|
46
|
-
Dir.chdir(cwd) do
|
47
|
-
require "posix/spawn"
|
48
|
-
POSIX::Spawn.spawn env, command, :out => output, :err => output
|
53
|
+
Process.spawn env, expanded_command(env), :out => output, :err => output
|
49
54
|
end
|
55
|
+
elsif Foreman.jruby_18?
|
56
|
+
require "posix/spawn"
|
57
|
+
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
58
|
+
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
|
50
59
|
elsif Foreman.ruby_18?
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
60
|
+
fork do
|
61
|
+
$stdout.reopen output
|
62
|
+
$stderr.reopen output
|
63
|
+
env.each { |k,v| ENV[k] = v }
|
64
|
+
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
65
|
+
Kernel.exec wrapped_command
|
58
66
|
end
|
59
67
|
else
|
60
|
-
|
61
|
-
|
62
|
-
end
|
68
|
+
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
69
|
+
Process.spawn env, wrapped_command, :out => output, :err => output
|
63
70
|
end
|
64
71
|
end
|
65
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
|
+
|
66
87
|
# Send a signal to this +Process+
|
67
88
|
#
|
68
89
|
# @param [String] signal The signal to send
|
@@ -93,10 +114,12 @@ class Foreman::Process
|
|
93
114
|
!alive?
|
94
115
|
end
|
95
116
|
|
96
|
-
|
97
|
-
|
117
|
+
# Returns the working directory for this +Process+
|
118
|
+
#
|
119
|
+
# @returns [String]
|
120
|
+
#
|
98
121
|
def cwd
|
99
|
-
@options[:cwd] || "."
|
122
|
+
File.expand_path(@options[:cwd] || ".")
|
100
123
|
end
|
101
124
|
|
102
125
|
end
|
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: mingw32
|
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: &70171274222360 !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: *70171274222360
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: win32console
|
27
|
-
requirement: &
|
27
|
+
requirement: &70171274248800 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 1.3.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70171274248800
|
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:
|