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 CHANGED
@@ -1,19 +1,24 @@
1
- process :unicorn do
2
- start do
3
- puts "ENV: #{environment}"
4
- end
5
- stop {}
6
- restart {}
7
- end
1
+ process :example_worker do
8
2
 
9
- process :worker do
10
- start {}
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 :cron do
16
- start {}
17
- stop {}
18
- restart {}
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 production -c config/unicorn.rb -D")
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.production.pid`")
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 production")
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 production")
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 production")
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
- ProcMan.run(ARGV[0], ARGV[1])
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.1.2'
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, environment = nil)
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.environment = environment
32
+ process.options = options
32
33
  if process.defined_method?(method)
33
- puts "\e[33m#{method.capitalize}ing #{process.name}\e[0m"
34
- process.send(method)
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
@@ -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
@@ -1,24 +1,60 @@
1
1
  module ProcMan
2
2
  class Process
3
3
 
4
- attr_writer :environment
4
+ attr_writer :options
5
5
 
6
- def initialize(name, options = {})
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
- @environment || 'development'
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.1.2
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
- - procman-1.1.1.gem
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