rhapr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -cfs
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rhapr.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec'
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :release => :spec
8
+
9
+ desc 'Run Specs'
10
+ RSpec::Core::RakeTask.new(:spec) do |spec|
11
+ spec.pattern = 'spec/**/*_spec.rb'
12
+ spec.verbose = true
13
+ spec.rspec_opts = ['--color']
14
+ end
data/bin/rhapr ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rhapr'
data/lib/rhapr.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rhapr/version'
2
+ require 'rhapr/environment'
3
+
4
+ module Rhapr
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,87 @@
1
+ module Rhapr
2
+ module Environment
3
+ attr_accessor :haproxy_pid, :config_path, :config, :exec
4
+
5
+ # @return [String] The path to the HAProxy configuration file. Set the ENV variable $HAPROXY_CONFIG to override defaults
6
+ def config_path
7
+ return(@config_path) if @config_path
8
+
9
+ if ENV['HAPROXY_CONFIG']
10
+ @config_path = ENV['HAPROXY_CONFIG']
11
+ else
12
+ %w{/etc/haproxy/haproxy.cfg /etc/haproxy.cfg /usr/local/etc/haproxy.cfg}.each {|cfg|
13
+ next unless File.exists?(cfg)
14
+
15
+ @config_path = cfg
16
+ }
17
+ end
18
+
19
+ return(@config_path)
20
+ end
21
+
22
+ # @return [String] The raw contents of the HAProxy configuration file.
23
+ def config
24
+ @config ||= begin
25
+ File.read(config_path)
26
+ rescue Errno::ENOENT => e
27
+ raise RuntimeError.new("Error openning file '#{config_path}'. Exception from File.read: #{e.exception}")
28
+ end
29
+ end
30
+
31
+ # @return [true, false] Whether or not the HAProxy executable can be found.
32
+ # @see Rhapr::Environment#exec
33
+ def has_exec?
34
+ !exec.nil?
35
+ end
36
+
37
+ # @return [String, nil] The path to the HAProxy executable will be returned, if found. Set ENV variable $HAPROXY_BIN to override
38
+ def exec
39
+ return(@exec) if @exec
40
+
41
+ @exec = ENV['HAPROXY_BIN']
42
+ @exec ||= `which haproxy`
43
+
44
+ if @exec.empty?
45
+ begin
46
+ `haproxy -v`
47
+ @exec = 'haproxy'
48
+ rescue Errno::ENOENT => e
49
+ @exec = nil
50
+ end
51
+ end
52
+
53
+ return(@exec)
54
+ end
55
+
56
+ # @return [String] The path to the HAProxy stats socket.
57
+ # @raise [RuntimeError] Raised if no stats socket has been specified, in the HAProxy configuration.
58
+ # @todo: Should there be an ENV var for this? Perhaps allow config-less runs of rhapr?
59
+ def socket
60
+ @socket ||= begin
61
+ config.match /stats\s+socket\s+([^\s]*)/
62
+ $1 || raise(RuntimeError.new "Expecting 'stats socket <UNIX_socket_path>' in #{config_path}")
63
+ end
64
+ end
65
+
66
+ # @return [String] Returns the path to the pidfile, specified in the HAProxy configuration. Returns an assumption, if not found.
67
+ # @todo: Should there even be an assumption? Does HAProxy create a pid file, if not told to by the configuration?
68
+ # @todo: Should there be an ENV var for this? Perhaps allow config-less runs of rhapr?
69
+ def pid
70
+ @pid ||= begin
71
+ config.match /pidfile ([^\s]*)/
72
+ @pid = $1 || '/var/run/haproxy.pid'
73
+ end
74
+ end
75
+
76
+ # @return [String, nil] Returns the PID of HAProxy as a string, if running. Nil otherwise.
77
+ # @todo: Look for something other than pidof, for searching the process list.
78
+ # Could read from the pid file, but there's potential that it will go stale.
79
+ def check_running
80
+ pidof = `pidof haproxy`
81
+ pidof.strip!
82
+
83
+ return pidof unless pidof.empty?
84
+ end
85
+ alias :pidof :check_running
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Rhapr
2
+ VERSION = '0.0.1'
3
+ end
data/rhapr.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'rhapr/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rhapr'
7
+ s.version = Rhapr::VERSION
8
+ s.authors = ['Scott Gonyea']
9
+ s.email = ['me@sgonyea.com']
10
+ s.homepage = 'https://github.com/sgonyea/rhapr'
11
+ s.summary = %q{Rhapr wraps around HAProxy}
12
+ s.description = %q{Rhapr is a ruby lib that wraps around HAProxy, enabling you to sanely decomission a process.}
13
+
14
+ s.add_dependency 'yard', '~>0.6'
15
+
16
+ s.add_development_dependency 'rspec', '~>2.4'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+ end
@@ -0,0 +1,6 @@
1
+ global
2
+ daemon
3
+ maxconn 100
4
+ quiet
5
+ pidfile /some/other/run/haproxy.pid
6
+ stats socket /tmp/haproxy
@@ -0,0 +1,4 @@
1
+ global
2
+ daemon
3
+ maxconn 100
4
+ quiet
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ IGNORE = /\.(gitmodules|png$|tar$|gz$|rbc$|gem$|pdf$)/
4
+
5
+ describe 'The application itself' do
6
+ it 'has no malformed whitespace' do
7
+ files = `git ls-files`.split("\n").select {|fn| fn !~ IGNORE}
8
+
9
+ files.should be_well_formed
10
+ end
11
+ end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rhapr::Environment do
4
+ class EnvTest
5
+ include Rhapr::Environment
6
+ end
7
+
8
+ before(:each) do
9
+ @env_test = EnvTest.new
10
+ end
11
+
12
+ describe '#config_path' do
13
+ it 'should set to the ENV variable, if present' do
14
+ ENV['HAPROXY_CONFIG'] = '/some/path.cfg'
15
+
16
+ @env_test.config_path.should == '/some/path.cfg'
17
+
18
+ # Clean up.
19
+ ENV.delete 'HAPROXY_CONFIG'
20
+ end
21
+
22
+ it 'should go down a list of pre-defined file names' do
23
+ File.stub!(:exists?).and_return(false)
24
+ File.should_receive(:exists?).with('/etc/haproxy.cfg').and_return(true)
25
+
26
+ @env_test.config_path.should == '/etc/haproxy.cfg'
27
+ end
28
+
29
+ it 'should be nil if config files do not exist and $HAPROXY_CONFIG is not set' do
30
+ File.stub!(:exists?).and_return(false)
31
+ @env_test.config_path.should be_nil
32
+ end
33
+ end
34
+
35
+ describe '#config' do
36
+ before(:each) do
37
+ File.stub!(:exists?).and_return(false)
38
+ File.should_receive(:exists?).with('/etc/haproxy.cfg').and_return(true)
39
+ end
40
+
41
+ it 'should raise an exception if it cannot read from #config_path' do
42
+ File.should_receive(:read).and_raise(Errno::ENOENT)
43
+
44
+ lambda {
45
+ @env_test.config
46
+ }.should raise_error(RuntimeError)
47
+ end
48
+
49
+ it 'should read and return the contents of a file' do
50
+ File.should_receive(:read).and_return { "I can haz cfg ?\n" }
51
+
52
+ @env_test.config.should == "I can haz cfg ?\n"
53
+ end
54
+ end
55
+
56
+ describe '#exec' do
57
+ it 'should set to the ENV variable, if present' do
58
+ ENV['HAPROXY_BIN'] = '/usr/local/bin/haproxy'
59
+
60
+ @env_test.exec.should == '/usr/local/bin/haproxy'
61
+
62
+ # Clean up.
63
+ ENV.delete 'HAPROXY_BIN'
64
+ end
65
+
66
+ it 'should call out to the `which` command to find haproxy, if the ENV var is not set' do
67
+ @env_test.should_receive(:`).with('which haproxy').and_return('/opt/bin/haproxy')
68
+
69
+ @env_test.exec.should == '/opt/bin/haproxy'
70
+ end
71
+
72
+ it 'should call out to haproxy directly, if all else fails' do
73
+ @env_test.should_receive(:`).with('which haproxy').and_return('')
74
+ @env_test.should_receive(:`).with('haproxy -v').and_return("HA-Proxy version 1.4.15 2011/04/08\nCopyright 2000-2010 Willy Tarreau <w@1wt.eu>\n\n")
75
+
76
+ @env_test.exec.should == 'haproxy'
77
+ end
78
+
79
+ it 'should be nil if none of the above worked' do
80
+ @env_test.should_receive(:`).with('which haproxy').and_return('')
81
+ @env_test.should_receive(:`).with('haproxy -v').and_raise(Errno::ENOENT)
82
+
83
+ @env_test.exec.should be_nil
84
+ end
85
+ end
86
+
87
+ describe '#socket' do
88
+ it 'should parse out the io socket from the config file' do
89
+ @env_test.should_receive(:config).and_return { config_for(:basic_haproxy) }
90
+
91
+ @env_test.socket.should == '/tmp/haproxy'
92
+ end
93
+
94
+ it 'should raise an error if it cannot derive an io socket from the config file' do
95
+ @env_test.should_receive(:config).and_return { config_for(:crappy_haproxy) }
96
+
97
+ lambda {
98
+ @env_test.socket
99
+ }.should raise_error(RuntimeError)
100
+ end
101
+ end
102
+
103
+ describe '#pid' do
104
+ it 'should parse out the pidfile from the config file' do
105
+ @env_test.should_receive(:config).and_return { config_for(:basic_haproxy) }
106
+
107
+ @env_test.pid.should == '/some/other/run/haproxy.pid'
108
+ end
109
+
110
+ it 'should return a default path if it cannot derive an io socket from the config file' do
111
+ @env_test.should_receive(:config).and_return { config_for(:crappy_haproxy) }
112
+
113
+ @env_test.pid.should == '/var/run/haproxy.pid'
114
+ end
115
+ end
116
+
117
+ describe '#check_running, #pidof' do
118
+ pending 'TBD'
119
+ end
120
+ end
@@ -0,0 +1,11 @@
1
+ require 'bundler/setup'
2
+
3
+ Bundler.require :default
4
+ Bundler.require :development
5
+
6
+ Dir[ Bundler.root.join('spec/support/**/*.rb') ].each{|f| require f}
7
+
8
+ RSpec.configure do |c|
9
+ c.include CustomMatchers
10
+ c.include ConfigFixtures
11
+ end
@@ -0,0 +1,53 @@
1
+ require 'bundler'
2
+
3
+ module ConfigFixtures
4
+ attr_reader :config_fixtures
5
+
6
+ # @param [Symbol]
7
+ # @return [String]
8
+ def fixture_for(sym)
9
+ config_fixtures[sym][:fixture]
10
+ end
11
+ alias :config_for :fixture_for
12
+
13
+ def path_for(sym)
14
+ config_fixtures[sym][:path]
15
+ end
16
+
17
+ # @see ConfigFixtures#create_fixture_hash
18
+ def config_fixtures
19
+ @config_fixtures ||= begin
20
+ hash = Hash.new {|k,v| k[v] = {}}
21
+ hash.merge!(create_fixture_hash)
22
+ end
23
+ end
24
+
25
+ # @return [Hash{Symbol => String}]
26
+ def create_fixture_hash
27
+ Hash[ find_fixtures.map{|fpath| map_fixture(fpath) } ]
28
+ end
29
+
30
+ # @param [String]
31
+ # @return [Array<Symbol, String>]
32
+ def map_fixture(fpath)
33
+ [symbolize_filename(fpath), {:path => fpath, :fixture => read_file(fpath)}]
34
+ end
35
+
36
+ # @return [Array<String>]
37
+ def find_fixtures
38
+ Dir.glob Bundler.root.join('spec/config_fixtures/**.cfg')
39
+ end
40
+
41
+ # @param [String]
42
+ # @return [Symbol]
43
+ def symbolize_filename(fpath)
44
+ fname = File.basename(fpath)
45
+ fname.split(/\W/).shift.to_sym
46
+ end
47
+
48
+ # @param [String]
49
+ # @return [String]
50
+ def read_file(fpath)
51
+ File.read(fpath)
52
+ end
53
+ end
@@ -0,0 +1,44 @@
1
+ module CustomMatchers
2
+ class BeWellFormed
3
+ def matches?(files)
4
+ @errors = files.map {|filename|
5
+ [
6
+ check_for_tabs(filename),
7
+ excessive_spacing(filename),
8
+ newline_precedes_eof(filename)
9
+ ]
10
+ }.flatten.compact
11
+
12
+ @errors.empty?
13
+ end
14
+
15
+ def failure_message_for_should
16
+ @errors.join("\n")
17
+ end
18
+
19
+ private
20
+ def check_for_tabs(filename)
21
+ bad_lines = File.readlines(filename).each_with_index.map do |line, line_no|
22
+ line_no + 1 if line["\t"] and line !~ /^\s+#.*\s+\n$/
23
+ end.flatten.compact
24
+
25
+ "#{filename} has tab characters on lines #{bad_lines.join(', ')}" if bad_lines.any?
26
+ end
27
+
28
+ def excessive_spacing(filename)
29
+ bad_lines = File.readlines(filename).each_with_index.map do |line, line_no|
30
+ line_no + 1 if line =~ /\s+\n$/ and line !~ /^\s+#.*\s+\n$/
31
+ end.flatten.compact
32
+
33
+ "#{filename} has spaces on the EOL on lines #{bad_lines.join(', ')}" if bad_lines.any?
34
+ end
35
+
36
+ def newline_precedes_eof(filename)
37
+ "#{filename} does not have a newline (\\n) before EOF" if File.read(filename) !~ /\n$/
38
+ end
39
+ end
40
+
41
+ def be_well_formed
42
+ BeWellFormed.new
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rhapr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Scott Gonyea
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-01 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: yard
16
+ requirement: &2165531120 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.6'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2165531120
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2165523840 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.4'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2165523840
36
+ description: Rhapr is a ruby lib that wraps around HAProxy, enabling you to sanely
37
+ decomission a process.
38
+ email:
39
+ - me@sgonyea.com
40
+ executables:
41
+ - rhapr
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - .rspec
47
+ - Gemfile
48
+ - Rakefile
49
+ - bin/rhapr
50
+ - lib/rhapr.rb
51
+ - lib/rhapr/environment.rb
52
+ - lib/rhapr/version.rb
53
+ - rhapr.gemspec
54
+ - spec/config_fixtures/basic_haproxy.cfg
55
+ - spec/config_fixtures/crappy_haproxy.cfg
56
+ - spec/quality_spec.rb
57
+ - spec/rhapr/environment_spec.rb
58
+ - spec/spec_helper.rb
59
+ - spec/support/config_fixtures.rb
60
+ - spec/support/custom_matchers.rb
61
+ homepage: https://github.com/sgonyea/rhapr
62
+ licenses: []
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Rhapr wraps around HAProxy
85
+ test_files:
86
+ - spec/config_fixtures/basic_haproxy.cfg
87
+ - spec/config_fixtures/crappy_haproxy.cfg
88
+ - spec/quality_spec.rb
89
+ - spec/rhapr/environment_spec.rb
90
+ - spec/spec_helper.rb
91
+ - spec/support/config_fixtures.rb
92
+ - spec/support/custom_matchers.rb