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.
@@ -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
- while getopts ":hd:" OPT; do
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
- <string><%= process.command %></string>
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>
@@ -6,3 +6,11 @@ bash << "EOF"
6
6
  EOF
7
7
 
8
8
  end script
9
+
10
+ start on (started network-interface
11
+ or started network-manager
12
+ or started networking)
13
+
14
+ stop on (stopping network-interface
15
+ or stopping network-manager
16
+ or stopping networking)
@@ -8,8 +8,8 @@ module Foreman
8
8
  File.expand_path("../../bin/foreman-runner", __FILE__)
9
9
  end
10
10
 
11
- def self.jruby?
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
@@ -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
- begin
79
- exec engine.env, args.shelljoin
80
- rescue Errno::EACCES
81
- error "not executable: #{args.first}"
82
- rescue Errno::ENOENT
83
- error "command not found: #{args.first}"
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[:app_root], "Procfile"))
143
+ when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
129
144
  else "Procfile"
130
145
  end
131
146
  end
@@ -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.pid
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 => { "PORT" => port_for(process, n).to_s })
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
- (IO.select(@readers.values).first || []).each do |reader|
275
- data = reader.gets
276
- output_with_mutex name_for(@readers.invert[reader]), data
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(5) do
316
+ Timeout.timeout(options[:timeout]) do
306
317
  watch_for_termination while @running.length > 0
307
318
  end
308
319
  rescue Timeout::Error
@@ -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 true if Foreman.windows?
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 intense_cyan intense_yellow
48
- intense_green intense_magenta intense_red, intense_blue )
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
- require "win32console" if Foreman.windows?
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.chomp.split("\n").each do |message|
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"] = "intense_white"
92
+ colors["system"] = "bright_white"
94
93
  colors
95
94
  end
96
95
 
@@ -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
- when /\A"(.*)"\z/ then ax[key] = $1.gsub(/\\(.)/, '\1')
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
@@ -91,7 +91,7 @@ private ######################################################################
91
91
  end
92
92
 
93
93
  def shell_quote(value)
94
- '"' + Shellwords.escape(value) + '"'
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
- inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log}/#{name}-#{num}.log 2>&1'"
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
@@ -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 = options[:env] ? @options[:env].merge(options[:env]) : @options[: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 = command.dup
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
- Dir.chdir(cwd) do
52
- fork do
53
- $stdout.reopen output
54
- $stderr.reopen output
55
- env.each { |k,v| ENV[k] = v }
56
- exec command
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
- Dir.chdir(cwd) do
61
- Process.spawn env, command, :out => output, :err => output
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
- private
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
@@ -82,7 +82,7 @@ class Foreman::Procfile
82
82
  private
83
83
 
84
84
  def parse(filename)
85
- File.read(filename).split("\n").map do |line|
85
+ File.read(filename).gsub("\r\n","\n").split("\n").map do |line|
86
86
  if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
87
87
  [$1, $2]
88
88
  end
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.50.0"
3
+ VERSION = "0.61.0"
4
4
 
5
5
  end
@@ -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" "July 2012" "Foreman 0.50.0" "Foreman Manual"
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\-\-directory\fR
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
@@ -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
@@ -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="d\\"\\\\\\\|d/
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 ./alpha >> /var/log/app/alpha-1.log 2>&1'
3
- AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1'
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 ./alpha >> /var/log/app/alpha-1.log 2>&1'
3
- AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1'
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="5000"
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="5100"
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="5000"
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="5001"
21
+ environment=PORT=5001
22
22
 
23
23
  [group:app]
24
24
  programs=app-alpha-1,app-alpha-2
@@ -6,3 +6,11 @@ bash << "EOF"
6
6
  EOF
7
7
 
8
8
  end script
9
+
10
+ start on (started network-interface
11
+ or started network-manager
12
+ or started networking)
13
+
14
+ stop on (stopping network-interface
15
+ or stopping network-manager
16
+ or stopping networking)
@@ -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.50.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: 2012-07-11 00:00:00.000000000 Z
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: &70204077470000 !ruby/object:Gem::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: *70204077470000
24
+ version_requirements: *70171274222360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: win32console
27
- requirement: &70204077467940 !ruby/object:Gem::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: *70204077467940
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: