Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
199e7de97c | ||
|
|
defc40b911 | ||
|
|
37dcba0e33 | ||
|
|
d205e3ba2e | ||
|
|
9905334f01 | ||
|
|
dd292ed7da | ||
|
|
67ffbe2aa2 | ||
|
|
da8bba5941 | ||
|
|
2aa1cbf94f | ||
|
|
34a1163fe9 | ||
|
|
2e5f610b76 | ||
|
|
20392d98a1 | ||
|
|
e8538d9f45 | ||
|
|
4a51a2aa8a | ||
|
|
1905a7c310 | ||
|
|
134b31f599 | ||
|
|
2b97cb458a | ||
|
|
03d76d4254 | ||
|
|
133228f247 | ||
|
|
bfba2cad71 | ||
|
|
e245026f65 | ||
|
|
ffc73366b2 | ||
|
|
284503899a | ||
|
|
144be02bbd | ||
|
|
9734a2ed65 | ||
|
|
0fff148fe0 | ||
|
|
d19a9aa043 | ||
|
|
c3abaad353 | ||
|
|
b1f91d4505 | ||
|
|
0c7b8ddd79 | ||
|
|
189b751d9f | ||
|
|
619bd03bb8 | ||
|
|
fd836b46c0 | ||
|
|
2379259b33 | ||
|
|
baf842cdd4 | ||
|
|
5c06aaaa57 | ||
|
|
75b782b664 | ||
|
|
9b4bd10cdb | ||
|
|
fff82dc685 | ||
|
|
da0a9f2de3 | ||
|
|
7d77d8ff1a | ||
|
|
51e181da29 | ||
|
|
9866a341ca | ||
|
|
90848e7dea | ||
|
|
a92e24b17c | ||
|
|
669a920c1e | ||
|
|
d357197718 | ||
|
|
f6b57d7b92 | ||
|
|
e79588fd40 | ||
|
|
6611d818b1 | ||
|
|
ad4d59ae14 | ||
|
|
434f30fe42 | ||
|
|
95a1d49e9d |
+2
-3
@@ -2,10 +2,7 @@ script: bundle exec rake spec
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- rvm: 1.8.7
|
|
||||||
- rvm: jruby
|
- rvm: jruby
|
||||||
- rvm: rbx
|
|
||||||
- rvm: ree
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
@@ -16,7 +13,9 @@ notifications:
|
|||||||
- http://dx-helper.herokuapp.com/travis
|
- http://dx-helper.herokuapp.com/travis
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
|
- 1.8.7
|
||||||
- 1.9.2
|
- 1.9.2
|
||||||
- 1.9.3
|
- 1.9.3
|
||||||
- 2.0.0
|
- 2.0.0
|
||||||
|
- 2.1.0
|
||||||
- jruby
|
- jruby
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
## 0.63.0 (2013-04-15)
|
||||||
|
|
||||||
|
* Revert "Ensure foreman is the process group leader" [John Griffin]
|
||||||
|
* remove posix-spawn dependency as it does not work in jruby 1.7.3 [Andrew Brown & Corey Downing]
|
||||||
|
* Replace Foreman::Env with dotenv [Brandon Keepers]
|
||||||
|
* [foreman-runner] fix sourcing as . is rarely in PATH [Barry Allard]
|
||||||
|
* Fixed specs to pass. [Kentaro Kuribayashi]
|
||||||
|
* Permit underscore for command name in Procfile. [Kentaro Kuribayashi]
|
||||||
|
* Update man/foreman.1 [Patrick Ellis]
|
||||||
|
* Remove tmux option from man page [Donald Plummer]
|
||||||
|
* Prevent upstart export from deleting similarly named upstart files [Andy Morris]
|
||||||
|
* Add MIT license text [Per Andersson]
|
||||||
|
* use "start|stop\ on runlevel [x]" for upstart config [Nick Messick]
|
||||||
|
|
||||||
## 0.62.0 (2013-03-08)
|
## 0.62.0 (2013-03-08)
|
||||||
|
|
||||||
* Merge pull request #334 from ged/reentrant_signal_handlers [David Dollar]
|
* Merge pull request #334 from ged/reentrant_signal_handlers [David Dollar]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ platform :mingw do
|
|||||||
gem "win32console", "~> 1.3.0"
|
gem "win32console", "~> 1.3.0"
|
||||||
end
|
end
|
||||||
|
|
||||||
platform :jruby do
|
platform :jruby, :ruby_18 do
|
||||||
gem "posix-spawn", "~> 0.3.6"
|
gem "posix-spawn", "~> 0.3.6"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -18,6 +18,8 @@ group :development do
|
|||||||
gem 'rr', '~> 1.0.2'
|
gem 'rr', '~> 1.0.2'
|
||||||
gem 'rspec', '~> 2.0'
|
gem 'rspec', '~> 2.0'
|
||||||
gem "simplecov", :require => false
|
gem "simplecov", :require => false
|
||||||
gem 'timecop'
|
gem 'timecop', '0.6.1'
|
||||||
gem 'yard'
|
gem 'yard'
|
||||||
|
gem 'mime-types', '~> 1.25.1'
|
||||||
|
gem 'rdiscount', '~> 1.6.8'
|
||||||
end
|
end
|
||||||
|
|||||||
+33
-29
@@ -8,44 +8,46 @@ PATH
|
|||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
aws-s3 (0.6.2)
|
aws-s3 (0.6.3)
|
||||||
builder
|
builder
|
||||||
mime-types
|
mime-types
|
||||||
xml-simple
|
xml-simple
|
||||||
builder (3.0.0)
|
builder (3.2.2)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.2.5)
|
||||||
dotenv (0.7.0)
|
docile (1.1.3)
|
||||||
|
dotenv (0.10.0)
|
||||||
fakefs (0.3.2)
|
fakefs (0.3.2)
|
||||||
hpricot (0.8.6)
|
hpricot (0.8.6)
|
||||||
hpricot (0.8.6-java)
|
hpricot (0.8.6-java)
|
||||||
mime-types (1.16)
|
mime-types (1.25.1)
|
||||||
multi_json (1.0.4)
|
multi_json (1.9.0)
|
||||||
mustache (0.11.2)
|
mustache (0.99.5)
|
||||||
posix-spawn (0.3.6)
|
posix-spawn (0.3.8)
|
||||||
rake (0.9.2.2)
|
rake (10.1.1)
|
||||||
rdiscount (1.6.5)
|
rdiscount (1.6.8)
|
||||||
ronn (0.7.3)
|
ronn (0.7.3)
|
||||||
hpricot (>= 0.8.2)
|
hpricot (>= 0.8.2)
|
||||||
mustache (>= 0.7.0)
|
mustache (>= 0.7.0)
|
||||||
rdiscount (>= 1.5.8)
|
rdiscount (>= 1.5.8)
|
||||||
rr (1.0.2)
|
rr (1.0.5)
|
||||||
rspec (2.8.0)
|
rspec (2.14.1)
|
||||||
rspec-core (~> 2.8.0)
|
rspec-core (~> 2.14.0)
|
||||||
rspec-expectations (~> 2.8.0)
|
rspec-expectations (~> 2.14.0)
|
||||||
rspec-mocks (~> 2.8.0)
|
rspec-mocks (~> 2.14.0)
|
||||||
rspec-core (2.8.0)
|
rspec-core (2.14.8)
|
||||||
rspec-expectations (2.8.0)
|
rspec-expectations (2.14.5)
|
||||||
diff-lcs (~> 1.1.2)
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
rspec-mocks (2.8.0)
|
rspec-mocks (2.14.6)
|
||||||
simplecov (0.5.4)
|
simplecov (0.8.2)
|
||||||
multi_json (~> 1.0.3)
|
docile (~> 1.1.0)
|
||||||
simplecov-html (~> 0.5.3)
|
multi_json
|
||||||
simplecov-html (0.5.3)
|
simplecov-html (~> 0.8.0)
|
||||||
thor (0.16.0)
|
simplecov-html (0.8.0)
|
||||||
timecop (0.3.5)
|
thor (0.18.1)
|
||||||
win32console (1.3.0-x86-mingw32)
|
timecop (0.6.1)
|
||||||
xml-simple (1.0.15)
|
win32console (1.3.2-x86-mingw32)
|
||||||
yard (0.8.2)
|
xml-simple (1.1.3)
|
||||||
|
yard (0.8.7.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
java
|
java
|
||||||
@@ -56,12 +58,14 @@ DEPENDENCIES
|
|||||||
aws-s3
|
aws-s3
|
||||||
fakefs (~> 0.3.2)
|
fakefs (~> 0.3.2)
|
||||||
foreman!
|
foreman!
|
||||||
|
mime-types (~> 1.25.1)
|
||||||
posix-spawn (~> 0.3.6)
|
posix-spawn (~> 0.3.6)
|
||||||
rake
|
rake
|
||||||
|
rdiscount (~> 1.6.8)
|
||||||
ronn
|
ronn
|
||||||
rr (~> 1.0.2)
|
rr (~> 1.0.2)
|
||||||
rspec (~> 2.0)
|
rspec (~> 2.0)
|
||||||
simplecov
|
simplecov
|
||||||
timecop
|
timecop (= 0.6.1)
|
||||||
win32console (~> 1.3.0)
|
win32console (~> 1.3.0)
|
||||||
yard
|
yard
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ Manage Procfile-based applications
|
|||||||
* [shoreman](https://github.com/hecticjeff/shoreman) - shell
|
* [shoreman](https://github.com/hecticjeff/shoreman) - shell
|
||||||
* [honcho](https://github.com/nickstenning/honcho) - python
|
* [honcho](https://github.com/nickstenning/honcho) - python
|
||||||
* [norman](https://github.com/josh/norman) - node.js
|
* [norman](https://github.com/josh/norman) - node.js
|
||||||
|
* [forego](https://github.com/ddollar/forego) - Go
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
pre-start script
|
||||||
|
|
||||||
|
bash << "EOF"
|
||||||
|
mkdir -p <%= log %>
|
||||||
|
chown -R <%= user %> <%= log %>
|
||||||
|
mkdir -p <%= run %>
|
||||||
|
chown -R <%= user %> <%= run %>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
end script
|
||||||
|
|
||||||
|
start on runlevel [2345]
|
||||||
|
|
||||||
|
stop on runlevel [016]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
start on starting <%= app %>-<%= name.gsub('_', '-') %>
|
||||||
|
stop on stopping <%= app %>-<%= name.gsub('_', '-') %>
|
||||||
|
respawn
|
||||||
|
|
||||||
|
env PORT=<%= port %><% engine.env.each_pair do |var, env| %>
|
||||||
|
env <%= var.upcase %>=<%= env %><% end %>
|
||||||
|
|
||||||
|
exec start-stop-daemon --start --chuid <%= user %> --chdir <%= engine.root %> --make-pidfile --pidfile <%= run %>/<%= app %>-<%= name %>-<%= num %>.pid --exec <%= executable %><%= arguments %> >> <%= log %>/<%= app %>-<%= name %>-<%= num %>.log 2>&1
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
start on starting <%= app %>
|
||||||
|
stop on stopping <%= app %>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
Wants=<%= process_master_names.join(' ') %>
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=<%= user %>
|
||||||
|
WorkingDirectory=<%= engine.root %>
|
||||||
|
Environment=PORT=<%= port %><% engine.env.each_pair do |var,env| %>
|
||||||
|
Environment=<%= var.upcase %>=<%= env %><% end %>
|
||||||
|
ExecStart=/bin/bash -lc '<%= process.command %>'
|
||||||
|
Restart=always
|
||||||
|
StandardInput=null
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=%n
|
||||||
|
KillMode=process
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
Wants=<%= process_names.join(' ') %>
|
||||||
@@ -2,4 +2,4 @@ start on starting <%= app %>-<%= name %>
|
|||||||
stop on stopping <%= app %>-<%= name %>
|
stop on stopping <%= app %>-<%= name %>
|
||||||
respawn
|
respawn
|
||||||
|
|
||||||
exec su - <%= user %> -c 'cd <%= engine.root %>; export PORT=<%= port %>;<% engine.env.each_pair do |var,env| %> export <%= var.upcase %>=<%= shell_quote(env) %>; <% end %> <%= process.command %> >> <%= log %>/<%=name%>-<%=num%>.log 2>&1'
|
exec su - <%= user %> -s /bin/sh -c 'cd <%= engine.root %>; export PORT=<%= port %>;<% engine.env.each_pair do |var,env| %> export <%= var.upcase %>=<%= shell_quote(env) %>; <% end %> exec <%= process.command %> >> <%= log %>/<%=name%>-<%=num%>.log 2>&1'
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ file pkg("foreman-#{version}.tgz") => distribution_files do |t|
|
|||||||
assemble_distribution
|
assemble_distribution
|
||||||
assemble_gems
|
assemble_gems
|
||||||
rm_f "bin/foreman"
|
rm_f "bin/foreman"
|
||||||
assemble resource("tgz/foreman"), "foreman", 0755
|
assemble resource("tgz/foreman"), "bin/foreman", 0755
|
||||||
end
|
end
|
||||||
|
|
||||||
sh "tar czvf #{t.name} foreman"
|
sh "tar czvf #{t.name} foreman"
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
+20
-14
@@ -34,6 +34,7 @@ class Foreman::CLI < Thor
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start(process=nil)
|
def start(process=nil)
|
||||||
|
require_posix_spawn_for_ruby_18!
|
||||||
check_procfile!
|
check_procfile!
|
||||||
load_environment!
|
load_environment!
|
||||||
engine.load_procfile(procfile)
|
engine.load_procfile(procfile)
|
||||||
@@ -45,6 +46,7 @@ class Foreman::CLI < Thor
|
|||||||
|
|
||||||
method_option :app, :type => :string, :aliases => "-a"
|
method_option :app, :type => :string, :aliases => "-a"
|
||||||
method_option :log, :type => :string, :aliases => "-l"
|
method_option :log, :type => :string, :aliases => "-l"
|
||||||
|
method_option :run, :type => :string, :aliases => "-r", :desc => "Specify the pid file directory, defaults to /var/run/<application>"
|
||||||
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
||||||
method_option :port, :type => :numeric, :aliases => "-p"
|
method_option :port, :type => :numeric, :aliases => "-p"
|
||||||
method_option :user, :type => :string, :aliases => "-u"
|
method_option :user, :type => :string, :aliases => "-u"
|
||||||
@@ -81,22 +83,18 @@ class Foreman::CLI < Thor
|
|||||||
engine.load_procfile(procfile)
|
engine.load_procfile(procfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
pid = fork do
|
begin
|
||||||
begin
|
engine.env.each { |k,v| ENV[k] = v }
|
||||||
engine.env.each { |k,v| ENV[k] = v }
|
if args.size == 1 && process = engine.process(args.first)
|
||||||
if args.size == 1 && process = engine.process(args.first)
|
process.exec(:env => engine.env)
|
||||||
process.exec(:env => engine.env)
|
else
|
||||||
else
|
exec args.shelljoin
|
||||||
exec args.shelljoin
|
|
||||||
end
|
|
||||||
rescue Errno::EACCES
|
|
||||||
error "not executable: #{args.first}"
|
|
||||||
rescue Errno::ENOENT
|
|
||||||
error "command not found: #{args.first}"
|
|
||||||
end
|
end
|
||||||
|
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
|
end
|
||||||
|
|
||||||
desc "version", "Display Foreman gem version"
|
desc "version", "Display Foreman gem version"
|
||||||
@@ -137,6 +135,14 @@ private ######################################################################
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def require_posix_spawn_for_ruby_18!
|
||||||
|
begin
|
||||||
|
Kernel.require 'posix/spawn' # Use Kernel explicitly so we can mock the require call in the spec
|
||||||
|
rescue LoadError
|
||||||
|
error "foreman requires gem `posix-spawn` on Ruby #{RUBY_VERSION}. Please `gem install posix-spawn`."
|
||||||
|
end if Foreman.ruby_18?
|
||||||
|
end
|
||||||
|
|
||||||
def procfile
|
def procfile
|
||||||
case
|
case
|
||||||
when options[:procfile] then options[:procfile]
|
when options[:procfile] then options[:procfile]
|
||||||
|
|||||||
+15
-22
@@ -176,19 +176,14 @@ class Foreman::Engine
|
|||||||
#
|
#
|
||||||
# @param [String] signal The signal to send to each process
|
# @param [String] signal The signal to send to each process
|
||||||
#
|
#
|
||||||
def kill_children(signal="SIGTERM")
|
def kill_children( signal="SIGTERM" )
|
||||||
if Foreman.windows?
|
@running.each do |pid, (process, index)|
|
||||||
@running.each do |pid, (process, index)|
|
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
||||||
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
|
||||||
begin
|
|
||||||
Process.kill(signal, pid)
|
|
||||||
rescue Errno::ESRCH, Errno::EPERM
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
Process.kill signal, *@running.keys unless @running.empty?
|
Process.kill( signal, pid )
|
||||||
rescue Errno::ESRCH, Errno::EPERM
|
rescue Errno::ESRCH, Errno::EPERM => err
|
||||||
|
system " %p when sending signal %p to pid %d: %s" %
|
||||||
|
[ err.class, signal, pid, err.message ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -198,14 +193,7 @@ class Foreman::Engine
|
|||||||
# @param [String] signal The signal to send
|
# @param [String] signal The signal to send
|
||||||
#
|
#
|
||||||
def killall(signal="SIGTERM")
|
def killall(signal="SIGTERM")
|
||||||
if Foreman.windows?
|
kill_children(signal)
|
||||||
kill_children(signal)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Process.kill "-#{signal}", Process.pid
|
|
||||||
rescue Errno::ESRCH, Errno::EPERM
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get the process formation
|
# Get the process formation
|
||||||
@@ -302,6 +290,10 @@ private
|
|||||||
|
|
||||||
def name_for(pid)
|
def name_for(pid)
|
||||||
process, index = @running[pid]
|
process, index = @running[pid]
|
||||||
|
name_for_index(process, index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_for_index(process, index)
|
||||||
[ @names[process], index.to_s ].compact.join(".")
|
[ @names[process], index.to_s ].compact.join(".")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -350,7 +342,8 @@ private
|
|||||||
reader, writer = create_pipe
|
reader, writer = create_pipe
|
||||||
begin
|
begin
|
||||||
pid = process.run(:output => writer, :env => {
|
pid = process.run(:output => writer, :env => {
|
||||||
"PORT" => port_for(process, n).to_s
|
"PORT" => port_for(process, n).to_s,
|
||||||
|
"PS" => name_for_index(process, n)
|
||||||
})
|
})
|
||||||
writer.puts "started with pid #{pid}"
|
writer.puts "started with pid #{pid}"
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
@@ -422,7 +415,7 @@ private
|
|||||||
end
|
end
|
||||||
rescue Timeout::Error
|
rescue Timeout::Error
|
||||||
system "sending SIGKILL to all processes"
|
system "sending SIGKILL to all processes"
|
||||||
killall "SIGKILL"
|
kill_children "SIGKILL"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ end
|
|||||||
require "foreman/export/base"
|
require "foreman/export/base"
|
||||||
require "foreman/export/inittab"
|
require "foreman/export/inittab"
|
||||||
require "foreman/export/upstart"
|
require "foreman/export/upstart"
|
||||||
|
require "foreman/export/daemon"
|
||||||
require "foreman/export/bluepill"
|
require "foreman/export/bluepill"
|
||||||
require "foreman/export/runit"
|
require "foreman/export/runit"
|
||||||
require "foreman/export/supervisord"
|
require "foreman/export/supervisord"
|
||||||
require "foreman/export/launchd"
|
require "foreman/export/launchd"
|
||||||
|
require "foreman/export/systemd"
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ class Foreman::Export::Base
|
|||||||
error("Must specify a location") unless location
|
error("Must specify a location") unless location
|
||||||
FileUtils.mkdir_p(location) rescue error("Could not create: #{location}")
|
FileUtils.mkdir_p(location) rescue error("Could not create: #{location}")
|
||||||
FileUtils.mkdir_p(log) rescue error("Could not create: #{log}")
|
FileUtils.mkdir_p(log) rescue error("Could not create: #{log}")
|
||||||
|
FileUtils.mkdir_p(run) rescue error("Could not create: #{run}")
|
||||||
FileUtils.chown(user, nil, log) rescue error("Could not chown #{log} to #{user}")
|
FileUtils.chown(user, nil, log) rescue error("Could not chown #{log} to #{user}")
|
||||||
|
FileUtils.chown(user, nil, run) rescue error("Could not chown #{run} to #{user}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
@@ -58,6 +60,10 @@ class Foreman::Export::Base
|
|||||||
options[:log] || "/var/log/#{app}"
|
options[:log] || "/var/log/#{app}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
options[:run] || "/var/run/#{app}"
|
||||||
|
end
|
||||||
|
|
||||||
def user
|
def user
|
||||||
options[:user] || app
|
options[:user] || app
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
require "erb"
|
||||||
|
require "foreman/export"
|
||||||
|
|
||||||
|
class Foreman::Export::Daemon < Foreman::Export::Base
|
||||||
|
|
||||||
|
def export
|
||||||
|
super
|
||||||
|
|
||||||
|
(Dir["#{location}/#{app}-*.conf"] << "#{location}/#{app}.conf").each do |file|
|
||||||
|
clean file
|
||||||
|
end
|
||||||
|
|
||||||
|
write_template "daemon/master.conf.erb", "#{app}.conf", binding
|
||||||
|
|
||||||
|
engine.each_process do |name, process|
|
||||||
|
next if engine.formation[name] < 1
|
||||||
|
write_template "daemon/process_master.conf.erb", "#{app}-#{name}.conf", binding
|
||||||
|
|
||||||
|
1.upto(engine.formation[name]) do |num|
|
||||||
|
port = engine.port_for(process, num)
|
||||||
|
arguments = process.command.split(" ")
|
||||||
|
executable = arguments.slice!(0)
|
||||||
|
arguments = arguments.size > 0 ? " -- #{arguments.join(' ')}" : ""
|
||||||
|
write_template "daemon/process.conf.erb", "#{app}-#{name}-#{num}.conf", binding
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
require "erb"
|
||||||
|
require "foreman/export"
|
||||||
|
|
||||||
|
class Foreman::Export::Systemd < Foreman::Export::Base
|
||||||
|
|
||||||
|
def export
|
||||||
|
super
|
||||||
|
|
||||||
|
Dir["#{location}/#{app}*.target"].concat(Dir["#{location}/#{app}*.service"]).each do |file|
|
||||||
|
clean file
|
||||||
|
end
|
||||||
|
|
||||||
|
process_master_names = []
|
||||||
|
|
||||||
|
engine.each_process do |name, process|
|
||||||
|
next if engine.formation[name] < 1
|
||||||
|
|
||||||
|
process_names = []
|
||||||
|
|
||||||
|
1.upto(engine.formation[name]) do |num|
|
||||||
|
port = engine.port_for(process, num)
|
||||||
|
write_template "systemd/process.service.erb", "#{app}-#{name}-#{num}.service", binding
|
||||||
|
process_names << "#{app}-#{name}-#{num}.service"
|
||||||
|
end
|
||||||
|
|
||||||
|
write_template "systemd/process_master.target.erb", "#{app}-#{name}.target", binding
|
||||||
|
process_master_names << "#{app}-#{name}.target"
|
||||||
|
end
|
||||||
|
|
||||||
|
write_template "systemd/master.target.erb", "#{app}.target", binding
|
||||||
|
end
|
||||||
|
end
|
||||||
+17
-13
@@ -1,4 +1,5 @@
|
|||||||
require "foreman"
|
require "foreman"
|
||||||
|
require "shellwords"
|
||||||
|
|
||||||
class Foreman::Process
|
class Foreman::Process
|
||||||
|
|
||||||
@@ -47,25 +48,18 @@ class Foreman::Process
|
|||||||
def run(options={})
|
def run(options={})
|
||||||
env = @options[:env].merge(options[:env] || {})
|
env = @options[:env].merge(options[:env] || {})
|
||||||
output = options[:output] || $stdout
|
output = options[:output] || $stdout
|
||||||
|
runner = "#{Foreman.runner}".shellescape
|
||||||
|
|
||||||
if Foreman.windows?
|
if Foreman.windows?
|
||||||
Dir.chdir(cwd) do
|
Dir.chdir(cwd) do
|
||||||
Process.spawn env, expanded_command(env), :out => output, :err => output
|
Process.spawn env, expanded_command(env), :out => output, :err => output
|
||||||
end
|
end
|
||||||
elsif Foreman.jruby_18?
|
elsif Foreman.jruby_18? || Foreman.ruby_18?
|
||||||
require "posix/spawn"
|
require "posix/spawn"
|
||||||
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
wrapped_command = "#{runner} -d '#{cwd.shellescape}' -p -- #{expanded_command(env)}"
|
||||||
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
|
POSIX::Spawn.spawn(*spawn_args(env, wrapped_command.shellsplit, {:out => output, :err => output}))
|
||||||
elsif Foreman.ruby_18?
|
|
||||||
fork do
|
|
||||||
$stdout.reopen output
|
|
||||||
$stderr.reopen output
|
|
||||||
env.each { |k,v| ENV[k] = v }
|
|
||||||
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
|
||||||
Kernel.exec wrapped_command
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
wrapped_command = "#{runner} -d '#{cwd.shellescape}' -p -- #{command}"
|
||||||
Process.spawn env, wrapped_command, :out => output, :err => output
|
Process.spawn env, wrapped_command, :out => output, :err => output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -122,4 +116,14 @@ class Foreman::Process
|
|||||||
File.expand_path(@options[:cwd] || ".")
|
File.expand_path(@options[:cwd] || ".")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def spawn_args(env, argv, options)
|
||||||
|
args = []
|
||||||
|
args << env
|
||||||
|
args += argv
|
||||||
|
args << options
|
||||||
|
args
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
+23
-2
@@ -1,7 +1,7 @@
|
|||||||
.\" generated with Ronn/v0.7.3
|
.\" generated with Ronn/v0.7.3
|
||||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||||
.
|
.
|
||||||
.TH "FOREMAN" "1" "January 2013" "Foreman 0.61.0" "Foreman Manual"
|
.TH "FOREMAN" "1" "May 2013" "Foreman 0.63.0" "Foreman Manual"
|
||||||
.
|
.
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
\fBforeman\fR \- manage Procfile\-based applications
|
\fBforeman\fR \- manage Procfile\-based applications
|
||||||
@@ -107,9 +107,18 @@ bluepill
|
|||||||
inittab
|
inittab
|
||||||
.
|
.
|
||||||
.IP "\(bu" 4
|
.IP "\(bu" 4
|
||||||
|
launchd
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
runit
|
runit
|
||||||
.
|
.
|
||||||
.IP "\(bu" 4
|
.IP "\(bu" 4
|
||||||
|
supervisord
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
systemd
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
upstart
|
upstart
|
||||||
.
|
.
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
@@ -130,6 +139,18 @@ EX02:4:respawn:/bin/su \- example \-c \'PORT=5100 bundle exec rake jobs:work >>
|
|||||||
.
|
.
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
.
|
.
|
||||||
|
.SH "SYSTEMD EXPORT"
|
||||||
|
Will create a series of systemd scripts in the location you specify\. Scripts will be structured to make the following commands valid:
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
\fBsystemctl start appname\.target\fR
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
\fBsystemctl stop appname\-processname\.target\fR
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
\fBsystemctl restart appname\-processname\-3\.service\fR
|
||||||
|
.
|
||||||
.SH "UPSTART EXPORT"
|
.SH "UPSTART EXPORT"
|
||||||
Will create a series of upstart scripts in the location you specify\. Scripts will be structured to make the following commands valid:
|
Will create a series of upstart scripts in the location you specify\. Scripts will be structured to make the following commands valid:
|
||||||
.
|
.
|
||||||
@@ -157,7 +178,7 @@ job: bundle exec rake jobs:work
|
|||||||
.IP "" 0
|
.IP "" 0
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
A process name may contain letters, numbers amd the underscore character\. You can validate your Procfile format using the \fBcheck\fR command:
|
A process name may contain letters, numbers and the underscore character\. You can validate your Procfile format using the \fBcheck\fR command:
|
||||||
.
|
.
|
||||||
.IP "" 4
|
.IP "" 4
|
||||||
.
|
.
|
||||||
|
|||||||
+19
-2
@@ -101,8 +101,14 @@ foreman currently supports the following output formats:
|
|||||||
|
|
||||||
* inittab
|
* inittab
|
||||||
|
|
||||||
|
* launchd
|
||||||
|
|
||||||
* runit
|
* runit
|
||||||
|
|
||||||
|
* supervisord
|
||||||
|
|
||||||
|
* systemd
|
||||||
|
|
||||||
* upstart
|
* upstart
|
||||||
|
|
||||||
## INITTAB EXPORT
|
## INITTAB EXPORT
|
||||||
@@ -114,6 +120,17 @@ Will export a chunk of inittab-compatible configuration:
|
|||||||
EX02:4:respawn:/bin/su - example -c 'PORT=5100 bundle exec rake jobs:work >> /var/log/job-1.log 2>&1'
|
EX02:4:respawn:/bin/su - example -c 'PORT=5100 bundle exec rake jobs:work >> /var/log/job-1.log 2>&1'
|
||||||
# ----- end foreman example processes -----
|
# ----- end foreman example processes -----
|
||||||
|
|
||||||
|
## SYSTEMD EXPORT
|
||||||
|
|
||||||
|
Will create a series of systemd scripts in the location you specify. Scripts
|
||||||
|
will be structured to make the following commands valid:
|
||||||
|
|
||||||
|
`systemctl start appname.target`
|
||||||
|
|
||||||
|
`systemctl stop appname-processname.target`
|
||||||
|
|
||||||
|
`systemctl restart appname-processname-3.service`
|
||||||
|
|
||||||
## UPSTART EXPORT
|
## UPSTART EXPORT
|
||||||
|
|
||||||
Will create a series of upstart scripts in the location you specify. Scripts
|
Will create a series of upstart scripts in the location you specify. Scripts
|
||||||
@@ -133,7 +150,7 @@ to run it.
|
|||||||
web: bundle exec thin start
|
web: bundle exec thin start
|
||||||
job: bundle exec rake jobs:work
|
job: bundle exec rake jobs:work
|
||||||
|
|
||||||
A process name may contain letters, numbers amd the underscore character.
|
A process name may contain letters, numbers and the underscore character.
|
||||||
You can validate your Procfile format using the `check` command:
|
You can validate your Procfile format using the `check` command:
|
||||||
|
|
||||||
$ foreman check
|
$ foreman check
|
||||||
@@ -168,7 +185,7 @@ Export the application in upstart format:
|
|||||||
|
|
||||||
Run one process type from the application defined in a specific Procfile:
|
Run one process type from the application defined in a specific Procfile:
|
||||||
|
|
||||||
$ foreman start alpha -p ~/myapp/Procfile
|
$ foreman start alpha -f ~/myapp/Procfile
|
||||||
|
|
||||||
## COPYRIGHT
|
## COPYRIGHT
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ describe "Foreman::CLI", :fakefs do
|
|||||||
output.should =~ /test.1 \| testing/
|
output.should =~ /test.1 \| testing/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "sets PS variable with the process name" do
|
||||||
|
without_fakefs do
|
||||||
|
output = foreman("start -f #{resource_path("Procfile")}")
|
||||||
|
output.should =~ /ps.1 \| PS env var is ps.1/
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -93,4 +100,12 @@ describe "Foreman::CLI", :fakefs do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "when posix-spawn is not present on ruby 1.8" do
|
||||||
|
it "should fail with an error" do
|
||||||
|
mock(Kernel).require('posix/spawn') { raise LoadError }
|
||||||
|
output = foreman("start -f #{resource_path("Procfile")}")
|
||||||
|
output.should == "ERROR: foreman requires gem `posix-spawn` on Ruby #{RUBY_VERSION}. Please `gem install posix-spawn`.\n"
|
||||||
|
end
|
||||||
|
end if running_ruby_18?
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
require "spec_helper"
|
||||||
|
require "foreman/engine"
|
||||||
|
require "foreman/export/daemon"
|
||||||
|
require "tmpdir"
|
||||||
|
|
||||||
|
describe Foreman::Export::Daemon, :fakefs do
|
||||||
|
let(:procfile) { write_procfile("/tmp/app/Procfile") }
|
||||||
|
let(:formation) { nil }
|
||||||
|
let(:engine) { Foreman::Engine.new(:formation => formation).load_procfile(procfile) }
|
||||||
|
let(:options) { Hash.new }
|
||||||
|
let(:daemon) { Foreman::Export::Daemon.new("/tmp/init", engine, options) }
|
||||||
|
|
||||||
|
before(:each) { load_export_templates_into_fakefs("daemon") }
|
||||||
|
before(:each) { stub(daemon).say }
|
||||||
|
|
||||||
|
it "exports to the filesystem" do
|
||||||
|
daemon.export
|
||||||
|
|
||||||
|
File.read("/tmp/init/app.conf").should == example_export_file("daemon/app.conf")
|
||||||
|
File.read("/tmp/init/app-alpha.conf").should == example_export_file("daemon/app-alpha.conf")
|
||||||
|
File.read("/tmp/init/app-alpha-1.conf").should == example_export_file("daemon/app-alpha-1.conf")
|
||||||
|
File.read("/tmp/init/app-bravo.conf").should == example_export_file("daemon/app-bravo.conf")
|
||||||
|
File.read("/tmp/init/app-bravo-1.conf").should == example_export_file("daemon/app-bravo-1.conf")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "cleans up if exporting into an existing dir" do
|
||||||
|
mock(FileUtils).rm("/tmp/init/app.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha-1.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo-1.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo-bar.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo-bar-1.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo_bar.conf")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo_bar-1.conf")
|
||||||
|
|
||||||
|
daemon.export
|
||||||
|
daemon.export
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not delete exported files for similarly named applications" do
|
||||||
|
FileUtils.mkdir_p "/tmp/init"
|
||||||
|
|
||||||
|
["app2", "app2-alpha", "app2-alpha-1"].each do |name|
|
||||||
|
path = "/tmp/init/#{name}.conf"
|
||||||
|
FileUtils.touch(path)
|
||||||
|
dont_allow(FileUtils).rm(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
daemon.export
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with a formation" do
|
||||||
|
let(:formation) { "alpha=2" }
|
||||||
|
|
||||||
|
it "exports to the filesystem with concurrency" do
|
||||||
|
daemon.export
|
||||||
|
|
||||||
|
File.read("/tmp/init/app.conf").should == example_export_file("daemon/app.conf")
|
||||||
|
File.read("/tmp/init/app-alpha.conf").should == example_export_file("daemon/app-alpha.conf")
|
||||||
|
File.read("/tmp/init/app-alpha-1.conf").should == example_export_file("daemon/app-alpha-1.conf")
|
||||||
|
File.read("/tmp/init/app-alpha-2.conf").should == example_export_file("daemon/app-alpha-2.conf")
|
||||||
|
File.exists?("/tmp/init/app-bravo-1.conf").should == false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with alternate templates" do
|
||||||
|
let(:template) { "/tmp/alternate" }
|
||||||
|
let(:options) { { :app => "app", :template => template } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
FileUtils.mkdir_p template
|
||||||
|
File.open("#{template}/master.conf.erb", "w") { |f| f.puts "alternate_template" }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can export with alternate template files" do
|
||||||
|
daemon.export
|
||||||
|
File.read("/tmp/init/app.conf").should == "alternate_template\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with alternate templates from home dir" do
|
||||||
|
|
||||||
|
before do
|
||||||
|
FileUtils.mkdir_p File.expand_path("~/.foreman/templates/daemon")
|
||||||
|
File.open(File.expand_path("~/.foreman/templates/daemon/master.conf.erb"), "w") do |file|
|
||||||
|
file.puts "default_alternate_template"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can export with alternate template files" do
|
||||||
|
daemon.export
|
||||||
|
File.read("/tmp/init/app.conf").should == "default_alternate_template\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -31,6 +31,6 @@ describe Foreman::Export::Runit, :fakefs do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "creates a full path to the export directory" do
|
it "creates a full path to the export directory" do
|
||||||
expect { runit.export }.to_not raise_error(Errno::ENOENT)
|
expect { runit.export }.to_not raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
require "spec_helper"
|
||||||
|
require "foreman/engine"
|
||||||
|
require "foreman/export/systemd"
|
||||||
|
require "tmpdir"
|
||||||
|
|
||||||
|
describe Foreman::Export::Systemd, :fakefs do
|
||||||
|
let(:procfile) { write_procfile("/tmp/app/Procfile") }
|
||||||
|
let(:formation) { nil }
|
||||||
|
let(:engine) { Foreman::Engine.new(:formation => formation).load_procfile(procfile) }
|
||||||
|
let(:options) { Hash.new }
|
||||||
|
let(:systemd) { Foreman::Export::Systemd.new("/tmp/init", engine, options) }
|
||||||
|
|
||||||
|
before(:each) { load_export_templates_into_fakefs("systemd") }
|
||||||
|
before(:each) { stub(systemd).say }
|
||||||
|
|
||||||
|
it "exports to the filesystem" do
|
||||||
|
systemd.export
|
||||||
|
|
||||||
|
File.read("/tmp/init/app.target").should == example_export_file("systemd/app.target")
|
||||||
|
File.read("/tmp/init/app-alpha.target").should == example_export_file("systemd/app-alpha.target")
|
||||||
|
File.read("/tmp/init/app-alpha-1.service").should == example_export_file("systemd/app-alpha-1.service")
|
||||||
|
File.read("/tmp/init/app-bravo.target").should == example_export_file("systemd/app-bravo.target")
|
||||||
|
File.read("/tmp/init/app-bravo-1.service").should == example_export_file("systemd/app-bravo-1.service")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "cleans up if exporting into an existing dir" do
|
||||||
|
mock(FileUtils).rm("/tmp/init/app.target")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha.target")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-alpha-1.service")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo.target")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-bravo-1.service")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo-bar.target")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo-bar-1.service")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo_bar.target")
|
||||||
|
mock(FileUtils).rm("/tmp/init/app-foo_bar-1.service")
|
||||||
|
|
||||||
|
systemd.export
|
||||||
|
systemd.export
|
||||||
|
end
|
||||||
|
|
||||||
|
it "includes environment variables" do
|
||||||
|
engine.env['KEY'] = 'some "value"'
|
||||||
|
systemd.export
|
||||||
|
File.read("/tmp/init/app-alpha-1.service").should =~ /KEY=some "value"$/
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with a formation" do
|
||||||
|
let(:formation) { "alpha=2" }
|
||||||
|
|
||||||
|
it "exports to the filesystem with concurrency" do
|
||||||
|
systemd.export
|
||||||
|
|
||||||
|
File.read("/tmp/init/app.target").should == example_export_file("systemd/app.target")
|
||||||
|
File.read("/tmp/init/app-alpha.target").should == example_export_file("systemd/app-alpha.target")
|
||||||
|
File.read("/tmp/init/app-alpha-1.service").should == example_export_file("systemd/app-alpha-1.service")
|
||||||
|
File.read("/tmp/init/app-alpha-2.service").should == example_export_file("systemd/app-alpha-2.service")
|
||||||
|
File.exists?("/tmp/init/app-bravo-1.service").should == false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with alternate templates" do
|
||||||
|
let(:template) { "/tmp/alternate" }
|
||||||
|
let(:options) { { :app => "app", :template => template } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
FileUtils.mkdir_p template
|
||||||
|
File.open("#{template}/master.target.erb", "w") { |f| f.puts "alternate_template" }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can export with alternate template files" do
|
||||||
|
systemd.export
|
||||||
|
File.read("/tmp/init/app.target").should == "alternate_template\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with alternate templates from home dir" do
|
||||||
|
|
||||||
|
before do
|
||||||
|
FileUtils.mkdir_p File.expand_path("~/.foreman/templates/systemd")
|
||||||
|
File.open(File.expand_path("~/.foreman/templates/systemd/master.target.erb"), "w") do |file|
|
||||||
|
file.puts "default_alternate_template"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can export with alternate template files" do
|
||||||
|
systemd.export
|
||||||
|
File.read("/tmp/init/app.target").should == "default_alternate_template\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -41,7 +41,7 @@ describe Foreman::Process do
|
|||||||
|
|
||||||
it "should output utf8 properly" do
|
it "should output utf8 properly" do
|
||||||
process = Foreman::Process.new(resource_path("bin/utf8"))
|
process = Foreman::Process.new(resource_path("bin/utf8"))
|
||||||
run(process).should == "\xFF\x03\n".force_encoding('binary')
|
run(process).should == (Foreman.ruby_18? ? "\xFF\x03\n" : "\xFF\x03\n".force_encoding('binary'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ echo: bin/echo echoing
|
|||||||
env: bin/env FOO
|
env: bin/env FOO
|
||||||
test: bin/test
|
test: bin/test
|
||||||
utf8: bin/utf8
|
utf8: bin/utf8
|
||||||
|
ps: bin/echo PS env var is $PS
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
start on starting app-alpha
|
||||||
|
stop on stopping app-alpha
|
||||||
|
respawn
|
||||||
|
|
||||||
|
env PORT=5000
|
||||||
|
|
||||||
|
exec start-stop-daemon --start --chuid app --chdir /tmp/app --make-pidfile --pidfile /var/run/app/app-alpha-1.pid --exec ./alpha >> /var/log/app/app-alpha-1.log 2>&1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
start on starting app-alpha
|
||||||
|
stop on stopping app-alpha
|
||||||
|
respawn
|
||||||
|
|
||||||
|
env PORT=5001
|
||||||
|
|
||||||
|
exec start-stop-daemon --start --chuid app --chdir /tmp/app --make-pidfile --pidfile /var/run/app/app-alpha-2.pid --exec ./alpha >> /var/log/app/app-alpha-2.log 2>&1
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
start on starting app
|
||||||
|
stop on stopping app
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
start on starting app-bravo
|
||||||
|
stop on stopping app-bravo
|
||||||
|
respawn
|
||||||
|
|
||||||
|
env PORT=5100
|
||||||
|
|
||||||
|
exec start-stop-daemon --start --chuid app --chdir /tmp/app --make-pidfile --pidfile /var/run/app/app-bravo-1.pid --exec ./bravo >> /var/log/app/app-bravo-1.log 2>&1
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
start on starting app
|
||||||
|
stop on stopping app
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
pre-start script
|
||||||
|
|
||||||
|
bash << "EOF"
|
||||||
|
mkdir -p /var/log/app
|
||||||
|
chown -R app /var/log/app
|
||||||
|
mkdir -p /var/run/app
|
||||||
|
chown -R app /var/run/app
|
||||||
|
EOF
|
||||||
|
|
||||||
|
end script
|
||||||
|
|
||||||
|
start on runlevel [2345]
|
||||||
|
|
||||||
|
stop on runlevel [016]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=app
|
||||||
|
WorkingDirectory=/tmp/app
|
||||||
|
Environment=PORT=5000
|
||||||
|
ExecStart=/bin/bash -lc './alpha'
|
||||||
|
Restart=always
|
||||||
|
StandardInput=null
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=%n
|
||||||
|
KillMode=process
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=app-alpha.target
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=app
|
||||||
|
WorkingDirectory=/tmp/app
|
||||||
|
Environment=PORT=5001
|
||||||
|
ExecStart=/bin/bash -lc './alpha'
|
||||||
|
Restart=always
|
||||||
|
StandardInput=null
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=%n
|
||||||
|
KillMode=process
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=app-alpha.target
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=app.target
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=app
|
||||||
|
WorkingDirectory=/tmp/app
|
||||||
|
Environment=PORT=5100
|
||||||
|
ExecStart=/bin/bash -lc './bravo'
|
||||||
|
Restart=always
|
||||||
|
StandardInput=null
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=%n
|
||||||
|
KillMode=process
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=app-bravo.target
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[Unit]
|
||||||
|
StopWhenUnneeded=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=app.target
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[Unit]
|
||||||
+27
-5
@@ -10,6 +10,15 @@ require "fakefs/spec_helpers"
|
|||||||
|
|
||||||
$:.unshift File.expand_path("../../lib", __FILE__)
|
$:.unshift File.expand_path("../../lib", __FILE__)
|
||||||
|
|
||||||
|
begin
|
||||||
|
def running_ruby_18?
|
||||||
|
defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
|
||||||
|
end
|
||||||
|
require 'posix/spawn' if running_ruby_18?
|
||||||
|
rescue LoadError
|
||||||
|
STDERR.puts "WARNING: foreman requires gem `posix-spawn` on Ruby #{RUBY_VERSION}. Please `gem install posix-spawn`."
|
||||||
|
end
|
||||||
|
|
||||||
def mock_export_error(message)
|
def mock_export_error(message)
|
||||||
lambda { yield }.should raise_error(Foreman::Export::Exception, message)
|
lambda { yield }.should raise_error(Foreman::Export::Exception, message)
|
||||||
end
|
end
|
||||||
@@ -21,6 +30,10 @@ def mock_error(subject, message)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def make_pipe
|
||||||
|
IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
||||||
|
end
|
||||||
|
|
||||||
def foreman(args)
|
def foreman(args)
|
||||||
capture_stdout do
|
capture_stdout do
|
||||||
begin
|
begin
|
||||||
@@ -31,14 +44,18 @@ def foreman(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def forked_foreman(args)
|
def forked_foreman(args)
|
||||||
rd, wr = IO.pipe("BINARY")
|
rd, wr = make_pipe
|
||||||
Process.spawn("bundle exec bin/foreman #{args}", :out => wr, :err => wr)
|
if running_ruby_18?
|
||||||
|
POSIX::Spawn.spawn({}, "bundle exec bin/foreman #{args}", :out => wr, :err => wr)
|
||||||
|
else
|
||||||
|
Process.spawn("bundle exec bin/foreman #{args}", :out => wr, :err => wr)
|
||||||
|
end
|
||||||
wr.close
|
wr.close
|
||||||
rd.read
|
rd.read
|
||||||
end
|
end
|
||||||
|
|
||||||
def fork_and_capture(&blk)
|
def fork_and_capture(&blk)
|
||||||
rd, wr = IO.pipe("BINARY")
|
rd, wr = make_pipe
|
||||||
pid = fork do
|
pid = fork do
|
||||||
rd.close
|
rd.close
|
||||||
wr.sync = true
|
wr.sync = true
|
||||||
@@ -57,7 +74,11 @@ def fork_and_capture(&blk)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def fork_and_get_exitstatus(args)
|
def fork_and_get_exitstatus(args)
|
||||||
pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
|
pid = if running_ruby_18?
|
||||||
|
POSIX::Spawn.spawn({}, "bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
|
||||||
|
else
|
||||||
|
Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
|
||||||
|
end
|
||||||
Process.wait(pid)
|
Process.wait(pid)
|
||||||
$?.exitstatus
|
$?.exitstatus
|
||||||
end
|
end
|
||||||
@@ -141,7 +162,7 @@ end
|
|||||||
|
|
||||||
def capture_stdout
|
def capture_stdout
|
||||||
old_stdout = $stdout.dup
|
old_stdout = $stdout.dup
|
||||||
rd, wr = IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
rd, wr = make_pipe
|
||||||
$stdout = wr
|
$stdout = wr
|
||||||
yield
|
yield
|
||||||
wr.close
|
wr.close
|
||||||
@@ -156,4 +177,5 @@ RSpec.configure do |config|
|
|||||||
config.order = 'rand'
|
config.order = 'rand'
|
||||||
config.include FakeFS::SpecHelpers, :fakefs
|
config.include FakeFS::SpecHelpers, :fakefs
|
||||||
config.mock_with :rr
|
config.mock_with :rr
|
||||||
|
config.backtrace_exclusion_patterns = []
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user