foreman 0.48.0.pre1-java → 0.50.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/data/example/spawnee +1 -1
- data/lib/foreman.rb +4 -0
- data/lib/foreman/cli.rb +13 -6
- data/lib/foreman/engine.rb +41 -16
- data/lib/foreman/engine/cli.rb +9 -2
- data/lib/foreman/export.rb +1 -1
- data/lib/foreman/export/base.rb +65 -8
- data/lib/foreman/process.rb +21 -4
- data/lib/foreman/version.rb +1 -1
- data/man/foreman.1 +1 -1
- data/spec/foreman/cli_spec.rb +10 -0
- data/spec/spec_helper.rb +0 -1
- metadata +9 -9
data/data/example/spawnee
CHANGED
data/lib/foreman.rb
CHANGED
@@ -12,6 +12,10 @@ module Foreman
|
|
12
12
|
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
|
13
13
|
end
|
14
14
|
|
15
|
+
def self.ruby_18?
|
16
|
+
defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
|
17
|
+
end
|
18
|
+
|
15
19
|
def self.windows?
|
16
20
|
defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
|
17
21
|
end
|
data/lib/foreman/cli.rb
CHANGED
@@ -3,18 +3,23 @@ require "foreman/helpers"
|
|
3
3
|
require "foreman/engine"
|
4
4
|
require "foreman/engine/cli"
|
5
5
|
require "foreman/export"
|
6
|
+
require "foreman/version"
|
6
7
|
require "shellwords"
|
8
|
+
require "yaml"
|
7
9
|
require "thor"
|
8
10
|
|
9
11
|
class Foreman::CLI < Thor
|
10
12
|
|
11
13
|
include Foreman::Helpers
|
12
14
|
|
15
|
+
map ["-v", "--version"] => :version
|
16
|
+
|
13
17
|
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
14
18
|
class_option :root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
|
15
19
|
|
16
20
|
desc "start [PROCESS]", "Start the application (or a specific PROCESS)"
|
17
21
|
|
22
|
+
method_option :color, :type => :boolean, :aliases => "-c", :desc => "Force color to be enabled"
|
18
23
|
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
19
24
|
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
|
20
25
|
method_option :port, :type => :numeric, :aliases => "-p"
|
@@ -79,15 +84,17 @@ class Foreman::CLI < Thor
|
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
87
|
+
desc "version", "Display Foreman gem version"
|
88
|
+
|
89
|
+
def version
|
90
|
+
puts Foreman::VERSION
|
91
|
+
end
|
92
|
+
|
82
93
|
no_tasks do
|
83
94
|
def engine
|
84
95
|
@engine ||= begin
|
85
96
|
engine_class = Foreman::Engine::CLI
|
86
|
-
engine = engine_class.new(
|
87
|
-
:formation => options[:formation],
|
88
|
-
:port => options[:port],
|
89
|
-
:root => options[:root]
|
90
|
-
)
|
97
|
+
engine = engine_class.new(options)
|
91
98
|
engine
|
92
99
|
end
|
93
100
|
end
|
@@ -126,7 +133,7 @@ private ######################################################################
|
|
126
133
|
def options
|
127
134
|
original_options = super
|
128
135
|
return original_options unless File.exists?(".foreman")
|
129
|
-
defaults = YAML::load_file(".foreman") || {}
|
136
|
+
defaults = ::YAML::load_file(".foreman") || {}
|
130
137
|
Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
|
131
138
|
end
|
132
139
|
|
data/lib/foreman/engine.rb
CHANGED
@@ -24,7 +24,7 @@ class Foreman::Engine
|
|
24
24
|
def initialize(options={})
|
25
25
|
@options = options.dup
|
26
26
|
|
27
|
-
@options[:formation] ||= "all=1"
|
27
|
+
@options[:formation] ||= (options[:concurrency] || "all=1")
|
28
28
|
|
29
29
|
@env = {}
|
30
30
|
@mutex = Mutex.new
|
@@ -39,7 +39,7 @@ class Foreman::Engine
|
|
39
39
|
def start
|
40
40
|
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
|
41
41
|
trap("INT") { puts "SIGINT received"; terminate_gracefully }
|
42
|
-
trap("HUP") { puts "SIGHUP received"; terminate_gracefully }
|
42
|
+
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP'
|
43
43
|
|
44
44
|
startup
|
45
45
|
spawn_processes
|
@@ -99,10 +99,17 @@ class Foreman::Engine
|
|
99
99
|
# @param [String] signal The signal to send to each process
|
100
100
|
#
|
101
101
|
def killall(signal="SIGTERM")
|
102
|
-
|
103
|
-
|
102
|
+
if Foreman.windows?
|
103
|
+
@running.each do |pid, (process, index)|
|
104
|
+
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
105
|
+
begin
|
106
|
+
Process.kill(signal, pid)
|
107
|
+
rescue Errno::ESRCH, Errno::EPERM
|
108
|
+
end
|
109
|
+
end
|
110
|
+
else
|
104
111
|
begin
|
105
|
-
Process.kill
|
112
|
+
Process.kill "-#{signal}", Process.pid
|
106
113
|
rescue Errno::ESRCH, Errno::EPERM
|
107
114
|
end
|
108
115
|
end
|
@@ -154,11 +161,28 @@ class Foreman::Engine
|
|
154
161
|
#
|
155
162
|
# @param [Foreman::Process] process A +Process+ associated with this engine
|
156
163
|
# @param [Fixnum] instance The instance of the process
|
157
|
-
#
|
164
|
+
#
|
158
165
|
# @returns [Fixnum] port The port to use for this instance of this process
|
159
166
|
#
|
160
|
-
def port_for(process, instance)
|
161
|
-
|
167
|
+
def port_for(process, instance, base=nil)
|
168
|
+
if base
|
169
|
+
base + (@processes.index(process.process) * 100) + (instance - 1)
|
170
|
+
else
|
171
|
+
base_port + (@processes.index(process) * 100) + (instance - 1)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Get the base port for this foreman instance
|
176
|
+
#
|
177
|
+
# @returns [Fixnum] port The base port
|
178
|
+
#
|
179
|
+
def base_port
|
180
|
+
(options[:port] || env["PORT"] || ENV["PORT"] || 5000).to_i
|
181
|
+
end
|
182
|
+
|
183
|
+
# deprecated
|
184
|
+
def environment
|
185
|
+
env
|
162
186
|
end
|
163
187
|
|
164
188
|
private
|
@@ -179,10 +203,6 @@ private
|
|
179
203
|
|
180
204
|
## Helpers ##########################################################
|
181
205
|
|
182
|
-
def base_port
|
183
|
-
(options[:port] || env["PORT"] || ENV["PORT"] || 5000).to_i
|
184
|
-
end
|
185
|
-
|
186
206
|
def create_pipe
|
187
207
|
IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
188
208
|
end
|
@@ -193,7 +213,7 @@ private
|
|
193
213
|
end
|
194
214
|
|
195
215
|
def parse_formation(formation)
|
196
|
-
pairs =
|
216
|
+
pairs = formation.to_s.gsub(/\s/, "").split(",")
|
197
217
|
|
198
218
|
pairs.inject(Hash.new(0)) do |ax, pair|
|
199
219
|
process, amount = pair.split("=")
|
@@ -253,7 +273,7 @@ private
|
|
253
273
|
loop do
|
254
274
|
(IO.select(@readers.values).first || []).each do |reader|
|
255
275
|
data = reader.gets
|
256
|
-
output_with_mutex name_for(@readers.
|
276
|
+
output_with_mutex name_for(@readers.invert[reader]), data
|
257
277
|
end
|
258
278
|
end
|
259
279
|
rescue Exception => ex
|
@@ -275,8 +295,13 @@ private
|
|
275
295
|
def terminate_gracefully
|
276
296
|
return if @terminating
|
277
297
|
@terminating = true
|
278
|
-
|
279
|
-
|
298
|
+
if Foreman.windows?
|
299
|
+
system "sending SIGKILL to all processes"
|
300
|
+
killall "SIGKILL"
|
301
|
+
else
|
302
|
+
system "sending SIGTERM to all processes"
|
303
|
+
killall "SIGTERM"
|
304
|
+
end
|
280
305
|
Timeout.timeout(5) do
|
281
306
|
watch_for_termination while @running.length > 0
|
282
307
|
end
|
data/lib/foreman/engine/cli.rb
CHANGED
@@ -24,11 +24,14 @@ class Foreman::Engine::CLI < Foreman::Engine
|
|
24
24
|
:bright_white => 37,
|
25
25
|
}
|
26
26
|
|
27
|
-
def self.enable(io)
|
27
|
+
def self.enable(io, force=false)
|
28
28
|
io.extend(self)
|
29
|
+
@@color_force = force
|
29
30
|
end
|
30
31
|
|
31
32
|
def color?
|
33
|
+
return true if @@color_force
|
34
|
+
return true if Foreman.windows?
|
32
35
|
return false unless self.respond_to?(:isatty)
|
33
36
|
self.isatty && ENV["TERM"]
|
34
37
|
end
|
@@ -47,18 +50,22 @@ class Foreman::Engine::CLI < Foreman::Engine
|
|
47
50
|
def startup
|
48
51
|
@colors = map_colors
|
49
52
|
proctitle "foreman: master"
|
53
|
+
require "win32console" if Foreman.windows?
|
54
|
+
Color.enable($stdout, options[:color]) unless $stdout.respond_to?(:color?)
|
50
55
|
end
|
51
56
|
|
52
57
|
def output(name, data)
|
53
58
|
data.to_s.chomp.split("\n").each do |message|
|
54
|
-
Color.enable($stdout) unless $stdout.respond_to?(:color?)
|
55
59
|
output = ""
|
56
60
|
output += $stdout.color(@colors[name.split(".").first].to_sym)
|
57
61
|
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
58
62
|
output += $stdout.color(:reset)
|
59
63
|
output += message
|
60
64
|
$stdout.puts output
|
65
|
+
$stdout.flush
|
61
66
|
end
|
67
|
+
rescue Errno::EPIPE
|
68
|
+
terminate_gracefully
|
62
69
|
end
|
63
70
|
|
64
71
|
def shutdown
|
data/lib/foreman/export.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "foreman"
|
2
2
|
require "foreman/helpers"
|
3
|
+
require "pathname"
|
3
4
|
|
4
5
|
module Foreman::Export
|
5
6
|
extend Foreman::Helpers
|
@@ -31,4 +32,3 @@ require "foreman/export/bluepill"
|
|
31
32
|
require "foreman/export/runit"
|
32
33
|
require "foreman/export/supervisord"
|
33
34
|
require "foreman/export/launchd"
|
34
|
-
|
data/lib/foreman/export/base.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require "foreman/export"
|
2
|
+
require "ostruct"
|
3
|
+
require "pathname"
|
2
4
|
require "shellwords"
|
3
5
|
|
4
6
|
class Foreman::Export::Base
|
@@ -8,11 +10,37 @@ class Foreman::Export::Base
|
|
8
10
|
attr_reader :options
|
9
11
|
attr_reader :formation
|
10
12
|
|
13
|
+
# deprecated
|
14
|
+
attr_reader :port
|
15
|
+
|
11
16
|
def initialize(location, engine, options={})
|
12
17
|
@location = location
|
13
18
|
@engine = engine
|
14
19
|
@options = options.dup
|
15
20
|
@formation = engine.formation
|
21
|
+
|
22
|
+
# deprecated
|
23
|
+
def port
|
24
|
+
Foreman::Export::Base.warn_deprecation!
|
25
|
+
engine.base_port
|
26
|
+
end
|
27
|
+
|
28
|
+
# deprecated
|
29
|
+
def template
|
30
|
+
Foreman::Export::Base.warn_deprecation!
|
31
|
+
options[:template]
|
32
|
+
end
|
33
|
+
|
34
|
+
# deprecated
|
35
|
+
def @engine.procfile
|
36
|
+
Foreman::Export::Base.warn_deprecation!
|
37
|
+
@processes.map do |process|
|
38
|
+
OpenStruct.new(
|
39
|
+
:name => @names[process],
|
40
|
+
:process => process
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
16
44
|
end
|
17
45
|
|
18
46
|
def export
|
@@ -36,6 +64,18 @@ class Foreman::Export::Base
|
|
36
64
|
|
37
65
|
private ######################################################################
|
38
66
|
|
67
|
+
def self.warn_deprecation!
|
68
|
+
@@deprecation_warned ||= false
|
69
|
+
return if @@deprecation_warned
|
70
|
+
puts "WARNING: Using deprecated exporter interface. Please update your exporter"
|
71
|
+
puts "the interface shown in the upstart exporter:"
|
72
|
+
puts
|
73
|
+
puts "https://github.com/ddollar/foreman/blob/master/lib/foreman/export/upstart.rb"
|
74
|
+
puts "https://github.com/ddollar/foreman/blob/master/data/export/upstart/process.conf.erb"
|
75
|
+
puts
|
76
|
+
@@deprecation_warned = true
|
77
|
+
end
|
78
|
+
|
39
79
|
def error(message)
|
40
80
|
raise Foreman::Export::Exception.new(message)
|
41
81
|
end
|
@@ -54,13 +94,28 @@ private ######################################################################
|
|
54
94
|
'"' + Shellwords.escape(value) + '"'
|
55
95
|
end
|
56
96
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
97
|
+
# deprecated
|
98
|
+
def old_export_template(exporter, file, template_root)
|
99
|
+
if template_root && File.exist?(file_path = File.join(template_root, file))
|
100
|
+
File.read(file_path)
|
101
|
+
elsif File.exist?(file_path = File.expand_path(File.join("~/.foreman/templates", file)))
|
102
|
+
File.read(file_path)
|
103
|
+
else
|
104
|
+
File.read(File.expand_path("../../../../data/export/#{exporter}/#{file}", __FILE__))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def export_template(name, file=nil, template_root=nil)
|
109
|
+
if file && template_root
|
110
|
+
old_export_template name, file, template_root
|
111
|
+
else
|
112
|
+
name_without_first = name.split("/")[1..-1].join("/")
|
113
|
+
matchers = []
|
114
|
+
matchers << File.join(options[:template], name_without_first) if options[:template]
|
115
|
+
matchers << File.expand_path("~/.foreman/templates/#{name}")
|
116
|
+
matchers << File.expand_path("../../../../data/export/#{name}", __FILE__)
|
117
|
+
File.read(matchers.detect { |m| File.exists?(m) })
|
118
|
+
end
|
64
119
|
end
|
65
120
|
|
66
121
|
def write_template(name, target, binding)
|
@@ -81,7 +136,9 @@ private ######################################################################
|
|
81
136
|
def write_file(filename, contents)
|
82
137
|
say "writing: #{filename}"
|
83
138
|
|
84
|
-
File.
|
139
|
+
filename = File.join(location, filename) unless Pathname.new(filename).absolute?
|
140
|
+
|
141
|
+
File.open(filename, "w") do |file|
|
85
142
|
file.puts contents
|
86
143
|
end
|
87
144
|
end
|
data/lib/foreman/process.rb
CHANGED
@@ -36,16 +36,29 @@ class Foreman::Process
|
|
36
36
|
|
37
37
|
if Foreman.windows?
|
38
38
|
Dir.chdir(cwd) do
|
39
|
-
|
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
|
40
44
|
end
|
41
45
|
elsif Foreman.jruby?
|
42
46
|
Dir.chdir(cwd) do
|
43
47
|
require "posix/spawn"
|
44
|
-
POSIX::Spawn.spawn env, command, :out => output, :err => output
|
48
|
+
POSIX::Spawn.spawn env, command, :out => output, :err => output
|
49
|
+
end
|
50
|
+
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
|
45
58
|
end
|
46
59
|
else
|
47
60
|
Dir.chdir(cwd) do
|
48
|
-
Process.spawn env, command, :out => output, :err => output
|
61
|
+
Process.spawn env, command, :out => output, :err => output
|
49
62
|
end
|
50
63
|
end
|
51
64
|
end
|
@@ -55,7 +68,11 @@ class Foreman::Process
|
|
55
68
|
# @param [String] signal The signal to send
|
56
69
|
#
|
57
70
|
def kill(signal)
|
58
|
-
|
71
|
+
if Foreman.windows?
|
72
|
+
pid && Process.kill(signal, pid)
|
73
|
+
else
|
74
|
+
pid && Process.kill("-#{signal}", pid)
|
75
|
+
end
|
59
76
|
rescue Errno::ESRCH
|
60
77
|
false
|
61
78
|
end
|
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" "July 2012" "Foreman 0.50.0" "Foreman Manual"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBforeman\fR \- manage Procfile\-based applications
|
data/spec/foreman/cli_spec.rb
CHANGED
@@ -74,4 +74,14 @@ describe "Foreman::CLI", :fakefs do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
describe "version" do
|
78
|
+
it "displays gem version" do
|
79
|
+
foreman("version").chomp.should == Foreman::VERSION
|
80
|
+
end
|
81
|
+
|
82
|
+
it "displays gem version on shortcut command" do
|
83
|
+
foreman("-v").chomp.should == Foreman::VERSION
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
77
87
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.50.0
|
5
|
+
prerelease:
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- David Dollar
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70276765578980 !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: *70276765578980
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: posix-spawn
|
27
|
-
requirement: &
|
27
|
+
requirement: &70276765577720 !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: *70276765577720
|
36
36
|
description: Process manager for applications with multiple components
|
37
37
|
email: ddollar@gmail.com
|
38
38
|
executables:
|
@@ -135,9 +135,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
136
|
none: false
|
137
137
|
requirements:
|
138
|
-
- - ! '
|
138
|
+
- - ! '>='
|
139
139
|
- !ruby/object:Gem::Version
|
140
|
-
version:
|
140
|
+
version: '0'
|
141
141
|
requirements: []
|
142
142
|
rubyforge_project:
|
143
143
|
rubygems_version: 1.8.11
|