haproxy_manager 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2@haproxy_man --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Run all RSpec tests"
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
10
+ task :test => [:spec]
data/Readme.md ADDED
@@ -0,0 +1,21 @@
1
+ HaProxy Manager
2
+ ===============
3
+
4
+ Haproxy provides ways to add and remove servers on the fly and a lot of other things. This gem lets you use that via a nice ruby API, so that it can be used in applications for deployments testing and gathering statistics.
5
+
6
+ This was extracted out of our rolling deployment scheme.
7
+
8
+ Prerequsites
9
+ =============
10
+
11
+ For this to work haproxy
12
+
13
+ * Version 1.4 and above
14
+
15
+ * Should be running with the following configuration.
16
+
17
+ `stats socket /home/ubuntu/haproxysock level admin`
18
+
19
+ It means that haproxy will open a socket at /home/ubuntu/haproxysock. You can specify the level. We use `admin`.
20
+
21
+
@@ -0,0 +1,27 @@
1
+ require File.expand_path("../lib/haproxy_manager/version.rb", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "haproxy_manager"
5
+ s.version = HAProxyManager::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Sreekanth(sreeix)", "Smita Bhat(sbhat)"]
8
+ s.email = ["gabbar@activesphere.com"]
9
+ s.homepage = "https://github.com/althea/haproxy-manager"
10
+ s.summary = 'HAproxy manager for controlling haproxy'
11
+ s.description = 'Manages haproxy farms and servers'
12
+
13
+ s.rubyforge_project = "haproxy_manager"
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.default_executable = "couchup"
18
+
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency 'couchrest'
22
+
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'rake'
25
+ s.add_development_dependency 'mocha'
26
+ s.add_development_dependency 'bundler'
27
+ end
@@ -0,0 +1 @@
1
+ require 'haproxy_manager/instance'
@@ -0,0 +1,64 @@
1
+ require 'socket'
2
+ module HAProxyManager
3
+ class Instance
4
+ def initialize(socket)
5
+ @socket = HAPSocket.new(socket)
6
+ @print_response = Proc.new {|response| puts response}
7
+ backends = @socket.execute( "show stat -1 4 -1" )[1..-1].collect{|item| item.split(",")[0..1]}
8
+ @backends = backends.inject({}){|hash, items| (hash[items[0]] ||=[]) << items[1]; hash}
9
+ end
10
+
11
+ # Diables a server in the server in a backend for maintenance.
12
+ # If backend is not specified then all the backends in which the serverid exists are disabled.
13
+
14
+ def disable(serverid, backend = nil)
15
+ all_servers(serverid, backend).each do |item|
16
+ @socket.exec "disable server #{item[0]}/#{item[1]}", &@print_response
17
+ end
18
+ end
19
+
20
+ # Enables a server in the server in a backend.
21
+ # If backend is not specified then all the backends in which the serverid exists are enabled.
22
+ def enable(serverid, backend = nil)
23
+ all_servers(serverid, backend).each do |item|
24
+ @socket.exec "enable server #{item[0]}/#{item[1]}", &@print_response
25
+ end
26
+ end
27
+
28
+ def backends
29
+ @backends.keys
30
+ end
31
+
32
+ def servers(backend = nil)
33
+ backend.nil? ? @backends.values.flatten : @backends[backend]
34
+ end
35
+
36
+ private
37
+ def all_servers(serverid, backend)
38
+ if(backend.nil?)
39
+ items = @backends.collect{|a, b| [a, serverid] if b.include?(serverid)}.compact
40
+ else
41
+ items = [[backend, serverid]]
42
+ end
43
+ end
44
+ end
45
+
46
+ class HAPSocket
47
+ def initialize(file)
48
+ @file = file
49
+ end
50
+
51
+ def execute(cmd, &block)
52
+ socket = UNIXSocket.new(@file)
53
+ socket.write("#{cmd};")
54
+ response = []
55
+ socket.each do |line|
56
+ data = line.strip
57
+ next if data.empty?
58
+ response << data
59
+ end
60
+ yield response if block_given?
61
+ response
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module HAProxyManager
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ module HAProxyManager
3
+ describe Instance do
4
+ before(:all) do
5
+ @stat_response = ["# 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,",
6
+ "foo-farm,preprod-app,0,9,0,60,60,137789,34510620,3221358490,,0,,3,720,0,0,UP,12,1,0,562,143,45394,255790,,1,1,1,,113890,,2,0,,88,L7OK,200,20,0,134660,2028,147,230,0,0,,,,20,6,",
7
+ "foo-farm,preprod-bg,0,0,0,3,30,31,14333,380028,,0,,0,9,4,2,DOWN,5,1,0,4,10,2453494,4518397,,1,1,2,,6,,2,0,,2,L4CON,,0,0,16,0,0,0,0,0,,,,1,0,",
8
+ "foo-farm,preprod-test,0,0,0,0,30,0,0,0,,0,,0,0,0,0,DOWN,5,1,0,0,1,5017534,5017534,,1,1,3,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0,",
9
+ "foo-https-farm,preprod-app,0,0,0,3,60,6219,2577996,71804141,,0,,1,30,3,0,UP,12,1,0,559,137,45394,255774,,1,2,1,,1948,,2,0,,2,L7OK,200,109,0,5912,181,11,29,0,0,,,,501,0,",
10
+ "foo-https-farm,preprod-bg,0,0,0,0,30,0,0,0,,0,,0,0,0,0,DOWN,5,1,0,4,4,2453494,4518368,,1,2,2,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0,",
11
+ "foo-https-farm,preprod-test,0,0,0,0,30,0,0,0,,0,,0,0,0,0,DOWN,5,1,0,0,1,5017532,5017532,,1,2,3,,0,,2,0,,0,L4CON,,0,0,0,0,0,0,0,0,,,,0,0,"]
12
+ end
13
+ before(:each) do
14
+ HAPSocket.any_instance.expects(:execute).returns(@stat_response)
15
+ @instance = Instance.new("foo")
16
+ end
17
+
18
+ describe "creation" do
19
+ it "parses stats and lists backends" do
20
+ @instance.backends.size.should == 2
21
+ @instance.backends.should include "foo-farm"
22
+ @instance.backends.should include "foo-https-farm"
23
+ end
24
+
25
+ it "parses stats and lists servers" do
26
+ @instance.servers('foo-farm').size.should == 3
27
+ end
28
+ it "understands servers without backend are all servers" do
29
+ @instance.servers.size.should == 6
30
+ @instance.servers.should include "preprod-bg"
31
+ @instance.servers.should include "preprod-test"
32
+ end
33
+ end
34
+
35
+ describe "enables servers" do
36
+ it "enables a server" do
37
+ HAPSocket.any_instance.expects(:exec).with('enable server foo-farm/preprod-bg')
38
+ @instance.enable("preprod-bg", "foo-farm")
39
+ end
40
+
41
+ it "enables a all servers in multiple backends" do
42
+ HAPSocket.any_instance.expects(:exec).with('enable server foo-farm/preprod-bg')
43
+ HAPSocket.any_instance.expects(:exec).with('enable server foo-https-farm/preprod-bg')
44
+ @instance.enable("preprod-bg")
45
+ end
46
+
47
+ it "disables a server" do
48
+ HAPSocket.any_instance.expects(:exec).with('disable server foo-farm/preprod-bg')
49
+ @instance.disable("preprod-bg", "foo-farm")
50
+ end
51
+
52
+ it "disables a server in all backends" do
53
+ HAPSocket.any_instance.expects(:exec).with('disable server foo-farm/preprod-bg')
54
+ HAPSocket.any_instance.expects(:exec).with('disable server foo-https-farm/preprod-bg')
55
+ @instance.disable("preprod-bg")
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ require 'rspec'
2
+ require 'mocha'
3
+ require File.expand_path('../../lib/haproxy_manager', __FILE__)
4
+
5
+ RSpec.configure do |config|
6
+ config.mock_framework = :mocha
7
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: haproxy_manager
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sreekanth(sreeix)
9
+ - Smita Bhat(sbhat)
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: couchrest
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: mocha
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: bundler
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ description: Manages haproxy farms and servers
96
+ email:
97
+ - gabbar@activesphere.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .rvmrc
104
+ - Gemfile
105
+ - Rakefile
106
+ - Readme.md
107
+ - haproxy_manager.gemspec
108
+ - lib/haproxy_manager.rb
109
+ - lib/haproxy_manager/instance.rb
110
+ - lib/haproxy_manager/version.rb
111
+ - spec/instance_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/althea/haproxy-manager
114
+ licenses: []
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ segments:
126
+ - 0
127
+ hash: 1069670280984611263
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ segments:
135
+ - 0
136
+ hash: 1069670280984611263
137
+ requirements: []
138
+ rubyforge_project: haproxy_manager
139
+ rubygems_version: 1.8.24
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: HAproxy manager for controlling haproxy
143
+ test_files:
144
+ - spec/instance_spec.rb
145
+ - spec/spec_helper.rb