haproxy-api 0.1.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,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ M2NlM2NhYTUzYjEyYTQyMDcyYzUzNGFmMzRjYjgwYjU4NDVlMjgxZQ==
5
+ data.tar.gz: !binary |-
6
+ MzdiMmU4MTNhNTU0NmFlMjYyMGIyYThkMTk2ZDc1N2Y2NDVkYTM5ZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YTAyOTk4MjVmNDJmZWEwMTEwZDk2ODZkZDIxYTAxMmVkNTg3OWJlM2UwNDY4
10
+ YzlhOWIyY2I4OGYxZTFmNzU3MmJlYjk1YzFmZTYzNjUwMWNiN2E5MDA2MTBi
11
+ ZjVmOWMyZGFlNzFjNDk0MTRmOThlOGM4OTQwMmY0MjE5MWYzMTM=
12
+ data.tar.gz: !binary |-
13
+ MzczNTNkYmJhODc5NTlmNGE1MGZjNjNjOTIzZGQ3Njc4YmI4MzFlMDMyNTE1
14
+ MjI3ZTgzMWJiZTFjZTc0NmRmNTkyNmJkYzFmNDNiODdiYTMzMWI5NWZhMzAx
15
+ YmMyMDFlNjgwZWMzMWVkZDM1YzRiZjI3MDEwMzA4ZTk5OTI1MGI=
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ begin
4
+ require 'hapi/application/app.rb'
5
+ rescue LoadError => e
6
+ require 'rubygems'
7
+ path = File.expand_path '../../lib', __FILE__
8
+ $:.unshift(path) if File.directory?(path) && !$:.include?(path)
9
+ require 'hapi/application/app.rb'
10
+ end
@@ -0,0 +1,22 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'haproxy-api'
5
+ s.version = '0.1.1'
6
+ s.license = 'Apache-2.0'
7
+ s.author = 'Mike Schwankl'
8
+ s.email = 'schwankl@gmail.com'
9
+ s.homepage = 'https://github.com/schwankl/haproxy-api'
10
+ s.description = 'Haproxy API using sinatra'
11
+ s.summary = 'rest API using to haproxy'
12
+ s.executables = %(hapi)
13
+
14
+ s.platform = Gem::Platform::RUBY
15
+ s.extra_rdoc_files = %w()
16
+ s.add_dependency('sinatra', '1.4.7')
17
+ s.add_dependency('webrick', '1.3.1')
18
+
19
+ s.bindir = 'bin'
20
+ s.require_path = 'lib'
21
+ s.files = %w() + ["haproxy-api.gemspec"] + Dir.glob("lib/**/*") + Dir.glob('bin/**/*')
22
+ end
@@ -0,0 +1,201 @@
1
+ require 'sinatra'
2
+ require 'json'
3
+ require 'webrick'
4
+ require 'webrick/https'
5
+ require 'openssl'
6
+
7
+ CERT_PATH = ENV['CERT_PATH']
8
+
9
+ if CERT_PATH.nil? || !File.exists?(CERT_PATH+'/hapi.crt')
10
+ puts "set CERT_PATH env var to where your hapi.crt and hapi.key are"
11
+ exit 1
12
+ end
13
+
14
+ webrick_options = {
15
+ :Host => "0.0.0.0",
16
+ :Port => 443,
17
+ :Logger => WEBrick::Log::new($stderr, WEBrick::Log::DEBUG),
18
+ :DocumentRoot => "/ruby/htdocs",
19
+ :SSLEnable => true,
20
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
21
+ :SSLCertificate => OpenSSL::X509::Certificate.new( File.open(File.join(CERT_PATH, "/hapi.crt")).read),
22
+ :SSLPrivateKey => OpenSSL::PKey::RSA.new( File.open(File.join(CERT_PATH, "/hapi.key")).read),
23
+ :SSLCertName => [ [ "CN",WEBrick::Utils::getservername ] ]
24
+ }
25
+
26
+
27
+ class HaproxyApi < Sinatra::Base
28
+
29
+ $haproxy_config = '/etc/haproxy/haproxy.cfg'
30
+ if ENV['HAPROXY_CONFIG']
31
+ $haproxy_config = ENV['HAPROXY_CONFIG']
32
+ end
33
+ $mutable_haproxy_config = $haproxy_config + '.haproxy-api.json'
34
+
35
+ #before do
36
+ # request.body.rewind
37
+ # if request.body.size > 0
38
+ # @request_payload = JSON.parse request.body.read
39
+ # end
40
+ #end
41
+
42
+
43
+ def get_config
44
+ return { 'frontend' => {}, 'backend' => {} } if !File.exists?($mutable_haproxy_config)
45
+ return JSON.parse(File.read($mutable_haproxy_config))
46
+ end
47
+
48
+
49
+ def render(config)
50
+ content = ""
51
+ f = File.open($haproxy_config, "r")
52
+ in_gen_section = false
53
+ f.each_line do |line|
54
+ if line =~ /HAPROXY_API_GENERATED/
55
+ if in_gen_section
56
+ in_gen_section = false
57
+ else
58
+ in_gen_section = true
59
+ end
60
+ else
61
+ if !in_gen_section
62
+ content += line
63
+ end
64
+ end
65
+ end
66
+ f.close
67
+
68
+ content += "# HAPROXY_API_GENERATED - START\n"
69
+
70
+ config['frontend'].each_pair do |name, frontend|
71
+ content += "frontend #{name}\n"
72
+ content += " bind 0.0.0.0:#{frontend['port']}\n"
73
+ content += " default_backend #{name}-backend\n"
74
+ content += "\n"
75
+ end
76
+
77
+ config['backend'].each_pair do |name, backend|
78
+ content += "backend #{name}\n"
79
+ content += " balance #{backend['lbmethod']}\n"
80
+
81
+ if backend.has_key?('options')
82
+ backend['options'].each_pair do |k,v|
83
+ content += " option #{k} #{v}\n"
84
+ end
85
+ end
86
+
87
+ port = backend['port']
88
+ server_options = ""
89
+ if backend.has_key?('server_options')
90
+ backend['server_options'].each_pair do |k,v|
91
+ server_options += "#{k} #{v} "
92
+ end
93
+ end
94
+
95
+ backend['servers'].each do |server|
96
+ content += " server #{server}:#{port} #{server}:#{port} #{server_options} \n"
97
+ end
98
+ content += "\n"
99
+ end
100
+
101
+ content += "# HAPROXY_API_GENERATED - END\n"
102
+
103
+ return content
104
+ end
105
+
106
+
107
+ def set_config(config)
108
+ ts = Time.now.to_i
109
+ `cp #{$haproxy_config} #{$haproxy_config}.#{ts}`
110
+ content = render config
111
+ File.open($mutable_haproxy_config, 'w') { |file| file.write(JSON.dump(config)) }
112
+ File.open($haproxy_config, 'w') { |file| file.write(content) }
113
+
114
+ result = `/usr/sbin/haproxy -c -f #{$haproxy_config}`
115
+ if $?.to_i == 0
116
+ puts `systemctl restart haproxy`
117
+ else
118
+ puts "rolling back config - got:"
119
+ puts result
120
+ `cp #{$haproxy_config}.#{ts} #{$haproxy_config}`
121
+ return status(500)
122
+ end
123
+ end
124
+
125
+ get '/render' do
126
+ config = get_config
127
+ render config
128
+ end
129
+
130
+ get '/frontends' do
131
+ config = get_config
132
+ JSON.dump(config['frontend'])
133
+ end
134
+
135
+ get '/frontend/:id' do
136
+ config = get_config
137
+ id = params[:id]
138
+ return status(404) if !config['frontend'].has_key?(id)
139
+ JSON.dump(config['frontend'][id])
140
+ end
141
+
142
+ post '/frontend/:id' do
143
+ config = get_config
144
+
145
+ id = params[:id]
146
+ if config['frontend'].has_key?(id)
147
+ puts "#{id} already exists - use put"
148
+ return status(500)
149
+ end
150
+
151
+ frontend = JSON.parse request.body.read
152
+ config['frontend'][id] = frontend
153
+ set_config config
154
+ JSON.dump(frontend)
155
+ end
156
+
157
+ delete '/frontend/:id' do
158
+ config = get_config
159
+ config['frontend'].delete params[:id]
160
+ set_config config
161
+ end
162
+
163
+
164
+ get '/backends' do
165
+ config = get_config
166
+ JSON.dump(config['backend'])
167
+ end
168
+
169
+
170
+ get '/backend/:id' do
171
+ config = get_config
172
+ id = params[:id] + "-backend"
173
+ return status(404) if !config['backend'].has_key?(id)
174
+ JSON.dump(config['backend'][id])
175
+ end
176
+
177
+
178
+ post '/backend/:id' do
179
+ config = get_config
180
+ id = params[:id] + "-backend"
181
+ if config['backend'].has_key?(id)
182
+ puts "#{id} already exists - use put"
183
+ return status(500)
184
+ end
185
+ backend = JSON.parse request.body.read
186
+ config['backend'][id] = backend
187
+ set_config config
188
+ JSON.dump(backend)
189
+ end
190
+
191
+
192
+ delete '/backend/:id' do
193
+ config = get_config
194
+ config['backend'].delete(params[:id] + "-backend")
195
+ set_config config
196
+ end
197
+
198
+ end
199
+
200
+ Rack::Handler::WEBrick.run HaproxyApi, webrick_options
201
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: haproxy-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Mike Schwankl
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: webrick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.3.1
41
+ description: Haproxy API using sinatra
42
+ email: schwankl@gmail.com
43
+ executables:
44
+ - hapi
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - bin/hapi
49
+ - haproxy-api.gemspec
50
+ - lib/hapi/application/app.rb
51
+ homepage: https://github.com/schwankl/haproxy-api
52
+ licenses:
53
+ - Apache-2.0
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.4.8
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: rest API using to haproxy
75
+ test_files: []