procman 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Procfile +21 -16
- data/Procfile.template +24 -0
- data/README.md +71 -5
- data/bin/procman +23 -1
- data/lib/proc_man.rb +20 -5
- data/lib/proc_man/constraint.rb +34 -0
- data/lib/proc_man/deploy.rb +1 -1
- data/lib/proc_man/process.rb +39 -7
- metadata +3 -2
- data/procman-1.1.1.gem +0 -0
data/Procfile
CHANGED
@@ -1,19 +1,24 @@
|
|
1
|
-
process :
|
2
|
-
start do
|
3
|
-
puts "ENV: #{environment}"
|
4
|
-
end
|
5
|
-
stop {}
|
6
|
-
restart {}
|
7
|
-
end
|
1
|
+
process :example_worker do
|
8
2
|
|
9
|
-
process
|
10
|
-
|
11
|
-
stop {}
|
12
|
-
restart {}
|
13
|
-
end
|
3
|
+
# Only action this process in production on a specific host
|
4
|
+
# constraint :environment => 'production', :host => 'app01.myapp.com'
|
14
5
|
|
15
|
-
process
|
16
|
-
|
17
|
-
|
18
|
-
|
6
|
+
# Only action this process in development
|
7
|
+
constraint :environment => 'development'
|
8
|
+
|
9
|
+
# Define the action to be carried out when this process should start
|
10
|
+
start do
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
# Define the action to be carried out when this process should stop
|
15
|
+
stop do
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
# Define the action to be carried out when this process should restart
|
20
|
+
restart do
|
21
|
+
|
22
|
+
end
|
23
|
+
|
19
24
|
end
|
data/Procfile.template
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
process :example_worker do
|
2
|
+
|
3
|
+
# Only action this process in production on a specific host
|
4
|
+
# constraint :environment => 'production', :host => 'app01.myapp.com'
|
5
|
+
|
6
|
+
# Only action this process in development
|
7
|
+
# constraint :environment => 'development'
|
8
|
+
|
9
|
+
# Define the action to be carried out when this process should start
|
10
|
+
start do
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
# Define the action to be carried out when this process should stop
|
15
|
+
stop do
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
# Define the action to be carried out when this process should restart
|
20
|
+
restart do
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/README.md
CHANGED
@@ -10,6 +10,28 @@ your application as a whole.
|
|
10
10
|
The `Procfile` is a Ruby file which you can use to define how to manipulate
|
11
11
|
your processes.
|
12
12
|
|
13
|
+
## Setting up
|
14
|
+
|
15
|
+
If you're using Bundler (you should be) and wish to use procman, just include it within
|
16
|
+
your Gemfile and run `bundle` to install it.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'procman'
|
20
|
+
```
|
21
|
+
|
22
|
+
Once installed, you can execute commands as shown below but you should prefix `bundle exec`
|
23
|
+
to the start of the command.
|
24
|
+
|
25
|
+
## Creating your initial Procfile
|
26
|
+
|
27
|
+
The command line tool allows you to create an example `Procfile` with a simple command. This
|
28
|
+
will create a `Procfile` in the root of the directory you are currently within. You can then
|
29
|
+
open this template and make changes as appropriate for your applications.
|
30
|
+
|
31
|
+
```bash
|
32
|
+
$ procman init
|
33
|
+
```
|
34
|
+
|
13
35
|
## Example Procfile
|
14
36
|
|
15
37
|
Your Procfile can contain multiple types of process and each process should define
|
@@ -22,11 +44,11 @@ powered by our Ruby backgrounding system, rbg.
|
|
22
44
|
process :unicorn do
|
23
45
|
|
24
46
|
start do
|
25
|
-
system("umask 002 && bundle exec unicorn_rails -E
|
47
|
+
system("umask 002 && bundle exec unicorn_rails -E #{environment} -c #{root}/config/unicorn.rb -D")
|
26
48
|
end
|
27
49
|
|
28
50
|
stop do
|
29
|
-
system("kill `cat tmp/pids/unicorn.
|
51
|
+
system("kill `cat #{root}/tmp/pids/unicorn.#{environment}.pid`")
|
30
52
|
end
|
31
53
|
|
32
54
|
restart { stop and start }
|
@@ -34,22 +56,46 @@ process :unicorn do
|
|
34
56
|
end
|
35
57
|
|
36
58
|
process :worker do
|
59
|
+
|
60
|
+
constraint :environment => 'production', :host => /\.production\.myapp\z/
|
61
|
+
constraint :environment => 'development', :host => /\.local\z/
|
37
62
|
|
38
63
|
start do
|
39
|
-
system("bundle exec rbg start -c config/processes/worker.rb -E
|
64
|
+
system("bundle exec rbg start -c #{root}/config/processes/worker.rb -E #{environment}")
|
40
65
|
end
|
41
66
|
|
42
67
|
stop do
|
43
|
-
system("bundle exec rbg stop -c config/processes/worker.rb -E
|
68
|
+
system("bundle exec rbg stop -c #{root}/config/processes/worker.rb -E #{environment}")
|
44
69
|
end
|
45
70
|
|
46
71
|
restart do
|
47
|
-
system("bundle exec rbg reload -c config/processes/worker.rb -E
|
72
|
+
system("bundle exec rbg reload -c #{root}/config/processes/worker.rb -E #{environment}")
|
48
73
|
end
|
49
74
|
|
50
75
|
end
|
51
76
|
```
|
52
77
|
|
78
|
+
### Specifying constraints
|
79
|
+
|
80
|
+
If you only want certain processes to execute under certain environments or on specific hosts,
|
81
|
+
you can use constraints to restrict these.
|
82
|
+
|
83
|
+
You can specify any number of constraints for a process as shown below. If no constraints are defined
|
84
|
+
for a specific process, it will always be included when your action is executed. If a constraint is
|
85
|
+
added, the process's action will only be invoked when at least one of the constraints is matched otherwise
|
86
|
+
it will be skipped.
|
87
|
+
|
88
|
+
Constraints are configured by adding `constraint` "rules" to your process definitions.
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
# execute always in production
|
92
|
+
constraint :environment => 'production'
|
93
|
+
# execute on hosts where the hostname ends in .local
|
94
|
+
constraint :host => /\.local\z/
|
95
|
+
# execute in prodution and where the hostname is 'app01'
|
96
|
+
constraint :environment => 'production', :host => 'app01'
|
97
|
+
```
|
98
|
+
|
53
99
|
## Executing process commands
|
54
100
|
|
55
101
|
Once you have a Procfile, you can execute commands by sending them to the `procman`
|
@@ -60,6 +106,24 @@ the command using `bundle exec procman`.
|
|
60
106
|
* `procman stop` - stop your processes
|
61
107
|
* `procman restart` - restart your processes
|
62
108
|
|
109
|
+
In fact, you can define any actions you wish. You do not need to be constrained by start,
|
110
|
+
stop & restart. If you executed `procman jump`, it would call the `jump` method for each
|
111
|
+
process within your `Procfile`. There are various action names which are reserved, including:
|
112
|
+
`name`, `options`, `environment`, `host`, `root` and `constraint`.
|
113
|
+
|
114
|
+
Also, You can pass options to these methods to add extra functionality.
|
115
|
+
|
116
|
+
* `-e` - allows you specify the environment which is provided as the environment variable in your methods.
|
117
|
+
* `--processes` - allows you to specify which processes (comma separated) should be executed in the action.
|
118
|
+
|
119
|
+
Some examples of how to execute these options:
|
120
|
+
|
121
|
+
```bash
|
122
|
+
$ procman start -e production
|
123
|
+
$ procman start -e production --processes worker
|
124
|
+
$ procman start --processes worker,unicorn
|
125
|
+
```
|
126
|
+
|
63
127
|
## Executing on deployment
|
64
128
|
|
65
129
|
You can use the included Capistrano recipe to automatically run your procman start/stop/restart
|
@@ -68,3 +132,5 @@ commands whenever you deploy. Just require the deploy recipes in your `Capfile`.
|
|
68
132
|
```ruby
|
69
133
|
require 'proc_man/deploy'
|
70
134
|
```
|
135
|
+
|
136
|
+
This requires that you are using bundler and the `procman` gem has been included in your Gemfile.
|
data/bin/procman
CHANGED
@@ -1,7 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'proc_man'
|
3
3
|
begin
|
4
|
-
|
4
|
+
|
5
|
+
# Convert command line arguments into the appropriate ruby objects
|
6
|
+
args = ARGV.dup
|
7
|
+
final_args = []
|
8
|
+
options = {}
|
9
|
+
until args.empty?
|
10
|
+
arg = args.shift
|
11
|
+
if arg =~ /\A\-/
|
12
|
+
options[arg.gsub(/\A\-+/, '').to_sym] = args.shift
|
13
|
+
else
|
14
|
+
final_args << arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
command = final_args.first
|
19
|
+
case command
|
20
|
+
when 'init'
|
21
|
+
ProcMan.init
|
22
|
+
else
|
23
|
+
# Execute the command
|
24
|
+
ProcMan.run(final_args.first, options)
|
25
|
+
end
|
26
|
+
|
5
27
|
rescue ProcMan::Error => e
|
6
28
|
puts "\e[31m" + e.message + "\e[0m"
|
7
29
|
Process.exit(1)
|
data/lib/proc_man.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'proc_man/process'
|
2
2
|
require 'proc_man/procfile'
|
3
|
+
require 'proc_man/constraint'
|
3
4
|
|
4
5
|
module ProcMan
|
5
6
|
|
6
|
-
VERSION = '1.
|
7
|
+
VERSION = '1.2.0'
|
7
8
|
|
8
9
|
class Error < StandardError; end
|
9
10
|
|
@@ -22,16 +23,18 @@ module ProcMan
|
|
22
23
|
@processes ||= Array.new
|
23
24
|
end
|
24
25
|
|
25
|
-
def run(method,
|
26
|
+
def run(method, options = {})
|
26
27
|
load_procfile(File.expand_path('./Procfile'))
|
27
28
|
if method.nil?
|
28
29
|
raise Error, "Command to execute was not specified. For example, pass 'start' to start processes."
|
29
30
|
else
|
30
31
|
for process in self.processes
|
31
|
-
process.
|
32
|
+
process.options = options
|
32
33
|
if process.defined_method?(method)
|
33
|
-
|
34
|
-
|
34
|
+
if process.execute?
|
35
|
+
puts "\e[33m#{method.capitalize}ing #{process.name}\e[0m"
|
36
|
+
process.send(method)
|
37
|
+
end
|
35
38
|
else
|
36
39
|
puts "\e[31mThe #{process.name} process does not implement a '#{method}' method\e[0m"
|
37
40
|
end
|
@@ -39,5 +42,17 @@ module ProcMan
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
45
|
+
# Create a new Procfile template in the current directory root
|
46
|
+
def init
|
47
|
+
path = File.expand_path('./Procfile')
|
48
|
+
if File.file?(path)
|
49
|
+
raise Error, "Procfile already exists at #{path}"
|
50
|
+
else
|
51
|
+
template_path = File.expand_path('../../Procfile.template', __FILE__)
|
52
|
+
File.open(path, 'w') { |f| f.write(File.read(template_path)) }
|
53
|
+
puts "\e[32mProcfile created at #{path}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
42
57
|
end
|
43
58
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ProcMan
|
2
|
+
class Constraint
|
3
|
+
|
4
|
+
def initialize(process, conditions)
|
5
|
+
@process = process
|
6
|
+
@conditions = conditions
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?
|
10
|
+
matches = 0
|
11
|
+
for key, value in @conditions
|
12
|
+
matches += 1 if compare(value, @process.send(key).to_s.downcase)
|
13
|
+
end
|
14
|
+
@conditions.size > 0 && matches == @conditions.size
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def compare(condition, value)
|
20
|
+
value = value.to_s.downcase
|
21
|
+
case condition
|
22
|
+
when String
|
23
|
+
condition.to_s.downcase == value
|
24
|
+
when Regexp
|
25
|
+
!!condition.match(value)
|
26
|
+
when Array
|
27
|
+
condition.any? { |c| compare(c, value) }
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/proc_man/deploy.rb
CHANGED
@@ -20,7 +20,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
20
20
|
after :restart, "procman:restart"
|
21
21
|
|
22
22
|
def procman_command(command)
|
23
|
-
command = "sh -c \"cd #{deploy_to} && bundle exec procman #{command} #{environment}\""
|
23
|
+
command = "sh -c \"cd #{deploy_to} && bundle exec procman #{command} --environment #{environment}\""
|
24
24
|
if user = fetch(:procman_user, 'app')
|
25
25
|
command = "sudo -u #{user} #{command}"
|
26
26
|
end
|
data/lib/proc_man/process.rb
CHANGED
@@ -1,24 +1,60 @@
|
|
1
1
|
module ProcMan
|
2
2
|
class Process
|
3
3
|
|
4
|
-
attr_writer :
|
4
|
+
attr_writer :options
|
5
5
|
|
6
|
-
|
6
|
+
# Initializes the new process by receiving it's name
|
7
|
+
def initialize(name)
|
7
8
|
@name = name
|
9
|
+
@constraints = []
|
8
10
|
end
|
9
11
|
|
12
|
+
# Returns the name of the process
|
10
13
|
def name
|
11
14
|
@name
|
12
15
|
end
|
13
16
|
|
17
|
+
# Returns a hash of options which the user has specified
|
18
|
+
def options
|
19
|
+
@options ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the current environment
|
14
23
|
def environment
|
15
|
-
|
24
|
+
self.options[:environment] || self.options[:e] || self.options[:env] || 'development'
|
16
25
|
end
|
17
26
|
|
27
|
+
# Returns the current root directory path
|
18
28
|
def root
|
19
29
|
@root ||= File.expand_path('./')
|
20
30
|
end
|
21
31
|
|
32
|
+
## Returns the current hostname of the machine executing this action
|
33
|
+
def host
|
34
|
+
@host ||= `hostname -f`.strip
|
35
|
+
end
|
36
|
+
|
37
|
+
## Sets a constraint for this process
|
38
|
+
def constraint(hash = {})
|
39
|
+
@constraints << Constraint.new(self, hash)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Specifies whether or not actions for this process should be executed
|
43
|
+
# in the current context.
|
44
|
+
def execute?
|
45
|
+
(@constraints.empty? || @constraints.any?(&:matches?)) &&
|
46
|
+
(self.options[:processes].nil? || self.options[:processes].split(',').include?(self.name.to_s))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Specifies whether or not the provided method has been defined in the Procfile
|
50
|
+
# for this process.
|
51
|
+
def defined_method?(name)
|
52
|
+
instance_variable_get("@#{name}").is_a?(Proc)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Stores and calls different process actions for this process. If there is no
|
56
|
+
# block provided and we don't have a method it will return false otherwise it
|
57
|
+
# will store or call the action as appropriate.
|
22
58
|
def method_missing(method, &block)
|
23
59
|
if block_given?
|
24
60
|
instance_variable_set("@#{method}", block)
|
@@ -29,9 +65,5 @@ module ProcMan
|
|
29
65
|
end
|
30
66
|
end
|
31
67
|
|
32
|
-
def defined_method?(name)
|
33
|
-
instance_variable_get("@#{name}").is_a?(Proc)
|
34
|
-
end
|
35
|
-
|
36
68
|
end
|
37
69
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: procman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -20,13 +20,14 @@ extensions: []
|
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
22
|
- bin/procman
|
23
|
+
- lib/proc_man/constraint.rb
|
23
24
|
- lib/proc_man/deploy.rb
|
24
25
|
- lib/proc_man/process.rb
|
25
26
|
- lib/proc_man/procfile.rb
|
26
27
|
- lib/proc_man.rb
|
27
28
|
- LICENCE
|
28
29
|
- Procfile
|
29
|
-
-
|
30
|
+
- Procfile.template
|
30
31
|
- procman.gemspec
|
31
32
|
- README.md
|
32
33
|
homepage: http://atechmedia.com
|
data/procman-1.1.1.gem
DELETED
Binary file
|