foreman 0.50.0-mingw32 → 0.61.0-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|