foreman 0.57.0 → 0.58.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.
@@ -4,14 +4,25 @@
4
4
  <dict>
5
5
  <key>Label</key>
6
6
  <string><%= "#{app}-#{name}-#{num}" %></string>
7
+ <key>EnvironmentVariables</key>
8
+ <dict>
9
+ <%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
10
+ <key><%= var.upcase %></key>
11
+ <string><%= env %></string>
12
+ <%- end -%>
13
+ </dict>
7
14
  <key>ProgramArguments</key>
8
15
  <array>
9
- <string><%= process.command %></string>
16
+ <%- command_args.each do |command| -%>
17
+ <string><%= command %></string>
18
+ <%- end -%>
10
19
  </array>
11
20
  <key>KeepAlive</key>
12
21
  <true/>
13
22
  <key>RunAtLoad</key>
14
23
  <true/>
24
+ <key>StandardOutPath</key>
25
+ <string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
15
26
  <key>StandardErrorPath</key>
16
27
  <string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
17
28
  <key>UserName</key>
@@ -0,0 +1,54 @@
1
+ if defined?(Capistrano)
2
+ Capistrano::Configuration.instance(:must_exist).load do
3
+
4
+ namespace :foreman do
5
+ desc <<-DESC
6
+ Export the Procfile to upstart. Will use sudo if available.
7
+
8
+ You can override any of these defaults by setting the variables shown below.
9
+
10
+ set :foreman_format, "upstart"
11
+ set :foreman_location, "/etc/init"
12
+ set :foreman_procfile, "Procfile"
13
+ set :foreman_app, application
14
+ set :foreman_user, user
15
+ set :foreman_log, "#{shared_path}/log"
16
+ set :foreman_concurrency, false
17
+ DESC
18
+ task :export, :roles => :app do
19
+ bundle_cmd = fetch(:bundle_cmd, "bundle")
20
+ foreman_format = fetch(:foreman_format, "upstart")
21
+ foreman_location = fetch(:foreman_location, "/etc/init")
22
+ foreman_procfile = fetch(:foreman_procfile, "Procfile")
23
+ foreman_app = fetch(:foreman_app, application)
24
+ foreman_user = fetch(:foreman_user, user)
25
+ foreman_log = fetch(:foreman_log, "#{shared_path}/log")
26
+ foreman_concurrency = fetch(:foreman_concurrency, false)
27
+
28
+ args = ["#{foreman_format} #{foreman_location}"]
29
+ args << "-f #{foreman_procfile}"
30
+ args << "-a #{foreman_app}"
31
+ args << "-u #{foreman_user}"
32
+ args << "-l #{foreman_log}"
33
+ args << "-c #{foreman_concurrency}" if foreman_concurrency
34
+ run "cd #{release_path} && #{sudo} #{bundle_cmd} exec foreman export #{args.join(' ')}"
35
+ end
36
+
37
+ desc "Start the application services"
38
+ task :start, :roles => :app do
39
+ run "#{sudo} start #{application}"
40
+ end
41
+
42
+ desc "Stop the application services"
43
+ task :stop, :roles => :app do
44
+ run "#{sudo} stop #{application}"
45
+ end
46
+
47
+ desc "Restart the application services"
48
+ task :restart, :roles => :app do
49
+ run "#{sudo} start #{application} || #{sudo} restart #{application}"
50
+ end
51
+
52
+ end
53
+ end
54
+ end
data/lib/foreman/cli.rb CHANGED
@@ -86,6 +86,7 @@ class Foreman::CLI < Thor
86
86
  end
87
87
  end
88
88
  Process.wait(pid)
89
+ exit $?.exitstatus
89
90
  end
90
91
 
91
92
  desc "version", "Display Foreman gem version"
@@ -129,7 +130,7 @@ private ######################################################################
129
130
  def procfile
130
131
  case
131
132
  when options[:procfile] then options[:procfile]
132
- when options[:root] then File.expand_path(File.join(options[:app_root], "Procfile"))
133
+ when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
133
134
  else "Procfile"
134
135
  end
135
136
  end
@@ -257,7 +257,6 @@ private
257
257
  reader, writer = create_pipe
258
258
  begin
259
259
  pid = process.run(:output => writer, :env => {
260
- "HOME" => process.cwd,
261
260
  "PORT" => port_for(process, n).to_s
262
261
  })
263
262
  writer.puts "started with pid #{pid}"
data/lib/foreman/env.rb CHANGED
@@ -9,8 +9,10 @@ class Foreman::Env
9
9
  if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
10
10
  key = $1
11
11
  case val = $2
12
+ # Remove single quotes
12
13
  when /\A'(.*)'\z/ then ax[key] = $1
13
- when /\A"(.*)"\z/ then ax[key] = $1.gsub(/\\(.)/, '\1')
14
+ # Remove double quotes and unescape string preserving newline characters
15
+ when /\A"(.*)"\z/ then ax[key] = $1.gsub('\n', "\n").gsub(/\\(.)/, '\1')
14
16
  else ax[key] = val
15
17
  end
16
18
  end
@@ -119,7 +119,7 @@ private ######################################################################
119
119
  end
120
120
 
121
121
  def write_template(name, target, binding)
122
- compiled = ERB.new(export_template(name)).result(binding)
122
+ compiled = ERB.new(export_template(name), nil, '-').result(binding)
123
123
  write_file target, compiled
124
124
  end
125
125
 
@@ -13,7 +13,16 @@ class Foreman::Export::Inittab < Foreman::Export::Base
13
13
  1.upto(engine.formation[name]) do |num|
14
14
  id = app.slice(0, 2).upcase + sprintf("%02d", index)
15
15
  port = engine.port_for(process, num)
16
- inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log}/#{name}-#{num}.log 2>&1'"
16
+
17
+ commands = []
18
+ commands << "cd #{engine.root}"
19
+ commands << "export PORT=#{port}"
20
+ engine.env.each_pair do |var, env|
21
+ commands << "export #{var.upcase}=#{shell_quote(env)}"
22
+ end
23
+ commands << "#{process.command} >> #{log}/#{name}-#{num}.log 2>&1"
24
+
25
+ inittab << "#{id}:4:respawn:/bin/su - #{user} -c '#{commands.join(";")}'"
17
26
  index += 1
18
27
  end
19
28
  end
@@ -7,6 +7,8 @@ class Foreman::Export::Launchd < Foreman::Export::Base
7
7
  super
8
8
  engine.each_process do |name, process|
9
9
  1.upto(engine.formation[name]) do |num|
10
+ port = engine.port_for(process, num)
11
+ command_args = process.command.split(" ")
10
12
  write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding
11
13
  end
12
14
  end
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.57.0"
3
+ VERSION = "0.58.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" "July 2012" "Foreman 0.51.0" "Foreman Manual"
4
+ .TH "FOREMAN" "1" "July 2012" "Foreman 0.57.0" "Foreman Manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBforeman\fR \- manage Procfile\-based applications
@@ -72,6 +72,11 @@ describe "Foreman::CLI", :fakefs do
72
72
  it "includes the environment" do
73
73
  forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
74
74
  end
75
+
76
+ it "exits with the same exit code as the command" do
77
+ fork_and_get_exitstatus("run echo 1").should == 0
78
+ fork_and_get_exitstatus("run date 'invalid_date'").should == 1
79
+ end
75
80
  end
76
81
 
77
82
  describe "version" do
@@ -90,6 +90,14 @@ describe "Foreman::Engine", :fakefs do
90
90
  subject.env["OTHER"].should == 'escaped"quote'
91
91
  end
92
92
 
93
+ it "should handle multiline strings" do
94
+ File.open("/tmp/env", "w") do |f|
95
+ f.puts 'FOO="bar\nbaz"'
96
+ end
97
+ subject.load_env "/tmp/env"
98
+ subject.env["FOO"].should == "bar\nbaz"
99
+ end
100
+
93
101
  it "should fail if specified and doesnt exist" do
94
102
  lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT)
95
103
  end
@@ -18,4 +18,14 @@ describe Foreman::Export::Launchd, :fakefs do
18
18
  File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default")
19
19
  end
20
20
 
21
+ context "with multiple command arguments" do
22
+ let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", "charlie") }
23
+
24
+ it "splits each command argument" do
25
+ launchd.export
26
+ File.read("/tmp/init/app-alpha-1.plist").should == example_export_file("launchd/launchd-c.default")
27
+ end
28
+
29
+ end
30
+
21
31
  end
@@ -1,4 +1,4 @@
1
1
  # ----- foreman app processes -----
2
- AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
3
- AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1'
2
+ AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
3
+ AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5001;./alpha >> /var/log/app/alpha-2.log 2>&1'
4
4
  # ----- end foreman app processes -----
@@ -1,4 +1,4 @@
1
1
  # ----- foreman app processes -----
2
- AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
3
- AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1'
2
+ AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
3
+ AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5100;./bravo >> /var/log/app/bravo-1.log 2>&1'
4
4
  # ----- end foreman app processes -----
@@ -4,6 +4,11 @@
4
4
  <dict>
5
5
  <key>Label</key>
6
6
  <string>app-alpha-1</string>
7
+ <key>EnvironmentVariables</key>
8
+ <dict>
9
+ <key>PORT</key>
10
+ <string>5000</string>
11
+ </dict>
7
12
  <key>ProgramArguments</key>
8
13
  <array>
9
14
  <string>./alpha</string>
@@ -12,6 +17,8 @@
12
17
  <true/>
13
18
  <key>RunAtLoad</key>
14
19
  <true/>
20
+ <key>StandardOutPath</key>
21
+ <string>/var/log/app/app-alpha-1.log</string>
15
22
  <key>StandardErrorPath</key>
16
23
  <string>/var/log/app/app-alpha-1.log</string>
17
24
  <key>UserName</key>
@@ -4,6 +4,11 @@
4
4
  <dict>
5
5
  <key>Label</key>
6
6
  <string>app-bravo-1</string>
7
+ <key>EnvironmentVariables</key>
8
+ <dict>
9
+ <key>PORT</key>
10
+ <string>5100</string>
11
+ </dict>
7
12
  <key>ProgramArguments</key>
8
13
  <array>
9
14
  <string>./bravo</string>
@@ -12,6 +17,8 @@
12
17
  <true/>
13
18
  <key>RunAtLoad</key>
14
19
  <true/>
20
+ <key>StandardOutPath</key>
21
+ <string>/var/log/app/app-bravo-1.log</string>
15
22
  <key>StandardErrorPath</key>
16
23
  <string>/var/log/app/app-bravo-1.log</string>
17
24
  <key>UserName</key>
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>app-alpha-1</string>
7
+ <key>EnvironmentVariables</key>
8
+ <dict>
9
+ <key>PORT</key>
10
+ <string>5000</string>
11
+ </dict>
12
+ <key>ProgramArguments</key>
13
+ <array>
14
+ <string>./alpha</string>
15
+ <string>charlie</string>
16
+ </array>
17
+ <key>KeepAlive</key>
18
+ <true/>
19
+ <key>RunAtLoad</key>
20
+ <true/>
21
+ <key>StandardOutPath</key>
22
+ <string>/var/log/app/app-alpha-1.log</string>
23
+ <key>StandardErrorPath</key>
24
+ <string>/var/log/app/app-alpha-1.log</string>
25
+ <key>UserName</key>
26
+ <string>app</string>
27
+ <key>WorkingDirectory</key>
28
+ <string>/tmp/app</string>
29
+ </dict>
30
+ </plist>
data/spec/spec_helper.rb CHANGED
@@ -58,6 +58,12 @@ def fork_and_capture(&blk)
58
58
  end
59
59
  end
60
60
 
61
+ def fork_and_get_exitstatus(args)
62
+ pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
63
+ Process.wait(pid)
64
+ $?.exitstatus
65
+ end
66
+
61
67
  def mock_exit(&block)
62
68
  block.should raise_error(SystemExit)
63
69
  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.57.0
4
+ version: 0.58.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: 2012-08-21 00:00:00.000000000 Z
12
+ date: 2012-09-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
- requirement: &70227591758760 !ruby/object:Gem::Requirement
16
+ requirement: &70177359356080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 0.13.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70227591758760
24
+ version_requirements: *70177359356080
25
25
  description: Process manager for applications with multiple components
26
26
  email: ddollar@gmail.com
27
27
  executables:
@@ -48,6 +48,7 @@ files:
48
48
  - data/export/upstart/master.conf.erb
49
49
  - data/export/upstart/process.conf.erb
50
50
  - data/export/upstart/process_master.conf.erb
51
+ - lib/foreman/capistrano.rb
51
52
  - lib/foreman/cli.rb
52
53
  - lib/foreman/distribution.rb
53
54
  - lib/foreman/engine/cli.rb
@@ -92,6 +93,7 @@ files:
92
93
  - spec/resources/export/inittab/inittab.default
93
94
  - spec/resources/export/launchd/launchd-a.default
94
95
  - spec/resources/export/launchd/launchd-b.default
96
+ - spec/resources/export/launchd/launchd-c.default
95
97
  - spec/resources/export/runit/app-alpha-1/log/run
96
98
  - spec/resources/export/runit/app-alpha-1/run
97
99
  - spec/resources/export/runit/app-alpha-2/log/run
@@ -121,18 +123,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
123
  - - ! '>='
122
124
  - !ruby/object:Gem::Version
123
125
  version: '0'
124
- segments:
125
- - 0
126
- hash: 1574791230196847546
127
126
  required_rubygems_version: !ruby/object:Gem::Requirement
128
127
  none: false
129
128
  requirements:
130
129
  - - ! '>='
131
130
  - !ruby/object:Gem::Version
132
131
  version: '0'
133
- segments:
134
- - 0
135
- hash: 1574791230196847546
136
132
  requirements: []
137
133
  rubyforge_project:
138
134
  rubygems_version: 1.8.11
@@ -140,4 +136,3 @@ signing_key:
140
136
  specification_version: 3
141
137
  summary: Process manager for applications with multiple components
142
138
  test_files: []
143
- has_rdoc: