foreman 0.8.0 → 0.9.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/data/example/Pstypes +2 -0
- data/data/example/error +5 -0
- data/data/example/log/neverdie.log +4 -0
- data/data/example/ticker +6 -0
- data/{export → data/export}/upstart/master.conf.erb +0 -0
- data/{export → data/export}/upstart/process.conf.erb +0 -0
- data/{export → data/export}/upstart/process_master.conf.erb +0 -0
- data/lib/foreman.rb +1 -1
- data/lib/foreman/cli.rb +10 -10
- data/lib/foreman/engine.rb +21 -17
- data/lib/foreman/export/base.rb +1 -1
- data/lib/foreman/export/inittab.rb +2 -2
- data/man/foreman.1 +16 -12
- data/spec/foreman/cli_spec.rb +8 -8
- data/spec/foreman/engine_spec.rb +7 -7
- data/spec/spec_helper.rb +2 -2
- metadata +45 -23
data/data/example/error
ADDED
data/data/example/ticker
ADDED
File without changes
|
File without changes
|
File without changes
|
data/lib/foreman.rb
CHANGED
data/lib/foreman/cli.rb
CHANGED
@@ -5,7 +5,7 @@ require "thor"
|
|
5
5
|
|
6
6
|
class Foreman::CLI < Thor
|
7
7
|
|
8
|
-
class_option :
|
8
|
+
class_option :pstypes, :type => :string, :aliases => "-f", :desc => "Default: Pstypes"
|
9
9
|
|
10
10
|
desc "start [PROCESS]", "Start the application, or a specific process"
|
11
11
|
|
@@ -14,7 +14,7 @@ class Foreman::CLI < Thor
|
|
14
14
|
:banner => '"alpha=5,bar=3"'
|
15
15
|
|
16
16
|
def start(process=nil)
|
17
|
-
|
17
|
+
check_pstypes!
|
18
18
|
|
19
19
|
if process
|
20
20
|
engine.execute(process, options)
|
@@ -33,7 +33,7 @@ class Foreman::CLI < Thor
|
|
33
33
|
:banner => '"alpha=5,bar=3"'
|
34
34
|
|
35
35
|
def export(format, location=nil)
|
36
|
-
|
36
|
+
check_pstypes!
|
37
37
|
|
38
38
|
formatter = case format
|
39
39
|
when "upstart" then Foreman::Export::Upstart
|
@@ -49,16 +49,16 @@ class Foreman::CLI < Thor
|
|
49
49
|
|
50
50
|
private ######################################################################
|
51
51
|
|
52
|
-
def
|
53
|
-
error("
|
52
|
+
def check_pstypes!
|
53
|
+
error("#{pstypes} does not exist.") unless File.exist?(pstypes)
|
54
54
|
end
|
55
55
|
|
56
56
|
def engine
|
57
|
-
@engine ||= Foreman::Engine.new(
|
57
|
+
@engine ||= Foreman::Engine.new(pstypes)
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
options[:
|
60
|
+
def pstypes
|
61
|
+
options[:pstypes] || "Pstypes"
|
62
62
|
end
|
63
63
|
|
64
64
|
private ######################################################################
|
@@ -68,8 +68,8 @@ private ######################################################################
|
|
68
68
|
exit 1
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
72
|
-
File.exist?(
|
71
|
+
def pstypes_exists?(pstypes)
|
72
|
+
File.exist?(pstypes)
|
73
73
|
end
|
74
74
|
|
75
75
|
end
|
data/lib/foreman/engine.rb
CHANGED
@@ -8,21 +8,21 @@ require "fileutils"
|
|
8
8
|
|
9
9
|
class Foreman::Engine
|
10
10
|
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :pstypes
|
12
12
|
attr_reader :directory
|
13
13
|
|
14
14
|
extend Term::ANSIColor
|
15
15
|
|
16
16
|
COLORS = [ cyan, yellow, green, magenta, red ]
|
17
17
|
|
18
|
-
def initialize(
|
19
|
-
@
|
20
|
-
@directory = File.expand_path(File.dirname(
|
18
|
+
def initialize(pstypes)
|
19
|
+
@pstypes = read_pstypes(pstypes)
|
20
|
+
@directory = File.expand_path(File.dirname(pstypes))
|
21
21
|
end
|
22
22
|
|
23
23
|
def processes
|
24
24
|
@processes ||= begin
|
25
|
-
|
25
|
+
pstypes.split("\n").inject({}) do |hash, line|
|
26
26
|
next if line.strip == ""
|
27
27
|
name, command = line.split(" ", 2)
|
28
28
|
process = Foreman::Process.new(name, command)
|
@@ -66,36 +66,40 @@ private ######################################################################
|
|
66
66
|
concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
|
67
67
|
|
68
68
|
1.upto(concurrency[process.name]) do |num|
|
69
|
-
fork_individual(process, port_for(process, num, options[:port]))
|
69
|
+
fork_individual(process, num, port_for(process, num, options[:port]))
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def fork_individual(process, port)
|
73
|
+
def fork_individual(process, num, port)
|
74
74
|
ENV["PORT"] = port.to_s
|
75
|
+
ENV["PS"] = "#{process.name}.#{num}"
|
75
76
|
|
76
77
|
pid = Process.fork do
|
77
78
|
run(process)
|
78
79
|
end
|
79
80
|
|
80
|
-
info "started with pid #{pid}", process
|
81
|
+
info "started with pid #{pid}, PORT=#{port}", process
|
81
82
|
running_processes[pid] = process
|
82
83
|
end
|
83
84
|
|
84
85
|
def run(process, log_to_file=true)
|
85
86
|
proctitle "ruby: foreman #{process.name}"
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
begin
|
89
|
+
Dir.chdir directory do
|
90
|
+
FileUtils.mkdir_p "log"
|
91
|
+
command = process.command
|
90
92
|
|
91
|
-
begin
|
92
93
|
PTY.spawn("#{process.command} 2>&1") do |stdin, stdout, pid|
|
93
94
|
until stdin.eof?
|
94
95
|
info stdin.gets, process
|
95
96
|
end
|
96
97
|
end
|
97
|
-
|
98
|
+
end
|
99
|
+
rescue PTY::ChildExited, Interrupt
|
100
|
+
begin
|
98
101
|
info "process exiting", process
|
102
|
+
rescue Interrupt
|
99
103
|
end
|
100
104
|
end
|
101
105
|
end
|
@@ -125,8 +129,8 @@ private ######################################################################
|
|
125
129
|
end
|
126
130
|
|
127
131
|
def pad_process_name(process)
|
128
|
-
name = process ? "#{
|
129
|
-
name.ljust(longest_process_name +
|
132
|
+
name = process ? "#{ENV["PS"]}" : "system"
|
133
|
+
name.ljust(longest_process_name + 3) # add 3 for process number padding
|
130
134
|
end
|
131
135
|
|
132
136
|
def print_info
|
@@ -140,8 +144,8 @@ private ######################################################################
|
|
140
144
|
$0 = title
|
141
145
|
end
|
142
146
|
|
143
|
-
def
|
144
|
-
File.read(
|
147
|
+
def read_pstypes(pstypes)
|
148
|
+
File.read(pstypes)
|
145
149
|
end
|
146
150
|
|
147
151
|
def watch_for_termination
|
data/lib/foreman/export/base.rb
CHANGED
@@ -24,7 +24,7 @@ private ######################################################################
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def export_template(name)
|
27
|
-
File.read(File.expand_path("../../../../export/#{name}", __FILE__))
|
27
|
+
File.read(File.expand_path("../../../../data/export/#{name}", __FILE__))
|
28
28
|
end
|
29
29
|
|
30
30
|
def write_file(filename, contents)
|
@@ -27,8 +27,8 @@ class Foreman::Export::Inittab < Foreman::Export::Base
|
|
27
27
|
inittab = inittab.join("\n") + "\n"
|
28
28
|
|
29
29
|
if fname
|
30
|
-
FileUtils.mkdir_p(log_root)
|
31
|
-
FileUtils.chown(user, nil, log_root)
|
30
|
+
FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
|
31
|
+
FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
|
32
32
|
write_file(fname, inittab)
|
33
33
|
else
|
34
34
|
puts inittab
|
data/man/foreman.1
CHANGED
@@ -1,10 +1,10 @@
|
|
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" "October 2010" "Foreman 0.8.0" "Foreman Manual"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
|
-
\fBforeman\fR \- manage
|
7
|
+
\fBforeman\fR \- manage Pstypes\-based applications
|
8
8
|
.
|
9
9
|
.SH "SYNOPSIS"
|
10
10
|
\fBforeman start [process]\fR
|
@@ -13,13 +13,13 @@
|
|
13
13
|
\fBforeman export <format> [location]\fR
|
14
14
|
.
|
15
15
|
.SH "DESCRIPTION"
|
16
|
-
\fBForeman\fR is a manager for
|
16
|
+
\fBForeman\fR is a manager for Pstypes\-based applications\. Its aim is to abstract away the details of the Pstypes format, and allow you to either run your application directly or export it to some other process management format\.
|
17
17
|
.
|
18
18
|
.SH "RUNNING"
|
19
19
|
\fBforeman start\fR is used to run your application directly from the command line\.
|
20
20
|
.
|
21
21
|
.P
|
22
|
-
If no additional parameters are passed, foreman will run one instance of each type of process defined in your
|
22
|
+
If no additional parameters are passed, foreman will run one instance of each type of process defined in your Pstypes\.
|
23
23
|
.
|
24
24
|
.P
|
25
25
|
If a parameter is passed, foreman will run one instance of the specified application type\.
|
@@ -28,8 +28,12 @@ If a parameter is passed, foreman will run one instance of the specified applica
|
|
28
28
|
The following options control how the application is run:
|
29
29
|
.
|
30
30
|
.TP
|
31
|
-
\fB\-
|
32
|
-
|
31
|
+
\fB\-c\fR, \fB\-\-concurrency\fR
|
32
|
+
Specify the number of each process type to run\. The value passed in should be in the format \fBprocess=num,process=num\fR
|
33
|
+
.
|
34
|
+
.TP
|
35
|
+
\fB\-p\fR, \fB\-\-port\fR
|
36
|
+
Specify which port to use as the base for this application\. Should be a multiple of 1000\.
|
33
37
|
.
|
34
38
|
.SH "EXPORTING"
|
35
39
|
\fBforeman export\fR is used to export your application to another process management format\.
|
@@ -64,8 +68,8 @@ Specify the user the application should be run as\. Defaults to the app name
|
|
64
68
|
These options control all modes of foreman\'s operation\.
|
65
69
|
.
|
66
70
|
.TP
|
67
|
-
\fB\-f\fR, \fB\-\-
|
68
|
-
Specify an alternate location for the application\'s
|
71
|
+
\fB\-f\fR, \fB\-\-pstypes\fR
|
72
|
+
Specify an alternate location for the application\'s Pstypes\. This file\'s containing directory will be assumed to be the root directory of the application\.
|
69
73
|
.
|
70
74
|
.SH "EXPORT FORMATS"
|
71
75
|
foreman currently supports the following output formats:
|
@@ -106,8 +110,8 @@ Will create a series of upstart scripts in the location you specify\. Scripts wi
|
|
106
110
|
.P
|
107
111
|
\fBrestart appname\-processname\-3\fR
|
108
112
|
.
|
109
|
-
.SH "
|
110
|
-
A
|
113
|
+
.SH "PSTYPES"
|
114
|
+
A Pstyes file should contain both a name for the process and the command used to run it\.
|
111
115
|
.
|
112
116
|
.IP "" 4
|
113
117
|
.
|
@@ -147,13 +151,13 @@ $ foreman export upstart /etc/init
|
|
147
151
|
.IP "" 0
|
148
152
|
.
|
149
153
|
.P
|
150
|
-
Run one process type from the application defined in a specific
|
154
|
+
Run one process type from the application defined in a specific Pstypes:
|
151
155
|
.
|
152
156
|
.IP "" 4
|
153
157
|
.
|
154
158
|
.nf
|
155
159
|
|
156
|
-
$ foreman start alpha \-p ~/app/
|
160
|
+
$ foreman start alpha \-p ~/app/Pstypes
|
157
161
|
.
|
158
162
|
.fi
|
159
163
|
.
|
data/spec/foreman/cli_spec.rb
CHANGED
@@ -5,17 +5,17 @@ describe "Foreman::CLI" do
|
|
5
5
|
subject { Foreman::CLI.new }
|
6
6
|
|
7
7
|
describe "start" do
|
8
|
-
describe "with a non-existent
|
8
|
+
describe "with a non-existent Pstypes" do
|
9
9
|
it "prints an error" do
|
10
|
-
mock_error(subject, "
|
10
|
+
mock_error(subject, "Pstypes does not exist.") do
|
11
11
|
dont_allow.instance_of(Foreman::Engine).start
|
12
12
|
subject.start
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
describe "with a
|
18
|
-
before(:each) {
|
17
|
+
describe "with a Pstypes" do
|
18
|
+
before(:each) { write_pstypes }
|
19
19
|
|
20
20
|
it "runs successfully" do
|
21
21
|
dont_allow(subject).error
|
@@ -26,17 +26,17 @@ describe "Foreman::CLI" do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe "export" do
|
29
|
-
describe "with a non-existent
|
29
|
+
describe "with a non-existent Pstypes" do
|
30
30
|
it "prints an error" do
|
31
|
-
mock_error(subject, "
|
31
|
+
mock_error(subject, "Pstypes does not exist.") do
|
32
32
|
dont_allow.instance_of(Foreman::Engine).export
|
33
33
|
subject.export("testapp")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
describe "with a
|
39
|
-
before(:each) {
|
38
|
+
describe "with a Pstypes" do
|
39
|
+
before(:each) { write_pstypes }
|
40
40
|
|
41
41
|
describe "with an invalid formatter" do
|
42
42
|
it "prints an error" do
|
data/spec/foreman/engine_spec.rb
CHANGED
@@ -2,18 +2,18 @@ require "spec_helper"
|
|
2
2
|
require "foreman/engine"
|
3
3
|
|
4
4
|
describe "Foreman::Engine" do
|
5
|
-
subject { Foreman::Engine.new("
|
5
|
+
subject { Foreman::Engine.new("Pstypes") }
|
6
6
|
|
7
7
|
describe "initialize" do
|
8
|
-
describe "without an existing
|
8
|
+
describe "without an existing Pstypes" do
|
9
9
|
it "raises an error" do
|
10
10
|
lambda { subject }.should raise_error
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe "with a
|
14
|
+
describe "with a Pstypes" do
|
15
15
|
it "reads the processes" do
|
16
|
-
|
16
|
+
write_pstypes
|
17
17
|
subject.processes["alpha"].command.should == "./alpha"
|
18
18
|
subject.processes["bravo"].command.should == "./bravo"
|
19
19
|
end
|
@@ -22,7 +22,7 @@ describe "Foreman::Engine" do
|
|
22
22
|
|
23
23
|
describe "start" do
|
24
24
|
it "forks the processes" do
|
25
|
-
|
25
|
+
write_pstypes
|
26
26
|
mock(subject).fork(subject.processes["alpha"], {})
|
27
27
|
mock(subject).fork(subject.processes["bravo"], {})
|
28
28
|
mock(subject).watch_for_termination
|
@@ -30,7 +30,7 @@ describe "Foreman::Engine" do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "handles concurrency" do
|
33
|
-
|
33
|
+
write_pstypes
|
34
34
|
mock(subject).fork_individual(subject.processes["alpha"], 5000)
|
35
35
|
mock(subject).fork_individual(subject.processes["alpha"], 5001)
|
36
36
|
mock(subject).fork_individual(subject.processes["bravo"], 5100)
|
@@ -41,7 +41,7 @@ describe "Foreman::Engine" do
|
|
41
41
|
|
42
42
|
describe "execute" do
|
43
43
|
it "runs the processes" do
|
44
|
-
|
44
|
+
write_pstypes
|
45
45
|
mock(subject).fork(subject.processes["alpha"], {})
|
46
46
|
mock(subject).watch_for_termination
|
47
47
|
subject.execute("alpha")
|
data/spec/spec_helper.rb
CHANGED
@@ -24,8 +24,8 @@ def write_foreman_config(app)
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
File.open(
|
27
|
+
def write_pstypes(pstypes="Pstypes")
|
28
|
+
File.open(pstypes, "w") do |file|
|
29
29
|
file.puts "alpha ./alpha"
|
30
30
|
file.puts "bravo ./bravo"
|
31
31
|
end
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 62196273
|
5
|
+
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 9
|
9
9
|
- 0
|
10
|
-
|
10
|
+
- beta
|
11
|
+
- 1
|
12
|
+
version: 0.9.0.beta.1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- |
|
@@ -17,7 +19,7 @@ autorequire:
|
|
17
19
|
bindir: bin
|
18
20
|
cert_chain: []
|
19
21
|
|
20
|
-
date: 2010-
|
22
|
+
date: 2010-10-15 00:00:00 -07:00
|
21
23
|
default_executable:
|
22
24
|
dependencies:
|
23
25
|
- !ruby/object:Gem::Dependency
|
@@ -50,6 +52,20 @@ dependencies:
|
|
50
52
|
version_requirements: *id002
|
51
53
|
- !ruby/object:Gem::Dependency
|
52
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
type: :development
|
64
|
+
name: ronn
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
69
|
none: false
|
54
70
|
requirements:
|
55
71
|
- - ~>
|
@@ -63,9 +79,9 @@ dependencies:
|
|
63
79
|
type: :development
|
64
80
|
name: fakefs
|
65
81
|
prerelease: false
|
66
|
-
version_requirements: *
|
82
|
+
version_requirements: *id004
|
67
83
|
- !ruby/object:Gem::Dependency
|
68
|
-
requirement: &
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
69
85
|
none: false
|
70
86
|
requirements:
|
71
87
|
- - ~>
|
@@ -79,9 +95,9 @@ dependencies:
|
|
79
95
|
type: :development
|
80
96
|
name: rcov
|
81
97
|
prerelease: false
|
82
|
-
version_requirements: *
|
98
|
+
version_requirements: *id005
|
83
99
|
- !ruby/object:Gem::Dependency
|
84
|
-
requirement: &
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
85
101
|
none: false
|
86
102
|
requirements:
|
87
103
|
- - ~>
|
@@ -95,9 +111,9 @@ dependencies:
|
|
95
111
|
type: :development
|
96
112
|
name: rr
|
97
113
|
prerelease: false
|
98
|
-
version_requirements: *
|
114
|
+
version_requirements: *id006
|
99
115
|
- !ruby/object:Gem::Dependency
|
100
|
-
requirement: &
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
101
117
|
none: false
|
102
118
|
requirements:
|
103
119
|
- - ~>
|
@@ -113,9 +129,9 @@ dependencies:
|
|
113
129
|
type: :development
|
114
130
|
name: rspec
|
115
131
|
prerelease: false
|
116
|
-
version_requirements: *
|
132
|
+
version_requirements: *id007
|
117
133
|
- !ruby/object:Gem::Dependency
|
118
|
-
requirement: &
|
134
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
119
135
|
none: false
|
120
136
|
requirements:
|
121
137
|
- - ~>
|
@@ -129,9 +145,9 @@ dependencies:
|
|
129
145
|
type: :runtime
|
130
146
|
name: term-ansicolor
|
131
147
|
prerelease: false
|
132
|
-
version_requirements: *
|
148
|
+
version_requirements: *id008
|
133
149
|
- !ruby/object:Gem::Dependency
|
134
|
-
requirement: &
|
150
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
135
151
|
none: false
|
136
152
|
requirements:
|
137
153
|
- - ~>
|
@@ -145,7 +161,7 @@ dependencies:
|
|
145
161
|
type: :runtime
|
146
162
|
name: thor
|
147
163
|
prerelease: false
|
148
|
-
version_requirements: *
|
164
|
+
version_requirements: *id009
|
149
165
|
description: Process manager for applications with multiple components
|
150
166
|
email: |
|
151
167
|
<ddollar@gmail.com>
|
@@ -159,10 +175,14 @@ extra_rdoc_files: []
|
|
159
175
|
files:
|
160
176
|
- bin/foreman
|
161
177
|
- man/foreman.1
|
162
|
-
- export/upstart/master.conf.erb
|
163
|
-
- export/upstart/process.conf.erb
|
164
|
-
- export/upstart/process_master.conf.erb
|
165
178
|
- README.markdown
|
179
|
+
- data/example/Pstypes
|
180
|
+
- data/example/error
|
181
|
+
- data/example/log/neverdie.log
|
182
|
+
- data/example/ticker
|
183
|
+
- data/export/upstart/master.conf.erb
|
184
|
+
- data/export/upstart/process.conf.erb
|
185
|
+
- data/export/upstart/process_master.conf.erb
|
166
186
|
- lib/foreman.rb
|
167
187
|
- lib/foreman/cli.rb
|
168
188
|
- lib/foreman/engine.rb
|
@@ -200,12 +220,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
220
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
221
|
none: false
|
202
222
|
requirements:
|
203
|
-
- - "
|
223
|
+
- - ">"
|
204
224
|
- !ruby/object:Gem::Version
|
205
|
-
hash:
|
225
|
+
hash: 25
|
206
226
|
segments:
|
207
|
-
-
|
208
|
-
|
227
|
+
- 1
|
228
|
+
- 3
|
229
|
+
- 1
|
230
|
+
version: 1.3.1
|
209
231
|
requirements: []
|
210
232
|
|
211
233
|
rubyforge_project: nowarning
|