Compare commits

...

41 Commits

Author SHA1 Message Date
David Dollar
64f0749d16 0.59.0 2012-09-15 11:49:46 +09:00
David Dollar
6b77ca1e46 Merge pull request #246 from jeremyevans/patch-1
Don't have foreman-runner depend on bash
2012-09-14 19:48:03 -07:00
Jeremy Evans
6a44dd3fd3 Use /bin/sh instead of bash for foreman-runner
/bin/sh should be installed by default on all unix machines, bash
is not necessarily installed on all machines.
2012-09-14 17:35:54 -07:00
David Dollar
6c04dab649 0.58.0 2012-09-14 18:10:05 +09:00
David Dollar
96e26e7412 dont set HOME 2012-09-14 17:44:32 +09:00
David Dollar
a2c03cc402 Merge pull request #217 from danielfarrell/capistrano
Add capistrano export support
2012-09-14 01:42:34 -07:00
David Dollar
803115c0c4 Merge pull request #226 from alachaum/master
CLI: fix directory option
2012-09-14 01:41:36 -07:00
David Dollar
a4343187ad Merge pull request #239 from indrekj/master
Use path and env variables in the inittab export
2012-09-14 01:41:18 -07:00
David Dollar
98af1f0943 Merge pull request #261 from martinisoft/launchd_environment
Launchd environment
2012-09-14 01:34:35 -07:00
David Dollar
af2d4762a8 Merge pull request #250 from szimek/249_multiline_strings
Handle multiline strings in .env file
2012-09-14 01:34:10 -07:00
Aaron Kalin
1d06124457 Add StandardOutPath to launchd export 2012-09-11 15:04:15 -05:00
Aaron Kalin
698e6ae092 Add command argument string splitting
launchd uses exec() under the hood when you specify ProgramArguments
or Program so you must break apart program arguments into separate
strings in an array or the command will fail
2012-09-10 19:10:47 -05:00
Aaron Kalin
c617ddb3b2 Cleanup launchd exporter
Also suppresses the deprecation warning for the launchd exporter when
using port instead of engine.port_for
2012-09-10 18:21:51 -05:00
Aaron Kalin
f6d4badcd2 Enable trim_mode via '-' in ERB templates
This adds whitespace supression optionally, similar to the default
behavior in Rails ActionView ERB templates.

Just add - to a %> like so: -%> and it will remove trailing whitespace
and newlines. This can also be done to the beginning tag for removing
newlines from the beginning of the tag line.
2012-09-10 18:18:56 -05:00
Aaron Kalin
f29bf49a35 Add support for setting environment variables 2012-09-05 18:27:10 -05:00
David Dollar
e06d36b27c dont test 1.8.7 or rbx 2012-08-24 12:49:35 -04:00
David Dollar
85e62dfbeb Merge pull request #254 from omarkhan/master
foreman run should exit with the same code as its command
2012-08-24 09:14:45 -07:00
Omar Khan
574e852710 foreman run should exit with the same code as its command 2012-08-24 16:50:05 +01:00
David Dollar
68f098c1d2 update docs 2012-08-21 10:59:21 -04:00
David Dollar
e8bdafdfc1 changelog 2012-08-21 10:58:58 -04:00
David Dollar
4abd3ebedb 0.57.0 2012-08-21 10:58:11 -04:00
David Dollar
f765436dde fix errant space 2012-08-21 10:58:00 -04:00
David Dollar
b5c513b4b5 Merge pull request #247 from asanghi/master
start on boot worked with network-interface but not network
2012-08-21 07:56:30 -07:00
Aditya Sanghi
ee761ff098 Another fix for PR #229 2012-08-21 20:16:28 +05:30
David Dollar
27c22deb6c update changelog 2012-08-19 12:05:37 -04:00
David Dollar
681a9f7e61 0.56.0 2012-08-19 12:05:07 -04:00
David Dollar
8335a2b1ba read .profile, not .profile.d 2012-08-16 12:57:22 -04:00
David Dollar
407425ca78 update changelog 2012-08-14 17:08:14 -04:00
David Dollar
6ca505b4cd 0.55.0 2012-08-14 17:07:52 -04:00
David Dollar
612eae5e21 use a forked process to exec a run with environment 2012-08-14 17:07:39 -04:00
David Dollar
497b5ea1eb update changelog 2012-08-14 17:03:28 -04:00
David Dollar
cd384e0d59 0.54.0 2012-08-14 17:00:19 -04:00
David Dollar
8921cac35b use Foreman::Process to extract command running 2012-08-14 17:00:01 -04:00
Szymon Nowak
7d6de5b2a7 Handle multiline strings in .env file 2012-08-14 11:09:21 +02:00
Aditya Sanghi
cc4306492e run on reboot works with network-interface not network 2012-08-12 14:17:39 +05:30
David Dollar
6042783e82 Merge pull request #245 from brntbeer/env_bash_fix
changed to check env for bash
2012-08-08 14:09:19 -07:00
brntbeer
b7b3a9f898 changed to check env for bash 2012-08-08 13:53:36 -07:00
Indrek Juhkam
8b204db2f0 Use path and env variables in the inittab export 2012-07-31 21:44:31 +03:00
David Dollar
15643dcb3f changelog 2012-07-24 11:18:42 -04:00
Arnaud Lachaume
ebe160d425 fixed the directory option 2012-07-14 11:48:24 +10:00
Daniel Farrell
0a61b1a62f Add capistrano export support 2012-06-22 15:49:19 -04:00
25 changed files with 217 additions and 36 deletions

View File

@@ -16,9 +16,7 @@ notifications:
- http://dx-helper.herokuapp.com/travis
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- jruby
- rbx
- ree

View File

@@ -1,3 +1,24 @@
## 0.57.0 (2012-08-21)
* fix startup checks for upstart exporter [Aditya Sanghi]
## 0.56.0 (2012-08-19)
* read .profile, not .profile.d [David Dollar]
## 0.55.0 (2012-08-14)
* use a forked process to exec a run with environment [David Dollar]
## 0.54.0 (2012-08-14)
* use Foreman::Process to extract command running [David Dollar]
* changed to check env for bash [brntbeer]
## 0.53.0 (2012-07-24)
* put app root in $HOME [David Dollar]
## 0.52.0 (2012-07-24)
* wrap command in a runner that sources .profile.d scripts [David Dollar]

View File

@@ -1,7 +1,7 @@
PATH
remote: .
specs:
foreman (0.53.0)
foreman (0.59.0)
thor (>= 0.13.6)
GEM
@@ -39,7 +39,7 @@ GEM
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
thor (0.15.4)
thor (0.16.0)
timecop (0.3.5)
win32console (1.3.0-x86-mingw32)
xml-simple (1.0.15)

View File

@@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
#
#/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...]
#/
@@ -16,12 +16,12 @@ usage() {
exit
}
read_profiled=""
read_profile=""
while getopts ":hd:p" OPT; do
case $OPT in
d) cd "$OPTARG" ;;
p) read_profiled="1" ;;
p) read_profile="1" ;;
h) usage ;;
\?) error "invalid option: -$OPTARG" ;;
:) error "option -$OPTARG requires an argument" ;;
@@ -32,13 +32,10 @@ shift $((OPTIND-1))
[ -z "$1" ] && usage
if [ "$read_profiled" == "1" ]; then
shopt -s nullglob
for script in .profile.d/*; do
echo "sourcing $script"
source $script
done
shopt -u nullglob
if [ "$read_profile" = "1" ]; then
if [ -f .profile ]; then
. .profile
fi
fi
exec "$@"

View File

@@ -4,14 +4,25 @@
<dict>
<key>Label</key>
<string><%= "#{app}-#{name}-#{num}" %></string>
<key>EnvironmentVariables</key>
<dict>
<%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
<key><%= var.upcase %></key>
<string><%= env %></string>
<%- end -%>
</dict>
<key>ProgramArguments</key>
<array>
<string><%= process.command %></string>
<%- command_args.each do |command| -%>
<string><%= command %></string>
<%- end -%>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>StandardErrorPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>UserName</key>

View File

@@ -7,5 +7,10 @@ EOF
end script
start on started network
stop on stopping network
start on (started network-interface
or started network-manager
or started networking)
stop on (stopping network-interface
or stopping network-manager
or stopping networking)

54
lib/foreman/capistrano.rb Normal file
View File

@@ -0,0 +1,54 @@
if defined?(Capistrano)
Capistrano::Configuration.instance(:must_exist).load do
namespace :foreman do
desc <<-DESC
Export the Procfile to upstart. Will use sudo if available.
You can override any of these defaults by setting the variables shown below.
set :foreman_format, "upstart"
set :foreman_location, "/etc/init"
set :foreman_procfile, "Procfile"
set :foreman_app, application
set :foreman_user, user
set :foreman_log, "#{shared_path}/log"
set :foreman_concurrency, false
DESC
task :export, :roles => :app do
bundle_cmd = fetch(:bundle_cmd, "bundle")
foreman_format = fetch(:foreman_format, "upstart")
foreman_location = fetch(:foreman_location, "/etc/init")
foreman_procfile = fetch(:foreman_procfile, "Procfile")
foreman_app = fetch(:foreman_app, application)
foreman_user = fetch(:foreman_user, user)
foreman_log = fetch(:foreman_log, "#{shared_path}/log")
foreman_concurrency = fetch(:foreman_concurrency, false)
args = ["#{foreman_format} #{foreman_location}"]
args << "-f #{foreman_procfile}"
args << "-a #{foreman_app}"
args << "-u #{foreman_user}"
args << "-l #{foreman_log}"
args << "-c #{foreman_concurrency}" if foreman_concurrency
run "cd #{release_path} && #{sudo} #{bundle_cmd} exec foreman export #{args.join(' ')}"
end
desc "Start the application services"
task :start, :roles => :app do
run "#{sudo} start #{application}"
end
desc "Stop the application services"
task :stop, :roles => :app do
run "#{sudo} stop #{application}"
end
desc "Restart the application services"
task :restart, :roles => :app do
run "#{sudo} start #{application} || #{sudo} restart #{application}"
end
end
end
end

View File

@@ -75,13 +75,18 @@ class Foreman::CLI < Thor
def run(*args)
load_environment!
begin
exec engine.env, args.shelljoin
rescue Errno::EACCES
error "not executable: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
pid = fork do
begin
engine.env.each { |k,v| ENV[k] = v }
exec args.shelljoin
rescue Errno::EACCES
error "not executable: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
end
end
Process.wait(pid)
exit $?.exitstatus
end
desc "version", "Display Foreman gem version"
@@ -125,7 +130,7 @@ private ######################################################################
def procfile
case
when options[:procfile] then options[:procfile]
when options[:root] then File.expand_path(File.join(options[:app_root], "Procfile"))
when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
else "Procfile"
end
end

View File

@@ -257,7 +257,6 @@ private
reader, writer = create_pipe
begin
pid = process.run(:output => writer, :env => {
"HOME" => process.cwd,
"PORT" => port_for(process, n).to_s
})
writer.puts "started with pid #{pid}"

View File

@@ -9,8 +9,10 @@ class Foreman::Env
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key = $1
case val = $2
# Remove single quotes
when /\A'(.*)'\z/ then ax[key] = $1
when /\A"(.*)"\z/ then ax[key] = $1.gsub(/\\(.)/, '\1')
# Remove double quotes and unescape string preserving newline characters
when /\A"(.*)"\z/ then ax[key] = $1.gsub('\n', "\n").gsub(/\\(.)/, '\1')
else ax[key] = val
end
end

View File

@@ -119,7 +119,7 @@ private ######################################################################
end
def write_template(name, target, binding)
compiled = ERB.new(export_template(name)).result(binding)
compiled = ERB.new(export_template(name), nil, '-').result(binding)
write_file target, compiled
end

View File

@@ -13,7 +13,16 @@ class Foreman::Export::Inittab < Foreman::Export::Base
1.upto(engine.formation[name]) do |num|
id = app.slice(0, 2).upcase + sprintf("%02d", index)
port = engine.port_for(process, num)
inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log}/#{name}-#{num}.log 2>&1'"
commands = []
commands << "cd #{engine.root}"
commands << "export PORT=#{port}"
engine.env.each_pair do |var, env|
commands << "export #{var.upcase}=#{shell_quote(env)}"
end
commands << "#{process.command} >> #{log}/#{name}-#{num}.log 2>&1"
inittab << "#{id}:4:respawn:/bin/su - #{user} -c '#{commands.join(";")}'"
index += 1
end
end

View File

@@ -7,6 +7,8 @@ class Foreman::Export::Launchd < Foreman::Export::Base
super
engine.each_process do |name, process|
1.upto(engine.formation[name]) do |num|
port = engine.port_for(process, num)
command_args = process.command.split(" ")
write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding
end
end

View File

@@ -1,5 +1,5 @@
module Foreman
VERSION = "0.53.0"
VERSION = "0.59.0"
end

View File

@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "FOREMAN" "1" "July 2012" "Foreman 0.51.0" "Foreman Manual"
.TH "FOREMAN" "1" "July 2012" "Foreman 0.57.0" "Foreman Manual"
.
.SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications

View File

@@ -72,6 +72,11 @@ describe "Foreman::CLI", :fakefs do
it "includes the environment" do
forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
end
it "exits with the same exit code as the command" do
fork_and_get_exitstatus("run echo 1").should == 0
fork_and_get_exitstatus("run date 'invalid_date'").should == 1
end
end
describe "version" do

View File

@@ -90,6 +90,14 @@ describe "Foreman::Engine", :fakefs do
subject.env["OTHER"].should == 'escaped"quote'
end
it "should handle multiline strings" do
File.open("/tmp/env", "w") do |f|
f.puts 'FOO="bar\nbaz"'
end
subject.load_env "/tmp/env"
subject.env["FOO"].should == "bar\nbaz"
end
it "should fail if specified and doesnt exist" do
lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT)
end

View File

@@ -18,4 +18,14 @@ describe Foreman::Export::Launchd, :fakefs do
File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default")
end
context "with multiple command arguments" do
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", "charlie") }
it "splits each command argument" do
launchd.export
File.read("/tmp/init/app-alpha-1.plist").should == example_export_file("launchd/launchd-c.default")
end
end
end

View File

@@ -1,4 +1,4 @@
# ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1'
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5001;./alpha >> /var/log/app/alpha-2.log 2>&1'
# ----- end foreman app processes -----

View File

@@ -1,4 +1,4 @@
# ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1'
AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5100;./bravo >> /var/log/app/bravo-1.log 2>&1'
# ----- end foreman app processes -----

View File

@@ -4,6 +4,11 @@
<dict>
<key>Label</key>
<string>app-alpha-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
@@ -12,6 +17,8 @@
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key>

View File

@@ -4,6 +4,11 @@
<dict>
<key>Label</key>
<string>app-bravo-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5100</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./bravo</string>
@@ -12,6 +17,8 @@
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>UserName</key>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>app-alpha-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
<string>charlie</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key>
<string>app</string>
<key>WorkingDirectory</key>
<string>/tmp/app</string>
</dict>
</plist>

View File

@@ -7,5 +7,10 @@ EOF
end script
start on started network
stop on stopping network
start on (started network-interface
or started network-manager
or started networking)
stop on (stopping network-interface
or stopping network-manager
or stopping networking)

View File

@@ -58,6 +58,12 @@ def fork_and_capture(&blk)
end
end
def fork_and_get_exitstatus(args)
pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
Process.wait(pid)
$?.exitstatus
end
def mock_exit(&block)
block.should raise_error(SystemExit)
end