foreman 0.50.0-x86-mswin32

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.
Files changed (81) hide show
  1. data/README.md +46 -0
  2. data/bin/foreman +7 -0
  3. data/bin/foreman-runner +32 -0
  4. data/bin/taskman +8 -0
  5. data/data/example/Procfile +4 -0
  6. data/data/example/Procfile.without_colon +2 -0
  7. data/data/example/error +7 -0
  8. data/data/example/log/neverdie.log +4 -0
  9. data/data/example/spawnee +14 -0
  10. data/data/example/spawner +7 -0
  11. data/data/example/ticker +14 -0
  12. data/data/example/utf8 +11 -0
  13. data/data/export/bluepill/master.pill.erb +28 -0
  14. data/data/export/launchd/launchd.plist.erb +22 -0
  15. data/data/export/runit/log/run.erb +7 -0
  16. data/data/export/runit/run.erb +3 -0
  17. data/data/export/supervisord/app.conf.erb +27 -0
  18. data/data/export/upstart/master.conf.erb +8 -0
  19. data/data/export/upstart/process.conf.erb +5 -0
  20. data/data/export/upstart/process_master.conf.erb +2 -0
  21. data/lib/foreman.rb +23 -0
  22. data/lib/foreman/cli.rb +140 -0
  23. data/lib/foreman/distribution.rb +9 -0
  24. data/lib/foreman/engine.rb +313 -0
  25. data/lib/foreman/engine/cli.rb +105 -0
  26. data/lib/foreman/env.rb +27 -0
  27. data/lib/foreman/export.rb +34 -0
  28. data/lib/foreman/export/base.rb +146 -0
  29. data/lib/foreman/export/bluepill.rb +12 -0
  30. data/lib/foreman/export/inittab.rb +33 -0
  31. data/lib/foreman/export/launchd.rb +15 -0
  32. data/lib/foreman/export/runit.rb +34 -0
  33. data/lib/foreman/export/supervisord.rb +16 -0
  34. data/lib/foreman/export/upstart.rb +25 -0
  35. data/lib/foreman/helpers.rb +45 -0
  36. data/lib/foreman/process.rb +102 -0
  37. data/lib/foreman/procfile.rb +92 -0
  38. data/lib/foreman/version.rb +5 -0
  39. data/man/foreman.1 +244 -0
  40. data/spec/foreman/cli_spec.rb +87 -0
  41. data/spec/foreman/engine_spec.rb +104 -0
  42. data/spec/foreman/export/base_spec.rb +19 -0
  43. data/spec/foreman/export/bluepill_spec.rb +37 -0
  44. data/spec/foreman/export/inittab_spec.rb +40 -0
  45. data/spec/foreman/export/launchd_spec.rb +21 -0
  46. data/spec/foreman/export/runit_spec.rb +36 -0
  47. data/spec/foreman/export/supervisord_spec.rb +36 -0
  48. data/spec/foreman/export/upstart_spec.rb +88 -0
  49. data/spec/foreman/export_spec.rb +24 -0
  50. data/spec/foreman/helpers_spec.rb +26 -0
  51. data/spec/foreman/process_spec.rb +48 -0
  52. data/spec/foreman/procfile_spec.rb +41 -0
  53. data/spec/foreman_spec.rb +16 -0
  54. data/spec/helper_spec.rb +18 -0
  55. data/spec/resources/Procfile +4 -0
  56. data/spec/resources/bin/echo +2 -0
  57. data/spec/resources/bin/env +2 -0
  58. data/spec/resources/bin/test +2 -0
  59. data/spec/resources/bin/utf8 +2 -0
  60. data/spec/resources/export/bluepill/app-concurrency.pill +49 -0
  61. data/spec/resources/export/bluepill/app.pill +46 -0
  62. data/spec/resources/export/inittab/inittab.concurrency +4 -0
  63. data/spec/resources/export/inittab/inittab.default +4 -0
  64. data/spec/resources/export/launchd/launchd-a.default +22 -0
  65. data/spec/resources/export/launchd/launchd-b.default +22 -0
  66. data/spec/resources/export/runit/app-alpha-1/log/run +7 -0
  67. data/spec/resources/export/runit/app-alpha-1/run +3 -0
  68. data/spec/resources/export/runit/app-alpha-2/log/run +7 -0
  69. data/spec/resources/export/runit/app-alpha-2/run +3 -0
  70. data/spec/resources/export/runit/app-bravo-1/log/run +7 -0
  71. data/spec/resources/export/runit/app-bravo-1/run +3 -0
  72. data/spec/resources/export/supervisord/app-alpha-1.conf +24 -0
  73. data/spec/resources/export/supervisord/app-alpha-2.conf +24 -0
  74. data/spec/resources/export/upstart/app-alpha-1.conf +5 -0
  75. data/spec/resources/export/upstart/app-alpha-2.conf +5 -0
  76. data/spec/resources/export/upstart/app-alpha.conf +2 -0
  77. data/spec/resources/export/upstart/app-bravo-1.conf +5 -0
  78. data/spec/resources/export/upstart/app-bravo.conf +2 -0
  79. data/spec/resources/export/upstart/app.conf +8 -0
  80. data/spec/spec_helper.rb +153 -0
  81. metadata +148 -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 ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "foreman/cli"
6
+
7
+ Foreman::CLI.start
@@ -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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "foreman/cli"
6
+
7
+ Foreman::CLI.engine_class = Foreman::TmuxEngine
8
+ Foreman::CLI.start
@@ -0,0 +1,4 @@
1
+ ticker: ruby ./ticker $PORT
2
+ error: ruby ./error
3
+ utf8: ruby ./utf8
4
+ spawner: ./spawner
@@ -0,0 +1,2 @@
1
+ ticker ./ticker $PORT
2
+ error ./error
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $stdout.sync = true
4
+
5
+ puts "will error in 10s"
6
+ sleep 5
7
+ raise "Dying"
@@ -0,0 +1,4 @@
1
+ tick
2
+ tick
3
+ ./never_die:6:in `sleep': Interrupt
4
+ from ./never_die:6
@@ -0,0 +1,14 @@
1
+ #!/bin/sh
2
+
3
+ NAME="$1"
4
+
5
+ sigterm() {
6
+ echo "$NAME: got sigterm"
7
+ }
8
+
9
+ #trap sigterm SIGTERM
10
+
11
+ while true; do
12
+ echo "$NAME: ping $$"
13
+ sleep 1
14
+ done
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ ./spawnee A &
4
+ ./spawnee B &
5
+ ./spawnee C &
6
+
7
+ wait
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $stdout.sync = true
4
+
5
+ %w( SIGINT SIGTERM ).each do |signal|
6
+ trap(signal) do
7
+ puts "received #{signal} but i'm ignoring it!"
8
+ end
9
+ end
10
+
11
+ while true
12
+ puts "tick: #{ARGV.inspect} -- FOO:#{ENV["FOO"]}"
13
+ sleep 1
14
+ end
data/data/example/utf8 ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: BINARY
3
+
4
+ $stdout.sync = true
5
+
6
+ while true
7
+ puts "\u65e5\u672c\u8a9e\u6587\u5b57\u5217"
8
+ puts "\u0915\u0932\u094d\u0907\u0928\u0643\u0637\u0628\u041a\u0430\u043b\u0438\u043d\u0430"
9
+ puts "\xff\x03"
10
+ sleep 1
11
+ end
@@ -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 = "<%= 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,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>
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ LOG=<%= log %>/<%= name %>-<%= num %>
5
+
6
+ test -d "$LOG" || mkdir -p m2750 "$LOG" && chown <%= user %> "$LOG"
7
+ exec chpst -u <%= user %> svlogd "$LOG"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
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(',') %>
@@ -0,0 +1,8 @@
1
+ pre-start script
2
+
3
+ bash << "EOF"
4
+ mkdir -p <%= log %>
5
+ chown -R <%= user %> <%= log %>
6
+ EOF
7
+
8
+ end script
@@ -0,0 +1,5 @@
1
+ start on starting <%= app %>-<%= name %>
2
+ stop on stopping <%= app %>-<%= name %>
3
+ respawn
4
+
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'
@@ -0,0 +1,2 @@
1
+ start on starting <%= app %>
2
+ stop on stopping <%= app %>
data/lib/foreman.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "foreman/version"
2
+
3
+ module Foreman
4
+
5
+ class AppDoesNotExist < Exception; end
6
+
7
+ def self.runner
8
+ File.expand_path("../../bin/foreman-runner", __FILE__)
9
+ end
10
+
11
+ def self.jruby?
12
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
13
+ end
14
+
15
+ def self.ruby_18?
16
+ defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
17
+ end
18
+
19
+ def self.windows?
20
+ defined?(RUBY_PLATFORM) and RUBY_PLATFORM =~ /(win|w)32$/
21
+ end
22
+
23
+ end
@@ -0,0 +1,140 @@
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 "thor"
10
+
11
+ class Foreman::CLI < 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"'
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
34
+
35
+ def start(process=nil)
36
+ check_procfile!
37
+ load_environment!
38
+ engine.load_procfile(procfile)
39
+ engine.options[:formation] = "#{process}=1" if process
40
+ engine.start
41
+ end
42
+
43
+ desc "export FORMAT LOCATION", "Export the application to another process management format"
44
+
45
+ method_option :app, :type => :string, :aliases => "-a"
46
+ method_option :log, :type => :string, :aliases => "-l"
47
+ method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
48
+ method_option :port, :type => :numeric, :aliases => "-p"
49
+ method_option :user, :type => :string, :aliases => "-u"
50
+ method_option :template, :type => :string, :aliases => "-t"
51
+ method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
52
+
53
+ def export(format, location=nil)
54
+ check_procfile!
55
+ load_environment!
56
+ engine.load_procfile(procfile)
57
+ formatter = Foreman::Export.formatter(format)
58
+ formatter.new(location, engine, options).export
59
+ rescue Foreman::Export::Exception => ex
60
+ error ex.message
61
+ end
62
+
63
+ desc "check", "Validate your application's Procfile"
64
+
65
+ def check
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(', ')})"
70
+ end
71
+
72
+ desc "run COMMAND [ARGS...]", "Run a command using your application's environment"
73
+
74
+ method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
75
+
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
85
+ end
86
+
87
+ desc "version", "Display Foreman gem version"
88
+
89
+ def version
90
+ puts Foreman::VERSION
91
+ end
92
+
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
101
+ end
102
+
103
+ private ######################################################################
104
+
105
+ def error(message)
106
+ puts "ERROR: #{message}"
107
+ exit 1
108
+ end
109
+
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
131
+ end
132
+
133
+ def options
134
+ original_options = super
135
+ return original_options unless File.exists?(".foreman")
136
+ defaults = ::YAML::load_file(".foreman") || {}
137
+ Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
138
+ end
139
+
140
+ end