Compare commits
53 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,10 +2,7 @@ script: bundle exec rake spec
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: 1.8.7
|
||||
- rvm: jruby
|
||||
- rvm: rbx
|
||||
- rvm: ree
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -16,7 +13,9 @@ notifications:
|
||||
- http://dx-helper.herokuapp.com/travis
|
||||
|
||||
rvm:
|
||||
- 1.8.7
|
||||
- 1.9.2
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- 2.1.0
|
||||
- jruby
|
||||
|
||||
14
Changelog.md
14
Changelog.md
@@ -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)
|
||||
|
||||
* Merge pull request #334 from ged/reentrant_signal_handlers [David Dollar]
|
||||
|
||||
6
Gemfile
6
Gemfile
@@ -6,7 +6,7 @@ platform :mingw do
|
||||
gem "win32console", "~> 1.3.0"
|
||||
end
|
||||
|
||||
platform :jruby do
|
||||
platform :jruby, :ruby_18 do
|
||||
gem "posix-spawn", "~> 0.3.6"
|
||||
end
|
||||
|
||||
@@ -18,6 +18,8 @@ group :development do
|
||||
gem 'rr', '~> 1.0.2'
|
||||
gem 'rspec', '~> 2.0'
|
||||
gem "simplecov", :require => false
|
||||
gem 'timecop'
|
||||
gem 'timecop', '0.6.1'
|
||||
gem 'yard'
|
||||
gem 'mime-types', '~> 1.25.1'
|
||||
gem 'rdiscount', '~> 1.6.8'
|
||||
end
|
||||
|
||||
62
Gemfile.lock
62
Gemfile.lock
@@ -8,44 +8,46 @@ PATH
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
aws-s3 (0.6.2)
|
||||
aws-s3 (0.6.3)
|
||||
builder
|
||||
mime-types
|
||||
xml-simple
|
||||
builder (3.0.0)
|
||||
diff-lcs (1.1.3)
|
||||
dotenv (0.7.0)
|
||||
builder (3.2.2)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.3)
|
||||
dotenv (0.10.0)
|
||||
fakefs (0.3.2)
|
||||
hpricot (0.8.6)
|
||||
hpricot (0.8.6-java)
|
||||
mime-types (1.16)
|
||||
multi_json (1.0.4)
|
||||
mustache (0.11.2)
|
||||
posix-spawn (0.3.6)
|
||||
rake (0.9.2.2)
|
||||
rdiscount (1.6.5)
|
||||
mime-types (1.25.1)
|
||||
multi_json (1.9.0)
|
||||
mustache (0.99.5)
|
||||
posix-spawn (0.3.8)
|
||||
rake (10.1.1)
|
||||
rdiscount (1.6.8)
|
||||
ronn (0.7.3)
|
||||
hpricot (>= 0.8.2)
|
||||
mustache (>= 0.7.0)
|
||||
rdiscount (>= 1.5.8)
|
||||
rr (1.0.2)
|
||||
rspec (2.8.0)
|
||||
rspec-core (~> 2.8.0)
|
||||
rspec-expectations (~> 2.8.0)
|
||||
rspec-mocks (~> 2.8.0)
|
||||
rspec-core (2.8.0)
|
||||
rspec-expectations (2.8.0)
|
||||
diff-lcs (~> 1.1.2)
|
||||
rspec-mocks (2.8.0)
|
||||
simplecov (0.5.4)
|
||||
multi_json (~> 1.0.3)
|
||||
simplecov-html (~> 0.5.3)
|
||||
simplecov-html (0.5.3)
|
||||
thor (0.16.0)
|
||||
timecop (0.3.5)
|
||||
win32console (1.3.0-x86-mingw32)
|
||||
xml-simple (1.0.15)
|
||||
yard (0.8.2)
|
||||
rr (1.0.5)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.8)
|
||||
rspec-expectations (2.14.5)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
simplecov (0.8.2)
|
||||
docile (~> 1.1.0)
|
||||
multi_json
|
||||
simplecov-html (~> 0.8.0)
|
||||
simplecov-html (0.8.0)
|
||||
thor (0.18.1)
|
||||
timecop (0.6.1)
|
||||
win32console (1.3.2-x86-mingw32)
|
||||
xml-simple (1.1.3)
|
||||
yard (0.8.7.3)
|
||||
|
||||
PLATFORMS
|
||||
java
|
||||
@@ -56,12 +58,14 @@ DEPENDENCIES
|
||||
aws-s3
|
||||
fakefs (~> 0.3.2)
|
||||
foreman!
|
||||
mime-types (~> 1.25.1)
|
||||
posix-spawn (~> 0.3.6)
|
||||
rake
|
||||
rdiscount (~> 1.6.8)
|
||||
ronn
|
||||
rr (~> 1.0.2)
|
||||
rspec (~> 2.0)
|
||||
simplecov
|
||||
timecop
|
||||
timecop (= 0.6.1)
|
||||
win32console (~> 1.3.0)
|
||||
yard
|
||||
|
||||
@@ -32,6 +32,7 @@ Manage Procfile-based applications
|
||||
* [shoreman](https://github.com/hecticjeff/shoreman) - shell
|
||||
* [honcho](https://github.com/nickstenning/honcho) - python
|
||||
* [norman](https://github.com/josh/norman) - node.js
|
||||
* [forego](https://github.com/ddollar/forego) - Go
|
||||
|
||||
## Authors
|
||||
|
||||
|
||||
14
data/export/daemon/master.conf.erb
Normal file
14
data/export/daemon/master.conf.erb
Normal file
@@ -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]
|
||||
8
data/export/daemon/process.conf.erb
Normal file
8
data/export/daemon/process.conf.erb
Normal file
@@ -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
|
||||
2
data/export/daemon/process_master.conf.erb
Normal file
2
data/export/daemon/process_master.conf.erb
Normal file
@@ -0,0 +1,2 @@
|
||||
start on starting <%= app %>
|
||||
stop on stopping <%= app %>
|
||||
6
data/export/systemd/master.target.erb
Normal file
6
data/export/systemd/master.target.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
[Unit]
|
||||
StopWhenUnneeded=true
|
||||
Wants=<%= process_master_names.join(' ') %>
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
15
data/export/systemd/process.service.erb
Normal file
15
data/export/systemd/process.service.erb
Normal file
@@ -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
|
||||
3
data/export/systemd/process_master.target.erb
Normal file
3
data/export/systemd/process_master.target.erb
Normal file
@@ -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 %>
|
||||
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'
|
||||
|
||||
2
dist/tgz.rake
vendored
2
dist/tgz.rake
vendored
@@ -4,7 +4,7 @@ file pkg("foreman-#{version}.tgz") => distribution_files do |t|
|
||||
assemble_distribution
|
||||
assemble_gems
|
||||
rm_f "bin/foreman"
|
||||
assemble resource("tgz/foreman"), "foreman", 0755
|
||||
assemble resource("tgz/foreman"), "bin/foreman", 0755
|
||||
end
|
||||
|
||||
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
|
||||
@@ -34,6 +34,7 @@ class Foreman::CLI < Thor
|
||||
end
|
||||
|
||||
def start(process=nil)
|
||||
require_posix_spawn_for_ruby_18!
|
||||
check_procfile!
|
||||
load_environment!
|
||||
engine.load_procfile(procfile)
|
||||
@@ -45,6 +46,7 @@ class Foreman::CLI < Thor
|
||||
|
||||
method_option :app, :type => :string, :aliases => "-a"
|
||||
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 :port, :type => :numeric, :aliases => "-p"
|
||||
method_option :user, :type => :string, :aliases => "-u"
|
||||
@@ -81,22 +83,18 @@ class Foreman::CLI < Thor
|
||||
engine.load_procfile(procfile)
|
||||
end
|
||||
|
||||
pid = fork do
|
||||
begin
|
||||
engine.env.each { |k,v| ENV[k] = v }
|
||||
if args.size == 1 && process = engine.process(args.first)
|
||||
process.exec(:env => engine.env)
|
||||
else
|
||||
exec args.shelljoin
|
||||
end
|
||||
rescue Errno::EACCES
|
||||
error "not executable: #{args.first}"
|
||||
rescue Errno::ENOENT
|
||||
error "command not found: #{args.first}"
|
||||
begin
|
||||
engine.env.each { |k,v| ENV[k] = v }
|
||||
if args.size == 1 && process = engine.process(args.first)
|
||||
process.exec(:env => engine.env)
|
||||
else
|
||||
exec args.shelljoin
|
||||
end
|
||||
rescue Errno::EACCES
|
||||
error "not executable: #{args.first}"
|
||||
rescue Errno::ENOENT
|
||||
error "command not found: #{args.first}"
|
||||
end
|
||||
Process.wait(pid)
|
||||
exit $?.exitstatus
|
||||
end
|
||||
|
||||
desc "version", "Display Foreman gem version"
|
||||
@@ -137,6 +135,14 @@ private ######################################################################
|
||||
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
|
||||
case
|
||||
when options[:procfile] then options[:procfile]
|
||||
|
||||
@@ -176,19 +176,14 @@ class Foreman::Engine
|
||||
#
|
||||
# @param [String] signal The signal to send to each process
|
||||
#
|
||||
def kill_children(signal="SIGTERM")
|
||||
if Foreman.windows?
|
||||
@running.each do |pid, (process, index)|
|
||||
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
||||
begin
|
||||
Process.kill(signal, pid)
|
||||
rescue Errno::ESRCH, Errno::EPERM
|
||||
end
|
||||
end
|
||||
else
|
||||
def kill_children( signal="SIGTERM" )
|
||||
@running.each do |pid, (process, index)|
|
||||
system "sending #{signal} to #{name_for(pid)} at pid #{pid}"
|
||||
begin
|
||||
Process.kill signal, *@running.keys unless @running.empty?
|
||||
rescue Errno::ESRCH, Errno::EPERM
|
||||
Process.kill( signal, pid )
|
||||
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
|
||||
@@ -198,14 +193,7 @@ class Foreman::Engine
|
||||
# @param [String] signal The signal to send
|
||||
#
|
||||
def killall(signal="SIGTERM")
|
||||
if Foreman.windows?
|
||||
kill_children(signal)
|
||||
else
|
||||
begin
|
||||
Process.kill "-#{signal}", Process.pid
|
||||
rescue Errno::ESRCH, Errno::EPERM
|
||||
end
|
||||
end
|
||||
kill_children(signal)
|
||||
end
|
||||
|
||||
# Get the process formation
|
||||
@@ -302,6 +290,10 @@ private
|
||||
|
||||
def name_for(pid)
|
||||
process, index = @running[pid]
|
||||
name_for_index(process, index)
|
||||
end
|
||||
|
||||
def name_for_index(process, index)
|
||||
[ @names[process], index.to_s ].compact.join(".")
|
||||
end
|
||||
|
||||
@@ -350,7 +342,8 @@ private
|
||||
reader, writer = create_pipe
|
||||
begin
|
||||
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}"
|
||||
rescue Errno::ENOENT
|
||||
@@ -422,7 +415,7 @@ private
|
||||
end
|
||||
rescue Timeout::Error
|
||||
system "sending SIGKILL to all processes"
|
||||
killall "SIGKILL"
|
||||
kill_children "SIGKILL"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -28,7 +28,9 @@ end
|
||||
require "foreman/export/base"
|
||||
require "foreman/export/inittab"
|
||||
require "foreman/export/upstart"
|
||||
require "foreman/export/daemon"
|
||||
require "foreman/export/bluepill"
|
||||
require "foreman/export/runit"
|
||||
require "foreman/export/supervisord"
|
||||
require "foreman/export/launchd"
|
||||
require "foreman/export/systemd"
|
||||
|
||||
@@ -47,7 +47,9 @@ class Foreman::Export::Base
|
||||
error("Must specify a location") unless location
|
||||
FileUtils.mkdir_p(location) rescue error("Could not create: #{location}")
|
||||
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, run) rescue error("Could not chown #{run} to #{user}")
|
||||
end
|
||||
|
||||
def app
|
||||
@@ -58,6 +60,10 @@ class Foreman::Export::Base
|
||||
options[:log] || "/var/log/#{app}"
|
||||
end
|
||||
|
||||
def run
|
||||
options[:run] || "/var/run/#{app}"
|
||||
end
|
||||
|
||||
def user
|
||||
options[:user] || app
|
||||
end
|
||||
|
||||
28
lib/foreman/export/daemon.rb
Normal file
28
lib/foreman/export/daemon.rb
Normal file
@@ -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
|
||||
32
lib/foreman/export/systemd.rb
Normal file
32
lib/foreman/export/systemd.rb
Normal file
@@ -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
|
||||
@@ -1,4 +1,5 @@
|
||||
require "foreman"
|
||||
require "shellwords"
|
||||
|
||||
class Foreman::Process
|
||||
|
||||
@@ -47,25 +48,18 @@ class Foreman::Process
|
||||
def run(options={})
|
||||
env = @options[:env].merge(options[:env] || {})
|
||||
output = options[:output] || $stdout
|
||||
|
||||
runner = "#{Foreman.runner}".shellescape
|
||||
|
||||
if Foreman.windows?
|
||||
Dir.chdir(cwd) do
|
||||
Process.spawn env, expanded_command(env), :out => output, :err => output
|
||||
end
|
||||
elsif Foreman.jruby_18?
|
||||
elsif Foreman.jruby_18? || Foreman.ruby_18?
|
||||
require "posix/spawn"
|
||||
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
|
||||
POSIX::Spawn.spawn env, wrapped_command, :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
|
||||
wrapped_command = "#{runner} -d '#{cwd.shellescape}' -p -- #{expanded_command(env)}"
|
||||
POSIX::Spawn.spawn(*spawn_args(env, wrapped_command.shellsplit, {:out => output, :err => output}))
|
||||
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
|
||||
end
|
||||
end
|
||||
@@ -122,4 +116,14 @@ class Foreman::Process
|
||||
File.expand_path(@options[:cwd] || ".")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def spawn_args(env, argv, options)
|
||||
args = []
|
||||
args << env
|
||||
args += argv
|
||||
args << options
|
||||
args
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" generated with Ronn/v0.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"
|
||||
\fBforeman\fR \- manage Procfile\-based applications
|
||||
@@ -107,9 +107,18 @@ bluepill
|
||||
inittab
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
launchd
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
runit
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
supervisord
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
systemd
|
||||
.
|
||||
.IP "\(bu" 4
|
||||
upstart
|
||||
.
|
||||
.IP "" 0
|
||||
@@ -130,6 +139,18 @@ EX02:4:respawn:/bin/su \- example \-c \'PORT=5100 bundle exec rake jobs:work >>
|
||||
.
|
||||
.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"
|
||||
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
|
||||
.
|
||||
.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
|
||||
.
|
||||
|
||||
@@ -101,8 +101,14 @@ foreman currently supports the following output formats:
|
||||
|
||||
* inittab
|
||||
|
||||
* launchd
|
||||
|
||||
* runit
|
||||
|
||||
* supervisord
|
||||
|
||||
* systemd
|
||||
|
||||
* upstart
|
||||
|
||||
## 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'
|
||||
# ----- 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
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
$ foreman check
|
||||
@@ -168,7 +185,7 @@ Export the application in upstart format:
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -44,6 +44,13 @@ describe "Foreman::CLI", :fakefs do
|
||||
output.should =~ /test.1 \| testing/
|
||||
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
|
||||
|
||||
@@ -93,4 +100,12 @@ describe "Foreman::CLI", :fakefs do
|
||||
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
|
||||
|
||||
97
spec/foreman/export/daemon_spec.rb
Normal file
97
spec/foreman/export/daemon_spec.rb
Normal file
@@ -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
|
||||
|
||||
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
|
||||
|
||||
91
spec/foreman/export/systemd_spec.rb
Normal file
91
spec/foreman/export/systemd_spec.rb
Normal file
@@ -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
|
||||
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
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@ echo: bin/echo echoing
|
||||
env: bin/env FOO
|
||||
test: bin/test
|
||||
utf8: bin/utf8
|
||||
ps: bin/echo PS env var is $PS
|
||||
|
||||
7
spec/resources/export/daemon/app-alpha-1.conf
Normal file
7
spec/resources/export/daemon/app-alpha-1.conf
Normal file
@@ -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
|
||||
7
spec/resources/export/daemon/app-alpha-2.conf
Normal file
7
spec/resources/export/daemon/app-alpha-2.conf
Normal file
@@ -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
|
||||
2
spec/resources/export/daemon/app-alpha.conf
Normal file
2
spec/resources/export/daemon/app-alpha.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
start on starting app
|
||||
stop on stopping app
|
||||
7
spec/resources/export/daemon/app-bravo-1.conf
Normal file
7
spec/resources/export/daemon/app-bravo-1.conf
Normal file
@@ -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
|
||||
2
spec/resources/export/daemon/app-bravo.conf
Normal file
2
spec/resources/export/daemon/app-bravo.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
start on starting app
|
||||
stop on stopping app
|
||||
14
spec/resources/export/daemon/app.conf
Normal file
14
spec/resources/export/daemon/app.conf
Normal file
@@ -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]
|
||||
17
spec/resources/export/systemd/app-alpha-1.service
Normal file
17
spec/resources/export/systemd/app-alpha-1.service
Normal file
@@ -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
|
||||
17
spec/resources/export/systemd/app-alpha-2.service
Normal file
17
spec/resources/export/systemd/app-alpha-2.service
Normal file
@@ -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
|
||||
5
spec/resources/export/systemd/app-alpha.target
Normal file
5
spec/resources/export/systemd/app-alpha.target
Normal file
@@ -0,0 +1,5 @@
|
||||
[Unit]
|
||||
StopWhenUnneeded=true
|
||||
|
||||
[Install]
|
||||
WantedBy=app.target
|
||||
17
spec/resources/export/systemd/app-bravo-1.service
Normal file
17
spec/resources/export/systemd/app-bravo-1.service
Normal file
@@ -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
|
||||
5
spec/resources/export/systemd/app-bravo.target
Normal file
5
spec/resources/export/systemd/app-bravo.target
Normal file
@@ -0,0 +1,5 @@
|
||||
[Unit]
|
||||
StopWhenUnneeded=true
|
||||
|
||||
[Install]
|
||||
WantedBy=app.target
|
||||
1
spec/resources/export/systemd/app.target
Normal file
1
spec/resources/export/systemd/app.target
Normal file
@@ -0,0 +1 @@
|
||||
[Unit]
|
||||
@@ -10,6 +10,15 @@ require "fakefs/spec_helpers"
|
||||
|
||||
$:.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)
|
||||
lambda { yield }.should raise_error(Foreman::Export::Exception, message)
|
||||
end
|
||||
@@ -21,6 +30,10 @@ def mock_error(subject, message)
|
||||
end
|
||||
end
|
||||
|
||||
def make_pipe
|
||||
IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
||||
end
|
||||
|
||||
def foreman(args)
|
||||
capture_stdout do
|
||||
begin
|
||||
@@ -31,14 +44,18 @@ def foreman(args)
|
||||
end
|
||||
|
||||
def forked_foreman(args)
|
||||
rd, wr = IO.pipe("BINARY")
|
||||
Process.spawn("bundle exec bin/foreman #{args}", :out => wr, :err => wr)
|
||||
rd, wr = make_pipe
|
||||
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
|
||||
rd.read
|
||||
end
|
||||
|
||||
def fork_and_capture(&blk)
|
||||
rd, wr = IO.pipe("BINARY")
|
||||
rd, wr = make_pipe
|
||||
pid = fork do
|
||||
rd.close
|
||||
wr.sync = true
|
||||
@@ -57,7 +74,11 @@ def fork_and_capture(&blk)
|
||||
end
|
||||
|
||||
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)
|
||||
$?.exitstatus
|
||||
end
|
||||
@@ -141,7 +162,7 @@ end
|
||||
|
||||
def capture_stdout
|
||||
old_stdout = $stdout.dup
|
||||
rd, wr = IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
|
||||
rd, wr = make_pipe
|
||||
$stdout = wr
|
||||
yield
|
||||
wr.close
|
||||
@@ -156,4 +177,5 @@ RSpec.configure do |config|
|
||||
config.order = 'rand'
|
||||
config.include FakeFS::SpecHelpers, :fakefs
|
||||
config.mock_with :rr
|
||||
config.backtrace_exclusion_patterns = []
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user