procman 1.1.2 → 1.2.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/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
|