foreman 0.3.2 → 0.4.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/Rakefile CHANGED
@@ -6,6 +6,7 @@ $:.unshift File.expand_path("../lib", __FILE__)
6
6
  require "foreman"
7
7
 
8
8
  task :default => :spec
9
+ task :release => :man
9
10
 
10
11
  desc "Run all specs"
11
12
  Rspec::Core::RakeTask.new(:spec) do |t|
@@ -23,6 +24,16 @@ Rspec::Core::RakeTask.new("rcov:build") do |t|
23
24
  t.rcov_opts = [ "--exclude", Gem.default_dir , "--exclude", "spec" ]
24
25
  end
25
26
 
27
+ desc 'Build the manual'
28
+ task :man do
29
+ require 'ronn'
30
+ ENV['RONN_MANUAL'] = "Foreman Manual"
31
+ ENV['RONN_ORGANIZATION'] = "Foreman #{Foreman::VERSION}"
32
+ sh "ronn -w -s toc -r5 --markdown man/*.ronn"
33
+ sh "git add man/*.?"
34
+ sh "git commit -m \"updating man pages\""
35
+ end
36
+
26
37
  ######################################################
27
38
 
28
39
  begin
data/lib/foreman.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.3.2"
3
+ VERSION = "0.4.1"
4
4
 
5
5
  class AppDoesNotExist < Exception; end
6
6
 
data/lib/foreman/cli.rb CHANGED
@@ -6,46 +6,58 @@ require "thor"
6
6
 
7
7
  class Foreman::CLI < Thor
8
8
 
9
- desc "start [PROCFILE]", "Run the app described in PROCFILE"
9
+ class_option :procfile, :type => :string, :aliases => "-p", :desc => "Default: ./Procfile"
10
10
 
11
- def start(procfile="Procfile")
12
- error "#{procfile} does not exist." unless procfile_exists?(procfile)
13
- Foreman::Engine.new(procfile).start
14
- end
11
+ desc "start [PROCESS]", "Start the application, or a specific process"
15
12
 
16
- desc "execute PROCESS [PROCFILE]", "Run an instance of the specified process from PROCFILE"
13
+ method_option :screen, :type => :boolean, :aliases => "-s"
17
14
 
18
- def execute(process, procfile="Procfile")
19
- error "#{procfile} does not exist." unless procfile_exists?(procfile)
20
- Foreman::Engine.new(procfile).execute(process)
15
+ def start(process=nil)
16
+ check_procfile!
17
+
18
+ if process
19
+ engine.execute(process)
20
+ elsif options[:screen]
21
+ engine.screen
22
+ else
23
+ engine.start
24
+ end
21
25
  end
22
26
 
23
- desc "screen [PROCFILE]", "Run the app described in PROCFILE as screen windows"
27
+ desc "export FORMAT LOCATION", "Export the application to another process management format"
24
28
 
25
- def screen(procfile="Procfile")
26
- error "#{procfile} does not exist." unless procfile_exists?(procfile)
27
- Foreman::Engine.new(procfile).screen
28
- end
29
+ method_option :app, :type => :string, :aliases => "-a"
30
+ method_option :concurrency, :type => :string, :aliases => "-c",
31
+ :banner => '"alpha=5,bar=3"'
29
32
 
30
- desc "export APP [PROCFILE] [FORMAT]", "Export the app described in PROCFILE as APP to another FORMAT"
31
-
32
- def export(app, procfile="Procfile", format="upstart")
33
- error "#{procfile} does not exist." unless procfile_exists?(procfile)
33
+ def export(format, location=nil)
34
+ check_procfile!
34
35
 
35
36
  formatter = case format
36
37
  when "upstart" then Foreman::Export::Upstart
37
38
  else error "Unknown export format: #{format}."
38
39
  end
39
40
 
40
- formatter.new(Foreman::Engine.new(procfile)).export(app)
41
+ formatter.new(engine).export(location,
42
+ :name => options[:app],
43
+ :concurrency => options[:concurrency]
44
+ )
45
+ rescue Foreman::Export::Exception => ex
46
+ error ex.message
41
47
  end
42
48
 
43
- desc "scale APP PROCESS AMOUNT", "Change the concurrency of a given process type"
49
+ private ######################################################################
50
+
51
+ def check_procfile!
52
+ error("Procfile does not exist.") unless File.exist?(procfile)
53
+ end
54
+
55
+ def engine
56
+ @engine ||= Foreman::Engine.new(procfile)
57
+ end
44
58
 
45
- def scale(app, process, amount)
46
- config = Foreman::Configuration.new(app)
47
- error "No such process: #{process}." unless config.processes[process]
48
- config.scale(process, amount)
59
+ def procfile
60
+ options[:procfile] || "./Procfile"
49
61
  end
50
62
 
51
63
  private ######################################################################
@@ -83,8 +83,8 @@ private ######################################################################
83
83
  info stdin.gets, process
84
84
  end
85
85
  end
86
- rescue PTY::ChildExited
87
- # exited
86
+ rescue PTY::ChildExited, Interrupt
87
+ info "process exiting", process
88
88
  end
89
89
  end
90
90
  end
@@ -1,6 +1,7 @@
1
1
  require "foreman"
2
2
 
3
3
  module Foreman::Export
4
+ class Exception < ::Exception; end
4
5
  end
5
6
 
6
7
  require "foreman/export/upstart"
@@ -0,0 +1,48 @@
1
+ require "foreman/configuration"
2
+ require "foreman/export"
3
+
4
+ class Foreman::Export::Base
5
+
6
+ attr_reader :engine
7
+
8
+ def initialize(engine)
9
+ @engine = engine
10
+ end
11
+
12
+ def export
13
+ raise "export method must be overridden"
14
+ end
15
+
16
+ private ######################################################################
17
+
18
+ def error(message)
19
+ raise Foreman::Export::Exception.new(message)
20
+ end
21
+
22
+ def say(message)
23
+ puts "[foreman export] %s" % message
24
+ end
25
+
26
+ def export_template(name)
27
+ File.read(File.expand_path("../../../../export/#{name}", __FILE__))
28
+ end
29
+
30
+ def parse_concurrency(concurrency)
31
+ @concurrency ||= begin
32
+ pairs = concurrency.to_s.gsub(/\s/, "").split(",")
33
+ pairs.inject(Hash.new(1)) do |hash, pair|
34
+ process, amount = pair.split("=")
35
+ hash.update(process => amount.to_i)
36
+ end
37
+ end
38
+ end
39
+
40
+ def write_file(filename, contents)
41
+ say "writing: #{filename}"
42
+
43
+ File.open(filename, "w") do |file|
44
+ file.puts contents
45
+ end
46
+ end
47
+
48
+ end
@@ -1,51 +1,42 @@
1
+ require "erb"
1
2
  require "foreman/configuration"
2
- require "foreman/export"
3
+ require "foreman/export/base"
3
4
 
4
- class Foreman::Export::Upstart
5
+ class Foreman::Export::Upstart < Foreman::Export::Base
5
6
 
6
- attr_reader :engine
7
+ def export(location, options={})
8
+ error("Must specify a location") unless location
7
9
 
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)
10
+ FileUtils.mkdir_p location
17
11
 
18
- write_file "/etc/init/#{app}.conf", <<-UPSTART_MASTER
19
- pre-start script
12
+ app = options[:app] || File.basename(engine.directory)
20
13
 
21
- bash << "EOF"
22
- mkdir -p /var/log/#{app}
14
+ Dir["#{location}/#{app}*.conf"].each do |file|
15
+ say "cleaning up: #{file}"
16
+ FileUtils.rm(file)
17
+ end
23
18
 
24
- if [ -f /etc/foreman/#{app}.conf ]; then
25
- source /etc/foreman/#{app}.conf
26
- fi
19
+ concurrency = parse_concurrency(options[:concurrency])
27
20
 
28
- for process in $( echo "$#{app}_processes" ); do
29
- process_count_config="#{app}_$process"
30
- process_count=${!process_count_config}
21
+ master_template = export_template("upstart/master.conf.erb")
22
+ master_config = ERB.new(master_template).result(binding)
23
+ write_file "#{location}/#{app}.conf", master_config
31
24
 
32
- for ((i=1; i<=${process_count:=1}; i+=1)); do
33
- start #{app}-$process NUM=$i
34
- done
35
- done
36
- EOF
25
+ process_template = export_template("upstart/process.conf.erb")
26
+
27
+ engine.processes.values.each do |process|
28
+ 1.upto(concurrency[process.name]) do |num|
29
+ process_config = ERB.new(process_template).result(binding)
30
+ write_file "#{location}/#{app}-#{process.name}-#{num}.conf", process_config
31
+ end
32
+ end
37
33
 
38
- end script
34
+ return
35
+ write_file "#{location}/#{app}.conf", <<-UPSTART_MASTER
39
36
  UPSTART_MASTER
40
37
 
41
- engine.processes.values.each do |process|
42
- write_file "/etc/init/#{app}-#{process.name}.conf", <<-UPSTART_CHILD
43
- instance $NUM
44
- stop on stopping #{app}
45
- respawn
46
-
47
- chdir #{engine.directory}
48
- exec #{process.command} >>/var/log/#{app}/#{process.name}.log 2>&1
38
+ engine.processes.each do |process|
39
+ write_file process_conf, <<-UPSTART_CHILD
49
40
  UPSTART_CHILD
50
41
  end
51
42
 
@@ -55,12 +46,4 @@ exec #{process.command} >>/var/log/#{app}/#{process.name}.log 2>&1
55
46
  config.write
56
47
  end
57
48
 
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
49
  end
@@ -25,27 +25,6 @@ describe "Foreman::CLI" do
25
25
  end
26
26
  end
27
27
 
28
- describe "execute" do
29
- describe "with a non-existent Procfile" do
30
- it "prints an error" do
31
- mock_error(subject, "Procfile does not exist.") do
32
- dont_allow.instance_of(Foreman::Engine).start
33
- subject.execute("alpha")
34
- end
35
- end
36
- end
37
-
38
- describe "with a Procfile" do
39
- before(:each) { write_procfile }
40
-
41
- it "runs successfully" do
42
- dont_allow(subject).error
43
- mock.instance_of(Foreman::Engine).execute("alpha")
44
- subject.execute("alpha")
45
- end
46
- end
47
- end
48
-
49
28
  describe "export" do
50
29
  describe "with a non-existent Procfile" do
51
30
  it "prints an error" do
@@ -62,7 +41,7 @@ describe "Foreman::CLI" do
62
41
  describe "with an invalid formatter" do
63
42
  it "prints an error" do
64
43
  mock_error(subject, "Unknown export format: invalidformatter.") do
65
- subject.export("testapp", "Procfile", "invalidformatter")
44
+ subject.export("invalidformatter")
66
45
  end
67
46
  end
68
47
  end
@@ -72,33 +51,11 @@ describe "Foreman::CLI" do
72
51
 
73
52
  it "runs successfully" do
74
53
  dont_allow(subject).error
75
- subject.export("testapp")
76
- end
77
- end
78
- end
79
- end
80
-
81
- describe "scale" do
82
- describe "without an existing configuration" do
83
- it "displays an error" do
84
- mock_error(subject, "No such process: alpha.") do
85
- subject.scale("testapp", "alpha", "2")
86
- end
87
- end
88
- end
89
-
90
- describe "with an existing configuration" do
91
- before(:each) { write_foreman_config("testapp") }
92
-
93
- it "scales a process that exists" do
94
- mock.instance_of(Foreman::Configuration).scale("alpha", "2")
95
- subject.scale("testapp", "alpha", "2")
96
- end
97
-
98
- it "errors if a process that does not exist is specified" do
99
- mock_error(subject, "No such process: invalidprocess.") do
100
- dont_allow.instance_of(Foreman::Configuration).scale
101
- subject.scale("testapp", "invalidprocess", "2")
54
+ mock.instance_of(Foreman::Export::Upstart).export("/tmp/foo", {
55
+ :concurrency => nil,
56
+ :name => nil
57
+ })
58
+ subject.export("upstart", "/tmp/foo")
102
59
  end
103
60
  end
104
61
  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: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 2
10
- version: 0.3.2
8
+ - 4
9
+ - 1
10
+ version: 0.4.1
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-22 00:00:00 -04:00
18
+ date: 2010-06-23 00:00:00 -04:00
19
19
  default_executable: foreman
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -146,6 +146,7 @@ files:
146
146
  - lib/foreman/configuration.rb
147
147
  - lib/foreman/engine.rb
148
148
  - lib/foreman/export.rb
149
+ - lib/foreman/export/base.rb
149
150
  - lib/foreman/export/upstart.rb
150
151
  - lib/foreman/process.rb
151
152
  - spec/foreman/cli_spec.rb