foreman 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = Foreman
2
2
 
3
- === Procfile
3
+ == Procfile
4
4
 
5
5
  alpha ./bin/alpha
6
6
  bravo ./bin/bravo some args
@@ -10,18 +10,26 @@
10
10
 
11
11
  === Running
12
12
 
13
+ Log files will be output to standard out, colorized to aid in visual separation.
14
+
13
15
  $ foreman start
14
- [foreman] [Tue May 18 01:27:08 UTC 2010] [alpha] started with pid 4393
15
- [foreman] [Tue May 18 01:27:08 UTC 2010] [bravo] started with pid 4394
16
- [foreman] [Tue May 18 01:27:08 UTC 2010] [charlie] started with pid 4395
16
+ [01:27:08] [alpha] started with pid 4393
17
+ [01:27:08] [bravo] started with pid 4394
18
+ [01:27:08] [charlie] started with pid 4395
19
+ [01:27:08] [bravo] initializing...
20
+ [01:27:08] [bravo] complete
17
21
 
18
- === Standardized Logging
22
+ === Using Screen
23
+
24
+ Launch the processes in a screen session in indivudal windows
25
+
26
+ $ foreman screen
27
+
28
+ == Single Process Execution
19
29
 
20
- log/alpha.log
21
- log/bravo.log
22
- log/charlie.log
30
+ $ foreman execute alpha
23
31
 
24
- == Upstart
32
+ == Exporting to Upstart
25
33
 
26
34
  === Export to upstart scripts
27
35
 
@@ -74,4 +82,4 @@ MIT
74
82
 
75
83
  == Copyright
76
84
 
77
- (c) 2010 David Dollar
85
+ (c) 2010 David Dollar
data/Rakefile CHANGED
@@ -53,8 +53,10 @@ begin
53
53
  s.add_development_dependency 'rr', '~> 0.10.11'
54
54
  s.add_development_dependency 'rspec', '~> 2.0.0'
55
55
 
56
+ s.add_dependency 'term-ansicolor', '~> 1.0.5'
56
57
  s.add_dependency 'thor', '~> 0.13.6'
57
58
  end
59
+ Jeweler::GemcutterTasks.new
58
60
  rescue LoadError
59
61
  puts "Jeweler not available. Install it with: sudo gem install jeweler"
60
62
  end
data/lib/foreman.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
 
5
5
  class AppDoesNotExist < Exception; end
6
6
 
@@ -1,12 +1,18 @@
1
1
  require "foreman"
2
2
  require "foreman/process"
3
+ require "pty"
3
4
  require "tempfile"
5
+ require "term/ansicolor"
4
6
 
5
7
  class Foreman::Engine
6
8
 
7
9
  attr_reader :procfile
8
10
  attr_reader :directory
9
11
 
12
+ extend Term::ANSIColor
13
+
14
+ COLORS = [ cyan, yellow, green, magenta, on_blue ]
15
+
10
16
  def initialize(procfile)
11
17
  @procfile = read_procfile(procfile)
12
18
  @directory = File.expand_path(File.dirname(procfile))
@@ -17,6 +23,7 @@ class Foreman::Engine
17
23
  procfile.split("\n").inject({}) do |hash, line|
18
24
  next if line.strip == ""
19
25
  process = Foreman::Process.new(*line.split(" ", 2))
26
+ process.color = next_color
20
27
  hash.update(process.name => process)
21
28
  end
22
29
  end
@@ -32,7 +39,7 @@ class Foreman::Engine
32
39
  trap("TERM") { kill_and_exit("TERM") }
33
40
  trap("INT") { kill_and_exit("INT") }
34
41
 
35
- run_loop
42
+ watch_for_termination
36
43
  end
37
44
 
38
45
  def screen
@@ -69,23 +76,29 @@ private ######################################################################
69
76
  Dir.chdir directory do
70
77
  FileUtils.mkdir_p "log"
71
78
  command = process.command
72
- command << " >>log/#{process.name}.log 2>&1" if log_to_file
73
- system command
74
- exit $?.exitstatus || 255
79
+
80
+ PTY.spawn("#{process.command} 2>&1") do |stdin, stdout, pid|
81
+ until stdin.eof?
82
+ info stdin.gets, process
83
+ end
84
+ end
75
85
  end
76
86
  end
77
87
 
78
88
  def kill_and_exit(signal="TERM")
79
89
  info "termination requested"
80
90
  running_processes.each do |pid, process|
81
- info "killing pid #{pid}", process
91
+ info "killing #{process.name} in pid #{pid}"
82
92
  Process.kill(signal, pid)
83
93
  end
84
94
  exit 0
85
95
  end
86
96
 
87
97
  def info(message, process=nil)
88
- puts "[foreman] [#{Time.now.utc}] [#{process ? process.name : "system"}] #{message}"
98
+ print process.color if process
99
+ print "[#{Time.now.strftime("%H:%M:%S")}] [#{process ? process.name : "system"}] #{message.chomp}"
100
+ print Term::ANSIColor.reset
101
+ puts
89
102
  end
90
103
 
91
104
  def print_info
@@ -103,17 +116,21 @@ private ######################################################################
103
116
  File.read(procfile)
104
117
  end
105
118
 
106
- def run_loop
107
- while true
108
- pid, status = Process.wait2
109
- process = running_processes.delete(pid)
110
- info "exited with code #{status}", process
111
- fork process
112
- end
119
+ def watch_for_termination
120
+ pid, status = Process.wait2
121
+ process = running_processes.delete(pid)
122
+ info "process terminated", process
123
+ kill_and_exit
113
124
  end
114
125
 
115
126
  def running_processes
116
127
  @running_processes ||= {}
117
128
  end
118
129
 
130
+ def next_color
131
+ @current_color ||= -1
132
+ @current_color += 1
133
+ @current_color >= COLORS.length ? "" : COLORS[@current_color]
134
+ end
135
+
119
136
  end
@@ -50,7 +50,7 @@ exec #{process.command} >>/var/log/#{app}/#{process.name}.log 2>&1
50
50
  end
51
51
 
52
52
  engine.processes.each do |name, process|
53
- config.scale(name, 1)
53
+ config.processes[name] ||= 1
54
54
  end
55
55
  config.write
56
56
  end
@@ -4,6 +4,7 @@ class Foreman::Process
4
4
 
5
5
  attr_reader :name
6
6
  attr_reader :command
7
+ attr_accessor :color
7
8
 
8
9
  def initialize(name, command)
9
10
  @name = name
@@ -25,7 +25,7 @@ describe "Foreman::Engine" do
25
25
  write_procfile
26
26
  mock(subject).fork(subject.processes["alpha"])
27
27
  mock(subject).fork(subject.processes["bravo"])
28
- mock(subject).run_loop
28
+ mock(subject).watch_for_termination
29
29
  subject.start
30
30
  end
31
31
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - David Dollar
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-09 00:00:00 -04:00
18
+ date: 2010-06-22 00:00:00 -04:00
19
19
  default_executable: foreman
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -99,9 +99,25 @@ dependencies:
99
99
  type: :development
100
100
  version_requirements: *id005
101
101
  - !ruby/object:Gem::Dependency
102
- name: thor
102
+ name: term-ansicolor
103
103
  prerelease: false
104
104
  requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ hash: 29
110
+ segments:
111
+ - 1
112
+ - 0
113
+ - 5
114
+ version: 1.0.5
115
+ type: :runtime
116
+ version_requirements: *id006
117
+ - !ruby/object:Gem::Dependency
118
+ name: thor
119
+ prerelease: false
120
+ requirement: &id007 !ruby/object:Gem::Requirement
105
121
  none: false
106
122
  requirements:
107
123
  - - ~>
@@ -113,7 +129,7 @@ dependencies:
113
129
  - 6
114
130
  version: 0.13.6
115
131
  type: :runtime
116
- version_requirements: *id006
132
+ version_requirements: *id007
117
133
  description: Process manager for applications with multiple components
118
134
  email: ddollar@gmail.com
119
135
  executables:
@@ -141,7 +157,7 @@ files:
141
157
  - spec/foreman_spec.rb
142
158
  - spec/spec_helper.rb
143
159
  - README.rdoc
144
- has_rdoc: true
160
+ has_rdoc: false
145
161
  homepage: http://github.com/ddollar/foreman
146
162
  licenses: []
147
163