overman 0.0.1 → 0.87.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -0
- data/bin/foreman-runner +41 -0
- data/bin/overman +7 -0
- data/data/example/Procfile +4 -0
- data/data/example/Procfile.without_colon +2 -0
- data/data/example/error +7 -0
- data/data/example/log/neverdie.log +4 -0
- data/data/example/spawnee +14 -0
- data/data/example/spawner +7 -0
- data/data/example/ticker +14 -0
- data/data/example/utf8 +11 -0
- data/data/export/bluepill/master.pill.erb +28 -0
- data/data/export/daemon/master.conf.erb +14 -0
- data/data/export/daemon/process.conf.erb +8 -0
- data/data/export/daemon/process_master.conf.erb +2 -0
- data/data/export/launchd/launchd.plist.erb +33 -0
- data/data/export/runit/log/run.erb +7 -0
- data/data/export/runit/run.erb +4 -0
- data/data/export/supervisord/app.conf.erb +31 -0
- data/data/export/systemd/master.target.erb +5 -0
- data/data/export/systemd/process.service.erb +21 -0
- data/data/export/upstart/master.conf.erb +2 -0
- data/data/export/upstart/process.conf.erb +15 -0
- data/data/export/upstart/process_master.conf.erb +2 -0
- data/lib/foreman/cli.rb +162 -0
- data/lib/foreman/distribution.rb +9 -0
- data/lib/foreman/engine/cli.rb +105 -0
- data/lib/foreman/engine.rb +494 -0
- data/lib/foreman/env.rb +29 -0
- data/lib/foreman/export/base.rb +171 -0
- data/lib/foreman/export/bluepill.rb +12 -0
- data/lib/foreman/export/daemon.rb +28 -0
- data/lib/foreman/export/inittab.rb +42 -0
- data/lib/foreman/export/launchd.rb +22 -0
- data/lib/foreman/export/runit.rb +34 -0
- data/lib/foreman/export/supervisord.rb +16 -0
- data/lib/foreman/export/systemd.rb +34 -0
- data/lib/foreman/export/upstart.rb +46 -0
- data/lib/foreman/export.rb +36 -0
- data/lib/foreman/helpers.rb +45 -0
- data/lib/foreman/process.rb +81 -0
- data/lib/foreman/procfile.rb +94 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/create_file.rb +103 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/create_link.rb +59 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/directory.rb +118 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/empty_directory.rb +135 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/file_manipulation.rb +327 -0
- data/lib/foreman/vendor/thor/lib/thor/actions/inject_into_file.rb +103 -0
- data/lib/foreman/vendor/thor/lib/thor/actions.rb +318 -0
- data/lib/foreman/vendor/thor/lib/thor/base.rb +656 -0
- data/lib/foreman/vendor/thor/lib/thor/command.rb +133 -0
- data/lib/foreman/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +85 -0
- data/lib/foreman/vendor/thor/lib/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/foreman/vendor/thor/lib/thor/core_ext/ordered_hash.rb +129 -0
- data/lib/foreman/vendor/thor/lib/thor/error.rb +32 -0
- data/lib/foreman/vendor/thor/lib/thor/group.rb +281 -0
- data/lib/foreman/vendor/thor/lib/thor/invocation.rb +177 -0
- data/lib/foreman/vendor/thor/lib/thor/line_editor/basic.rb +35 -0
- data/lib/foreman/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
- data/lib/foreman/vendor/thor/lib/thor/line_editor.rb +17 -0
- data/lib/foreman/vendor/thor/lib/thor/parser/argument.rb +70 -0
- data/lib/foreman/vendor/thor/lib/thor/parser/arguments.rb +175 -0
- data/lib/foreman/vendor/thor/lib/thor/parser/option.rb +146 -0
- data/lib/foreman/vendor/thor/lib/thor/parser/options.rb +220 -0
- data/lib/foreman/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/foreman/vendor/thor/lib/thor/rake_compat.rb +71 -0
- data/lib/foreman/vendor/thor/lib/thor/runner.rb +322 -0
- data/lib/foreman/vendor/thor/lib/thor/shell/basic.rb +436 -0
- data/lib/foreman/vendor/thor/lib/thor/shell/color.rb +149 -0
- data/lib/foreman/vendor/thor/lib/thor/shell/html.rb +126 -0
- data/lib/foreman/vendor/thor/lib/thor/shell.rb +81 -0
- data/lib/foreman/vendor/thor/lib/thor/util.rb +268 -0
- data/lib/foreman/vendor/thor/lib/thor/version.rb +3 -0
- data/lib/foreman/vendor/thor/lib/thor.rb +492 -0
- data/lib/foreman/version.rb +5 -0
- data/lib/foreman.rb +17 -0
- data/man/overman.1 +284 -0
- data/spec/foreman/cli_spec.rb +111 -0
- data/spec/foreman/engine_spec.rb +114 -0
- data/spec/foreman/export/base_spec.rb +19 -0
- data/spec/foreman/export/bluepill_spec.rb +37 -0
- data/spec/foreman/export/daemon_spec.rb +97 -0
- data/spec/foreman/export/inittab_spec.rb +40 -0
- data/spec/foreman/export/launchd_spec.rb +31 -0
- data/spec/foreman/export/runit_spec.rb +36 -0
- data/spec/foreman/export/supervisord_spec.rb +38 -0
- data/spec/foreman/export/systemd_spec.rb +155 -0
- data/spec/foreman/export/upstart_spec.rb +118 -0
- data/spec/foreman/export_spec.rb +24 -0
- data/spec/foreman/helpers_spec.rb +26 -0
- data/spec/foreman/process_spec.rb +71 -0
- data/spec/foreman/procfile_spec.rb +57 -0
- data/spec/foreman_spec.rb +16 -0
- data/spec/helper_spec.rb +19 -0
- data/spec/resources/Procfile +5 -0
- data/spec/resources/Procfile.bad +2 -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 +81 -0
- data/spec/resources/export/daemon/app-alpha-1.conf +7 -0
- data/spec/resources/export/daemon/app-alpha-2.conf +7 -0
- data/spec/resources/export/daemon/app-alpha.conf +2 -0
- data/spec/resources/export/daemon/app-bravo-1.conf +7 -0
- data/spec/resources/export/daemon/app-bravo.conf +2 -0
- data/spec/resources/export/daemon/app.conf +14 -0
- data/spec/resources/export/inittab/inittab.concurrency +4 -0
- data/spec/resources/export/inittab/inittab.default +6 -0
- data/spec/resources/export/launchd/launchd-a.default +29 -0
- data/spec/resources/export/launchd/launchd-b.default +29 -0
- data/spec/resources/export/launchd/launchd-c.default +30 -0
- data/spec/resources/export/runit/app-alpha-1/log/run +7 -0
- data/spec/resources/export/runit/app-alpha-1/run +4 -0
- data/spec/resources/export/runit/app-alpha-2/log/run +7 -0
- data/spec/resources/export/runit/app-alpha-2/run +4 -0
- data/spec/resources/export/runit/app-bravo-1/log/run +7 -0
- data/spec/resources/export/runit/app-bravo-1/run +4 -0
- data/spec/resources/export/supervisord/app-alpha-1.conf +42 -0
- data/spec/resources/export/supervisord/app-alpha-2.conf +22 -0
- data/spec/resources/export/systemd/app-alpha.1.service +18 -0
- data/spec/resources/export/systemd/app-alpha.2.service +18 -0
- data/spec/resources/export/systemd/app-alpha.target +2 -0
- data/spec/resources/export/systemd/app-bravo.1.service +18 -0
- data/spec/resources/export/systemd/app-bravo.target +2 -0
- data/spec/resources/export/systemd/app.target +5 -0
- data/spec/resources/export/upstart/app-alpha-1.conf +11 -0
- data/spec/resources/export/upstart/app-alpha-2.conf +11 -0
- data/spec/resources/export/upstart/app-alpha.conf +2 -0
- data/spec/resources/export/upstart/app-bravo-1.conf +11 -0
- data/spec/resources/export/upstart/app-bravo.conf +2 -0
- data/spec/resources/export/upstart/app.conf +2 -0
- data/spec/spec_helper.rb +177 -0
- metadata +147 -16
- data/lib/overman/version.rb +0 -5
- data/lib/overman.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16dff0543ec0529199820c87e2bb1aa9df5ddfe0d2287c8993a4f223d72a6c85
|
4
|
+
data.tar.gz: f586a1017a45d1d8e517af84157441e1f28e910e35a15f069cfd69de8e8bc31b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f88e4b71f8936627deea9c573f83c8071778738b769bc490127d14527adafb80202901b2b47ae09fe62d05d6c8a3933ee458215e03c020022b067fc09f91932
|
7
|
+
data.tar.gz: 20c42a00a35ace143e4234c4b80958c6981a010987373c48748a1df522fd2e643ffd811eed231c20b5305829173fc2379e622f4c759f9c3c9a4595b79c6ce2a8
|
data/README.md
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Overman (`ddollar/foreman` fork)
|
2
|
+
|
3
|
+
[![CI](https://github.com/spinels/overman/actions/workflows/ci.yml/badge.svg)](https://github.com/spinels/overman/actions/workflows/ci.yml)
|
4
|
+
|
5
|
+
Manage Procfile-based applications
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
$ gem install overman
|
10
|
+
|
11
|
+
Ruby users should take care *not* to install overman in their project's `Gemfile`. See this [wiki article](https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman) for more details.
|
12
|
+
|
13
|
+
## Getting Started
|
14
|
+
|
15
|
+
* http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
|
16
|
+
|
17
|
+
## Supported Ruby versions
|
18
|
+
|
19
|
+
See [ci.yml](.github/workflows/ci.yml) for a list of Ruby versions against which Foreman is tested.
|
20
|
+
|
21
|
+
## Documentation
|
22
|
+
|
23
|
+
* [man page](http://ddollar.github.io/foreman/)
|
24
|
+
* [wiki](https://github.com/ddollar/foreman/wiki)
|
25
|
+
* [changelog](https://github.com/ddollar/foreman/blob/master/Changelog.md)
|
26
|
+
|
27
|
+
## Ports
|
28
|
+
|
29
|
+
* [forego](https://github.com/ddollar/forego) - Go
|
30
|
+
* [node-foreman](https://github.com/strongloop/node-foreman) - Node.js
|
31
|
+
* [gaffer](https://github.com/jingweno/gaffer) - Java/JVM
|
32
|
+
* [goreman](https://github.com/mattn/goreman) - Go
|
33
|
+
* [honcho](https://github.com/nickstenning/honcho) - python
|
34
|
+
* [proclet](https://github.com/kazeburo/Proclet) - Perl
|
35
|
+
* [shoreman](https://github.com/chrismytton/shoreman) - shell
|
36
|
+
* [crank](https://github.com/arktisklada/crank) - Crystal
|
37
|
+
* [houseman](https://github.com/fujimura/houseman) - Haskell
|
38
|
+
* [spm](https://github.com/bytegust/spm) - Go
|
39
|
+
|
40
|
+
## Authors
|
41
|
+
|
42
|
+
#### Created and maintained by
|
43
|
+
David Dollar
|
44
|
+
|
45
|
+
#### Patches contributed by
|
46
|
+
[Contributor List](https://github.com/ddollar/foreman/contributors)
|
47
|
+
|
48
|
+
## License
|
49
|
+
|
50
|
+
Foreman is licensed under the MIT license.
|
51
|
+
|
52
|
+
See LICENSE for the full license text.
|
data/bin/foreman-runner
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
#/ Usage: foreman-runner [-d <dir>] [-p] <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
|
+
read_profile=""
|
20
|
+
|
21
|
+
while getopts ":hd:p" OPT; do
|
22
|
+
case $OPT in
|
23
|
+
d) cd "$OPTARG" ;;
|
24
|
+
p) read_profile="1" ;;
|
25
|
+
h) usage ;;
|
26
|
+
\?) error "invalid option: -$OPTARG" ;;
|
27
|
+
:) error "option -$OPTARG requires an argument" ;;
|
28
|
+
esac
|
29
|
+
done
|
30
|
+
|
31
|
+
shift $((OPTIND-1))
|
32
|
+
|
33
|
+
[ -z "$1" ] && usage
|
34
|
+
|
35
|
+
if [ "$read_profile" = "1" ]; then
|
36
|
+
if [ -f .profile ]; then
|
37
|
+
. ./.profile
|
38
|
+
fi
|
39
|
+
fi
|
40
|
+
|
41
|
+
exec "$@"
|
data/bin/overman
ADDED
data/data/example/error
ADDED
data/data/example/ticker
ADDED
data/data/example/utf8
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/bluepill.log") do |app|
|
2
|
+
|
3
|
+
app.uid = "<%= user %>"
|
4
|
+
app.gid = "<%= user %>"
|
5
|
+
|
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 = %Q{<%= process.command %>}
|
11
|
+
|
12
|
+
process.working_dir = "<%= engine.root %>"
|
13
|
+
process.daemonize = true
|
14
|
+
process.environment = <%= engine.env.merge("PORT" => port.to_s).inspect %>
|
15
|
+
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
16
|
+
process.stop_grace_time = 45.seconds
|
17
|
+
|
18
|
+
process.stdout = process.stderr = "<%= log %>/<%= app %>-<%= name %>-<%= num %>.log"
|
19
|
+
|
20
|
+
process.monitor_children do |children|
|
21
|
+
children.stop_command "kill {{PID}}"
|
22
|
+
end
|
23
|
+
|
24
|
+
process.group = "<%= app %>-<%= name %>"
|
25
|
+
end
|
26
|
+
<% end %>
|
27
|
+
<% end %>
|
28
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
start on starting <%= app %>-<%= name.gsub('_', '-') %>
|
2
|
+
stop on stopping <%= app %>-<%= name.gsub('_', '-') %>
|
3
|
+
respawn
|
4
|
+
|
5
|
+
env PORT=<%= port %><% engine.env.each_pair do |var, env| %>
|
6
|
+
env <%= var %>=<%= env %><% end %>
|
7
|
+
|
8
|
+
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,33 @@
|
|
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>EnvironmentVariables</key>
|
8
|
+
<dict>
|
9
|
+
<%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
|
10
|
+
<key><%= var %></key>
|
11
|
+
<string><%= env %></string>
|
12
|
+
<%- end -%>
|
13
|
+
</dict>
|
14
|
+
<key>ProgramArguments</key>
|
15
|
+
<array>
|
16
|
+
<%- command_args.each do |command| -%>
|
17
|
+
<string><%= command %></string>
|
18
|
+
<%- end -%>
|
19
|
+
</array>
|
20
|
+
<key>KeepAlive</key>
|
21
|
+
<true/>
|
22
|
+
<key>RunAtLoad</key>
|
23
|
+
<true/>
|
24
|
+
<key>StandardOutPath</key>
|
25
|
+
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
|
26
|
+
<key>StandardErrorPath</key>
|
27
|
+
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
|
28
|
+
<key>UserName</key>
|
29
|
+
<string><%= user %></string>
|
30
|
+
<key>WorkingDirectory</key>
|
31
|
+
<string><%= engine.root %></string>
|
32
|
+
</dict>
|
33
|
+
</plist>
|
@@ -0,0 +1,31 @@
|
|
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
|
+
value = shell_quote(value)
|
9
|
+
value = value.gsub('\=', '=')
|
10
|
+
value = value.gsub('\&', '&')
|
11
|
+
value = value.gsub('\?', '?')
|
12
|
+
"#{key}=\"#{value}\""
|
13
|
+
end
|
14
|
+
app_names << full_name
|
15
|
+
-%>
|
16
|
+
[program:<%= full_name %>]
|
17
|
+
command=<%= process.command %>
|
18
|
+
autostart=true
|
19
|
+
autorestart=true
|
20
|
+
stdout_logfile=<%= log %>/<%= name %>-<%= num %>.log
|
21
|
+
stderr_logfile=<%= log %>/<%= name %>-<%= num %>.error.log
|
22
|
+
user=<%= user %>
|
23
|
+
directory=<%= engine.root %>
|
24
|
+
environment=<%= environment.join(',') %>
|
25
|
+
|
26
|
+
<%
|
27
|
+
end
|
28
|
+
end
|
29
|
+
-%>
|
30
|
+
[group:<%= app %>]
|
31
|
+
programs=<%= app_names.join(',') %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
[Unit]
|
2
|
+
PartOf=<%= app %>.target
|
3
|
+
StopWhenUnneeded=yes
|
4
|
+
|
5
|
+
[Service]
|
6
|
+
User=<%= user %>
|
7
|
+
WorkingDirectory=<%= engine.root %>
|
8
|
+
Environment=PORT=<%= port %>
|
9
|
+
Environment=PS=<%= process_name %>
|
10
|
+
<% engine.env.each_pair do |var,env| -%>
|
11
|
+
Environment="<%= var %>=<%= env %>"
|
12
|
+
<% end -%>
|
13
|
+
ExecStart=/bin/bash -lc 'exec -a "<%= app %>-<%= process_name %>" <%= process.command %>'
|
14
|
+
Restart=always
|
15
|
+
RestartSec=14s
|
16
|
+
StandardInput=null
|
17
|
+
StandardOutput=syslog
|
18
|
+
StandardError=syslog
|
19
|
+
SyslogIdentifier=%n
|
20
|
+
KillMode=mixed
|
21
|
+
TimeoutStopSec=<%= engine.options[:timeout] %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
start on starting <%= app %>-<%= name %>
|
2
|
+
stop on stopping <%= app %>-<%= name %>
|
3
|
+
respawn
|
4
|
+
|
5
|
+
env PORT=<%= port %>
|
6
|
+
<% engine.env.each do |name,value| -%>
|
7
|
+
<% next if name.upcase == "PORT" -%>
|
8
|
+
env <%= name %>='<%= value.gsub(/'/, "'\"'\"'") %>'
|
9
|
+
<% end -%>
|
10
|
+
|
11
|
+
setuid <%= user %>
|
12
|
+
|
13
|
+
chdir <%= engine.root %>
|
14
|
+
|
15
|
+
exec <%= process.command %>
|
data/lib/foreman/cli.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require "foreman"
|
2
|
+
require "foreman/helpers"
|
3
|
+
require "foreman/engine"
|
4
|
+
require "foreman/engine/cli"
|
5
|
+
require "foreman/export"
|
6
|
+
require "foreman/version"
|
7
|
+
require "shellwords"
|
8
|
+
require "yaml"
|
9
|
+
require "foreman/vendor/thor/lib/thor"
|
10
|
+
|
11
|
+
class Foreman::CLI < Foreman::Thor
|
12
|
+
|
13
|
+
include Foreman::Helpers
|
14
|
+
|
15
|
+
map ["-v", "--version"] => :version
|
16
|
+
|
17
|
+
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
18
|
+
class_option :root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
|
19
|
+
|
20
|
+
desc "start [PROCESS]", "Start the application (or a specific PROCESS)"
|
21
|
+
|
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"', :desc => 'Specify what processes will run and how many. Default: "all=1"'
|
25
|
+
method_option :port, :type => :numeric, :aliases => "-p"
|
26
|
+
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shutdown gracefully before receiving a SIGKILL, defaults to 5."
|
27
|
+
method_option :timestamp, :type => :boolean, :default => true, :desc => "Include timestamp in output"
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# Hackery. Take the run method away from Thor so that we can redefine it.
|
31
|
+
def is_thor_reserved_word?(word, type)
|
32
|
+
return false if word == "run"
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def start(process=nil)
|
38
|
+
check_procfile!
|
39
|
+
load_environment!
|
40
|
+
engine.load_procfile(procfile)
|
41
|
+
engine.options[:formation] = "#{process}=1" if process
|
42
|
+
engine.start
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "export FORMAT LOCATION", "Export the application to another process management format"
|
46
|
+
|
47
|
+
method_option :app, :type => :string, :aliases => "-a"
|
48
|
+
method_option :log, :type => :string, :aliases => "-l"
|
49
|
+
method_option :run, :type => :string, :aliases => "-r", :desc => "Specify the pid file directory, defaults to /var/run/<application>"
|
50
|
+
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
51
|
+
method_option :port, :type => :numeric, :aliases => "-p"
|
52
|
+
method_option :user, :type => :string, :aliases => "-u"
|
53
|
+
method_option :template, :type => :string, :aliases => "-t"
|
54
|
+
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"', :desc => 'Specify what processes will run and how many. Default: "all=1"'
|
55
|
+
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shutdown gracefully before receiving a SIGKILL, defaults to 5."
|
56
|
+
|
57
|
+
def export(format, location=nil)
|
58
|
+
check_procfile!
|
59
|
+
load_environment!
|
60
|
+
engine.load_procfile(procfile)
|
61
|
+
formatter = Foreman::Export.formatter(format)
|
62
|
+
formatter.new(location, engine, options).export
|
63
|
+
rescue Foreman::Export::Exception => ex
|
64
|
+
error ex.message
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "check", "Validate your application's Procfile"
|
68
|
+
|
69
|
+
def check
|
70
|
+
check_procfile!
|
71
|
+
engine.load_procfile(procfile)
|
72
|
+
error "no processes defined" unless engine.processes.length > 0
|
73
|
+
puts "valid procfile detected (#{engine.process_names.join(', ')})"
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "run COMMAND [ARGS...]", "Run a command using your application's environment"
|
77
|
+
|
78
|
+
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
|
79
|
+
stop_on_unknown_option! :run
|
80
|
+
|
81
|
+
def run(*args)
|
82
|
+
load_environment!
|
83
|
+
|
84
|
+
if File.file?(procfile)
|
85
|
+
engine.load_procfile(procfile)
|
86
|
+
end
|
87
|
+
|
88
|
+
pid = fork do
|
89
|
+
begin
|
90
|
+
engine.env.each { |k,v| ENV[k] = v }
|
91
|
+
if args.size == 1 && process = engine.process(args.first)
|
92
|
+
process.exec(:env => engine.env)
|
93
|
+
else
|
94
|
+
exec args.shelljoin
|
95
|
+
end
|
96
|
+
rescue Errno::EACCES
|
97
|
+
error "not executable: #{args.first}"
|
98
|
+
rescue Errno::ENOENT
|
99
|
+
error "command not found: #{args.first}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
trap("INT") do
|
103
|
+
Process.kill(:INT, pid)
|
104
|
+
end
|
105
|
+
Process.wait(pid)
|
106
|
+
exit $?.exitstatus || 0
|
107
|
+
rescue Interrupt
|
108
|
+
end
|
109
|
+
|
110
|
+
desc "version", "Display Foreman gem version"
|
111
|
+
|
112
|
+
def version
|
113
|
+
puts Foreman::VERSION
|
114
|
+
end
|
115
|
+
|
116
|
+
no_tasks do
|
117
|
+
def engine
|
118
|
+
@engine ||= begin
|
119
|
+
engine_class = Foreman::Engine::CLI
|
120
|
+
engine = engine_class.new(options)
|
121
|
+
engine
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private ######################################################################
|
127
|
+
|
128
|
+
def error(message)
|
129
|
+
puts "ERROR: #{message}"
|
130
|
+
exit 1
|
131
|
+
end
|
132
|
+
|
133
|
+
def check_procfile!
|
134
|
+
error("#{procfile} does not exist.") unless File.file?(procfile)
|
135
|
+
end
|
136
|
+
|
137
|
+
def load_environment!
|
138
|
+
if options[:env]
|
139
|
+
options[:env].split(",").each do |file|
|
140
|
+
engine.load_env file
|
141
|
+
end
|
142
|
+
else
|
143
|
+
default_env = File.join(engine.root, ".env")
|
144
|
+
engine.load_env default_env if File.file?(default_env)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def procfile
|
149
|
+
case
|
150
|
+
when options[:procfile] then options[:procfile]
|
151
|
+
when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
|
152
|
+
else "Procfile"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def options
|
157
|
+
original_options = super
|
158
|
+
return original_options unless File.file?(".foreman")
|
159
|
+
defaults = ::YAML::load_file(".foreman") || {}
|
160
|
+
Foreman::Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
|
161
|
+
end
|
162
|
+
end
|
@@ -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 false 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 bright_cyan bright_yellow
|
48
|
+
bright_green bright_magenta bright_red bright_blue )
|
49
|
+
|
50
|
+
def startup
|
51
|
+
@colors = map_colors
|
52
|
+
proctitle "foreman: master" unless Foreman.windows?
|
53
|
+
Color.enable($stdout, options[:color])
|
54
|
+
end
|
55
|
+
|
56
|
+
def output(name, data)
|
57
|
+
data.to_s.lines.map(&:chomp).each do |message|
|
58
|
+
output = ""
|
59
|
+
output += $stdout.color(@colors[name.split(".").first].to_sym)
|
60
|
+
output += "#{Time.now.strftime("%H:%M:%S")} " if options[:timestamp]
|
61
|
+
output += "#{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"] = "bright_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
|