foreman 0.0.1
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/README.rdoc +77 -0
- data/Rakefile +60 -0
- data/bin/foreman +7 -0
- data/lib/foreman.rb +8 -0
- data/lib/foreman/cli.rb +50 -0
- data/lib/foreman/configuration.rb +59 -0
- data/lib/foreman/engine.rb +91 -0
- data/lib/foreman/export.rb +6 -0
- data/lib/foreman/export/upstart.rb +66 -0
- data/lib/foreman/process.rb +13 -0
- data/spec/foreman/cli_spec.rb +88 -0
- data/spec/foreman/configuration_spec.rb +2 -0
- data/spec/foreman/engine_spec.rb +2 -0
- data/spec/foreman/export/upstart_spec.rb +2 -0
- data/spec/foreman/export_spec.rb +2 -0
- data/spec/foreman/process_spec.rb +2 -0
- data/spec/foreman_spec.rb +11 -0
- data/spec/spec_helper.rb +36 -0
- metadata +186 -0
data/README.rdoc
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
= Foreman
|
2
|
+
|
3
|
+
=== Procfile
|
4
|
+
|
5
|
+
alpha ./bin/alpha
|
6
|
+
bravo ./bin/bravo some args
|
7
|
+
charlie ./bin/charlie -n 5
|
8
|
+
|
9
|
+
== Development mode
|
10
|
+
|
11
|
+
=== Running
|
12
|
+
|
13
|
+
$ 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
|
17
|
+
|
18
|
+
=== Standardized Logging
|
19
|
+
|
20
|
+
log/alpha.log
|
21
|
+
log/bravo.log
|
22
|
+
log/charlie.log
|
23
|
+
|
24
|
+
== Upstart
|
25
|
+
|
26
|
+
=== Export to upstart scripts
|
27
|
+
|
28
|
+
$ foreman export sampleapp
|
29
|
+
|
30
|
+
$ initctl list | grep sampleapp
|
31
|
+
sampleapp start/running
|
32
|
+
sampleapp-alpha (1) start/running, process 4204
|
33
|
+
sampleapp-bravo (1) start/running, process 4589
|
34
|
+
sampleapp-charlie (1) start/running, process 4597
|
35
|
+
|
36
|
+
=== Change process concurrency levels
|
37
|
+
|
38
|
+
$ foreman scale sampleapp alpha 4
|
39
|
+
sampleapp-alpha (2) start/running, process 4164
|
40
|
+
sampleapp-alpha (3) start/running, process 4166
|
41
|
+
sampleapp-alpha (4) start/running, process 4168
|
42
|
+
|
43
|
+
$ initctl list | grep sampleapp
|
44
|
+
sampleapp start/running
|
45
|
+
sampleapp-alpha (4) start/running, process 4168
|
46
|
+
sampleapp-alpha (3) start/running, process 4166
|
47
|
+
sampleapp-alpha (2) start/running, process 4164
|
48
|
+
sampleapp-alpha (1) start/running, process 4204
|
49
|
+
sampleapp-bravo (1) start/running, process 4589
|
50
|
+
sampleapp-charlie (1) start/running, process 4597
|
51
|
+
|
52
|
+
$ foreman scale sampleapp alpha 1
|
53
|
+
sampleapp-alpha stop/waiting
|
54
|
+
sampleapp-alpha stop/waiting
|
55
|
+
sampleapp-alpha stop/waiting
|
56
|
+
|
57
|
+
=== Good Upstart citizen
|
58
|
+
|
59
|
+
All Upstart commands work as expected
|
60
|
+
|
61
|
+
$ start sampleapp
|
62
|
+
$ stop sampleapp
|
63
|
+
$ restart sampleapp
|
64
|
+
|
65
|
+
=== Standardized Logging
|
66
|
+
|
67
|
+
/var/log/sampleapp/alpha.log
|
68
|
+
/var/log/sampleapp/bravo.log
|
69
|
+
/var/log/sampleapp/charlie.log
|
70
|
+
|
71
|
+
== License
|
72
|
+
|
73
|
+
MIT
|
74
|
+
|
75
|
+
== Copyright
|
76
|
+
|
77
|
+
(c) 2010 David Dollar
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
|
5
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
6
|
+
require "foreman"
|
7
|
+
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
desc "Run all specs"
|
11
|
+
Rspec::Core::RakeTask.new(:spec) do |t|
|
12
|
+
t.pattern = 'spec/**/*_spec.rb'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Generate RCov code coverage report"
|
16
|
+
task :rcov => "rcov:build" do
|
17
|
+
%x{ open coverage/index.html }
|
18
|
+
end
|
19
|
+
|
20
|
+
Rspec::Core::RakeTask.new("rcov:build") do |t|
|
21
|
+
t.pattern = 'spec/**/*_spec.rb'
|
22
|
+
t.rcov = true
|
23
|
+
t.rcov_opts = [ "--exclude", Gem.default_dir , "--exclude", "spec" ]
|
24
|
+
end
|
25
|
+
|
26
|
+
######################################################
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'jeweler'
|
30
|
+
Jeweler::Tasks.new do |s|
|
31
|
+
s.name = "foreman"
|
32
|
+
s.version = Foreman::VERSION
|
33
|
+
|
34
|
+
s.summary = "Process manager for applications with multiple components"
|
35
|
+
s.description = s.summary
|
36
|
+
s.author = "David Dollar"
|
37
|
+
s.email = "ddollar@gmail.com"
|
38
|
+
s.homepage = "http://github.com/ddollar/foreman"
|
39
|
+
|
40
|
+
s.platform = Gem::Platform::RUBY
|
41
|
+
s.has_rdoc = false
|
42
|
+
|
43
|
+
s.files = %w(Rakefile README.md) + Dir["{bin,lib,spec}/**/*"]
|
44
|
+
s.require_path = "lib"
|
45
|
+
|
46
|
+
# #s.bindir = "bin"
|
47
|
+
# s.executables = Dir["bin/*"]
|
48
|
+
s.default_executable = "foreman"
|
49
|
+
|
50
|
+
s.add_development_dependency 'fakefs', '~> 0.2.1'
|
51
|
+
s.add_development_dependency 'rake', '~> 0.8.7'
|
52
|
+
s.add_development_dependency 'rcov', '~> 0.9.8'
|
53
|
+
s.add_development_dependency 'rr', '~> 0.10.11'
|
54
|
+
s.add_development_dependency 'rspec', '~> 2.0.0'
|
55
|
+
|
56
|
+
s.add_dependency 'thor', '~> 0.13.6'
|
57
|
+
end
|
58
|
+
rescue LoadError
|
59
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
60
|
+
end
|
data/bin/foreman
ADDED
data/lib/foreman.rb
ADDED
data/lib/foreman/cli.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "foreman"
|
2
|
+
require "foreman/configuration"
|
3
|
+
require "foreman/engine"
|
4
|
+
require "foreman/export"
|
5
|
+
require "thor"
|
6
|
+
|
7
|
+
class Foreman::CLI < Thor
|
8
|
+
|
9
|
+
desc "start [PROCFILE]", "Run the app described in PROCFILE"
|
10
|
+
|
11
|
+
def start(procfile="Procfile")
|
12
|
+
error "#{procfile} does not exist." unless procfile_exists?(procfile)
|
13
|
+
Foreman::Engine.new(procfile).start
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "export APP [PROCFILE] [FORMAT]", "Export the app described in PROCFILE as APP to another FORMAT"
|
17
|
+
|
18
|
+
def export(app, procfile="Procfile", format="upstart")
|
19
|
+
error "#{procfile} does not exist." unless procfile_exists?(procfile)
|
20
|
+
|
21
|
+
formatter = case format
|
22
|
+
when "upstart" then Foreman::Export::Upstart
|
23
|
+
else error "Unknown export format: #{format}."
|
24
|
+
end
|
25
|
+
|
26
|
+
formatter.new(Foreman::Engine.new(procfile)).export(app)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "scale APP PROCESS AMOUNT", "Change the concurrency of a given process type"
|
30
|
+
|
31
|
+
def scale(app, process, amount)
|
32
|
+
config = Foreman::Configuration.new(app)
|
33
|
+
error "No such process: #{process}." unless config.processes[process]
|
34
|
+
config.scale(process, amount)
|
35
|
+
rescue Foreman::AppDoesNotExist
|
36
|
+
error "No such app: #{app}."
|
37
|
+
end
|
38
|
+
|
39
|
+
private ######################################################################
|
40
|
+
|
41
|
+
def error(message)
|
42
|
+
puts "ERROR: #{message}"
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def procfile_exists?(procfile)
|
47
|
+
File.exist?(procfile)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "foreman"
|
2
|
+
|
3
|
+
class Foreman::Configuration
|
4
|
+
|
5
|
+
attr_reader :app
|
6
|
+
attr_reader :processes
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
@processes = {}
|
11
|
+
read_initial_config
|
12
|
+
end
|
13
|
+
|
14
|
+
def scale(process, amount)
|
15
|
+
old_amount = processes[process].to_i
|
16
|
+
processes[process] = amount.to_i
|
17
|
+
amount = amount.to_i
|
18
|
+
|
19
|
+
if (old_amount < amount)
|
20
|
+
((old_amount + 1) .. amount).each { |num| run "start #{app}-#{process} NUM=#{num}" }
|
21
|
+
elsif (amount < old_amount)
|
22
|
+
((amount + 1) .. old_amount).each { |num| run "stop #{app}-#{process} NUM=#{num}" }
|
23
|
+
end
|
24
|
+
|
25
|
+
write
|
26
|
+
end
|
27
|
+
|
28
|
+
def write
|
29
|
+
write_file "/etc/foreman/#{app}.conf", <<-UPSTART_CONFIG
|
30
|
+
#{app}_processes="#{processes.keys.join(' ')}"
|
31
|
+
#{processes.keys.map { |k| "#{app}_#{k}=\"#{processes[k]}\"" }.join("\n")}
|
32
|
+
UPSTART_CONFIG
|
33
|
+
end
|
34
|
+
|
35
|
+
private ######################################################################
|
36
|
+
|
37
|
+
def read_initial_config
|
38
|
+
config = File.read("/etc/foreman/#{app}.conf").split("\n").inject({}) do |accum, line|
|
39
|
+
key, value = line.match(/^(.+?)\s*=\s*"(.+?)"\s*$/).captures
|
40
|
+
#accum.update(parts(1) => parts(2))
|
41
|
+
accum.update(key => value)
|
42
|
+
end
|
43
|
+
config["#{app}_processes"].split(" ").each do |process|
|
44
|
+
processes[process] = config["#{app}_#{process}"].to_i
|
45
|
+
end
|
46
|
+
rescue Errno::ENOENT
|
47
|
+
end
|
48
|
+
|
49
|
+
def run(command)
|
50
|
+
system command
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_file(filename, contents)
|
54
|
+
File.open(filename, "w") do |file|
|
55
|
+
file.puts contents
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "foreman"
|
2
|
+
require "foreman/process"
|
3
|
+
|
4
|
+
class Foreman::Engine
|
5
|
+
|
6
|
+
attr_reader :procfile
|
7
|
+
attr_reader :directory
|
8
|
+
|
9
|
+
def initialize(procfile)
|
10
|
+
@procfile = read_procfile(procfile)
|
11
|
+
@directory = File.expand_path(File.dirname(procfile))
|
12
|
+
end
|
13
|
+
|
14
|
+
def processes
|
15
|
+
@processes ||= begin
|
16
|
+
procfile.split("\n").inject({}) do |hash, line|
|
17
|
+
next if line.strip == ""
|
18
|
+
process = Foreman::Process.new(*line.split(" ", 2))
|
19
|
+
hash.update(process.name => process)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def start
|
25
|
+
proctitle "ruby: foreman master"
|
26
|
+
|
27
|
+
processes.each do |name, process|
|
28
|
+
fork process
|
29
|
+
end
|
30
|
+
|
31
|
+
trap("TERM") { kill_and_exit("TERM") }
|
32
|
+
trap("INT") { kill_and_exit("INT") }
|
33
|
+
|
34
|
+
while true
|
35
|
+
pid, status = Process.wait2
|
36
|
+
process = running_processes.delete(pid)
|
37
|
+
info "exited with code #{status}", process
|
38
|
+
fork process
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private ######################################################################
|
43
|
+
|
44
|
+
def fork(process)
|
45
|
+
pid = Process.fork do
|
46
|
+
proctitle "ruby: foreman #{process.name}"
|
47
|
+
|
48
|
+
Dir.chdir directory do
|
49
|
+
FileUtils.mkdir_p "log"
|
50
|
+
system "#{process.command} >>log/#{process.name}.log 2>&1"
|
51
|
+
exit $?.exitstatus || 255
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
info "started with pid #{pid}", process
|
56
|
+
running_processes[pid] = process
|
57
|
+
end
|
58
|
+
|
59
|
+
def kill_and_exit(signal="TERM")
|
60
|
+
info "termination requested"
|
61
|
+
running_processes.each do |pid, process|
|
62
|
+
info "killing pid #{pid}", process
|
63
|
+
Process.kill(signal, pid)
|
64
|
+
end
|
65
|
+
exit 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def info(message, process=nil)
|
69
|
+
puts "[foreman] [#{Time.now.utc}] [#{process ? process.name : "system"}] #{message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_info
|
73
|
+
info "currently running processes:"
|
74
|
+
running_processes.each do |pid, process|
|
75
|
+
info "pid #{pid}", process
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def read_procfile(procfile)
|
80
|
+
File.read(procfile)
|
81
|
+
end
|
82
|
+
|
83
|
+
def running_processes
|
84
|
+
@running_processes ||= {}
|
85
|
+
end
|
86
|
+
|
87
|
+
def proctitle(title)
|
88
|
+
$0 = title
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "foreman/configuration"
|
2
|
+
require "foreman/export"
|
3
|
+
|
4
|
+
class Foreman::Export::Upstart
|
5
|
+
|
6
|
+
attr_reader :engine
|
7
|
+
|
8
|
+
def initialize(engine)
|
9
|
+
@engine = engine
|
10
|
+
end
|
11
|
+
|
12
|
+
def export(app)
|
13
|
+
FileUtils.mkdir_p "/etc/foreman"
|
14
|
+
FileUtils.mkdir_p "/etc/init"
|
15
|
+
|
16
|
+
config = Foreman::Configuration.new(app)
|
17
|
+
|
18
|
+
engine.processes.each do |name, process|
|
19
|
+
config.scale(name, 1)
|
20
|
+
end
|
21
|
+
config.write
|
22
|
+
|
23
|
+
write_file "/etc/init/#{app}.conf", <<-UPSTART_MASTER
|
24
|
+
pre-start script
|
25
|
+
|
26
|
+
bash << "EOF"
|
27
|
+
mkdir -p /var/log/#{app}
|
28
|
+
|
29
|
+
if [ -f /etc/foreman/#{app}.conf ]; then
|
30
|
+
source /etc/foreman/#{app}.conf
|
31
|
+
fi
|
32
|
+
|
33
|
+
for process in $( echo "$#{app}_processes" ); do
|
34
|
+
process_count_config="#{app}_$process"
|
35
|
+
process_count=${!process_count_config}
|
36
|
+
|
37
|
+
for ((i=1; i<=${process_count:=1}; i+=1)); do
|
38
|
+
start #{app}-$process NUM=$i
|
39
|
+
done
|
40
|
+
done
|
41
|
+
EOF
|
42
|
+
|
43
|
+
end script
|
44
|
+
UPSTART_MASTER
|
45
|
+
|
46
|
+
engine.processes.values.each do |process|
|
47
|
+
write_file "/etc/init/#{app}-#{process.name}.conf", <<-UPSTART_CHILD
|
48
|
+
instance $NUM
|
49
|
+
stop on stopping #{app}
|
50
|
+
respawn
|
51
|
+
|
52
|
+
chdir #{engine.directory}
|
53
|
+
exec #{process.command} >>/var/log/#{app}/#{process.name}.log 2>&1
|
54
|
+
UPSTART_CHILD
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private ######################################################################
|
59
|
+
|
60
|
+
def write_file(filename, contents)
|
61
|
+
File.open(filename, "w") do |file|
|
62
|
+
file.puts contents
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "foreman/cli"
|
3
|
+
|
4
|
+
describe "Foreman::CLI" do
|
5
|
+
subject { Foreman::CLI.new }
|
6
|
+
|
7
|
+
describe "start" do
|
8
|
+
#let(:engine) { stub_engine }
|
9
|
+
|
10
|
+
describe "with a non-existent Procifile" do
|
11
|
+
it "prints an error" do
|
12
|
+
mock_error(subject, "Procfile does not exist.") do
|
13
|
+
dont_allow.instance_of(Foreman::Engine).start
|
14
|
+
subject.start
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "with a Procfile" do
|
20
|
+
before(:each) { write_procfile }
|
21
|
+
|
22
|
+
it "runs successfully" do
|
23
|
+
dont_allow(subject).error
|
24
|
+
mock.instance_of(Foreman::Engine).start
|
25
|
+
subject.start
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "export" do
|
31
|
+
describe "with a non-existent Procifile" do
|
32
|
+
it "prints an error" do
|
33
|
+
mock_error(subject, "Procfile does not exist.") do
|
34
|
+
dont_allow.instance_of(Foreman::Engine).export
|
35
|
+
subject.export("testapp")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "with a Procfile" do
|
41
|
+
before(:each) { write_procfile }
|
42
|
+
|
43
|
+
describe "with an invalid formatter" do
|
44
|
+
it "prints an error" do
|
45
|
+
mock_error(subject, "Unknown export format: invalidformatter.") do
|
46
|
+
subject.export("testapp", "Procfile", "invalidformatter")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "with a valid config" do
|
52
|
+
before(:each) { write_foreman_config("testapp") }
|
53
|
+
|
54
|
+
it "runs successfully" do
|
55
|
+
dont_allow(subject).error
|
56
|
+
subject.export("testapp")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "scale" do
|
63
|
+
describe "without an existing configuration" do
|
64
|
+
it "displays an error" do
|
65
|
+
mock_error(subject, "No such app: testapp.") do
|
66
|
+
subject.scale("testapp", "alpha", "2")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "with an existing configuration" do
|
72
|
+
before(:each) { write_foreman_config("testapp") }
|
73
|
+
|
74
|
+
it "scales a process that exists" do
|
75
|
+
mock.instance_of(Foreman::Configuration).scale("alpha", "2")
|
76
|
+
subject.scale("testapp", "alpha", "2")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "errors if a process that does not exist is specified" do
|
80
|
+
mock_error(subject, "No such process: invalidprocess.") do
|
81
|
+
dont_allow.instance_of(Foreman::Configuration).scale
|
82
|
+
subject.scale("testapp", "invalidprocess", "2")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "fakefs/spec_helpers"
|
2
|
+
require "rspec"
|
3
|
+
|
4
|
+
$:.unshift "lib"
|
5
|
+
|
6
|
+
def mock_error(subject, message)
|
7
|
+
mock_exit do
|
8
|
+
mock(subject).puts("ERROR: #{message}")
|
9
|
+
yield
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock_exit(&block)
|
14
|
+
block.should raise_error(SystemExit)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_foreman_config(app)
|
18
|
+
File.open("/etc/foreman/#{app}.conf", "w") do |file|
|
19
|
+
file.puts %{#{app}_processes="alpha bravo"}
|
20
|
+
file.puts %{#{app}_alpha="1"}
|
21
|
+
file.puts %{#{app}_bravo="2"}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_procfile(procfile="Procfile")
|
26
|
+
File.open(procfile, "w") do |file|
|
27
|
+
file.puts "alpha ./alpha"
|
28
|
+
file.puts "bravo ./bravo"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Rspec.configure do |config|
|
33
|
+
config.color_enabled = true
|
34
|
+
config.include FakeFS::SpecHelpers
|
35
|
+
config.mock_with :rr
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: foreman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- David Dollar
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-05-20 00:00:00 -04:00
|
19
|
+
default_executable: foreman
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: fakefs
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 21
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 2
|
33
|
+
- 1
|
34
|
+
version: 0.2.1
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 49
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 8
|
49
|
+
- 7
|
50
|
+
version: 0.8.7
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rcov
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 43
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 9
|
65
|
+
- 8
|
66
|
+
version: 0.9.8
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rr
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 33
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 10
|
81
|
+
- 11
|
82
|
+
version: 0.10.11
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rspec
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 15
|
94
|
+
segments:
|
95
|
+
- 2
|
96
|
+
- 0
|
97
|
+
- 0
|
98
|
+
version: 2.0.0
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: thor
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 39
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
- 13
|
113
|
+
- 6
|
114
|
+
version: 0.13.6
|
115
|
+
type: :runtime
|
116
|
+
version_requirements: *id006
|
117
|
+
description: Process manager for applications with multiple components
|
118
|
+
email: ddollar@gmail.com
|
119
|
+
executables:
|
120
|
+
- foreman
|
121
|
+
extensions: []
|
122
|
+
|
123
|
+
extra_rdoc_files:
|
124
|
+
- README.rdoc
|
125
|
+
files:
|
126
|
+
- Rakefile
|
127
|
+
- bin/foreman
|
128
|
+
- lib/foreman.rb
|
129
|
+
- lib/foreman/cli.rb
|
130
|
+
- lib/foreman/configuration.rb
|
131
|
+
- lib/foreman/engine.rb
|
132
|
+
- lib/foreman/export.rb
|
133
|
+
- lib/foreman/export/upstart.rb
|
134
|
+
- lib/foreman/process.rb
|
135
|
+
- spec/foreman/cli_spec.rb
|
136
|
+
- spec/foreman/configuration_spec.rb
|
137
|
+
- spec/foreman/engine_spec.rb
|
138
|
+
- spec/foreman/export/upstart_spec.rb
|
139
|
+
- spec/foreman/export_spec.rb
|
140
|
+
- spec/foreman/process_spec.rb
|
141
|
+
- spec/foreman_spec.rb
|
142
|
+
- spec/spec_helper.rb
|
143
|
+
- README.rdoc
|
144
|
+
has_rdoc: false
|
145
|
+
homepage: http://github.com/ddollar/foreman
|
146
|
+
licenses: []
|
147
|
+
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options:
|
150
|
+
- --charset=UTF-8
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
hash: 3
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
version: "0"
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
hash: 3
|
168
|
+
segments:
|
169
|
+
- 0
|
170
|
+
version: "0"
|
171
|
+
requirements: []
|
172
|
+
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 1.3.7
|
175
|
+
signing_key:
|
176
|
+
specification_version: 3
|
177
|
+
summary: Process manager for applications with multiple components
|
178
|
+
test_files:
|
179
|
+
- spec/foreman/cli_spec.rb
|
180
|
+
- spec/foreman/configuration_spec.rb
|
181
|
+
- spec/foreman/engine_spec.rb
|
182
|
+
- spec/foreman/export/upstart_spec.rb
|
183
|
+
- spec/foreman/export_spec.rb
|
184
|
+
- spec/foreman/process_spec.rb
|
185
|
+
- spec/foreman_spec.rb
|
186
|
+
- spec/spec_helper.rb
|