sam-shepherd 0.8.2

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.
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'sam'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/sam ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'sam'
6
+
7
+ Hanami::CLI.new(Sam::CLI::Commands).call
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sam/version'
4
+ require 'sam/errors'
5
+ require 'sam/cli'
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hanami/cli'
4
+
5
+ module Sam
6
+ module CLI
7
+ module Commands
8
+ extend Hanami::CLI::Registry
9
+
10
+ require_relative 'cli/version'
11
+
12
+ 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
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'puma/spawner'
4
+ require_relative 'puma/reaper'
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,10 @@
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.
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,33 @@
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
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module CLI
5
+ module Commands
6
+ class Version < Hanami::CLI::Command
7
+ desc 'Prints the current Sam version'
8
+
9
+ def call(*)
10
+ puts Sam::VERSION
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sam
4
+ module Errors
5
+ class PidfileNotFound < StandardError
6
+ end
7
+
8
+ class ConfigfileNotFound < StandardError
9
+ end
10
+
11
+ class ProcessNotFound < Errno::ESRCH
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
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'
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/cli'
4
+
5
+ module Sam
6
+ module Puma
7
+ class Identifier
8
+ def call(config_file)
9
+ setup_configurator(config_file)
10
+ Integer(read_pidfile)
11
+ end
12
+
13
+ private
14
+
15
+ def configuration
16
+ setup_configurator unless @configurator
17
+ @configurator
18
+ end
19
+
20
+ def setup_configurator(config_file)
21
+ @configurator ||= (::Puma::Configuration.new({}) { |config| config.load config_file.to_s }).load
22
+ rescue Errno::ENOENT
23
+ raise Errors::ConfigfileNotFound, "File #{config_file} not found"
24
+ end
25
+
26
+ def read_pidfile
27
+ IO.readlines(@configurator.fetch(:pidfile)).join.chomp
28
+ rescue Errno::ENOENT # frozen_string_literal: true
29
+ raise Errors::PidfileNotFound, "PID File #{@configurator.fetch(:pidfile)} not found"
30
+ end
31
+ end
32
+ end
33
+ end