haproxy 0.0.1

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,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in haproxy.gemspec
4
+ gemspec
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ # -*- mode: ruby; encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "haproxy/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "haproxy"
7
+ s.version = Haproxy::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Leandro López (inkel)"]
10
+ s.email = ["inkel.ar@gmail.com"]
11
+ s.homepage = "http://rubygems.org/gems/haproxy"
12
+ s.summary = %q{HAProxy interface for reading statistics or managing servers (requires HAProxy 1.4+)}
13
+ s.description = %q{This gem is intended for use as a HAProxy interface when you need to read statistics or if you like to manage proxies thru Ruby}
14
+
15
+ s.rubyforge_project = "haproxy"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,21 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ require 'uri'
5
+ Dir["#{libdir}/haproxy/*.rb"].each do |file|
6
+ require file
7
+ end
8
+
9
+ module HAProxy
10
+
11
+ def self.read_stats(from)
12
+ uri = URI.parse(from)
13
+
14
+ if uri.is_a?(URI::Generic) and File.socket?(uri.path)
15
+ HAProxy::SocketReader.new(uri.path)
16
+ else
17
+ raise NotImplementedError, "Currently only sockets are implemented"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,32 @@
1
+ module HAProxy
2
+ class CSVParser
3
+
4
+ # Uses CSV header from HAProxy 1.5, which is backwards compatible
5
+ COLUMNS = "pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt".split(",").map(&:to_sym)
6
+ LIMIT = COLUMNS.length
7
+
8
+ def self.parse(line)
9
+ line.strip!
10
+ unless line.start_with? "#"
11
+ data = line.split(',')
12
+ pxname = data.shift
13
+
14
+ stats = { :pxname => pxname }
15
+
16
+ data.each_with_index do |value, i|
17
+ if i < LIMIT
18
+ stats[COLUMNS[i + 1]] = value
19
+ else
20
+ stats[:extra] = Array.new if stats[:extra].nil?
21
+ stats[:extra] << value
22
+ end
23
+ end
24
+
25
+ stats
26
+ else
27
+ raise ArgumentError, "Line is a comment"
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,93 @@
1
+ require 'socket'
2
+ require 'haproxy/stats_reader'
3
+ require 'haproxy/csv_parser'
4
+
5
+ module HAProxy
6
+ class SocketReader < HAProxy::StatsReader
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def info
13
+ returning({}) do |info|
14
+ send_cmd "show info" do |line|
15
+ key, value = line.split(': ')
16
+ info[key.downcase.gsub('-', '_').to_sym] = value
17
+ end
18
+ end
19
+ end
20
+
21
+ def errors
22
+ returning("") do |errors|
23
+ send_cmd "show errors" do |line|
24
+ errors << line
25
+ end
26
+ end
27
+ end
28
+
29
+ def sessions
30
+ returning([]) do |sess|
31
+ send_cmd "show sess" do |line|
32
+ sess << line
33
+ end
34
+ end
35
+ end
36
+
37
+ TYPES = {
38
+ :frontend => 1,
39
+ :backend => 2,
40
+ :server => 4
41
+ }
42
+
43
+ def stats(types=[:all], options={})
44
+ params = {
45
+ :proxy => :all,
46
+ :server => :all
47
+ }.merge(options)
48
+
49
+ params[:proxy] = "-1" if params[:proxy].eql?(:all)
50
+ params[:server] = "-1" if params[:server].eql?(:all)
51
+
52
+ types = [types] unless types.is_a?(Array)
53
+
54
+ params[:type] = case
55
+ when types.eql?([:all])
56
+ "-1"
57
+ else
58
+ types.map{ |type| TYPES[type] }.inject(:+)
59
+ end
60
+
61
+ cmd = "show stat #{params[:proxy]} #{params[:type]} #{params[:server]}"
62
+
63
+ returning([]) do |stats|
64
+ send_cmd(cmd) do |line|
65
+ stats << CSVParser.parse(line) unless line.start_with?('#')
66
+ end
67
+ end
68
+ end
69
+
70
+ def frontends
71
+ stats :frontend, :proxy => :all, :server => :all
72
+ end
73
+
74
+ def backends
75
+ stats :frontend, :proxy => :all, :server => :all
76
+ end
77
+
78
+ def servers
79
+ stats :server, :proxy => :all, :server => :all
80
+ end
81
+
82
+ protected
83
+
84
+ def send_cmd(cmd, &block)
85
+ socket = UNIXSocket.new(@path)
86
+ socket.puts(cmd)
87
+ socket.each do |line|
88
+ yield(line.strip)
89
+ end
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,51 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ module HAProxy
5
+
6
+ class StatsReader
7
+
8
+ def info
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def errors
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def sessions
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def stats
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def frontends
25
+ raise NotImplementedError
26
+ end
27
+
28
+ def backends
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def servers
33
+ raise NotImplementedError
34
+ end
35
+
36
+ protected
37
+
38
+ # Borrowed from Rails 3
39
+ def returning(value)
40
+ yield(value)
41
+ value
42
+ end
43
+
44
+ private
45
+
46
+ def initialize
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,3 @@
1
+ module Haproxy
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: haproxy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - "Leandro L\xC3\xB3pez (inkel)"
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-29 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: This gem is intended for use as a HAProxy interface when you need to read statistics or if you like to manage proxies thru Ruby
22
+ email:
23
+ - inkel.ar@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - Rakefile
34
+ - haproxy.gemspec
35
+ - lib/haproxy.rb
36
+ - lib/haproxy/csv_parser.rb
37
+ - lib/haproxy/socket_reader.rb
38
+ - lib/haproxy/stats_reader.rb
39
+ - lib/haproxy/version.rb
40
+ has_rdoc: true
41
+ homepage: http://rubygems.org/gems/haproxy
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project: haproxy
68
+ rubygems_version: 1.3.7
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: HAProxy interface for reading statistics or managing servers (requires HAProxy 1.4+)
72
+ test_files: []
73
+