Compare commits

..
4 Commits
Author SHA1 Message Date
David Dollar 9b704ad852 0.48.0.pre2 2012-06-17 22:02:14 -04:00
David Dollar 43428175c3 allow color to be forced on 2012-06-17 22:02:00 -04:00
David Dollar 87f65e489c terminate gracefully if stdout goes away 2012-06-17 21:55:28 -04:00
David Dollar e5521f2cbb always flush output 2012-06-17 21:55:19 -04:00
20 changed files with 61 additions and 272 deletions
+4 -51
View File
@@ -1,55 +1,8 @@
## 0.54.0 (2012-08-14) ## 0.48.0.pre1 (2012-06-11)
* use Foreman::Process to extract command running [David Dollar] * Massive refactoring for programmatic control and stability [David Dollar]
* changed to check env for bash [brntbeer] * Procfile commands with shell interpolations now work again [David Dollar]
* Stop trying to test on Ruby 1.8 [David Dollar]
## 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]
* fix upstart export specs [David Dollar]
* Make upstart export start/stop with network [Daniel Farrell]
## 0.51.0 (2012-07-11)
* dont try to colorize windows [David Dollar]
## 0.50.0 (2012-07-11)
* handle windows [David Dollar]
## 0.49.0 (2012-07-11)
* 1.8 compatibility [David Dollar]
* use one pgroup for all of foreman and kill that since ruby 1.8 sucks at pgroups [David Dollar]
* better debugging [David Dollar]
## 0.48.0 (2012-07-10)
* allow old exporter format to work, but with deprecation warning [David Dollar]
* remove debugging code [David Dollar]
* Merge pull request #219 from MarkDBlackwell/patch-1 [David Dollar]
* Avoid crash by verifying the existence of SIGHUP before accessing it. [Mark D. Blackwell]
* allow color to be forced on [David Dollar]
* terminate gracefully if stdout goes away [David Dollar]
* always flush output [David Dollar]
* Merge pull request #212 from morgoth/added-version-command [David Dollar]
* added command for displaying foreman version [Wojciech Wnętrzak]
* Merge pull request #211 from morgoth/fixed-yaml-usage [David Dollar]
* fixed using YAML [Wojciech Wnętrzak]
* test on more things, but don't fail [David Dollar]
* changelog [David Dollar]
* 0.48.0.pre1 [David Dollar]
* foreman doesn't work on ruby 1.8, may try to fix later [David Dollar]
* use bash [David Dollar]
* massive refactoring for programmatic control and stability [David Dollar]
* Merge pull request #164 from hsume2/master [David Dollar]
* Only run tmux specs if tmux is installed [Henry Hsu]
* Do not assume BUNDLE_GEMFILE [Henry Hsu]
* Add support for starting procfile in tmux session [Henry Hsu]
## 0.47.0 (2012-06-07) ## 0.47.0 (2012-06-07)
+2 -2
View File
@@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
foreman (0.55.0) foreman (0.48.0.pre2)
thor (>= 0.13.6) thor (>= 0.13.6)
GEM GEM
@@ -39,7 +39,7 @@ GEM
multi_json (~> 1.0.3) multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3) simplecov-html (~> 0.5.3)
simplecov-html (0.5.3) simplecov-html (0.5.3)
thor (0.15.4) thor (0.15.2)
timecop (0.3.5) timecop (0.3.5)
win32console (1.3.0-x86-mingw32) win32console (1.3.0-x86-mingw32)
xml-simple (1.0.15) xml-simple (1.0.15)
+3 -15
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/bin/sh
# #
#/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...] #/ Usage: foreman-runner [-d <dir>] <command> [<args>...]
#/ #/
#/ Run a command with exec, optionally changing directory first #/ Run a command with exec, optionally changing directory first
@@ -16,12 +16,9 @@ usage() {
exit exit
} }
read_profiled="" while getopts ":hd:" OPT; do
while getopts ":hd:p" OPT; do
case $OPT in case $OPT in
d) cd "$OPTARG" ;; d) cd "$OPTARG" ;;
p) read_profiled="1" ;;
h) usage ;; h) usage ;;
\?) error "invalid option: -$OPTARG" ;; \?) error "invalid option: -$OPTARG" ;;
:) error "option -$OPTARG requires an argument" ;; :) error "option -$OPTARG requires an argument" ;;
@@ -32,13 +29,4 @@ shift $((OPTIND-1))
[ -z "$1" ] && usage [ -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
fi
exec "$@" exec "$@"
-2
View File
@@ -1,2 +0,0 @@
#!/bin/sh
export FOO=bar
+1 -1
View File
@@ -9,6 +9,6 @@ sigterm() {
#trap sigterm SIGTERM #trap sigterm SIGTERM
while true; do while true; do
echo "$NAME: ping $$" echo "$NAME: ping"
sleep 1 sleep 1
done done
-3
View File
@@ -6,6 +6,3 @@ bash << "EOF"
EOF EOF
end script end script
start on started network
stop on stopping network
-16
View File
@@ -1,16 +0,0 @@
file pkg("foreman-#{version}-x86-mswin32.gem") => distribution_files do |t|
Bundler.with_clean_env do
sh "env PLATFORM=mswin32 gem build foreman.gemspec"
end
sh "mv foreman-#{version}-x86-mswin32.gem #{t.name}"
end
task "mswin32:build" => pkg("foreman-#{version}-x86-mswin32.gem")
task "mswin32:clean" do
clean pkg("foreman-#{version}-x86-mswin32.gem")
end
task "mswin32:release" => "mswin32:build" do |t|
sh "gem push #{pkg("foreman-#{version}-x86-mswin32.gem")} || echo 'error'"
end
-4
View File
@@ -12,10 +12,6 @@ module Foreman
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java" defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
end end
def self.ruby_18?
defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
end
def self.windows? def self.windows?
defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/ defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
end end
+7 -21
View File
@@ -3,17 +3,13 @@ require "foreman/helpers"
require "foreman/engine" require "foreman/engine"
require "foreman/engine/cli" require "foreman/engine/cli"
require "foreman/export" require "foreman/export"
require "foreman/version"
require "shellwords" require "shellwords"
require "yaml"
require "thor" require "thor"
class Foreman::CLI < Thor class Foreman::CLI < Thor
include Foreman::Helpers include Foreman::Helpers
map ["-v", "--version"] => :version
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile" class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
class_option :root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory" class_option :root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
@@ -75,23 +71,13 @@ class Foreman::CLI < Thor
def run(*args) def run(*args)
load_environment! load_environment!
pid = fork do begin
begin exec engine.env, args.shelljoin
engine.env.each { |k,v| ENV[k] = v } rescue Errno::EACCES
exec args.shelljoin error "not executable: #{args.first}"
rescue Errno::EACCES rescue Errno::ENOENT
error "not executable: #{args.first}" error "command not found: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
end
end end
Process.wait(pid)
end
desc "version", "Display Foreman gem version"
def version
puts Foreman::VERSION
end end
no_tasks do no_tasks do
@@ -137,7 +123,7 @@ private ######################################################################
def options def options
original_options = super original_options = super
return original_options unless File.exists?(".foreman") return original_options unless File.exists?(".foreman")
defaults = ::YAML::load_file(".foreman") || {} defaults = YAML::load_file(".foreman") || {}
Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options)) Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
end end
+16 -44
View File
@@ -24,7 +24,7 @@ class Foreman::Engine
def initialize(options={}) def initialize(options={})
@options = options.dup @options = options.dup
@options[:formation] ||= (options[:concurrency] || "all=1") @options[:formation] ||= "all=1"
@env = {} @env = {}
@mutex = Mutex.new @mutex = Mutex.new
@@ -39,7 +39,7 @@ class Foreman::Engine
def start def start
trap("TERM") { puts "SIGTERM received"; terminate_gracefully } trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
trap("INT") { puts "SIGINT received"; terminate_gracefully } trap("INT") { puts "SIGINT received"; terminate_gracefully }
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP' trap("HUP") { puts "SIGHUP received"; terminate_gracefully }
startup startup
spawn_processes spawn_processes
@@ -99,17 +99,10 @@ class Foreman::Engine
# @param [String] signal The signal to send to each process # @param [String] signal The signal to send to each process
# #
def killall(signal="SIGTERM") def killall(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}", Process.pid Process.kill(signal, -1 * pid)
rescue Errno::ESRCH, Errno::EPERM rescue Errno::ESRCH, Errno::EPERM
end end
end end
@@ -164,25 +157,8 @@ class Foreman::Engine
# #
# @returns [Fixnum] port The port to use for this instance of this process # @returns [Fixnum] port The port to use for this instance of this process
# #
def port_for(process, instance, base=nil) def port_for(process, instance)
if base base_port + (@processes.index(process) * 100) + (instance - 1)
base + (@processes.index(process.process) * 100) + (instance - 1)
else
base_port + (@processes.index(process) * 100) + (instance - 1)
end
end
# Get the base port for this foreman instance
#
# @returns [Fixnum] port The base port
#
def base_port
(options[:port] || env["PORT"] || ENV["PORT"] || 5000).to_i
end
# deprecated
def environment
env
end end
private private
@@ -203,6 +179,10 @@ private
## Helpers ########################################################## ## Helpers ##########################################################
def base_port
(options[:port] || env["PORT"] || ENV["PORT"] || 5000).to_i
end
def create_pipe def create_pipe
IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY") IO.method(:pipe).arity.zero? ? IO.pipe : IO.pipe("BINARY")
end end
@@ -213,7 +193,7 @@ private
end end
def parse_formation(formation) def parse_formation(formation)
pairs = formation.to_s.gsub(/\s/, "").split(",") pairs = @options[:formation].to_s.gsub(/\s/, "").split(",")
pairs.inject(Hash.new(0)) do |ax, pair| pairs.inject(Hash.new(0)) do |ax, pair|
process, amount = pair.split("=") process, amount = pair.split("=")
@@ -256,10 +236,7 @@ private
1.upto(formation[@names[process]]) do |n| 1.upto(formation[@names[process]]) do |n|
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 })
"HOME" => process.cwd,
"PORT" => port_for(process, n).to_s
})
writer.puts "started with pid #{pid}" writer.puts "started with pid #{pid}"
rescue Errno::ENOENT rescue Errno::ENOENT
writer.puts "unknown command: #{process.command}" writer.puts "unknown command: #{process.command}"
@@ -276,7 +253,7 @@ private
loop do loop do
(IO.select(@readers.values).first || []).each do |reader| (IO.select(@readers.values).first || []).each do |reader|
data = reader.gets data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data output_with_mutex name_for(@readers.key(reader)), data
end end
end end
rescue Exception => ex rescue Exception => ex
@@ -298,13 +275,8 @@ private
def terminate_gracefully def terminate_gracefully
return if @terminating return if @terminating
@terminating = true @terminating = true
if Foreman.windows? system "sending SIGTERM to all processes"
system "sending SIGKILL to all processes" killall "SIGTERM"
killall "SIGKILL"
else
system "sending SIGTERM to all processes"
killall "SIGTERM"
end
Timeout.timeout(5) do Timeout.timeout(5) do
watch_for_termination while @running.length > 0 watch_for_termination while @running.length > 0
end end
+2 -3
View File
@@ -31,7 +31,6 @@ class Foreman::Engine::CLI < Foreman::Engine
def color? def color?
return true if @@color_force return true if @@color_force
return false if Foreman.windows?
return false unless self.respond_to?(:isatty) return false unless self.respond_to?(:isatty)
self.isatty && ENV["TERM"] self.isatty && ENV["TERM"]
end end
@@ -49,12 +48,12 @@ class Foreman::Engine::CLI < Foreman::Engine
def startup def startup
@colors = map_colors @colors = map_colors
proctitle "foreman: master" unless Foreman.windows? proctitle "foreman: master"
Color.enable($stdout, options[:color])
end end
def output(name, data) def output(name, data)
data.to_s.chomp.split("\n").each do |message| data.to_s.chomp.split("\n").each do |message|
Color.enable($stdout, options[:color]) unless $stdout.respond_to?(:color?)
output = "" output = ""
output += $stdout.color(@colors[name.split(".").first].to_sym) output += $stdout.color(@colors[name.split(".").first].to_sym)
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | " output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
+1 -1
View File
@@ -1,6 +1,5 @@
require "foreman" require "foreman"
require "foreman/helpers" require "foreman/helpers"
require "pathname"
module Foreman::Export module Foreman::Export
extend Foreman::Helpers extend Foreman::Helpers
@@ -32,3 +31,4 @@ 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"
+8 -65
View File
@@ -1,6 +1,4 @@
require "foreman/export" require "foreman/export"
require "ostruct"
require "pathname"
require "shellwords" require "shellwords"
class Foreman::Export::Base class Foreman::Export::Base
@@ -10,37 +8,11 @@ class Foreman::Export::Base
attr_reader :options attr_reader :options
attr_reader :formation attr_reader :formation
# deprecated
attr_reader :port
def initialize(location, engine, options={}) def initialize(location, engine, options={})
@location = location @location = location
@engine = engine @engine = engine
@options = options.dup @options = options.dup
@formation = engine.formation @formation = engine.formation
# deprecated
def port
Foreman::Export::Base.warn_deprecation!
engine.base_port
end
# deprecated
def template
Foreman::Export::Base.warn_deprecation!
options[:template]
end
# deprecated
def @engine.procfile
Foreman::Export::Base.warn_deprecation!
@processes.map do |process|
OpenStruct.new(
:name => @names[process],
:process => process
)
end
end
end end
def export def export
@@ -64,18 +36,6 @@ class Foreman::Export::Base
private ###################################################################### private ######################################################################
def self.warn_deprecation!
@@deprecation_warned ||= false
return if @@deprecation_warned
puts "WARNING: Using deprecated exporter interface. Please update your exporter"
puts "the interface shown in the upstart exporter:"
puts
puts "https://github.com/ddollar/foreman/blob/master/lib/foreman/export/upstart.rb"
puts "https://github.com/ddollar/foreman/blob/master/data/export/upstart/process.conf.erb"
puts
@@deprecation_warned = true
end
def error(message) def error(message)
raise Foreman::Export::Exception.new(message) raise Foreman::Export::Exception.new(message)
end end
@@ -94,28 +54,13 @@ private ######################################################################
'"' + Shellwords.escape(value) + '"' '"' + Shellwords.escape(value) + '"'
end end
# deprecated def export_template(name)
def old_export_template(exporter, file, template_root) name_without_first = name.split("/")[1..-1].join("/")
if template_root && File.exist?(file_path = File.join(template_root, file)) matchers = []
File.read(file_path) matchers << File.join(options[:template], name_without_first) if options[:template]
elsif File.exist?(file_path = File.expand_path(File.join("~/.foreman/templates", file))) matchers << File.expand_path("~/.foreman/templates/#{name}")
File.read(file_path) matchers << File.expand_path("../../../../data/export/#{name}", __FILE__)
else File.read(matchers.detect { |m| File.exists?(m) })
File.read(File.expand_path("../../../../data/export/#{exporter}/#{file}", __FILE__))
end
end
def export_template(name, file=nil, template_root=nil)
if file && template_root
old_export_template name, file, template_root
else
name_without_first = name.split("/")[1..-1].join("/")
matchers = []
matchers << File.join(options[:template], name_without_first) if options[:template]
matchers << File.expand_path("~/.foreman/templates/#{name}")
matchers << File.expand_path("../../../../data/export/#{name}", __FILE__)
File.read(matchers.detect { |m| File.exists?(m) })
end
end end
def write_template(name, target, binding) def write_template(name, target, binding)
@@ -136,9 +81,7 @@ private ######################################################################
def write_file(filename, contents) def write_file(filename, contents)
say "writing: #{filename}" say "writing: #{filename}"
filename = File.join(location, filename) unless Pathname.new(filename).absolute? File.open(File.join(location, filename), "w") do |file|
File.open(filename, "w") do |file|
file.puts contents file.puts contents
end end
end end
+11 -27
View File
@@ -36,27 +36,17 @@ class Foreman::Process
if Foreman.windows? if Foreman.windows?
Dir.chdir(cwd) do Dir.chdir(cwd) do
expanded_command = command.dup Process.spawn env, command, :out => output, :err => output, :new_pgroup => true
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
Process.spawn env, expanded_command, :out => output, :err => output
end end
elsif Foreman.jruby? elsif Foreman.jruby?
require "posix/spawn" Dir.chdir(cwd) do
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}" require "posix/spawn"
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output POSIX::Spawn.spawn env, command, :out => output, :err => output, :pgroup => 0
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}"
exec wrapped_command
end end
else else
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}" Dir.chdir(cwd) do
Process.spawn env, wrapped_command, :out => output, :err => output Process.spawn env, command, :out => output, :err => output, :pgroup => 0
end
end end
end end
@@ -65,11 +55,7 @@ class Foreman::Process
# @param [String] signal The signal to send # @param [String] signal The signal to send
# #
def kill(signal) def kill(signal)
if Foreman.windows? pid && Process.kill(signal, -1 * pid)
pid && Process.kill(signal, pid)
else
pid && Process.kill("-#{signal}", pid)
end
rescue Errno::ESRCH rescue Errno::ESRCH
false false
end end
@@ -90,12 +76,10 @@ class Foreman::Process
!alive? !alive?
end end
# Returns the working directory for this +Process+ private
#
# @returns [String]
#
def cwd def cwd
File.expand_path(@options[:cwd] || ".") @options[:cwd] || "."
end end
end end
+1 -1
View File
@@ -1,5 +1,5 @@
module Foreman module Foreman
VERSION = "0.55.0" VERSION = "0.48.0.pre2"
end end
+1 -1
View File
@@ -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" "July 2012" "Foreman 0.51.0" "Foreman Manual" .TH "FOREMAN" "1" "April 2012" "Foreman 0.46.0" "Foreman Manual"
. .
.SH "NAME" .SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications \fBforeman\fR \- manage Procfile\-based applications
-10
View File
@@ -74,14 +74,4 @@ describe "Foreman::CLI", :fakefs do
end end
end end
describe "version" do
it "displays gem version" do
foreman("version").chomp.should == Foreman::VERSION
end
it "displays gem version on shortcut command" do
foreman("-v").chomp.should == Foreman::VERSION
end
end
end end
-3
View File
@@ -6,6 +6,3 @@ bash << "EOF"
EOF EOF
end script end script
start on started network
stop on stopping network
+1
View File
@@ -54,6 +54,7 @@ def fork_and_capture(&blk)
Process.wait pid Process.wait pid
buffer = "" buffer = ""
until rd.eof? until rd.eof?
p [:foo]
buffer += rd.gets buffer += rd.gets
end end
end end
+2 -1
View File
@@ -32,7 +32,7 @@ def latest_release
end end
def newer_release def newer_release
tags = %x{ git tag --contains v#{latest_release} | grep -v pre }.split("\n").sort_by do |tag| tags = %x{ git tag --contains v#{latest_release} }.split("\n").sort_by do |tag|
Gem::Version.new(tag[1..-1]) Gem::Version.new(tag[1..-1])
end end
tags[1] tags[1]
@@ -60,6 +60,7 @@ end
desc "Cut a release" desc "Cut a release"
task :release do task :release do
Rake::Task["authors"].invoke
Rake::Task["changelog"].invoke Rake::Task["changelog"].invoke
Rake::Task["pages"].invoke Rake::Task["pages"].invoke
end end