synapse 0.2.1 → 0.8.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 +3 -0
- data/.mailmap +3 -0
- data/LICENSE.txt +2 -2
- data/Makefile +6 -0
- data/README.md +42 -13
- data/bin/synapse +29 -21
- data/config/hostheader_test.json +71 -0
- data/config/svcdir_test.json +46 -0
- data/config/synapse.conf.json +26 -32
- data/config/synapse_services/service1.json +24 -0
- data/config/synapse_services/service2.json +24 -0
- data/lib/synapse.rb +39 -24
- data/lib/synapse/base.rb +1 -1
- data/lib/synapse/haproxy.rb +579 -22
- data/lib/synapse/log.rb +24 -0
- data/lib/synapse/service_watcher.rb +10 -6
- data/lib/synapse/service_watcher/base.rb +33 -11
- data/lib/synapse/service_watcher/dns.rb +28 -20
- data/lib/synapse/service_watcher/docker.rb +108 -0
- data/lib/synapse/service_watcher/ec2tag.rb +1 -1
- data/lib/synapse/service_watcher/zookeeper.rb +25 -28
- data/lib/synapse/version.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/synapse.gemspec +2 -3
- metadata +15 -25
- data/Vagrantfile +0 -112
- data/chef/converge +0 -4
- data/chef/cookbooks/lxc/recipes/default.rb +0 -2
- data/chef/cookbooks/synapse/attributes/default.rb +0 -1
- data/chef/cookbooks/synapse/recipes/default.rb +0 -6
- data/chef/run.json +0 -8
- data/chef/run.rb +0 -2
- data/client/.RData +0 -0
- data/client/.Rhistory +0 -294
- data/client/bench_rewrite_config.dat +0 -2013
- data/client/benchmark-client.iml +0 -20
- data/client/pom.xml +0 -45
- data/client/src/main/java/ClientArsch.java +0 -68
- data/client/src/main/java/META-INF/MANIFEST.MF +0 -3
- data/haproxy.pid +0 -1
- data/lib/gen-rb/endpoint_types.rb +0 -65
- data/lib/gen-rb/thrift.rb +0 -65
- data/test.sh +0 -3
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"default_servers": [
|
3
|
+
{ "name": "default1", "host": "localhost", "port": 8080 }
|
4
|
+
],
|
5
|
+
"discovery": {
|
6
|
+
"method": "dns",
|
7
|
+
"nameserver": "10.10.1.13",
|
8
|
+
"servers": [
|
9
|
+
"0.www.example.com",
|
10
|
+
"1.www.example.com"
|
11
|
+
]
|
12
|
+
},
|
13
|
+
"haproxy": {
|
14
|
+
"server_options": "check inter 2s rise 3 fall 2",
|
15
|
+
"listen": [
|
16
|
+
"mode http",
|
17
|
+
"option httplog"
|
18
|
+
],
|
19
|
+
"backend": [
|
20
|
+
"mode http",
|
21
|
+
"option httpchk GET /health HTTP/1.0"
|
22
|
+
]
|
23
|
+
}
|
24
|
+
}
|
data/lib/synapse.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require "synapse/version"
|
2
|
+
require "synapse/service_watcher/base"
|
3
|
+
require "synapse/haproxy"
|
4
|
+
require "synapse/service_watcher"
|
5
|
+
require "synapse/log"
|
5
6
|
|
6
7
|
require 'logger'
|
7
8
|
require 'json'
|
@@ -10,10 +11,8 @@ include Synapse
|
|
10
11
|
|
11
12
|
module Synapse
|
12
13
|
class Synapse
|
14
|
+
include Logging
|
13
15
|
def initialize(opts={})
|
14
|
-
# disable configuration until this is started
|
15
|
-
@configure_enabled = false
|
16
|
-
|
17
16
|
# create the service watchers for all our services
|
18
17
|
raise "specify a list of services to connect in the config" unless opts.has_key?('services')
|
19
18
|
@service_watchers = create_service_watchers(opts['services'])
|
@@ -21,44 +20,60 @@ module Synapse
|
|
21
20
|
# create the haproxy object
|
22
21
|
raise "haproxy config section is missing" unless opts.has_key?('haproxy')
|
23
22
|
@haproxy = Haproxy.new(opts['haproxy'])
|
23
|
+
|
24
|
+
# configuration is initially enabled to configure on first loop
|
25
|
+
@config_updated = true
|
24
26
|
end
|
25
27
|
|
26
28
|
# start all the watchers and enable haproxy configuration
|
27
29
|
def run
|
28
30
|
log.info "synapse: starting..."
|
29
31
|
|
32
|
+
# start all the watchers
|
30
33
|
@service_watchers.map { |watcher| watcher.start }
|
31
|
-
@configure_enabled = true
|
32
|
-
configure
|
33
34
|
|
34
|
-
# loop
|
35
|
+
# main loop
|
35
36
|
loops = 0
|
36
|
-
loop do
|
37
|
-
|
37
|
+
loop do
|
38
|
+
@service_watchers.each do |w|
|
39
|
+
raise "synapse: service watcher #{w.name} failed ping!" unless w.ping?
|
40
|
+
end
|
41
|
+
|
42
|
+
if @config_updated
|
43
|
+
@config_updated = false
|
44
|
+
log.info "synapse: regenerating haproxy config"
|
45
|
+
@haproxy.update_config(@service_watchers)
|
46
|
+
else
|
47
|
+
sleep 1
|
48
|
+
end
|
49
|
+
|
38
50
|
loops += 1
|
39
51
|
log.debug "synapse: still running at #{Time.now}" if (loops % 60) == 0
|
40
52
|
end
|
53
|
+
|
54
|
+
rescue StandardError => e
|
55
|
+
log.error "synapse: encountered unexpected exception #{e.inspect} in main thread"
|
56
|
+
raise e
|
57
|
+
ensure
|
58
|
+
log.warn "synapse: exiting; sending stop signal to all watchers"
|
59
|
+
|
60
|
+
# stop all the watchers
|
61
|
+
@service_watchers.map(&:stop)
|
41
62
|
end
|
42
63
|
|
43
|
-
|
44
|
-
|
45
|
-
if @configure_enabled
|
46
|
-
log.info "synapse: regenerating haproxy config"
|
47
|
-
@haproxy.update_config(@service_watchers)
|
48
|
-
else
|
49
|
-
log.info "synapse: reconfigure requested, but it's not yet enabled"
|
50
|
-
end
|
64
|
+
def reconfigure!
|
65
|
+
@config_updated = true
|
51
66
|
end
|
52
67
|
|
53
68
|
private
|
54
69
|
def create_service_watchers(services={})
|
55
70
|
service_watchers =[]
|
56
|
-
services.each do |service_config|
|
57
|
-
service_watchers << ServiceWatcher.create(service_config, self)
|
71
|
+
services.each do |service_name, service_config|
|
72
|
+
service_watchers << ServiceWatcher.create(service_name, service_config, self)
|
58
73
|
end
|
59
|
-
|
74
|
+
|
60
75
|
return service_watchers
|
61
76
|
end
|
62
|
-
|
77
|
+
|
63
78
|
end
|
64
79
|
end
|
data/lib/synapse/base.rb
CHANGED
data/lib/synapse/haproxy.rb
CHANGED
@@ -1,8 +1,500 @@
|
|
1
|
+
require 'synapse/log'
|
2
|
+
|
1
3
|
require 'socket'
|
4
|
+
require 'digest'
|
2
5
|
|
3
6
|
module Synapse
|
4
7
|
class Haproxy
|
8
|
+
include Logging
|
5
9
|
attr_reader :opts
|
10
|
+
|
11
|
+
# these come from the documentation for haproxy 1.5
|
12
|
+
# http://haproxy.1wt.eu/download/1.5/doc/configuration.txt
|
13
|
+
@@section_fields = {
|
14
|
+
"backend" => [
|
15
|
+
"acl",
|
16
|
+
"appsession",
|
17
|
+
"balance",
|
18
|
+
"bind-process",
|
19
|
+
"block",
|
20
|
+
"compression",
|
21
|
+
"contimeout",
|
22
|
+
"cookie",
|
23
|
+
"default-server",
|
24
|
+
"description",
|
25
|
+
"disabled",
|
26
|
+
"dispatch",
|
27
|
+
"enabled",
|
28
|
+
"errorfile",
|
29
|
+
"errorloc",
|
30
|
+
"errorloc302",
|
31
|
+
"errorloc303",
|
32
|
+
"force-persist",
|
33
|
+
"fullconn",
|
34
|
+
"grace",
|
35
|
+
"hash-type",
|
36
|
+
"http-check disable-on-404",
|
37
|
+
"http-check expect",
|
38
|
+
"http-check send-state",
|
39
|
+
"http-request",
|
40
|
+
"http-response",
|
41
|
+
"id",
|
42
|
+
"ignore-persist",
|
43
|
+
"log",
|
44
|
+
"mode",
|
45
|
+
"option abortonclose",
|
46
|
+
"option accept-invalid-http-response",
|
47
|
+
"option allbackups",
|
48
|
+
"option checkcache",
|
49
|
+
"option forceclose",
|
50
|
+
"option forwardfor",
|
51
|
+
"option http-no-delay",
|
52
|
+
"option http-pretend-keepalive",
|
53
|
+
"option http-server-close",
|
54
|
+
"option httpchk",
|
55
|
+
"option httpclose",
|
56
|
+
"option httplog",
|
57
|
+
"option http_proxy",
|
58
|
+
"option independent-streams",
|
59
|
+
"option lb-agent-chk",
|
60
|
+
"option ldap-check",
|
61
|
+
"option log-health-checks",
|
62
|
+
"option mysql-check",
|
63
|
+
"option pgsql-check",
|
64
|
+
"option nolinger",
|
65
|
+
"option originalto",
|
66
|
+
"option persist",
|
67
|
+
"option redispatch",
|
68
|
+
"option redis-check",
|
69
|
+
"option smtpchk",
|
70
|
+
"option splice-auto",
|
71
|
+
"option splice-request",
|
72
|
+
"option splice-response",
|
73
|
+
"option srvtcpka",
|
74
|
+
"option ssl-hello-chk",
|
75
|
+
"option tcp-smart-connect",
|
76
|
+
"option tcpka",
|
77
|
+
"option tcplog",
|
78
|
+
"option transparent",
|
79
|
+
"persist rdp-cookie",
|
80
|
+
"redirect",
|
81
|
+
"redisp",
|
82
|
+
"redispatch",
|
83
|
+
"reqadd",
|
84
|
+
"reqallow",
|
85
|
+
"reqdel",
|
86
|
+
"reqdeny",
|
87
|
+
"reqiallow",
|
88
|
+
"reqidel",
|
89
|
+
"reqideny",
|
90
|
+
"reqipass",
|
91
|
+
"reqirep",
|
92
|
+
"reqisetbe",
|
93
|
+
"reqitarpit",
|
94
|
+
"reqpass",
|
95
|
+
"reqrep",
|
96
|
+
"reqsetbe",
|
97
|
+
"reqtarpit",
|
98
|
+
"retries",
|
99
|
+
"rspadd",
|
100
|
+
"rspdel",
|
101
|
+
"rspdeny",
|
102
|
+
"rspidel",
|
103
|
+
"rspideny",
|
104
|
+
"rspirep",
|
105
|
+
"rsprep",
|
106
|
+
"server",
|
107
|
+
"source",
|
108
|
+
"srvtimeout",
|
109
|
+
"stats admin",
|
110
|
+
"stats auth",
|
111
|
+
"stats enable",
|
112
|
+
"stats hide-version",
|
113
|
+
"stats http-request",
|
114
|
+
"stats realm",
|
115
|
+
"stats refresh",
|
116
|
+
"stats scope",
|
117
|
+
"stats show-desc",
|
118
|
+
"stats show-legends",
|
119
|
+
"stats show-node",
|
120
|
+
"stats uri",
|
121
|
+
"stick match",
|
122
|
+
"stick on",
|
123
|
+
"stick store-request",
|
124
|
+
"stick store-response",
|
125
|
+
"stick-table",
|
126
|
+
"tcp-request content",
|
127
|
+
"tcp-request inspect-delay",
|
128
|
+
"tcp-response content",
|
129
|
+
"tcp-response inspect-delay",
|
130
|
+
"timeout check",
|
131
|
+
"timeout connect",
|
132
|
+
"timeout contimeout",
|
133
|
+
"timeout http-keep-alive",
|
134
|
+
"timeout http-request",
|
135
|
+
"timeout queue",
|
136
|
+
"timeout server",
|
137
|
+
"timeout srvtimeout",
|
138
|
+
"timeout tarpit",
|
139
|
+
"timeout tunnel",
|
140
|
+
"transparent",
|
141
|
+
"use-server"
|
142
|
+
],
|
143
|
+
"defaults" => [
|
144
|
+
"backlog",
|
145
|
+
"balance",
|
146
|
+
"bind-process",
|
147
|
+
"clitimeout",
|
148
|
+
"compression",
|
149
|
+
"contimeout",
|
150
|
+
"cookie",
|
151
|
+
"default-server",
|
152
|
+
"default_backend",
|
153
|
+
"disabled",
|
154
|
+
"enabled",
|
155
|
+
"errorfile",
|
156
|
+
"errorloc",
|
157
|
+
"errorloc302",
|
158
|
+
"errorloc303",
|
159
|
+
"fullconn",
|
160
|
+
"grace",
|
161
|
+
"hash-type",
|
162
|
+
"http-check disable-on-404",
|
163
|
+
"http-check send-state",
|
164
|
+
"log",
|
165
|
+
"maxconn",
|
166
|
+
"mode",
|
167
|
+
"monitor-net",
|
168
|
+
"monitor-uri",
|
169
|
+
"option abortonclose",
|
170
|
+
"option accept-invalid-http-request",
|
171
|
+
"option accept-invalid-http-response",
|
172
|
+
"option allbackups",
|
173
|
+
"option checkcache",
|
174
|
+
"option clitcpka",
|
175
|
+
"option contstats",
|
176
|
+
"option dontlog-normal",
|
177
|
+
"option dontlognull",
|
178
|
+
"option forceclose",
|
179
|
+
"option forwardfor",
|
180
|
+
"option http-no-delay",
|
181
|
+
"option http-pretend-keepalive",
|
182
|
+
"option http-server-close",
|
183
|
+
"option http-use-proxy-header",
|
184
|
+
"option httpchk",
|
185
|
+
"option httpclose",
|
186
|
+
"option httplog",
|
187
|
+
"option http_proxy",
|
188
|
+
"option independent-streams",
|
189
|
+
"option lb-agent-chk",
|
190
|
+
"option ldap-check",
|
191
|
+
"option log-health-checks",
|
192
|
+
"option log-separate-errors",
|
193
|
+
"option logasap",
|
194
|
+
"option mysql-check",
|
195
|
+
"option pgsql-check",
|
196
|
+
"option nolinger",
|
197
|
+
"option originalto",
|
198
|
+
"option persist",
|
199
|
+
"option redispatch",
|
200
|
+
"option redis-check",
|
201
|
+
"option smtpchk",
|
202
|
+
"option socket-stats",
|
203
|
+
"option splice-auto",
|
204
|
+
"option splice-request",
|
205
|
+
"option splice-response",
|
206
|
+
"option srvtcpka",
|
207
|
+
"option ssl-hello-chk",
|
208
|
+
"option tcp-smart-accept",
|
209
|
+
"option tcp-smart-connect",
|
210
|
+
"option tcpka",
|
211
|
+
"option tcplog",
|
212
|
+
"option transparent",
|
213
|
+
"persist rdp-cookie",
|
214
|
+
"rate-limit sessions",
|
215
|
+
"redisp",
|
216
|
+
"redispatch",
|
217
|
+
"retries",
|
218
|
+
"source",
|
219
|
+
"srvtimeout",
|
220
|
+
"stats auth",
|
221
|
+
"stats enable",
|
222
|
+
"stats hide-version",
|
223
|
+
"stats realm",
|
224
|
+
"stats refresh",
|
225
|
+
"stats scope",
|
226
|
+
"stats show-desc",
|
227
|
+
"stats show-legends",
|
228
|
+
"stats show-node",
|
229
|
+
"stats uri",
|
230
|
+
"timeout check",
|
231
|
+
"timeout client",
|
232
|
+
"timeout clitimeout",
|
233
|
+
"timeout connect",
|
234
|
+
"timeout contimeout",
|
235
|
+
"timeout http-keep-alive",
|
236
|
+
"timeout http-request",
|
237
|
+
"timeout queue",
|
238
|
+
"timeout server",
|
239
|
+
"timeout srvtimeout",
|
240
|
+
"timeout tarpit",
|
241
|
+
"timeout tunnel",
|
242
|
+
"transparent",
|
243
|
+
"unique-id-format",
|
244
|
+
"unique-id-header"
|
245
|
+
],
|
246
|
+
"frontend" => [
|
247
|
+
"acl",
|
248
|
+
"backlog",
|
249
|
+
"bind",
|
250
|
+
"bind-process",
|
251
|
+
"block",
|
252
|
+
"capture cookie",
|
253
|
+
"capture request header",
|
254
|
+
"capture response header",
|
255
|
+
"clitimeout",
|
256
|
+
"compression",
|
257
|
+
"default_backend",
|
258
|
+
"description",
|
259
|
+
"disabled",
|
260
|
+
"enabled",
|
261
|
+
"errorfile",
|
262
|
+
"errorloc",
|
263
|
+
"errorloc302",
|
264
|
+
"errorloc303",
|
265
|
+
"force-persist",
|
266
|
+
"grace",
|
267
|
+
"http-request",
|
268
|
+
"http-response",
|
269
|
+
"id",
|
270
|
+
"ignore-persist",
|
271
|
+
"log",
|
272
|
+
"maxconn",
|
273
|
+
"mode",
|
274
|
+
"monitor fail",
|
275
|
+
"monitor-net",
|
276
|
+
"monitor-uri",
|
277
|
+
"option accept-invalid-http-request",
|
278
|
+
"option clitcpka",
|
279
|
+
"option contstats",
|
280
|
+
"option dontlog-normal",
|
281
|
+
"option dontlognull",
|
282
|
+
"option forceclose",
|
283
|
+
"option forwardfor",
|
284
|
+
"option http-no-delay",
|
285
|
+
"option http-pretend-keepalive",
|
286
|
+
"option http-server-close",
|
287
|
+
"option http-use-proxy-header",
|
288
|
+
"option httpclose",
|
289
|
+
"option httplog",
|
290
|
+
"option http_proxy",
|
291
|
+
"option independent-streams",
|
292
|
+
"option log-separate-errors",
|
293
|
+
"option logasap",
|
294
|
+
"option nolinger",
|
295
|
+
"option originalto",
|
296
|
+
"option socket-stats",
|
297
|
+
"option splice-auto",
|
298
|
+
"option splice-request",
|
299
|
+
"option splice-response",
|
300
|
+
"option tcp-smart-accept",
|
301
|
+
"option tcpka",
|
302
|
+
"option tcplog",
|
303
|
+
"rate-limit sessions",
|
304
|
+
"redirect",
|
305
|
+
"reqadd",
|
306
|
+
"reqallow",
|
307
|
+
"reqdel",
|
308
|
+
"reqdeny",
|
309
|
+
"reqiallow",
|
310
|
+
"reqidel",
|
311
|
+
"reqideny",
|
312
|
+
"reqipass",
|
313
|
+
"reqirep",
|
314
|
+
"reqisetbe",
|
315
|
+
"reqitarpit",
|
316
|
+
"reqpass",
|
317
|
+
"reqrep",
|
318
|
+
"reqsetbe",
|
319
|
+
"reqtarpit",
|
320
|
+
"rspadd",
|
321
|
+
"rspdel",
|
322
|
+
"rspdeny",
|
323
|
+
"rspidel",
|
324
|
+
"rspideny",
|
325
|
+
"rspirep",
|
326
|
+
"rsprep",
|
327
|
+
"tcp-request connection",
|
328
|
+
"tcp-request content",
|
329
|
+
"tcp-request inspect-delay",
|
330
|
+
"timeout client",
|
331
|
+
"timeout clitimeout",
|
332
|
+
"timeout http-keep-alive",
|
333
|
+
"timeout http-request",
|
334
|
+
"timeout tarpit",
|
335
|
+
"unique-id-format",
|
336
|
+
"unique-id-header",
|
337
|
+
"use_backend"
|
338
|
+
],
|
339
|
+
"listen" => [
|
340
|
+
"acl",
|
341
|
+
"appsession",
|
342
|
+
"backlog",
|
343
|
+
"balance",
|
344
|
+
"bind",
|
345
|
+
"bind-process",
|
346
|
+
"block",
|
347
|
+
"capture cookie",
|
348
|
+
"capture request header",
|
349
|
+
"capture response header",
|
350
|
+
"clitimeout",
|
351
|
+
"compression",
|
352
|
+
"contimeout",
|
353
|
+
"cookie",
|
354
|
+
"default-server",
|
355
|
+
"default_backend",
|
356
|
+
"description",
|
357
|
+
"disabled",
|
358
|
+
"dispatch",
|
359
|
+
"enabled",
|
360
|
+
"errorfile",
|
361
|
+
"errorloc",
|
362
|
+
"errorloc302",
|
363
|
+
"errorloc303",
|
364
|
+
"force-persist",
|
365
|
+
"fullconn",
|
366
|
+
"grace",
|
367
|
+
"hash-type",
|
368
|
+
"http-check disable-on-404",
|
369
|
+
"http-check expect",
|
370
|
+
"http-check send-state",
|
371
|
+
"http-request",
|
372
|
+
"http-response",
|
373
|
+
"id",
|
374
|
+
"ignore-persist",
|
375
|
+
"log",
|
376
|
+
"maxconn",
|
377
|
+
"mode",
|
378
|
+
"monitor fail",
|
379
|
+
"monitor-net",
|
380
|
+
"monitor-uri",
|
381
|
+
"option abortonclose",
|
382
|
+
"option accept-invalid-http-request",
|
383
|
+
"option accept-invalid-http-response",
|
384
|
+
"option allbackups",
|
385
|
+
"option checkcache",
|
386
|
+
"option clitcpka",
|
387
|
+
"option contstats",
|
388
|
+
"option dontlog-normal",
|
389
|
+
"option dontlognull",
|
390
|
+
"option forceclose",
|
391
|
+
"option forwardfor",
|
392
|
+
"option http-no-delay",
|
393
|
+
"option http-pretend-keepalive",
|
394
|
+
"option http-server-close",
|
395
|
+
"option http-use-proxy-header",
|
396
|
+
"option httpchk",
|
397
|
+
"option httpclose",
|
398
|
+
"option httplog",
|
399
|
+
"option http_proxy",
|
400
|
+
"option independent-streams",
|
401
|
+
"option lb-agent-chk",
|
402
|
+
"option ldap-check",
|
403
|
+
"option log-health-checks",
|
404
|
+
"option log-separate-errors",
|
405
|
+
"option logasap",
|
406
|
+
"option mysql-check",
|
407
|
+
"option pgsql-check",
|
408
|
+
"option nolinger",
|
409
|
+
"option originalto",
|
410
|
+
"option persist",
|
411
|
+
"option redispatch",
|
412
|
+
"option redis-check",
|
413
|
+
"option smtpchk",
|
414
|
+
"option socket-stats",
|
415
|
+
"option splice-auto",
|
416
|
+
"option splice-request",
|
417
|
+
"option splice-response",
|
418
|
+
"option srvtcpka",
|
419
|
+
"option ssl-hello-chk",
|
420
|
+
"option tcp-smart-accept",
|
421
|
+
"option tcp-smart-connect",
|
422
|
+
"option tcpka",
|
423
|
+
"option tcplog",
|
424
|
+
"option transparent",
|
425
|
+
"persist rdp-cookie",
|
426
|
+
"rate-limit sessions",
|
427
|
+
"redirect",
|
428
|
+
"redisp",
|
429
|
+
"redispatch",
|
430
|
+
"reqadd",
|
431
|
+
"reqallow",
|
432
|
+
"reqdel",
|
433
|
+
"reqdeny",
|
434
|
+
"reqiallow",
|
435
|
+
"reqidel",
|
436
|
+
"reqideny",
|
437
|
+
"reqipass",
|
438
|
+
"reqirep",
|
439
|
+
"reqisetbe",
|
440
|
+
"reqitarpit",
|
441
|
+
"reqpass",
|
442
|
+
"reqrep",
|
443
|
+
"reqsetbe",
|
444
|
+
"reqtarpit",
|
445
|
+
"retries",
|
446
|
+
"rspadd",
|
447
|
+
"rspdel",
|
448
|
+
"rspdeny",
|
449
|
+
"rspidel",
|
450
|
+
"rspideny",
|
451
|
+
"rspirep",
|
452
|
+
"rsprep",
|
453
|
+
"server",
|
454
|
+
"source",
|
455
|
+
"srvtimeout",
|
456
|
+
"stats admin",
|
457
|
+
"stats auth",
|
458
|
+
"stats enable",
|
459
|
+
"stats hide-version",
|
460
|
+
"stats http-request",
|
461
|
+
"stats realm",
|
462
|
+
"stats refresh",
|
463
|
+
"stats scope",
|
464
|
+
"stats show-desc",
|
465
|
+
"stats show-legends",
|
466
|
+
"stats show-node",
|
467
|
+
"stats uri",
|
468
|
+
"stick match",
|
469
|
+
"stick on",
|
470
|
+
"stick store-request",
|
471
|
+
"stick store-response",
|
472
|
+
"stick-table",
|
473
|
+
"tcp-request connection",
|
474
|
+
"tcp-request content",
|
475
|
+
"tcp-request inspect-delay",
|
476
|
+
"tcp-response content",
|
477
|
+
"tcp-response inspect-delay",
|
478
|
+
"timeout check",
|
479
|
+
"timeout client",
|
480
|
+
"timeout clitimeout",
|
481
|
+
"timeout connect",
|
482
|
+
"timeout contimeout",
|
483
|
+
"timeout http-keep-alive",
|
484
|
+
"timeout http-request",
|
485
|
+
"timeout queue",
|
486
|
+
"timeout server",
|
487
|
+
"timeout srvtimeout",
|
488
|
+
"timeout tarpit",
|
489
|
+
"timeout tunnel",
|
490
|
+
"transparent",
|
491
|
+
"unique-id-format",
|
492
|
+
"unique-id-header",
|
493
|
+
"use_backend",
|
494
|
+
"use-server"
|
495
|
+
]
|
496
|
+
}
|
497
|
+
|
6
498
|
def initialize(opts)
|
7
499
|
super()
|
8
500
|
|
@@ -22,7 +514,14 @@ module Synapse
|
|
22
514
|
end
|
23
515
|
|
24
516
|
@opts = opts
|
517
|
+
|
518
|
+
# how to restart haproxy
|
519
|
+
@restart_interval = 2
|
25
520
|
@restart_required = true
|
521
|
+
@last_restart = Time.new(0)
|
522
|
+
|
523
|
+
# a place to store the parsed haproxy config from each watcher
|
524
|
+
@watcher_configs = {}
|
26
525
|
end
|
27
526
|
|
28
527
|
def update_config(watchers)
|
@@ -45,29 +544,35 @@ module Synapse
|
|
45
544
|
|
46
545
|
# generates a new config based on the state of the watchers
|
47
546
|
def generate_config(watchers)
|
48
|
-
new_config = generate_base_config
|
49
|
-
|
547
|
+
new_config = generate_base_config
|
548
|
+
|
549
|
+
watchers.each do |watcher|
|
550
|
+
@watcher_configs[watcher.name] ||= parse_watcher_config(watcher)
|
551
|
+
|
552
|
+
new_config << generate_frontend_stanza(watcher, @watcher_configs[watcher.name]['frontend'])
|
553
|
+
new_config << generate_backend_stanza(watcher, @watcher_configs[watcher.name]['backend'])
|
554
|
+
end
|
50
555
|
|
51
556
|
log.debug "synapse: new haproxy config: #{new_config}"
|
52
|
-
return new_config
|
557
|
+
return new_config.flatten.join("\n")
|
53
558
|
end
|
54
559
|
|
55
560
|
# generates the global and defaults sections of the config file
|
56
561
|
def generate_base_config
|
57
|
-
base_config = "# auto-generated by synapse at #{Time.now}\n"
|
562
|
+
base_config = ["# auto-generated by synapse at #{Time.now}\n"]
|
58
563
|
|
59
564
|
%w{global defaults}.each do |section|
|
60
|
-
base_config << "
|
565
|
+
base_config << "#{section}"
|
61
566
|
@opts[section].each do |option|
|
62
|
-
base_config << "\t#{option}
|
567
|
+
base_config << "\t#{option}"
|
63
568
|
end
|
64
569
|
end
|
65
570
|
|
66
571
|
if @opts['extra_sections']
|
67
572
|
@opts['extra_sections'].each do |title, section|
|
68
|
-
base_config << "\n#{title}
|
573
|
+
base_config << "\n#{title}"
|
69
574
|
section.each do |option|
|
70
|
-
base_config << "\t#{option}
|
575
|
+
base_config << "\t#{option}"
|
71
576
|
end
|
72
577
|
end
|
73
578
|
end
|
@@ -75,24 +580,62 @@ module Synapse
|
|
75
580
|
return base_config
|
76
581
|
end
|
77
582
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
583
|
+
# split the haproxy config in each watcher into fields applicable in
|
584
|
+
# frontend and backend sections
|
585
|
+
def parse_watcher_config(watcher)
|
586
|
+
config = {}
|
587
|
+
%w{frontend backend}.each do |section|
|
588
|
+
config[section] = watcher.haproxy[section] || []
|
589
|
+
|
590
|
+
# copy over the settings from the 'listen' section that pertain to section
|
591
|
+
config[section].concat(
|
592
|
+
watcher.haproxy['listen'].select {|setting|
|
593
|
+
parsed_setting = setting.strip.gsub(/\s+/, ' ').downcase
|
594
|
+
@@section_fields[section].any? {|field| parsed_setting.start_with?(field)}
|
595
|
+
})
|
596
|
+
|
597
|
+
# pick only those fields that are valid and warn about the invalid ones
|
598
|
+
config[section].select!{|setting|
|
599
|
+
parsed_setting = setting.strip.gsub(/\s+/, ' ').downcase
|
600
|
+
if @@section_fields[section].any? {|field| parsed_setting.start_with?(field)}
|
601
|
+
true
|
602
|
+
else
|
603
|
+
log.warn "synapse: service #{watcher.name} contains invalid #{section} setting: '#{setting}'"
|
604
|
+
false
|
605
|
+
end
|
606
|
+
}
|
83
607
|
end
|
84
608
|
|
85
|
-
|
609
|
+
return config
|
610
|
+
end
|
86
611
|
|
87
|
-
|
88
|
-
|
612
|
+
# generates an individual stanza for a particular watcher
|
613
|
+
def generate_frontend_stanza(watcher, config)
|
614
|
+
unless watcher.haproxy.has_key?("port")
|
615
|
+
log.debug "synapse: not generating frontend stanza for watcher #{watcher.name} because it has no port defined"
|
616
|
+
return []
|
89
617
|
end
|
90
618
|
|
91
|
-
|
92
|
-
|
619
|
+
stanza = [
|
620
|
+
"\nfrontend #{watcher.name}",
|
621
|
+
config.map {|c| "\t#{c}"},
|
622
|
+
"\tbind #{@opts['bind_address'] || 'localhost'}:#{watcher.haproxy['port']}",
|
623
|
+
"\tdefault_backend #{watcher.name}"
|
624
|
+
]
|
625
|
+
end
|
626
|
+
|
627
|
+
def generate_backend_stanza(watcher, config)
|
628
|
+
if watcher.backends.empty?
|
629
|
+
log.warn "synapse: no backends found for watcher #{watcher.name}"
|
93
630
|
end
|
94
631
|
|
95
|
-
|
632
|
+
stanza = [
|
633
|
+
"\nbackend #{watcher.name}",
|
634
|
+
config.map {|c| "\t#{c}"},
|
635
|
+
watcher.backends.shuffle.map {|backend|
|
636
|
+
backend_name = construct_name(backend)
|
637
|
+
"\tserver #{backend_name} #{backend['host']}:#{backend['port']} #{watcher.haproxy['server_options']}" }
|
638
|
+
]
|
96
639
|
end
|
97
640
|
|
98
641
|
# tries to set active backends via haproxy's stats socket
|
@@ -134,13 +677,14 @@ module Synapse
|
|
134
677
|
end
|
135
678
|
|
136
679
|
watcher.backends.each do |backend|
|
137
|
-
|
138
|
-
|
680
|
+
backend_name = construct_name(backend)
|
681
|
+
unless cur_backends[watcher.name].include? backend_name
|
682
|
+
log.debug "synapse: restart required because we have a new backend #{watcher.name}/#{backend_name}"
|
139
683
|
@restart_required = true
|
140
684
|
return
|
141
685
|
end
|
142
686
|
|
143
|
-
enabled_backends[watcher.name] <<
|
687
|
+
enabled_backends[watcher.name] << backend_name
|
144
688
|
end
|
145
689
|
end
|
146
690
|
|
@@ -192,9 +736,22 @@ module Synapse
|
|
192
736
|
|
193
737
|
# restarts haproxy
|
194
738
|
def restart
|
739
|
+
# sleep if we restarted too recently
|
740
|
+
delay = (@last_restart - Time.now) + @restart_interval
|
741
|
+
sleep(delay) if delay > 0
|
742
|
+
|
743
|
+
# do the actual restart
|
195
744
|
res = `#{opts['reload_command']}`.chomp
|
196
745
|
raise "failed to reload haproxy via #{opts['reload_command']}: #{res}" unless $?.success?
|
746
|
+
|
747
|
+
@last_restart = Time.now()
|
197
748
|
@restart_required = false
|
198
749
|
end
|
750
|
+
|
751
|
+
# used to build unique, consistent haproxy names for backends
|
752
|
+
def construct_name(backend)
|
753
|
+
address_digest = Digest::SHA256.hexdigest(backend['host'])[0..7]
|
754
|
+
return "#{backend['name']}:#{backend['port']}_#{address_digest}"
|
755
|
+
end
|
199
756
|
end
|
200
757
|
end
|