foreman 0.23.1 → 0.24.0

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.
@@ -1,2 +1,2 @@
1
1
  ticker: ruby ./ticker $PORT
2
- error : ruby ./error
2
+ error: ruby ./error
@@ -3,7 +3,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
3
3
  app.uid = "<%= user %>"
4
4
  app.gid = "<%= user %>"
5
5
 
6
- <% engine.processes.values.each do |process| %>
6
+ <% engine.processes.each do |process| %>
7
7
  <% 1.upto(concurrency[process.name]) do |num| %>
8
8
  <% port = engine.port_for(process, num, options[:port]) %>
9
9
  app.process("<%= process.name %>-<%=num%>") do |process|
@@ -24,4 +24,4 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
24
24
  end
25
25
  <% end %>
26
26
  <% end %>
27
- end
27
+ end
data/lib/foreman/cli.rb CHANGED
@@ -53,9 +53,8 @@ class Foreman::CLI < Thor
53
53
  desc "check", "Validate your application's Procfile"
54
54
 
55
55
  def check
56
- processes = engine.processes_in_order.map { |p| p.first }
57
- error "no processes defined" unless processes.length > 0
58
- display "valid procfile detected (#{processes.join(', ')})"
56
+ error "no processes defined" unless engine.processes.length > 0
57
+ display "valid procfile detected (#{engine.processes.map(&:name).join(', ')})"
59
58
  end
60
59
 
61
60
  private ######################################################################
@@ -1,5 +1,6 @@
1
1
  require "foreman"
2
2
  require "foreman/process"
3
+ require "foreman/procfile"
3
4
  require "foreman/utils"
4
5
  require "pty"
5
6
  require "tempfile"
@@ -19,45 +20,17 @@ class Foreman::Engine
19
20
  COLORS = [ cyan, yellow, green, magenta, red ]
20
21
 
21
22
  def initialize(procfile, options={})
22
- @procfile = read_procfile(procfile)
23
+ @procfile = Foreman::Procfile.new(procfile)
23
24
  @directory = File.expand_path(File.dirname(procfile))
24
25
  @options = options
25
26
  @environment = read_environment_files(options[:env])
26
27
  end
27
28
 
28
- def processes
29
- @processes ||= begin
30
- @order = []
31
- procfile.split("\n").inject({}) do |hash, line|
32
- next hash if line.strip == ""
33
- name, command = line.split(/\s*:\s+/, 2)
34
- unless command
35
- warn_deprecated_procfile!
36
- name, command = line.split(/ +/, 2)
37
- end
38
- process = Foreman::Process.new(name, command)
39
- process.color = next_color
40
- @order << process.name
41
- hash.update(process.name => process)
42
- end
43
- end
44
- end
45
-
46
- def process_order
47
- processes
48
- @order.uniq
49
- end
50
-
51
- def processes_in_order
52
- process_order.map do |name|
53
- [name, processes[name]]
54
- end
55
- end
56
-
57
29
  def start
58
30
  proctitle "ruby: foreman master"
59
31
 
60
- processes_in_order.each do |name, process|
32
+ processes.each do |process|
33
+ process.color = next_color
61
34
  fork process
62
35
  end
63
36
 
@@ -68,8 +41,7 @@ class Foreman::Engine
68
41
  end
69
42
 
70
43
  def execute(name)
71
-
72
- fork processes[name]
44
+ fork procfile[name]
73
45
 
74
46
  trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
75
47
  trap("INT") { puts "SIGINT received"; terminate_gracefully }
@@ -77,9 +49,13 @@ class Foreman::Engine
77
49
  watch_for_termination
78
50
  end
79
51
 
52
+ def processes
53
+ procfile.processes
54
+ end
55
+
80
56
  def port_for(process, num, base_port=nil)
81
57
  base_port ||= 5000
82
- offset = processes_in_order.map { |p| p.first }.index(process.name) * 100
58
+ offset = procfile.process_names.index(process.name) * 100
83
59
  base_port.to_i + offset + num - 1
84
60
  end
85
61
 
@@ -134,6 +110,24 @@ private ######################################################################
134
110
  end
135
111
  end
136
112
 
113
+ def terminate_gracefully
114
+ info "sending SIGTERM to all processes"
115
+ kill_all "SIGTERM"
116
+ Timeout.timeout(3) { Process.waitall }
117
+ rescue Timeout::Error
118
+ info "sending SIGKILL to all processes"
119
+ kill_all "SIGKILL"
120
+ end
121
+
122
+ def watch_for_termination
123
+ pid, status = Process.wait2
124
+ process = running_processes.delete(pid)
125
+ info "process terminated", process
126
+ terminate_gracefully
127
+ kill_all
128
+ rescue Errno::ECHILD
129
+ end
130
+
137
131
  def info(message, process=nil)
138
132
  print process.color if process
139
133
  print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(process)} | "
@@ -149,7 +143,7 @@ private ######################################################################
149
143
 
150
144
  def longest_process_name
151
145
  @longest_process_name ||= begin
152
- longest = processes.keys.map { |name| name.length }.sort.last
146
+ longest = procfile.process_names.map { |name| name.length }.sort.last
153
147
  longest = 6 if longest < 6 # system
154
148
  longest
155
149
  end
@@ -160,30 +154,10 @@ private ######################################################################
160
154
  name.ljust(longest_process_name + 3) # add 3 for process number padding
161
155
  end
162
156
 
163
- def print_info
164
- info "currently running processes:"
165
- running_processes.each do |pid, process|
166
- info "pid #{pid}", process
167
- end
168
- end
169
-
170
157
  def proctitle(title)
171
158
  $0 = title
172
159
  end
173
160
 
174
- def read_procfile(procfile)
175
- File.read(procfile)
176
- end
177
-
178
- def watch_for_termination
179
- pid, status = Process.wait2
180
- process = running_processes.delete(pid)
181
- info "process terminated", process
182
- terminate_gracefully
183
- kill_all
184
- rescue Errno::ECHILD
185
- end
186
-
187
161
  def running_processes
188
162
  @running_processes ||= {}
189
163
  end
@@ -194,14 +168,6 @@ private ######################################################################
194
168
  @current_color >= COLORS.length ? "" : COLORS[@current_color]
195
169
  end
196
170
 
197
- def warn_deprecated_procfile!
198
- return if @already_warned_deprecated
199
- @already_warned_deprecated = true
200
- puts "!!! This format of Procfile is deprecated, and will not work starting in v0.12"
201
- puts "!!! Use a colon to separate the process name from the command"
202
- puts "!!! e.g. web: thin start"
203
- end
204
-
205
171
  def read_environment_files(filenames)
206
172
  environment = {}
207
173
 
@@ -225,13 +191,4 @@ private ######################################################################
225
191
  end
226
192
  end
227
193
 
228
- def terminate_gracefully
229
- info "sending SIGTERM to all processes"
230
- kill_all "SIGTERM"
231
- Timeout.timeout(3) { Process.waitall }
232
- rescue Timeout::Error
233
- info "sending SIGKILL to all processes"
234
- kill_all "SIGKILL"
235
- end
236
-
237
194
  end
@@ -26,7 +26,7 @@ class Foreman::Export::Upstart < Foreman::Export::Base
26
26
 
27
27
  process_template = export_template("upstart", "process.conf.erb", template_root)
28
28
 
29
- engine.processes.values.each do |process|
29
+ engine.processes.each do |process|
30
30
  process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
31
31
  process_master_config = ERB.new(process_master_template).result(binding)
32
32
  write_file "#{location}/#{app}-#{process.name}.conf", process_master_config
@@ -0,0 +1,37 @@
1
+ require "foreman"
2
+
3
+ # A valid Procfile entry is captured by this regex.
4
+ # All other lines are ignored.
5
+ #
6
+ # /^([A-Za-z0-9_]+):\s*(.+)$/
7
+ #
8
+ # $1 = name
9
+ # $2 = command
10
+ #
11
+ class Foreman::Procfile
12
+
13
+ attr_reader :processes
14
+
15
+ def initialize(filename)
16
+ @processes = parse_procfile(filename)
17
+ end
18
+
19
+ def process_names
20
+ processes.map(&:name)
21
+ end
22
+
23
+ def [](name)
24
+ processes.detect { |process| process.name == name }
25
+ end
26
+
27
+ private
28
+
29
+ def parse_procfile(filename)
30
+ File.read(filename).split("\n").map do |line|
31
+ if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
32
+ Foreman::Process.new($1, $2)
33
+ end
34
+ end.compact
35
+ end
36
+
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.23.1"
3
+ VERSION = "0.24.0"
4
4
 
5
5
  end
@@ -15,21 +15,8 @@ describe "Foreman::Engine" do
15
15
  before { write_procfile }
16
16
 
17
17
  it "reads the processes" do
18
- subject.processes["alpha"].command.should == "./alpha"
19
- subject.processes["bravo"].command.should == "./bravo"
20
- end
21
- end
22
-
23
- describe "with a deprecated Procfile" do
24
- before do
25
- File.open("Procfile", "w") do |file|
26
- file.puts "name command"
27
- end
28
- end
29
-
30
- it "should print a deprecation warning" do
31
- mock(subject).warn_deprecated_procfile!
32
- subject.processes.length.should == 1
18
+ subject.procfile["alpha"].command.should == "./alpha"
19
+ subject.procfile["bravo"].command.should == "./bravo"
33
20
  end
34
21
  end
35
22
  end
@@ -37,8 +24,8 @@ describe "Foreman::Engine" do
37
24
  describe "start" do
38
25
  it "forks the processes" do
39
26
  write_procfile
40
- mock(subject).fork(subject.processes["alpha"])
41
- mock(subject).fork(subject.processes["bravo"])
27
+ mock(subject).fork(subject.procfile["alpha"])
28
+ mock(subject).fork(subject.procfile["bravo"])
42
29
  mock(subject).watch_for_termination
43
30
  subject.start
44
31
  end
@@ -46,9 +33,9 @@ describe "Foreman::Engine" do
46
33
  it "handles concurrency" do
47
34
  write_procfile
48
35
  engine = Foreman::Engine.new("Procfile",:concurrency => "alpha=2")
49
- mock(engine).fork_individual(engine.processes["alpha"], 1, 5000)
50
- mock(engine).fork_individual(engine.processes["alpha"], 2, 5001)
51
- mock(engine).fork_individual(engine.processes["bravo"], 1, 5100)
36
+ mock(engine).fork_individual(engine.procfile["alpha"], 1, 5000)
37
+ mock(engine).fork_individual(engine.procfile["alpha"], 2, 5001)
38
+ mock(engine).fork_individual(engine.procfile["bravo"], 1, 5100)
52
39
  mock(engine).watch_for_termination
53
40
  engine.start
54
41
  end
@@ -57,14 +44,13 @@ describe "Foreman::Engine" do
57
44
  describe "execute" do
58
45
  it "runs the processes" do
59
46
  write_procfile
60
- mock(subject).fork(subject.processes["alpha"])
47
+ mock(subject).fork(subject.procfile["alpha"])
61
48
  mock(subject).watch_for_termination
62
49
  subject.execute("alpha")
63
50
  end
64
51
  end
65
52
 
66
53
  describe "environment" do
67
-
68
54
  before(:each) do
69
55
  write_procfile
70
56
  stub(Process).fork
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.23.1
4
+ version: 0.24.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: term-ansicolor
16
- requirement: &70129124490300 !ruby/object:Gem::Requirement
16
+ requirement: &70155363724260 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.0.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70129124490300
24
+ version_requirements: *70155363724260
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thor
27
- requirement: &70129124481440 !ruby/object:Gem::Requirement
27
+ requirement: &70155363722660 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 0.13.6
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70129124481440
35
+ version_requirements: *70155363722660
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
  - lib/foreman/export/upstart.rb
60
60
  - lib/foreman/export.rb
61
61
  - lib/foreman/process.rb
62
+ - lib/foreman/procfile.rb
62
63
  - lib/foreman/utils.rb
63
64
  - lib/foreman/version.rb
64
65
  - lib/foreman.rb
@@ -93,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
93
94
  version: '0'
94
95
  segments:
95
96
  - 0
96
- hash: 4036267716300472320
97
+ hash: 3975386254476166563
97
98
  required_rubygems_version: !ruby/object:Gem::Requirement
98
99
  none: false
99
100
  requirements:
@@ -102,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
103
  version: '0'
103
104
  segments:
104
105
  - 0
105
- hash: 4036267716300472320
106
+ hash: 3975386254476166563
106
107
  requirements: []
107
108
  rubyforge_project:
108
109
  rubygems_version: 1.8.10