foreman 0.25.0 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ LOG=<%= log_root %>/<%= process.name %>-<%= num %>
5
+
6
+ test -d "$LOG" || mkdir -p m2750 "$LOG" && chown <%= user %> "$LOG"
7
+ exec chpst -u <%= user %> svlogd "$LOG"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ cd <%= engine.directory %>
3
+ exec chpst -u <%= user %> -e <%= process_env_directory %> <%= process.command %>
data/lib/foreman/cli.rb CHANGED
@@ -42,6 +42,7 @@ class Foreman::CLI < Thor
42
42
  when "inittab" then Foreman::Export::Inittab
43
43
  when "upstart" then Foreman::Export::Upstart
44
44
  when "bluepill" then Foreman::Export::Bluepill
45
+ when "runit" then Foreman::Export::Runit
45
46
  else error "Unknown export format: #{format}."
46
47
  end
47
48
 
@@ -28,6 +28,7 @@ class Foreman::Engine
28
28
 
29
29
  def start
30
30
  proctitle "ruby: foreman master"
31
+ termtitle "#{File.basename(@directory)} - foreman (#{processes.size} processes)"
31
32
 
32
33
  processes.each do |process|
33
34
  process.color = next_color
@@ -41,6 +42,7 @@ class Foreman::Engine
41
42
  end
42
43
 
43
44
  def execute(name)
45
+ error "no such process: #{name}" unless procfile[name]
44
46
  fork procfile[name]
45
47
 
46
48
  trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
@@ -96,7 +98,7 @@ private ######################################################################
96
98
  end
97
99
  end
98
100
  end
99
- rescue PTY::ChildExited, Interrupt, Errno::EIO
101
+ rescue PTY::ChildExited, Interrupt, Errno::EIO, Errno::ENOENT
100
102
  begin
101
103
  info "process exiting", process
102
104
  rescue Interrupt
@@ -158,6 +160,10 @@ private ######################################################################
158
160
  $0 = title
159
161
  end
160
162
 
163
+ def termtitle(title)
164
+ printf("\033]0;#{title}\007")
165
+ end
166
+
161
167
  def running_processes
162
168
  @running_processes ||= {}
163
169
  end
@@ -8,3 +8,4 @@ require "foreman/export/base"
8
8
  require "foreman/export/inittab"
9
9
  require "foreman/export/upstart"
10
10
  require "foreman/export/bluepill"
11
+ require "foreman/export/runit"
@@ -23,7 +23,6 @@ class Foreman::Export::Bluepill < Foreman::Export::Base
23
23
  master_template = export_template("bluepill", "master.pill.erb", template_root)
24
24
  master_config = ERB.new(master_template).result(binding)
25
25
  write_file "#{location}/#{app}.pill", master_config
26
-
27
26
  end
28
27
 
29
28
  end
@@ -12,7 +12,7 @@ class Foreman::Export::Inittab < Foreman::Export::Base
12
12
  inittab = []
13
13
  inittab << "# ----- foreman #{app} processes -----"
14
14
 
15
- engine.processes.values.inject(1) do |index, process|
15
+ engine.processes.inject(1) do |index, process|
16
16
  1.upto(concurrency[process.name]) do |num|
17
17
  id = app.slice(0, 2).upcase + sprintf("%02d", index)
18
18
  port = engine.port_for(process, num, options[:port])
@@ -0,0 +1,60 @@
1
+ require "erb"
2
+ require "foreman/export"
3
+
4
+ class Foreman::Export::Runit < Foreman::Export::Base
5
+ ENV_VARIABLE_REGEX = /([a-zA-Z_]+[a-zA-Z0-9_]*)=(\S+)/
6
+
7
+ def export(location, options={})
8
+ error("Must specify a location") unless location
9
+
10
+ app = options[:app] || File.basename(engine.directory)
11
+ user = options[:user] || app
12
+ log_root = options[:log] || "/var/log/#{app}"
13
+ template_root = options[:template]
14
+
15
+ concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
16
+
17
+ run_template = export_template('runit', 'run.erb', template_root)
18
+ log_run_template = export_template('runit', 'log_run.erb', template_root)
19
+
20
+ engine.processes.each do |process|
21
+ 1.upto(concurrency[process.name]) do |num|
22
+ process_directory = "#{location}/#{app}-#{process.name}-#{num}"
23
+ process_env_directory = "#{process_directory}/env"
24
+ process_log_directory = "#{process_directory}/log"
25
+
26
+ create_directory process_directory
27
+ create_directory process_env_directory
28
+ create_directory process_log_directory
29
+
30
+ run = ERB.new(run_template).result(binding)
31
+ write_file "#{process_directory}/run", run
32
+
33
+ port = engine.port_for(process, num, options[:port])
34
+ environment_variables = {'PORT' => port}.
35
+ merge(engine.environment).
36
+ merge(inline_variables(process.command))
37
+
38
+ environment_variables.each_pair do |var, env|
39
+ write_file "#{process_env_directory}/#{var.upcase}", env
40
+ end
41
+
42
+ log_run = ERB.new(log_run_template).result(binding)
43
+ write_file "#{process_log_directory}/run", log_run
44
+
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ private
51
+ def create_directory(location)
52
+ say "creating: #{location}"
53
+ FileUtils.mkdir(location)
54
+ end
55
+
56
+ def inline_variables(command)
57
+ variable_name_regex =
58
+ Hash[*command.scan(ENV_VARIABLE_REGEX).flatten]
59
+ end
60
+ end
@@ -27,6 +27,7 @@ class Foreman::Export::Upstart < Foreman::Export::Base
27
27
  process_template = export_template("upstart", "process.conf.erb", template_root)
28
28
 
29
29
  engine.processes.each do |process|
30
+ next if (conc = concurrency[process.name]) < 1
30
31
  process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
31
32
  process_master_config = ERB.new(process_master_template).result(binding)
32
33
  write_file "#{location}/#{app}-#{process.name}.conf", process_master_config
data/lib/foreman/utils.rb CHANGED
@@ -3,7 +3,7 @@ require "foreman"
3
3
  class Foreman::Utils
4
4
 
5
5
  def self.parse_concurrency(concurrency)
6
- @concurrency ||= begin
6
+ begin
7
7
  pairs = concurrency.to_s.gsub(/\s/, "").split(",")
8
8
  pairs.inject(Hash.new(1)) do |hash, pair|
9
9
  process, amount = pair.split("=")
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.25.0"
3
+ VERSION = "0.26.0"
4
4
 
5
5
  end
data/man/foreman.1 CHANGED
@@ -1,7 +1,7 @@
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" "September 2011" "Foreman 0.23.0" "Foreman Manual"
4
+ .TH "FOREMAN" "1" "November 2011" "Foreman 0.25.0" "Foreman Manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBforeman\fR \- manage Procfile\-based applications
@@ -132,7 +132,7 @@ job: bundle exec rake jobs:work
132
132
  .IP "" 0
133
133
  .
134
134
  .P
135
- You can validate your Procfile format using the \fBcheck\fR command
135
+ A process name may contain letters, numbers amd the underscore character\. You can validate your Procfile format using the \fBcheck\fR command:
136
136
  .
137
137
  .IP "" 4
138
138
  .
@@ -48,6 +48,12 @@ describe "Foreman::Engine" do
48
48
  mock(subject).watch_for_termination
49
49
  subject.execute("alpha")
50
50
  end
51
+
52
+ it "shows an error running a process that doesnt exist" do
53
+ write_procfile
54
+ mock(subject).puts("ERROR: no such process: foo")
55
+ lambda { subject.execute("foo") }.should raise_error(SystemExit)
56
+ end
51
57
  end
52
58
 
53
59
  describe "environment" do
@@ -12,7 +12,7 @@ describe Foreman::Export::Bluepill do
12
12
  before(:each) { stub(bluepill).say }
13
13
 
14
14
  it "exports to the filesystem" do
15
- bluepill.export("/tmp/init")
15
+ bluepill.export("/tmp/init", :concurrency => "alpha=2")
16
16
 
17
17
  File.read("/tmp/init/app.pill").should == example_export_file("bluepill/app.pill")
18
18
  end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+ require "foreman/engine"
3
+ require "foreman/export/runit"
4
+ require "tmpdir"
5
+
6
+ describe Foreman::Export::Runit do
7
+ let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", 'bar=baz') }
8
+ let(:engine) { Foreman::Engine.new(procfile) }
9
+ let(:runit) { Foreman::Export::Runit.new(engine) }
10
+
11
+ before(:each) { load_export_templates_into_fakefs("runit") }
12
+ before(:each) { stub(runit).say }
13
+
14
+ it "exports to the filesystem" do
15
+ FileUtils.mkdir_p('/tmp/init')
16
+ runit.export('/tmp/init', :concurrency => 'alpha=2')
17
+
18
+ File.read("/tmp/init/app-alpha-1/run").should == example_export_file('runit/app-alpha-1-run')
19
+ File.read("/tmp/init/app-alpha-1/log/run").should ==
20
+ example_export_file('runit/app-alpha-1-log-run')
21
+ File.read("/tmp/init/app-alpha-1/env/PORT").should == "5000\n"
22
+ File.read("/tmp/init/app-alpha-1/env/BAR").should == "baz\n"
23
+
24
+ File.read("/tmp/init/app-alpha-2/run").should == example_export_file('runit/app-alpha-2-run')
25
+ File.read("/tmp/init/app-alpha-2/log/run").should ==
26
+ example_export_file('runit/app-alpha-2-log-run')
27
+ File.read("/tmp/init/app-alpha-2/env/PORT").should == "5001\n"
28
+ File.read("/tmp/init/app-alpha-2/env/BAR").should == "baz\n"
29
+
30
+ File.read("/tmp/init/app-bravo-1/run").should == example_export_file('runit/app-bravo-1-run')
31
+ File.read("/tmp/init/app-bravo-1/log/run").should ==
32
+ example_export_file('runit/app-bravo-1-log-run')
33
+ File.read("/tmp/init/app-bravo-1/env/PORT").should == "5100\n"
34
+ end
35
+ end
@@ -12,7 +12,7 @@ describe Foreman::Export::Upstart do
12
12
  before(:each) { stub(upstart).say }
13
13
 
14
14
  it "exports to the filesystem" do
15
- upstart.export("/tmp/init")
15
+ upstart.export("/tmp/init", :concurrency => "alpha=2")
16
16
 
17
17
  File.read("/tmp/init/app.conf").should == example_export_file("upstart/app.conf")
18
18
  File.read("/tmp/init/app-alpha.conf").should == example_export_file("upstart/app-alpha.conf")
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ LOG=/var/log/app/alpha-1
5
+
6
+ test -d "$LOG" || mkdir -p m2750 "$LOG" && chown app "$LOG"
7
+ exec chpst -u app svlogd "$LOG"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ cd /tmp/app
3
+ exec chpst -u app -e /tmp/init/app-alpha-1/env ./alpha bar=baz
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ LOG=/var/log/app/alpha-2
5
+
6
+ test -d "$LOG" || mkdir -p m2750 "$LOG" && chown app "$LOG"
7
+ exec chpst -u app svlogd "$LOG"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ cd /tmp/app
3
+ exec chpst -u app -e /tmp/init/app-alpha-2/env ./alpha bar=baz
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ LOG=/var/log/app/bravo-1
5
+
6
+ test -d "$LOG" || mkdir -p m2750 "$LOG" && chown app "$LOG"
7
+ exec chpst -u app svlogd "$LOG"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ cd /tmp/app
3
+ exec chpst -u app -e /tmp/init/app-bravo-1/env ./bravo
data/spec/spec_helper.rb CHANGED
@@ -28,9 +28,9 @@ def write_foreman_config(app)
28
28
  end
29
29
  end
30
30
 
31
- def write_procfile(procfile="Procfile")
31
+ def write_procfile(procfile="Procfile", alpha_env="")
32
32
  File.open(procfile, "w") do |file|
33
- file.puts "alpha: ./alpha"
33
+ file.puts "alpha: ./alpha" + " #{alpha_env}".rstrip
34
34
  file.puts "\n"
35
35
  file.puts "bravo:\t./bravo"
36
36
  end
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.25.0
4
+ version: 0.26.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-17 00:00:00.000000000Z
12
+ date: 2011-11-08 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: term-ansicolor
16
- requirement: &70259497066180 !ruby/object:Gem::Requirement
16
+ requirement: &70114771952400 !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: *70259497066180
24
+ version_requirements: *70114771952400
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thor
27
- requirement: &70259497065620 !ruby/object:Gem::Requirement
27
+ requirement: &70114771951120 !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: *70259497065620
35
+ version_requirements: *70114771951120
36
36
  description: Process manager for applications with multiple components
37
37
  email: ddollar@gmail.com
38
38
  executables:
@@ -47,6 +47,8 @@ files:
47
47
  - data/example/Procfile.without_colon
48
48
  - data/example/ticker
49
49
  - data/export/bluepill/master.pill.erb
50
+ - data/export/runit/log_run.erb
51
+ - data/export/runit/run.erb
50
52
  - data/export/upstart/master.conf.erb
51
53
  - data/export/upstart/process.conf.erb
52
54
  - data/export/upstart/process_master.conf.erb
@@ -56,6 +58,7 @@ files:
56
58
  - lib/foreman/export/base.rb
57
59
  - lib/foreman/export/bluepill.rb
58
60
  - lib/foreman/export/inittab.rb
61
+ - lib/foreman/export/runit.rb
59
62
  - lib/foreman/export/upstart.rb
60
63
  - lib/foreman/export.rb
61
64
  - lib/foreman/process.rb
@@ -67,11 +70,18 @@ files:
67
70
  - spec/foreman/cli_spec.rb
68
71
  - spec/foreman/engine_spec.rb
69
72
  - spec/foreman/export/bluepill_spec.rb
73
+ - spec/foreman/export/runit_spec.rb
70
74
  - spec/foreman/export/upstart_spec.rb
71
75
  - spec/foreman/export_spec.rb
72
76
  - spec/foreman/process_spec.rb
73
77
  - spec/foreman_spec.rb
74
78
  - spec/resources/export/bluepill/app.pill
79
+ - spec/resources/export/runit/app-alpha-1-log-run
80
+ - spec/resources/export/runit/app-alpha-1-run
81
+ - spec/resources/export/runit/app-alpha-2-log-run
82
+ - spec/resources/export/runit/app-alpha-2-run
83
+ - spec/resources/export/runit/app-bravo-1-log-run
84
+ - spec/resources/export/runit/app-bravo-1-run
75
85
  - spec/resources/export/upstart/app-alpha-1.conf
76
86
  - spec/resources/export/upstart/app-alpha-2.conf
77
87
  - spec/resources/export/upstart/app-alpha.conf
@@ -94,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
104
  version: '0'
95
105
  segments:
96
106
  - 0
97
- hash: 1985710685815215067
107
+ hash: -38436037074031590
98
108
  required_rubygems_version: !ruby/object:Gem::Requirement
99
109
  none: false
100
110
  requirements:
@@ -103,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
113
  version: '0'
104
114
  segments:
105
115
  - 0
106
- hash: 1985710685815215067
116
+ hash: -38436037074031590
107
117
  requirements: []
108
118
  rubyforge_project:
109
119
  rubygems_version: 1.8.10