foreman 0.25.0 → 0.26.0

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.
@@ -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