sam-shepherd 0.8.2 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f74445b9a25d5ab1038deeaa2b3ce215c657b3df4888ee6e01e2586919c189b
4
- data.tar.gz: '04593b3b97f42e5d083aa5eea1d20624815083eee2eb2e079a6505b8d83d5889'
3
+ metadata.gz: 06abe7f1d5b6691e01a1df7433ae4ed8d9f2ec0e153c3fe82dfc558677c33fa7
4
+ data.tar.gz: 204385c6f7c60f1ce2c18b7a44d98af94fc52850f2770725ab0418eeb158fa86
5
5
  SHA512:
6
- metadata.gz: 5dd1b4de7a1883409ed26e98f7156a1d761eb806e7a290540c8729cfda8916a972481e6c048bd715bf270c6d4bdb68bccc17c9e47cf0034538f9fc349e95b153
7
- data.tar.gz: 286afdcf6ba6806752e879ab7798ad6c6e4a0bef0b87940bda672105a00cade3b1f7e24fafd099cac333027213661079cce2899933a13bf61950ac16417a02db
6
+ metadata.gz: 6b2b3ea89e0147e321dbe787e25ab4480dca6144c4de4fb1a5369d9272a950caffb4b36120191134fa2d0cae3b9cc796f4f81e128e3695ed12f5dbc7f665665e
7
+ data.tar.gz: edc6d81e4befc3090877d25157681c888095922aea8cc7dffd39fae8a1407a4cf7459c6fad83412a3fb3e07079ab43ccd03c220c747c10f8cf7a3d005c8fed45
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sam-shepherd (0.8.2)
4
+ sam-shepherd (0.9.0)
5
5
  hanami-cli (~> 0.2)
6
6
  tty-command (~> 0.7)
7
7
 
@@ -22,7 +22,7 @@ GEM
22
22
  descendants_tracker (~> 0.0.4)
23
23
  ice_nine (~> 0.11.0)
24
24
  thread_safe (~> 0.3, >= 0.3.1)
25
- backports (3.11.1)
25
+ backports (3.11.3)
26
26
  builder (3.2.3)
27
27
  childprocess (0.9.0)
28
28
  ffi (~> 1.0, >= 1.0.11)
@@ -46,7 +46,7 @@ GEM
46
46
  backports (>= 3.8.0)
47
47
  cucumber-tag_expressions (~> 1.1.0)
48
48
  gherkin (>= 5.0.0)
49
- cucumber-expressions (5.0.14)
49
+ cucumber-expressions (5.0.17)
50
50
  cucumber-tag_expressions (1.1.1)
51
51
  cucumber-wire (0.0.1)
52
52
  descendants_tracker (0.0.4)
@@ -57,7 +57,7 @@ GEM
57
57
  equatable (0.5.0)
58
58
  erubis (2.7.0)
59
59
  ffi (1.9.23)
60
- flay (2.10.0)
60
+ flay (2.11.0)
61
61
  erubis (~> 2.7.0)
62
62
  path_expander (~> 1.0)
63
63
  ruby_parser (~> 3.0)
@@ -114,7 +114,7 @@ GEM
114
114
  nenv (~> 0.1)
115
115
  shellany (~> 0.0)
116
116
  parallel (1.12.1)
117
- parser (2.5.0.5)
117
+ parser (2.5.1.0)
118
118
  ast (~> 2.4.0)
119
119
  pastel (0.7.2)
120
120
  equatable (~> 0.5.0)
@@ -125,7 +125,7 @@ GEM
125
125
  coderay (~> 1.1.0)
126
126
  method_source (~> 0.9.0)
127
127
  public_suffix (3.0.2)
128
- puma (3.11.3)
128
+ puma (3.11.4)
129
129
  rack (2.0.4)
130
130
  rack-protection (2.0.1)
131
131
  rack
@@ -135,10 +135,10 @@ GEM
135
135
  rb-fsevent (0.10.3)
136
136
  rb-inotify (0.9.10)
137
137
  ffi (>= 0.5.0, < 2)
138
- reek (4.8.0)
138
+ reek (4.8.1)
139
139
  codeclimate-engine-rb (~> 0.4.0)
140
140
  parser (>= 2.5.0.0, < 2.6)
141
- rainbow (~> 3.0)
141
+ rainbow (>= 2.0, < 4.0)
142
142
  rspec (3.7.0)
143
143
  rspec-core (~> 3.7.0)
144
144
  rspec-expectations (~> 3.7.0)
@@ -152,7 +152,7 @@ GEM
152
152
  diff-lcs (>= 1.2.0, < 2.0)
153
153
  rspec-support (~> 3.7.0)
154
154
  rspec-support (3.7.1)
155
- rubocop (0.54.0)
155
+ rubocop (0.55.0)
156
156
  parallel (~> 1.10)
157
157
  parser (>= 2.5)
158
158
  powerpack (~> 0.1)
@@ -173,7 +173,7 @@ GEM
173
173
  ruby_parser (~> 3.8)
174
174
  tty-which (~> 0.3.0)
175
175
  virtus (~> 1.0)
176
- sexp_processor (4.10.1)
176
+ sexp_processor (4.11.0)
177
177
  shellany (0.0.1)
178
178
  simplecov (0.16.1)
179
179
  docile (~> 1.1)
@@ -190,7 +190,7 @@ GEM
190
190
  tilt (2.0.8)
191
191
  transproc (1.0.2)
192
192
  tty-color (0.4.2)
193
- tty-command (0.7.0)
193
+ tty-command (0.8.0)
194
194
  pastel (~> 0.7.0)
195
195
  tty-which (0.3.0)
196
196
  unicode-display_width (1.3.0)
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Sam
2
2
 
3
3
  [![Maintainability](https://api.codeclimate.com/v1/badges/a8c24394996582c1b59f/maintainability)](https://codeclimate.com/github/VAGAScom/sam/maintainability)
4
- [![Gem Version](https://badge.fury.io/rb/sam.svg)](https://badge.fury.io/rb/sam)
5
- [![Build Status](https://travis-ci.org/VAGAScom/sam.svg?branch=master)](https://travis-ci.org/VAGAScom/sam)
4
+ [![Gem Version](https://badge.fury.io/rb/sam-shepherd.svg)](https://badge.fury.io/rb/sam)
6
5
  [![Dependency Status](https://beta.gemnasium.com/badges/github.com/VAGAScom/sam.svg)](https://beta.gemnasium.com/projects/github.com/VAGAScom/sam)
7
6
 
8
7
 
@@ -29,13 +28,8 @@ Or install it yourself as:
29
28
 
30
29
  ## Usage
31
30
 
32
- **Sam** comes with the following commands:
31
+ **Sam** is pretty straightforward and you can rely on its internal documentation. By invoking `sam` you can see the list of available commands. For a more in-depth help for each command, you can pass a `-h` flag to it, like this: `sam run -h`
33
32
 
34
- 1. `unicorn start`: starts an `unicorn` instance
35
- 2. `unicorn stop`: stops an `unicorn` instance
36
- 3. `unicorn monitor`: start a monitoring loop over the running `unicorn` instance. It will forward the signals `HUP, USR2, TERM, QUIT, TTIN, TTOU` to the `unicorn` instance. `HUP` will do an graceful reload of the application
37
- 4. `unicorn reload`: reloads the `unicorn` instance by issuing a `USR2` followed by a `QUIT` signal a few seconds later
38
- 5. `unicorn run`: starts and monitors an `unicorn` instance
39
33
 
40
34
  ## Development
41
35
 
data/lib/sam/cli.rb CHANGED
@@ -1,42 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'hanami/cli'
4
+ require_relative 'servers'
4
5
 
5
6
  module Sam
6
7
  module CLI
7
8
  module Commands
8
9
  extend Hanami::CLI::Registry
9
10
 
10
- require_relative 'cli/version'
11
+ require_relative 'commands/version'
12
+ require_relative 'commands/spawner'
13
+ require_relative 'commands/reaper'
14
+ require_relative 'commands/reloader'
15
+ require_relative 'commands/monitor'
16
+ require_relative 'commands/runner'
11
17
 
12
18
  register 'version', Version
13
- begin
14
- gem 'unicorn'
15
- require_relative 'unicorn'
16
- require_relative 'cli/unicorn'
17
- register 'unicorn' do |cmd|
18
- cmd.register 'start', Unicorn::Spawner
19
- cmd.register 'stop', Unicorn::Reaper
20
- cmd.register 'reload', Unicorn::Reloader
21
- cmd.register 'monitor', Unicorn::Monitor
22
- cmd.register 'run', Unicorn::Runner
23
- end
24
- rescue Gem::LoadError
25
- warn 'Unicorn not found. Not loading unicorn commands'
26
- end
27
-
28
- begin
29
- gem 'puma'
30
- require_relative 'puma'
31
- require_relative 'cli/puma'
32
- register 'puma' do |cmd|
33
- cmd.register 'start', Puma::Spawner
34
- cmd.register 'stop', Puma::Reaper
35
- # cmd.register 'stop', Puma::Reaper
36
- end
37
- rescue Gem::LoadError
38
- warn 'Puma not found. Not loading puma commands'
39
- end
19
+ register 'start', Spawner
20
+ register 'stop', Reaper
21
+ register 'reload', Reloader
22
+ register 'monitor', Monitor
23
+ register 'run', Runner
40
24
  end
41
25
  end
42
26
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module CLI
5
+ module Commands
6
+ class Monitor < Hanami::CLI::Command
7
+ desc 'Monitor an already running server'
8
+
9
+ # rubocop:disable Metrics/LineLength
10
+ argument :server, required: true, values: %w[unicorn puma], desc: 'The application server to be started'
11
+ argument :config, required: true, desc: 'The path to the server configuration file'
12
+
13
+ option :timeout, aliases: ['-t'], default: 10, desc: 'The amount of time waiting for the server process to fork new workers'
14
+
15
+ example [
16
+ 'unicorn config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
17
+ ]
18
+ # rubocop:enable Metrics/LineLength
19
+
20
+ def call(server:, config:, timeout:)
21
+ path = Pathname.new(Dir.pwd).join(config)
22
+ Sam::Servers::Shepherd.new.call(server: server, config: path, timeout: timeout)
23
+ rescue Errors::ProcessNotFound
24
+ warn "#{server} exited"
25
+ exit 1
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module CLI
5
+ module Commands
6
+ class Reaper < Hanami::CLI::Command
7
+ # rubocop:disable Metrics/LineLength
8
+ desc 'Stops the server process'
9
+ argument :server, required: true, values: %w[unicorn puma], desc: 'The application server to be started'
10
+ argument :config, required: true, desc: 'The path to the server configuration file'
11
+
12
+ example [
13
+ 'puma config/puma/development.rb # Stops the server in production mode using the config/puma/development.rb config file'
14
+ ]
15
+ # rubocop:enable Metrics/LineLength
16
+
17
+ def call(server:, config:)
18
+ exit 1 unless server_found(server)
19
+ path = Pathname.new(Dir.pwd).join(config)
20
+ result = Sam::Servers::Predator.new.call(server: server, config: path)
21
+ warn "Hunted one #{server} with pid #{result}"
22
+ rescue Errors::PidfileNotFound
23
+ warn "No running #{server}s found"
24
+ exit 1
25
+ rescue Errors::ConfigfileNotFound => ex
26
+ warn ex.message
27
+ exit 1
28
+ end
29
+
30
+ private
31
+
32
+ def server_found(server)
33
+ gem server
34
+ rescue Gem::LoadError
35
+ warn "#{server} not found. Make sure it's in your Gemfile"
36
+ false
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module CLI
5
+ module Commands
6
+ class Reloader < Hanami::CLI::Command
7
+ desc 'Reloads the code on a running server'
8
+
9
+ # rubocop:disable Metrics/LineLength
10
+ argument :server, required: true, values: %w[unicorn puma], desc: 'The application server to be started'
11
+ argument :config, required: true, desc: 'The path to the server configuration file'
12
+
13
+ option :timeout, aliases: ['-t'], default: 10, desc: 'The amount of time waiting for the server process to fork new workers'
14
+
15
+ example [
16
+ 'puma config/server_settings.rb # Starts the server in test mode using the config/server_settings.rb config file',
17
+ 'unicorn config/server_settings.rb # Starts the server in production mode using the config/server_settings.rb config file'
18
+ ]
19
+ # rubocop:enable Metrics/LineLength
20
+
21
+ def call(server:, config:, timeout:)
22
+ path = Pathname.new(Dir.pwd).join(config)
23
+ Sam::Servers::Cloner.new.call(server: server, config: path, timeout: timeout)
24
+ rescue Errors::ProcessNotFound
25
+ warn "No running #{server}s found"
26
+ exit 1
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module CLI
5
+ module Commands
6
+ class Runner < Hanami::CLI::Command
7
+ desc 'Starts and monitor an already running server'
8
+ # rubocop:disable Metrics/LineLength
9
+ argument :server, required: true, values: %w[unicorn puma], desc: 'The application server to be started'
10
+ argument :config, required: true, desc: 'The path to the server configuration file'
11
+
12
+ option :env, values: %w[production development test staging], default: 'production', desc: 'RACK_ENV to be used', aliases: ['-e']
13
+ option :timeout, aliases: ['-t'], default: 10, desc: 'The amount of time waiting for the server process to fork new workers'
14
+
15
+ example [
16
+ 'puma config/server_settings.rb -e test # Starts and monitors the server in test mode using the config/server_settings.rb config file',
17
+ 'unicorn config/server_settings.rb #Starts and monitors the server in production mode using the config/server_settings.rb config file'
18
+ ]
19
+ # rubocop:enable Metrics/LineLength
20
+
21
+ def call(server:, config:, env:, timeout:)
22
+ Sam::Servers::Breeder.new.call(server: server, config: config, env: env)
23
+ Sam::Servers::Monitor.new.call(server: server, config: config, timeout: timeout)
24
+ rescue Sam::Errors::ProcessNotFound
25
+ warn "#{server} exited"
26
+ exit 1
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hanami/cli'
4
+
5
+ module Sam
6
+ module CLI
7
+ module Commands
8
+ class Spawner < Hanami::CLI::Command
9
+ desc 'Starts the server'
10
+
11
+ # rubocop:disable Metrics/LineLength
12
+ argument :server, required: true, values: %w[unicorn puma], desc: 'The application server to be started'
13
+ argument :config, required: true, desc: 'The path to the server configuration file'
14
+
15
+ option :env, values: %w[production development test staging], default: 'production', desc: 'RACK_ENV to be used', aliases: ['-e']
16
+
17
+ example [
18
+ 'puma config/server_settings.rb -e test # Starts the server in test mode using the config/server_settings.rb config file',
19
+ 'unicorn config/server_settings.rb # Starts the server in production mode using the config/server_settings.rb config file'
20
+ ]
21
+ # rubocop:enable Metrics/LineLength
22
+
23
+ def call(server:, config:, env:)
24
+ path_to_config = Pathname.new(Dir.pwd).join(config)
25
+ Sam::Servers::Breeder.new.call(server: server, config: path_to_config, env: env)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
File without changes
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ gem 'unicorn'
5
+ require 'unicorn'
6
+ require_relative 'servers/unicorn/identifier'
7
+ rescue Gem::LoadError
8
+ warn 'unicorn unavailable'
9
+ end
10
+
11
+ begin
12
+ gem 'puma'
13
+ require 'puma/cli'
14
+ require_relative 'servers/puma/identifier'
15
+ rescue Gem::LoadError
16
+ warn 'puma unavailable'
17
+ end
18
+
19
+ module Sam
20
+ module Servers
21
+ PUMA_PID = ->(config) { Sam::Puma::Identifier.new.call(config) }
22
+ UNICORN_PID = ->(config) { Sam::Unicorn::Identifier.new.call(config) }
23
+ end
24
+ end
25
+
26
+ require_relative 'servers/breeder'
27
+ require_relative 'servers/cloner'
28
+ require_relative 'servers/predator'
29
+ require_relative 'servers/shepherd'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-command'
4
+
5
+ module Sam
6
+ module Servers
7
+ class Breeder
8
+ UNICORN = 'bundle exec unicorn -D -c ${CONF_PATH} -E ${RACK_ENV}'
9
+ PUMA = 'bundle exec puma -C ${CONF_PATH} -e ${RACK_ENV}'
10
+
11
+ def initialize
12
+ @cmd = TTY::Command.new(timeout: 120, printer: :quiet)
13
+ end
14
+
15
+ def call(server:, config:, env: 'production')
16
+ cmdline = self.class.const_get(server.upcase)
17
+ @cmd.run(cmdline, env: { CONF_PATH: config, RACK_ENV: env })
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module Servers
5
+ class Cloner
6
+ PUMA_PID = ->(config) { Sam::Puma::Identifier.new.call(config) }
7
+ UNICORN_PID = ->(config) { Sam::Unicorn::Identifier.new.call(config) }
8
+
9
+ UNICORN_STRATEGY = lambda do |config, timeout = 10|
10
+ pid = UNICORN_PID.call(config)
11
+ Process.kill('USR2', pid)
12
+ sleep timeout
13
+ newpid = UNICORN_PID.call(config)
14
+ Process.kill('QUIT', pid)
15
+ newpid
16
+ end
17
+
18
+ PUMA_STRATEGY = lambda do |config, _timeout|
19
+ settings = (::Puma::Configuration.new({}) { |conf| conf.load config.to_s }).load
20
+ Process.kill(settings.file_options[:preload_app] ? 'USR1' : 'USR2', PUMA_PID.call(config))
21
+ end
22
+
23
+ def call(server:, config:, timeout: 10)
24
+ restart_strategy(server, config, timeout)
25
+ end
26
+
27
+ private
28
+
29
+ def restart_strategy(server, config, timeout)
30
+ self.class.const_get("#{server.upcase}_STRATEGY").call(config, timeout)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module Servers
5
+ class Predator
6
+ PUMA_PID = ->(config) { Sam::Puma::Identifier.new.call(config) }
7
+ UNICORN_PID = ->(config) { Sam::Unicorn::Identifier.new.call(config) }
8
+
9
+ def call(server:, config:)
10
+ @server = server
11
+ @config = config
12
+ Process.kill(signal, pid) && pid
13
+ end
14
+
15
+ private
16
+
17
+ def signal
18
+ @server == 'unicorn' ? 'QUIT' : 'INT'
19
+ end
20
+
21
+ def pid
22
+ @pid ||= self.class.const_get("#{@server.upcase}_PID").call(@config)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'puma/cli'
4
-
5
3
  module Sam
6
4
  module Puma
7
5
  class Identifier
@@ -1,30 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sam
4
- module Puma
4
+ module Servers
5
5
  class Shepherd
6
6
  def initialize
7
- setup_signal_handlers
7
+ trap_signals
8
8
  @restarting = false
9
9
  end
10
10
 
11
- def call(path, timeout: 10)
11
+ def call(server:, config:, timeout: 0.5)
12
+ @config = config
13
+ @server = server
12
14
  @timeout = timeout
13
- @config ||= Pathname.new(Dir.pwd).join(path)
14
15
  loop do
15
- alive?
16
- sleep 1
16
+ Process.kill(0, pid)
17
+ rescue Errno::ESRCH
18
+ raise Errors::ProcessNotFound unless @restarting
17
19
  end
18
20
  end
19
21
 
20
22
  private
21
23
 
22
24
  def pid
23
- @pid ||= Identifier.new.call(@config)
25
+ @pid ||= self.class.const_get("Sam::Servers::#{@server.upcase}_PID").call(@config)
24
26
  end
25
27
 
26
- def setup_signal_handlers
27
- trap('HUP') { reload_puma }
28
+ def trap_signals
29
+ trap('HUP') { reload_server }
28
30
  trap('QUIT') { forward_signal('QUIT') }
29
31
  trap('USR2') { forward_signal('USR2') }
30
32
  trap('TTOU') { forward_signal('TTOU') }
@@ -33,23 +35,17 @@ module Sam
33
35
  trap('INT') { forward_signal('INT') }
34
36
  end
35
37
 
36
- def reload_puma
38
+ def reload_server
37
39
  @restarting = true
38
- @pid = Cloner.new.call(@config, timeout: @timeout)
40
+ @pid = Cloner.new.call(server: @server, config: @config, timeout: @timeout)
39
41
  @restarting = false
40
42
  end
41
43
 
42
44
  def forward_signal(signal)
43
- warn "Sending #{signal} to unicorn #{pid}"
44
45
  Process.kill(signal, pid)
45
46
  end
46
47
 
47
- def alive?
48
- return if @restarting
49
- Process.kill(0, pid)
50
- rescue Errno::ESRCH
51
- raise Errors::ProcessNotFound
52
- end
48
+ def heartbeat; end
53
49
  end
54
50
  end
55
51
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'unicorn'
4
-
5
3
  module Sam
6
4
  module Unicorn
7
5
  class Identifier
data/lib/sam/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sam
4
- VERSION = '0.8.2'
4
+ VERSION = '0.9.0'
5
5
  end
data/sam.gemspec CHANGED
@@ -18,12 +18,12 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
20
  # to allow pushing to a single host or delete this section to allow pushing to any host.
21
- #if spec.respond_to?(:metadata)
21
+ # if spec.respond_to?(:metadata)
22
22
  # spec.metadata['allowed_push_host'] = 'https://gemfury.org'
23
- #else
23
+ # else
24
24
  # raise 'RubyGems 2.0 or newer is required to protect against ' \
25
25
  # 'public gem pushes.'
26
- #end
26
+ # end
27
27
 
28
28
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
29
  f.match(%r{^(test|spec|features)/})
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sam-shepherd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mereghost
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hanami-cli
@@ -258,29 +258,20 @@ files:
258
258
  - exe/sam
259
259
  - lib/sam.rb
260
260
  - lib/sam/cli.rb
261
- - lib/sam/cli/puma.rb
262
- - lib/sam/cli/puma/monitor.rb
263
- - lib/sam/cli/puma/reaper.rb
264
- - lib/sam/cli/puma/spawner.rb
265
- - lib/sam/cli/unicorn.rb
266
- - lib/sam/cli/unicorn/monitor.rb
267
- - lib/sam/cli/unicorn/reaper.rb
268
- - lib/sam/cli/unicorn/reloader.rb
269
- - lib/sam/cli/unicorn/runner.rb
270
- - lib/sam/cli/unicorn/spawner.rb
271
- - lib/sam/cli/version.rb
261
+ - lib/sam/commands/monitor.rb
262
+ - lib/sam/commands/reaper.rb
263
+ - lib/sam/commands/reloader.rb
264
+ - lib/sam/commands/runner.rb
265
+ - lib/sam/commands/spawner.rb
266
+ - lib/sam/commands/version.rb
272
267
  - lib/sam/errors.rb
273
- - lib/sam/puma.rb
274
- - lib/sam/puma/breeder.rb
275
- - lib/sam/puma/identifier.rb
276
- - lib/sam/puma/predator.rb
277
- - lib/sam/puma/shepherd.rb
278
- - lib/sam/unicorn.rb
279
- - lib/sam/unicorn/breeder.rb
280
- - lib/sam/unicorn/cloner.rb
281
- - lib/sam/unicorn/identifier.rb
282
- - lib/sam/unicorn/predator.rb
283
- - lib/sam/unicorn/shepherd.rb
268
+ - lib/sam/servers.rb
269
+ - lib/sam/servers/breeder.rb
270
+ - lib/sam/servers/cloner.rb
271
+ - lib/sam/servers/predator.rb
272
+ - lib/sam/servers/puma/identifier.rb
273
+ - lib/sam/servers/shepherd.rb
274
+ - lib/sam/servers/unicorn/identifier.rb
284
275
  - lib/sam/version.rb
285
276
  - sam.gemspec
286
277
  homepage: https://github.com/vagas/sam
data/lib/sam/cli/puma.rb DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'puma/spawner'
4
- require_relative 'puma/reaper'
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Puma
7
- class Monitor < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Monitor an already running unicorn'
10
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
11
- option :timeout, type: :integer, desc: 'The number of seconds to wait for starting the unicorn server', aliases: ['-t']
12
- example [
13
- '--config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
14
- ]
15
- # rubocop:enable Metrics/LineLength
16
-
17
- def call(config:)
18
- path = Pathname.new(Dir.pwd).join(config)
19
- Sam::Puma::Shepherd.new.call(path)
20
- rescue Errors::ProcessNotFound
21
- warn 'Puma exited'
22
- exit 1
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Puma
7
- class Reaper < Hanami::CLI::Command
8
- NO_MORE_PUMAS = 'Pumas are extinct =('
9
-
10
- # rubocop:disable Metrics/LineLength
11
- desc 'Stops the puma process'
12
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
13
-
14
- example [
15
- '-config config/server_settings.rb Stops the server in production mode using the config/server_settings.rb config file'
16
- ]
17
- # rubocop:enable Metrics/LineLength
18
-
19
- def call(config:)
20
- path = Pathname.new(Dir.pwd).join(config)
21
- result = Sam::Puma::Predator.new.call(path)
22
- warn "Hunted a puma with pid #{result}"
23
- rescue Errors::PidfileNotFound
24
- warn NO_MORE_PUMAS
25
- exit 1
26
- rescue Errors::ConfigfileNotFound => ex
27
- warn ex.message
28
- exit 1
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Puma
7
- class Spawner < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Start the puma process'
10
-
11
- option :environment, values: %w[production development test staging], default: 'production', desc: 'RACK_ENV to be used', aliases: %w[--env -e]
12
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/puma/production.rb', aliases: ['-c']
13
-
14
- example [
15
- '-e development #Starts the server in development mode',
16
- '-e production --config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
17
- ]
18
- # rubocop:enable Metrics/LineLength
19
-
20
- def call(environment:, config:)
21
- config = Pathname.new(Dir.pwd).join(config)
22
- Sam::Puma::Breeder.new.call(environment, config)
23
- warn "We have a newborn puma for environment #{environment} and configuration file: #{config}"
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'unicorn/monitor'
4
- require_relative 'unicorn/reaper'
5
- require_relative 'unicorn/reloader'
6
- require_relative 'unicorn/spawner'
7
- require_relative 'unicorn/runner'
8
-
9
- # Upstart reload sends SIGHUP to the process
10
- # Systemd expects an ExecReload= that syncronously reloads the confs.
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Unicorn
7
- class Monitor < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Monitor an already running unicorn'
10
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
11
- option :timeout, type: :integer, desc: 'The number of seconds to wait for starting the unicorn server', aliases: ['-t']
12
- example [
13
- '--config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
14
- ]
15
- # rubocop:enable Metrics/LineLength
16
-
17
- def call(config:)
18
- path = Pathname.new(Dir.pwd).join(config)
19
- Sam::Unicorn::Shepherd.new.call(path)
20
- rescue Errors::ProcessNotFound
21
- warn 'Unicorn exited'
22
- exit 1
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Unicorn
7
- class Reaper < Hanami::CLI::Command
8
- NO_MORE_UNICORNS = 'Unicorns are already extinct'
9
-
10
- # rubocop:disable Metrics/LineLength
11
- desc 'Stops the unicorn process'
12
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
13
-
14
- example [
15
- '-config config/server_settings.rb Stops the server in production mode using the config/server_settings.rb config file'
16
- ]
17
- # rubocop:enable Metrics/LineLength
18
-
19
- def call(config:)
20
- path = Pathname.new(Dir.pwd).join(config)
21
- result = Sam::Unicorn::Predator.new.call(path)
22
- warn "Hunted unicorn with pid #{result}"
23
- rescue Errors::PidfileNotFound
24
- warn NO_MORE_UNICORNS
25
- exit 1
26
- rescue Errors::ConfigfileNotFound => ex
27
- warn ex.message
28
- exit 1
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Unicorn
7
- class Reloader < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Reloads the unicorn configuration'
10
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
11
-
12
- example [
13
- '--config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
14
- ]
15
- # rubocop:enable Metrics/LineLength
16
-
17
- def call(config)
18
- path = Pathname.new(Dir.pwd).join(config)
19
- Sam::Unicorn::Cloner.new.call(path)
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Unicorn
7
- class Runner < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Monitor an already running unicorn'
10
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
11
- option :environment, values: %w[production development test staging], default: 'production', desc: 'RACK_ENV to be used', aliases: %w[--env -e]
12
- option :timeout, type: :integer, desc: 'The number of seconds to wait for starting the unicorn server', default: 5, aliases: ['-t']
13
- example [
14
- '--config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file',
15
- '-t 20 # Waits for 20 seconds for the master process to fork',
16
- '-e production --config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
17
-
18
- ]
19
- # rubocop:enable Metrics/LineLength
20
-
21
- def call(config:, environment:, timeout:)
22
- path = Pathname.new(Dir.pwd).join(config)
23
- Sam::Unicorn::Breeder.new.call(environment, path)
24
- Sam::Unicorn::Shepherd.new.call(path, timeout: Integer(timeout))
25
- rescue Errors::ProcessNotFound
26
- warn 'Unicorn seems dead.'
27
- exit 1
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module CLI
5
- module Commands
6
- module Unicorn
7
- class Spawner < Hanami::CLI::Command
8
- # rubocop:disable Metrics/LineLength
9
- desc 'Start the unicorn process'
10
-
11
- option :environment, values: %w[production development test staging], default: 'production', desc: 'RACK_ENV to be used', aliases: %w[--env -e]
12
- option :config, type: :path, desc: 'The path to the server configuration', default: 'config/unicorn/production.rb', aliases: ['-c']
13
-
14
- example [
15
- '-e development #Starts the server in development mode',
16
- '-e production --config=config/server_settings.rb #Starts the server in production mode using the config/server_settings.rb config file'
17
- ]
18
- # rubocop:enable Metrics/LineLength
19
-
20
- def call(environment:, config:)
21
- config = Pathname.new(Dir.pwd).join(config)
22
- Sam::Unicorn::Breeder.new.call(environment, config)
23
- warn "We have a newborn unicorn for environment #{environment} and configuration file: #{config}"
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
data/lib/sam/puma.rb DELETED
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'puma/identifier'
4
- require_relative 'puma/breeder'
5
- require_relative 'puma/predator'
6
- require_relative 'puma/shepherd'
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tty-command'
4
-
5
- module Sam
6
- module Puma
7
- class Breeder
8
- COMMAND = 'bundle exec puma -C ${CONF_PATH} -e ${RACK_ENV}'
9
-
10
- def call(env, config)
11
- cmd = TTY::Command.new(timeout: 120)
12
- cmd.run(COMMAND, env: { CONF_PATH: config, RACK_ENV: env })
13
- end
14
- end
15
- end
16
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module Puma
5
- class Predator
6
- def call(config)
7
- pid = Sam::Puma::Identifier.new.call(config)
8
- Process.kill('INT', pid) && pid
9
- end
10
- end
11
- end
12
- end
data/lib/sam/unicorn.rb DELETED
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'unicorn/identifier'
4
- require_relative 'unicorn/breeder'
5
- require_relative 'unicorn/predator'
6
- require_relative 'unicorn/cloner'
7
- require_relative 'unicorn/shepherd'
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tty-command'
4
-
5
- module Sam
6
- module Unicorn
7
- class Breeder
8
- COMMAND = 'bundle exec unicorn -D -c ${CONF_PATH} -E ${RACK_ENV}'
9
-
10
- def call(env, config)
11
- cmd = TTY::Command.new(timeout: 120)
12
- cmd.run(COMMAND, env: { CONF_PATH: config, RACK_ENV: env })
13
- end
14
- end
15
- end
16
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module Unicorn
5
- class Cloner
6
- def call(config, timeout: 10)
7
- pid = Identifier.new.call(config)
8
- # warn "Cloning unicorn tagged #{pid}"
9
- Process.kill('USR2', pid)
10
- # warn "Waiting #{timeout} seconds for clone process to conclude..."
11
- sleep timeout
12
- newpid = Identifier.new.call(config)
13
- # warn "New unicorn cloned with tag #{newpid}. Reaping it's predecessor..."
14
- Process.kill('QUIT', pid)
15
- newpid
16
- # warn 'No one suspects a thing.'
17
- rescue Errno::ESRCH
18
- raise Errors::ProcessNotFound, "No process with PID #{pid} found"
19
- end
20
- end
21
- end
22
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module Unicorn
5
- class Predator
6
- def call(config)
7
- pid = Sam::Unicorn::Identifier.new.call(config)
8
- Process.kill('QUIT', pid) && pid
9
- end
10
- end
11
- end
12
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Sam
4
- module Unicorn
5
- class Shepherd
6
- def initialize
7
- setup_signal_handlers
8
- @restarting = false
9
- end
10
-
11
- def call(path, timeout: 10)
12
- @timeout = timeout
13
- @config ||= Pathname.new(Dir.pwd).join(path)
14
- loop do
15
- alive?
16
- sleep 1
17
- end
18
- end
19
-
20
- private
21
-
22
- def pid
23
- @pid ||= Identifier.new.call(@config)
24
- end
25
-
26
- def setup_signal_handlers
27
- trap('HUP') { reload_unicorn }
28
- trap('QUIT') { forward_signal('QUIT') }
29
- trap('USR2') { forward_signal('USR2') }
30
- trap('TTOU') { forward_signal('TTOU') }
31
- trap('TTIN') { forward_signal('TTIN') }
32
- trap('TERM') { forward_signal('QUIT') }
33
- trap('INT') { forward_signal('INT') }
34
- end
35
-
36
- def reload_unicorn
37
- @restarting = true
38
- @pid = Cloner.new.call(@config, timeout: @timeout)
39
- @restarting = false
40
- end
41
-
42
- def forward_signal(signal)
43
- warn "Sending #{signal} to unicorn #{pid}"
44
- Process.kill(signal, pid)
45
- end
46
-
47
- def alive?
48
- return if @restarting
49
- Process.kill(0, pid)
50
- rescue Errno::ESRCH
51
- raise Errors::ProcessNotFound
52
- end
53
- end
54
- end
55
- end