foreman 0.31.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +46 -0
- data/bin/foreman-runner +32 -0
- data/bin/taskman +8 -0
- data/data/example/Procfile +4 -2
- data/data/example/spawnee +14 -0
- data/data/example/spawner +7 -0
- data/data/example/utf8 +11 -0
- data/data/export/bluepill/master.pill.erb +11 -10
- data/data/export/launchd/launchd.plist.erb +22 -0
- data/data/export/runit/log/run.erb +7 -0
- data/data/export/runit/run.erb +2 -2
- data/data/export/supervisord/app.conf.erb +27 -0
- data/data/export/upstart/master.conf.erb +2 -2
- data/data/export/upstart/process.conf.erb +3 -3
- data/lib/foreman/cli.rb +83 -34
- data/lib/foreman/engine/cli.rb +105 -0
- data/lib/foreman/engine.rb +232 -140
- data/lib/foreman/env.rb +27 -0
- data/lib/foreman/export/base.rb +108 -6
- data/lib/foreman/export/bluepill.rb +4 -20
- data/lib/foreman/export/inittab.rb +11 -16
- data/lib/foreman/export/launchd.rb +15 -0
- data/lib/foreman/export/runit.rb +15 -41
- data/lib/foreman/export/supervisord.rb +16 -0
- data/lib/foreman/export/upstart.rb +10 -28
- data/lib/foreman/export.rb +23 -0
- data/lib/foreman/helpers.rb +45 -0
- data/lib/foreman/process.rb +80 -46
- data/lib/foreman/procfile.rb +68 -14
- data/lib/foreman/version.rb +1 -1
- data/lib/foreman.rb +12 -7
- data/man/foreman.1 +29 -3
- data/spec/foreman/cli_spec.rb +54 -60
- data/spec/foreman/engine_spec.rb +64 -46
- data/spec/foreman/export/base_spec.rb +19 -0
- data/spec/foreman/export/bluepill_spec.rb +24 -6
- data/spec/foreman/export/inittab_spec.rb +40 -0
- data/spec/foreman/export/launchd_spec.rb +21 -0
- data/spec/foreman/export/runit_spec.rb +23 -22
- data/spec/foreman/export/supervisord_spec.rb +36 -0
- data/spec/foreman/export/upstart_spec.rb +49 -16
- data/spec/foreman/export_spec.rb +22 -0
- data/spec/foreman/helpers_spec.rb +26 -0
- data/spec/foreman/process_spec.rb +48 -2
- data/spec/foreman/procfile_spec.rb +41 -0
- data/spec/foreman_spec.rb +3 -20
- data/spec/helper_spec.rb +18 -0
- data/spec/resources/Procfile +4 -0
- data/spec/resources/bin/echo +2 -0
- data/spec/resources/bin/env +2 -0
- data/spec/resources/bin/test +2 -0
- data/spec/resources/bin/utf8 +2 -0
- data/spec/resources/export/bluepill/app-concurrency.pill +49 -0
- data/spec/resources/export/bluepill/app.pill +6 -25
- data/spec/resources/export/inittab/inittab.concurrency +4 -0
- data/spec/resources/export/inittab/inittab.default +4 -0
- data/spec/resources/export/launchd/launchd-a.default +22 -0
- data/spec/resources/export/launchd/launchd-b.default +22 -0
- data/spec/resources/export/supervisord/app-alpha-1.conf +24 -0
- data/spec/resources/export/supervisord/app-alpha-2.conf +24 -0
- data/spec/spec_helper.rb +93 -10
- metadata +72 -76
- data/README.markdown +0 -49
- data/bin/runner +0 -2
- data/data/export/runit/log_run.erb +0 -7
- data/lib/foreman/procfile_entry.rb +0 -22
- data/lib/foreman/utils.rb +0 -15
- /data/spec/resources/export/runit/{app-alpha-1-log-run → app-alpha-1/log/run} +0 -0
- /data/spec/resources/export/runit/{app-alpha-1-run → app-alpha-1/run} +0 -0
- /data/spec/resources/export/runit/{app-alpha-2-log-run → app-alpha-2/log/run} +0 -0
- /data/spec/resources/export/runit/{app-alpha-2-run → app-alpha-2/run} +0 -0
- /data/spec/resources/export/runit/{app-bravo-1-log-run → app-bravo-1/log/run} +0 -0
- /data/spec/resources/export/runit/{app-bravo-1-run → app-bravo-1/run} +0 -0
data/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Foreman
|
|
2
|
+
|
|
3
|
+
Manage Procfile-based applications
|
|
4
|
+
|
|
5
|
+
<table>
|
|
6
|
+
<tr>
|
|
7
|
+
<th>If you have...</th>
|
|
8
|
+
<th>Install with...</th>
|
|
9
|
+
</tr>
|
|
10
|
+
<tr>
|
|
11
|
+
<td>Ruby (MRI, JRuby, Windows)</td>
|
|
12
|
+
<td><pre>$ gem install foreman</pre></td>
|
|
13
|
+
</tr>
|
|
14
|
+
<tr>
|
|
15
|
+
<td>Mac OS X</td>
|
|
16
|
+
<td><a href="http://assets.foreman.io/foreman/foreman.pkg">foreman.pkg</a></td>
|
|
17
|
+
</tr>
|
|
18
|
+
</table>
|
|
19
|
+
|
|
20
|
+
## Getting Started
|
|
21
|
+
|
|
22
|
+
* http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
|
|
23
|
+
|
|
24
|
+
## Documentation
|
|
25
|
+
|
|
26
|
+
* [man page](http://ddollar.github.com/foreman)
|
|
27
|
+
* [wiki](http://github.com/ddollar/foreman/wiki)
|
|
28
|
+
* [changelog](https://github.com/ddollar/foreman/blob/master/Changelog.md)
|
|
29
|
+
|
|
30
|
+
## Ports
|
|
31
|
+
|
|
32
|
+
* [shoreman](https://github.com/hecticjeff/shoreman) - shell
|
|
33
|
+
* [honcho](https://github.com/nickstenning/honcho) - python
|
|
34
|
+
* [norman](https://github.com/josh/norman) - node.js
|
|
35
|
+
|
|
36
|
+
## Authors
|
|
37
|
+
|
|
38
|
+
#### Created and maintained by
|
|
39
|
+
David Dollar
|
|
40
|
+
|
|
41
|
+
#### Patches contributed by
|
|
42
|
+
[Contributor List](https://github.com/ddollar/foreman/contributors)
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT
|
data/bin/foreman-runner
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
#/ Usage: foreman-runner [-d <dir>] <command> [<args>...]
|
|
4
|
+
#/
|
|
5
|
+
#/ Run a command with exec, optionally changing directory first
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
error() {
|
|
10
|
+
echo $@ >&2
|
|
11
|
+
exit 1
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
usage() {
|
|
15
|
+
cat $0 | grep '^#/' | cut -c4-
|
|
16
|
+
exit
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
while getopts ":hd:" OPT; do
|
|
20
|
+
case $OPT in
|
|
21
|
+
d) cd "$OPTARG" ;;
|
|
22
|
+
h) usage ;;
|
|
23
|
+
\?) error "invalid option: -$OPTARG" ;;
|
|
24
|
+
:) error "option -$OPTARG requires an argument" ;;
|
|
25
|
+
esac
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
shift $((OPTIND-1))
|
|
29
|
+
|
|
30
|
+
[ -z "$1" ] && usage
|
|
31
|
+
|
|
32
|
+
exec "$@"
|
data/bin/taskman
ADDED
data/data/example/Procfile
CHANGED
data/data/example/utf8
ADDED
|
@@ -3,24 +3,25 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
|
|
|
3
3
|
app.uid = "<%= user %>"
|
|
4
4
|
app.gid = "<%= user %>"
|
|
5
5
|
|
|
6
|
-
<% engine.
|
|
7
|
-
<% 1.upto(
|
|
8
|
-
<% port = engine.port_for(process, num
|
|
9
|
-
app.process("<%=
|
|
10
|
-
process.start_command = "<%= process.command
|
|
6
|
+
<% engine.each_process do |name, process| %>
|
|
7
|
+
<% 1.upto(engine.formation[name]) do |num| %>
|
|
8
|
+
<% port = engine.port_for(process, num) %>
|
|
9
|
+
app.process("<%= name %>-<%= num %>") do |process|
|
|
10
|
+
process.start_command = "<%= process.command %>"
|
|
11
11
|
|
|
12
|
-
process.working_dir = "<%= engine.
|
|
12
|
+
process.working_dir = "<%= engine.root %>"
|
|
13
13
|
process.daemonize = true
|
|
14
|
-
process.environment =
|
|
14
|
+
process.environment = <%= engine.env.merge("PORT" => port.to_s).inspect %>
|
|
15
15
|
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
|
16
|
+
process.stop_grace_time = 45.seconds
|
|
16
17
|
|
|
17
|
-
process.stdout = process.stderr = "<%=
|
|
18
|
+
process.stdout = process.stderr = "<%= log %>/<%= app %>-<%= name %>-<%= num %>.log"
|
|
18
19
|
|
|
19
20
|
process.monitor_children do |children|
|
|
20
|
-
children.stop_command "kill
|
|
21
|
+
children.stop_command "kill {{PID}}"
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
process.group = "<%= app %>-<%=
|
|
24
|
+
process.group = "<%= app %>-<%= name %>"
|
|
24
25
|
end
|
|
25
26
|
<% end %>
|
|
26
27
|
<% end %>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string><%= "#{app}-#{name}-#{num}" %></string>
|
|
7
|
+
<key>ProgramArguments</key>
|
|
8
|
+
<array>
|
|
9
|
+
<string><%= process.command %></string>
|
|
10
|
+
</array>
|
|
11
|
+
<key>KeepAlive</key>
|
|
12
|
+
<true/>
|
|
13
|
+
<key>RunAtLoad</key>
|
|
14
|
+
<true/>
|
|
15
|
+
<key>StandardErrorPath</key>
|
|
16
|
+
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
|
|
17
|
+
<key>UserName</key>
|
|
18
|
+
<string><%= user %></string>
|
|
19
|
+
<key>WorkingDirectory</key>
|
|
20
|
+
<string><%= engine.root %></string>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
data/data/export/runit/run.erb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
cd <%= engine.
|
|
3
|
-
exec chpst -u <%= user %> -e <%=
|
|
2
|
+
cd <%= engine.root %>
|
|
3
|
+
exec chpst -u <%= user %> -e <%= File.join(location, "#{process_directory}/env") %> <%= process.command %>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%
|
|
2
|
+
app_names = []
|
|
3
|
+
engine.each_process do |name, process|
|
|
4
|
+
1.upto(engine.formation[name]) do |num|
|
|
5
|
+
port = engine.port_for(process, num)
|
|
6
|
+
full_name = "#{app}-#{name}-#{num}"
|
|
7
|
+
environment = engine.env.merge("PORT" => port.to_s).map do |key, value|
|
|
8
|
+
"#{key}=#{shell_quote(value)}"
|
|
9
|
+
end
|
|
10
|
+
app_names << full_name
|
|
11
|
+
%>
|
|
12
|
+
[program:<%= full_name %>]
|
|
13
|
+
command=<%= process.command %>
|
|
14
|
+
autostart=true
|
|
15
|
+
autorestart=true
|
|
16
|
+
stopsignal=QUIT
|
|
17
|
+
stdout_logfile=<%= log %>/<%= name %>-<%= num %>.log
|
|
18
|
+
stderr_logfile=<%= log %>/<%= name %>-<%= num %>.error.log
|
|
19
|
+
user=<%= user %>
|
|
20
|
+
directory=<%= engine.root %>
|
|
21
|
+
environment=<%= environment.join(',') %><%
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
%>
|
|
25
|
+
|
|
26
|
+
[group:<%= app %>]
|
|
27
|
+
programs=<%= app_names.join(',') %>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
start on starting <%= app %>-<%=
|
|
2
|
-
stop on stopping <%= app %>-<%=
|
|
1
|
+
start on starting <%= app %>-<%= name %>
|
|
2
|
+
stop on stopping <%= app %>-<%= name %>
|
|
3
3
|
respawn
|
|
4
4
|
|
|
5
|
-
exec su - <%= user %> -c 'cd <%= engine.
|
|
5
|
+
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'
|
data/lib/foreman/cli.rb
CHANGED
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
require "foreman"
|
|
2
|
+
require "foreman/helpers"
|
|
2
3
|
require "foreman/engine"
|
|
4
|
+
require "foreman/engine/cli"
|
|
3
5
|
require "foreman/export"
|
|
4
|
-
require "
|
|
6
|
+
require "foreman/version"
|
|
7
|
+
require "shellwords"
|
|
5
8
|
require "yaml"
|
|
9
|
+
require "thor"
|
|
6
10
|
|
|
7
11
|
class Foreman::CLI < Thor
|
|
8
12
|
|
|
13
|
+
include Foreman::Helpers
|
|
14
|
+
|
|
15
|
+
map ["-v", "--version"] => :version
|
|
16
|
+
|
|
9
17
|
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
|
18
|
+
class_option :root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
|
|
10
19
|
|
|
11
|
-
desc "start", "Start the application"
|
|
20
|
+
desc "start [PROCESS]", "Start the application (or a specific PROCESS)"
|
|
12
21
|
|
|
13
|
-
method_option :
|
|
14
|
-
method_option :
|
|
15
|
-
method_option :
|
|
22
|
+
method_option :color, :type => :boolean, :aliases => "-c", :desc => "Force color to be enabled"
|
|
23
|
+
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
|
24
|
+
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
|
|
25
|
+
method_option :port, :type => :numeric, :aliases => "-p"
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
# Hackery. Take the run method away from Thor so that we can redefine it.
|
|
29
|
+
def is_thor_reserved_word?(word, type)
|
|
30
|
+
return false if word == "run"
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
end
|
|
16
34
|
|
|
17
|
-
def start
|
|
35
|
+
def start(process=nil)
|
|
18
36
|
check_procfile!
|
|
37
|
+
load_environment!
|
|
38
|
+
engine.load_procfile(procfile)
|
|
39
|
+
engine.options[:formation] = "#{process}=1" if process
|
|
19
40
|
engine.start
|
|
20
41
|
end
|
|
21
42
|
|
|
@@ -27,22 +48,14 @@ class Foreman::CLI < Thor
|
|
|
27
48
|
method_option :port, :type => :numeric, :aliases => "-p"
|
|
28
49
|
method_option :user, :type => :string, :aliases => "-u"
|
|
29
50
|
method_option :template, :type => :string, :aliases => "-t"
|
|
30
|
-
method_option :concurrency, :type => :string, :aliases => "-c",
|
|
31
|
-
:banner => '"alpha=5,bar=3"'
|
|
51
|
+
method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
|
|
32
52
|
|
|
33
53
|
def export(format, location=nil)
|
|
34
54
|
check_procfile!
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
when "bluepill" then Foreman::Export::Bluepill
|
|
40
|
-
when "runit" then Foreman::Export::Runit
|
|
41
|
-
else error "Unknown export format: #{format}."
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
formatter.new(engine).export(location, options)
|
|
45
|
-
|
|
55
|
+
load_environment!
|
|
56
|
+
engine.load_procfile(procfile)
|
|
57
|
+
formatter = Foreman::Export.formatter(format)
|
|
58
|
+
formatter.new(location, engine, options).export
|
|
46
59
|
rescue Foreman::Export::Exception => ex
|
|
47
60
|
error ex.message
|
|
48
61
|
end
|
|
@@ -50,41 +63,77 @@ class Foreman::CLI < Thor
|
|
|
50
63
|
desc "check", "Validate your application's Procfile"
|
|
51
64
|
|
|
52
65
|
def check
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
check_procfile!
|
|
67
|
+
engine.load_procfile(procfile)
|
|
68
|
+
error "no processes defined" unless engine.processes.length > 0
|
|
69
|
+
puts "valid procfile detected (#{engine.process_names.join(', ')})"
|
|
55
70
|
end
|
|
56
71
|
|
|
57
|
-
|
|
72
|
+
desc "run COMMAND [ARGS...]", "Run a command using your application's environment"
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
error("#{procfile} does not exist.") unless File.exist?(procfile)
|
|
61
|
-
end
|
|
74
|
+
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
|
62
75
|
|
|
63
|
-
def
|
|
64
|
-
|
|
76
|
+
def run(*args)
|
|
77
|
+
load_environment!
|
|
78
|
+
begin
|
|
79
|
+
exec engine.env, args.shelljoin
|
|
80
|
+
rescue Errno::EACCES
|
|
81
|
+
error "not executable: #{args.first}"
|
|
82
|
+
rescue Errno::ENOENT
|
|
83
|
+
error "command not found: #{args.first}"
|
|
84
|
+
end
|
|
65
85
|
end
|
|
66
86
|
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
desc "version", "Display Foreman gem version"
|
|
88
|
+
|
|
89
|
+
def version
|
|
90
|
+
puts Foreman::VERSION
|
|
69
91
|
end
|
|
70
92
|
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
no_tasks do
|
|
94
|
+
def engine
|
|
95
|
+
@engine ||= begin
|
|
96
|
+
engine_class = Foreman::Engine::CLI
|
|
97
|
+
engine = engine_class.new(options)
|
|
98
|
+
engine
|
|
99
|
+
end
|
|
100
|
+
end
|
|
73
101
|
end
|
|
74
102
|
|
|
103
|
+
private ######################################################################
|
|
104
|
+
|
|
75
105
|
def error(message)
|
|
76
106
|
puts "ERROR: #{message}"
|
|
77
107
|
exit 1
|
|
78
108
|
end
|
|
79
109
|
|
|
80
|
-
def
|
|
81
|
-
File.exist?(procfile)
|
|
110
|
+
def check_procfile!
|
|
111
|
+
error("#{procfile} does not exist.") unless File.exist?(procfile)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def load_environment!
|
|
115
|
+
if options[:env]
|
|
116
|
+
options[:env].split(",").each do |file|
|
|
117
|
+
engine.load_env file
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
default_env = File.join(engine.root, ".env")
|
|
121
|
+
engine.load_env default_env if File.exists?(default_env)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def procfile
|
|
126
|
+
case
|
|
127
|
+
when options[:procfile] then options[:procfile]
|
|
128
|
+
when options[:root] then File.expand_path(File.join(options[:app_root], "Procfile"))
|
|
129
|
+
else "Procfile"
|
|
130
|
+
end
|
|
82
131
|
end
|
|
83
132
|
|
|
84
133
|
def options
|
|
85
134
|
original_options = super
|
|
86
135
|
return original_options unless File.exists?(".foreman")
|
|
87
|
-
defaults = YAML::load_file(".foreman") || {}
|
|
136
|
+
defaults = ::YAML::load_file(".foreman") || {}
|
|
88
137
|
Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
|
|
89
138
|
end
|
|
90
139
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require "foreman/engine"
|
|
2
|
+
|
|
3
|
+
class Foreman::Engine::CLI < Foreman::Engine
|
|
4
|
+
|
|
5
|
+
module Color
|
|
6
|
+
|
|
7
|
+
ANSI = {
|
|
8
|
+
:reset => 0,
|
|
9
|
+
:black => 30,
|
|
10
|
+
:red => 31,
|
|
11
|
+
:green => 32,
|
|
12
|
+
:yellow => 33,
|
|
13
|
+
:blue => 34,
|
|
14
|
+
:magenta => 35,
|
|
15
|
+
:cyan => 36,
|
|
16
|
+
:white => 37,
|
|
17
|
+
:bright_black => 30,
|
|
18
|
+
:bright_red => 31,
|
|
19
|
+
:bright_green => 32,
|
|
20
|
+
:bright_yellow => 33,
|
|
21
|
+
:bright_blue => 34,
|
|
22
|
+
:bright_magenta => 35,
|
|
23
|
+
:bright_cyan => 36,
|
|
24
|
+
:bright_white => 37,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def self.enable(io, force=false)
|
|
28
|
+
io.extend(self)
|
|
29
|
+
@@color_force = force
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def color?
|
|
33
|
+
return true if @@color_force
|
|
34
|
+
return true if Foreman.windows?
|
|
35
|
+
return false unless self.respond_to?(:isatty)
|
|
36
|
+
self.isatty && ENV["TERM"]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def color(name)
|
|
40
|
+
return "" unless color?
|
|
41
|
+
return "" unless ansi = ANSI[name.to_sym]
|
|
42
|
+
"\e[#{ansi}m"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
FOREMAN_COLORS = %w( cyan yellow green magenta red blue intense_cyan intense_yellow
|
|
48
|
+
intense_green intense_magenta intense_red, intense_blue )
|
|
49
|
+
|
|
50
|
+
def startup
|
|
51
|
+
@colors = map_colors
|
|
52
|
+
proctitle "foreman: master"
|
|
53
|
+
require "win32console" if Foreman.windows?
|
|
54
|
+
Color.enable($stdout, options[:color]) unless $stdout.respond_to?(:color?)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def output(name, data)
|
|
58
|
+
data.to_s.chomp.split("\n").each do |message|
|
|
59
|
+
output = ""
|
|
60
|
+
output += $stdout.color(@colors[name.split(".").first].to_sym)
|
|
61
|
+
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
|
62
|
+
output += $stdout.color(:reset)
|
|
63
|
+
output += message
|
|
64
|
+
$stdout.puts output
|
|
65
|
+
$stdout.flush
|
|
66
|
+
end
|
|
67
|
+
rescue Errno::EPIPE
|
|
68
|
+
terminate_gracefully
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def shutdown
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def name_padding
|
|
77
|
+
@name_padding ||= begin
|
|
78
|
+
index_padding = @names.values.map { |n| formation[n] }.max.to_s.length + 1
|
|
79
|
+
name_padding = @names.values.map { |n| n.length + index_padding }.sort.last
|
|
80
|
+
[ 6, name_padding ].max
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def pad_process_name(name)
|
|
85
|
+
name.ljust(name_padding, " ")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def map_colors
|
|
89
|
+
colors = Hash.new("white")
|
|
90
|
+
@names.values.each_with_index do |name, index|
|
|
91
|
+
colors[name] = FOREMAN_COLORS[index % FOREMAN_COLORS.length]
|
|
92
|
+
end
|
|
93
|
+
colors["system"] = "intense_white"
|
|
94
|
+
colors
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def proctitle(title)
|
|
98
|
+
$0 = title
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def termtitle(title)
|
|
102
|
+
printf("\033]0;#{title}\007") unless Foreman.windows?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|