multibinder 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/multibinder-haproxy-erb +40 -0
- data/bin/multibinder-haproxy-wrapper +64 -0
- data/haproxy/haproxy-multi@.service +20 -0
- data/haproxy/multibinder.service +10 -0
- data/lib/multibinder/version.rb +1 -1
- metadata +16 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00e47bebe4eec94c83ac430fb7d6c887e9159436
|
4
|
+
data.tar.gz: 5d839a52f9d793ca4c003dbcba8c2f5c5e3b97f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbb81e35458b82592b48cf48d6250c796640a94072995f359c54ee08a9d173717442bc518e4e82d758cd437f6796387a9e5e40cfc82de2f054d52869fbdc018e
|
7
|
+
data.tar.gz: 9dc6ea20ad3ffdb185c2c7a90ff1cd553449356f5952679258418b4e89674cf26e8fab62a02e7b539d892f42300abaddaa71c6897ac04d30920755e516962abd
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Takes arguments that will be fed to haproxy, but sneakily tweaks the argument
|
3
|
+
# to '-f' by ERB-parsing it and then providing the result.
|
4
|
+
|
5
|
+
require 'multibinder'
|
6
|
+
require 'socket'
|
7
|
+
require 'fcntl'
|
8
|
+
require 'erb'
|
9
|
+
|
10
|
+
haproxy_call = ARGV
|
11
|
+
|
12
|
+
# find and update '-f' argument to the output of ERB processing
|
13
|
+
abort 'multibinder-haproxy expects a configuration file to be passed to haproxy' if haproxy_call.index('-f').nil?
|
14
|
+
config_file_index = haproxy_call.index('-f') + 1
|
15
|
+
haproxy_erb = haproxy_call[config_file_index]
|
16
|
+
abort 'Config file must end with .erb' unless haproxy_erb.end_with? '.erb'
|
17
|
+
haproxy_cfg = haproxy_erb.sub('.erb', '')
|
18
|
+
haproxy_call[config_file_index] = haproxy_cfg
|
19
|
+
|
20
|
+
def bind_tcp(ip, port)
|
21
|
+
if ENV['MULTIBINDER_SOCK'] && !ENV['MULTIBINDER_SOCK'].empty?
|
22
|
+
# if we have multibinder, use it to reuse our binds safely
|
23
|
+
server = MultiBinder.bind ip, port, { :backlog => 10240 }
|
24
|
+
"fd@#{server.fileno}"
|
25
|
+
else
|
26
|
+
# otherwise resort to the old fashioned binds with downtime/packet loss
|
27
|
+
puts "WARNING: Using haproxy direct binds, restarts will cause error!"
|
28
|
+
"#{ip}:#{port}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
new_data = ERB.new(File.read(haproxy_erb)).result
|
33
|
+
File.write(haproxy_cfg, new_data)
|
34
|
+
|
35
|
+
if haproxy_call.index('--erb-write-only')
|
36
|
+
puts 'ERB config write requested without launching command, exiting.'
|
37
|
+
exit 0
|
38
|
+
end
|
39
|
+
|
40
|
+
Process.exec *haproxy_call, :close_others => false
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Runs multibinder-haproxy-erb with the same arguments, supporting a USR2 for reload.
|
3
|
+
|
4
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
5
|
+
$launch_haproxy = File.join(dir, "multibinder-haproxy-erb")
|
6
|
+
|
7
|
+
SERVICE_DIR = File.basename(dir)
|
8
|
+
SERVICE_NAME = SERVICE_DIR.split('-').drop(1).join('-')
|
9
|
+
|
10
|
+
abort 'multibinder-haproxy-wrapper expects a pid file to be passed to haproxy' if ARGV.index('-p').nil?
|
11
|
+
pid_file_index = ARGV.index('-p') + 1
|
12
|
+
$PID_FILE = ARGV[pid_file_index]
|
13
|
+
|
14
|
+
# launches a new instance. the haproxy-instance script automatically handles
|
15
|
+
# everything: when no existing pid exists, it starts haproxy normally. when
|
16
|
+
# an existing haproxy is running, it calls a new copy with `-sf` so that
|
17
|
+
# haproxy safely hands over execution to the new process.
|
18
|
+
def launch_instance
|
19
|
+
args = [$launch_haproxy] + ARGV
|
20
|
+
if File.exist? $PID_FILE
|
21
|
+
args << "-sf"
|
22
|
+
args.concat File.read($PID_FILE).split()
|
23
|
+
end
|
24
|
+
|
25
|
+
Process.spawn *args
|
26
|
+
end
|
27
|
+
|
28
|
+
def cleanup_existing
|
29
|
+
if File.exist? $PID_FILE
|
30
|
+
`kill -USR1 $(cat #{$PID_FILE}); rm #{$PID_FILE}`
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# A SIGUSR2 tells us to safely relaunch
|
35
|
+
Signal.trap("USR2") do
|
36
|
+
old_pids = File.read($PID_FILE)
|
37
|
+
|
38
|
+
launch_instance
|
39
|
+
|
40
|
+
# wait a while for the pid file to change. after a while, give up and unblock reloads
|
41
|
+
for i in 0..20
|
42
|
+
break if File.read($PID_FILE) != old_pids
|
43
|
+
sleep 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# If we try to kill haproxy, have them gracefully quit rather than terminate immediately
|
48
|
+
Signal.trap("TERM") do
|
49
|
+
cleanup_existing
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
|
53
|
+
# Start the first process itself
|
54
|
+
launch_instance
|
55
|
+
|
56
|
+
# Keep waitpid()ing forever.
|
57
|
+
begin
|
58
|
+
loop do
|
59
|
+
Process.waitpid
|
60
|
+
sleep 10
|
61
|
+
end
|
62
|
+
ensure
|
63
|
+
cleanup_existing
|
64
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=HAProxy Load Balancer
|
3
|
+
Documentation=man:haproxy(1)
|
4
|
+
Documentation=file:/usr/share/doc/haproxy/configuration.txt.gz
|
5
|
+
After=network.target syslog.service multibinder.service
|
6
|
+
Wants=syslog.service multibinder.service
|
7
|
+
|
8
|
+
[Service]
|
9
|
+
Environment=CONFIG=/etc/haproxy/%i.cfg.erb
|
10
|
+
Environment=MULTIBINDER_SOCK=/run/multibinder.sock
|
11
|
+
EnvironmentFile=-/etc/default/haproxy
|
12
|
+
ExecStartPre=/usr/local/bin/multibinder-haproxy-erb /usr/sbin/haproxy -f ${CONFIG} -c -q
|
13
|
+
ExecStart=/usr/local/bin/multibinder-haproxy-wrapper /usr/sbin/haproxy -Ds -f ${CONFIG} -p /run/haproxy-%i.pid $EXTRAOPTS
|
14
|
+
ExecReload=/bin/sh -c "/usr/local/bin/multibinder-haproxy-erb /usr/sbin/haproxy -c -f ${CONFIG}; /bin/kill -USR2 $MAINPID"
|
15
|
+
ExecStop=/bin/kill -TERM $MAINPID
|
16
|
+
KillMode=none
|
17
|
+
Restart=always
|
18
|
+
|
19
|
+
[Install]
|
20
|
+
WantedBy=multi-user.target
|
data/lib/multibinder/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multibinder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Theo Julienne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.5'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
description:
|
@@ -43,15 +43,21 @@ email:
|
|
43
43
|
- theojulienne@github.com
|
44
44
|
executables:
|
45
45
|
- multibinder
|
46
|
+
- multibinder-haproxy-erb
|
47
|
+
- multibinder-haproxy-wrapper
|
46
48
|
extensions: []
|
47
49
|
extra_rdoc_files: []
|
48
50
|
files:
|
49
|
-
- .gitignore
|
51
|
+
- ".gitignore"
|
50
52
|
- Gemfile
|
51
53
|
- LICENSE.txt
|
52
54
|
- README.md
|
53
55
|
- Rakefile
|
54
56
|
- bin/multibinder
|
57
|
+
- bin/multibinder-haproxy-erb
|
58
|
+
- bin/multibinder-haproxy-wrapper
|
59
|
+
- haproxy/haproxy-multi@.service
|
60
|
+
- haproxy/multibinder.service
|
55
61
|
- lib/multibinder.rb
|
56
62
|
- lib/multibinder/version.rb
|
57
63
|
- multibinder.gemspec
|
@@ -74,17 +80,17 @@ require_paths:
|
|
74
80
|
- lib
|
75
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
76
82
|
requirements:
|
77
|
-
- -
|
83
|
+
- - ">="
|
78
84
|
- !ruby/object:Gem::Version
|
79
85
|
version: '0'
|
80
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
87
|
requirements:
|
82
|
-
- -
|
88
|
+
- - ">="
|
83
89
|
- !ruby/object:Gem::Version
|
84
90
|
version: '0'
|
85
91
|
requirements: []
|
86
92
|
rubyforge_project:
|
87
|
-
rubygems_version: 2.
|
93
|
+
rubygems_version: 2.2.3
|
88
94
|
signing_key:
|
89
95
|
specification_version: 4
|
90
96
|
summary: multibinder is a tiny ruby server that makes writing zero-downtime-reload
|