consul-templaterb 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.gitreview +5 -0
- data/.rspec +2 -0
- data/.rubocop.yml +43 -0
- data/.ruby_app +0 -0
- data/.travis.yml +13 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +201 -0
- data/README.md +270 -0
- data/Rakefile +6 -0
- data/bin/consul-templaterb +246 -0
- data/consul-templaterb.gemspec +37 -0
- data/lib/consul/async/consul_endpoint.rb +279 -0
- data/lib/consul/async/consul_template.rb +323 -0
- data/lib/consul/async/consul_template_engine.rb +57 -0
- data/lib/consul/async/consul_template_render.rb +80 -0
- data/lib/consul/async/process_handler.rb +64 -0
- data/lib/consul/async/utilities.rb +17 -0
- data/lib/consul/async/version.rb +5 -0
- data/samples/checks.html.erb +96 -0
- data/samples/common/footer.html.erb +10 -0
- data/samples/common/header.html.erb +51 -0
- data/samples/consul_template.html.erb +94 -0
- data/samples/consul_template.json.erb +77 -0
- data/samples/consul_template.txt.erb +45 -0
- data/samples/consul_template.xml.erb +70 -0
- data/samples/criteo/haproxy.cfg.erb +163 -0
- data/samples/criteo_choregraphies.html.erb +91 -0
- data/samples/ha_proxy.cfg.erb +127 -0
- data/samples/keys.html.erb +38 -0
- data/samples/nodes.html.erb +17 -0
- data/samples/services.html.erb +89 -0
- metadata +189 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
<%
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
def build_node(e, name, attributes, text = nil)
|
5
|
+
xe = REXML::Element.new(name)
|
6
|
+
attributes.each do |name|
|
7
|
+
xe.add_attribute name, e[name]
|
8
|
+
end
|
9
|
+
xe.text = text if text
|
10
|
+
xe
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_datacenters
|
14
|
+
xdatacenters = REXML::Element.new 'datacenters'
|
15
|
+
datacenters.each do |dc|
|
16
|
+
xdc = REXML::Element.new 'datacenter'
|
17
|
+
xdc.add_attribute 'name', dc
|
18
|
+
xdc.add_attribute 'services', services(dc:dc).keys.count
|
19
|
+
xdc.add_attribute 'nodes', nodes(dc:dc).count
|
20
|
+
xdatacenters.add_element xdc
|
21
|
+
end
|
22
|
+
xdatacenters
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_services
|
26
|
+
xservices = REXML::Element.new 'services'
|
27
|
+
xservices.add_attribute 'count', services.count
|
28
|
+
services.each do |service_name, tags|
|
29
|
+
xserv = REXML::Element.new 'service'
|
30
|
+
xserv.add_attribute 'name', service_name
|
31
|
+
xserv.add_attribute 'tags', tags.sort.join(',')
|
32
|
+
xnodes = REXML::Element.new 'instances'
|
33
|
+
xnodes.add_attribute 'count', service(service_name).count
|
34
|
+
service(service_name).sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
|
35
|
+
xnode = REXML::Element.new 'service-instance'
|
36
|
+
xnode.add_attribute 'id', snode['Node']['ID'] if snode['Node']['ID']
|
37
|
+
xnode.add_attribute 'address', snode['Node']['Address']
|
38
|
+
xnode.add_attribute 'name', snode['Node']['Name']
|
39
|
+
xnode.add_attribute 'port', snode['Service']['Port'].to_i
|
40
|
+
xnode.add_attribute 'tags', snode['Service']['Tags'].sort.join(',')
|
41
|
+
xnode.add_attribute 'statuses', (snode['Checks'].map { |c| c['Status'] }.join(' '))
|
42
|
+
xnodes.add_element xnode
|
43
|
+
end
|
44
|
+
xserv.add_element xnodes
|
45
|
+
xservices.add_element xserv
|
46
|
+
end
|
47
|
+
xservices
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_nodes
|
51
|
+
xnodes = REXML::Element.new 'nodes'
|
52
|
+
xnodes.add_attribute 'count', nodes.count
|
53
|
+
nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
|
54
|
+
xnode = REXML::Element.new 'node'
|
55
|
+
xnode.add_attribute 'id', snode['ID']
|
56
|
+
xnode.add_attribute 'address', snode['Address']
|
57
|
+
xnode.add_attribute 'name', snode['Node']
|
58
|
+
xnodes.add xnode
|
59
|
+
end
|
60
|
+
xnodes
|
61
|
+
end
|
62
|
+
doc = REXML::Document.new '<consul-info/>'
|
63
|
+
doc << REXML::XMLDecl.new(version='1.0', 'UTF-8')
|
64
|
+
|
65
|
+
doc.root.add_element create_datacenters
|
66
|
+
doc.root.add_element create_services
|
67
|
+
doc.root.add_element create_nodes
|
68
|
+
result = ''
|
69
|
+
doc.write(result, 2)
|
70
|
+
%><%= result %>
|
@@ -0,0 +1,163 @@
|
|
1
|
+
<%
|
2
|
+
# This template can be configure the following way with environment variables
|
3
|
+
# Environment variables to filter services/instances
|
4
|
+
# SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
|
5
|
+
# INSTANCE_MUST_TAG: Second level of filtering (optional, default to SERVICES_TAG_FILTER)
|
6
|
+
# INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary)
|
7
|
+
# EXCLUDE_SERVICES: comma-separated services to exclude (default: consul-agent-http,mesos-slave,mesos-agent-watcher)
|
8
|
+
# Environment variables to configure HaProxy
|
9
|
+
# PORT0 : HaProxy main port (default to 8000)
|
10
|
+
# PORT1 : HaProxy admin port (default to 8001)
|
11
|
+
# HAPROXY_ADMIN_PORT: Port to listen
|
12
|
+
# HAPROXY_ADMIN_USER_PASSWORD: User:Password to access to stats (default: none)
|
13
|
+
# HAPROXY_SOCKET_FILE: HaProxy socket to control HaProxy
|
14
|
+
|
15
|
+
service_tag_filter = ENV['SERVICES_TAG_FILTER'] || 'http'
|
16
|
+
instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
|
17
|
+
instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG'] || 'canary'
|
18
|
+
kv_root = ENV['KV_ROOT'] || "services-data"
|
19
|
+
optional_dns_suffix = ENV['DNS_SUFFIX'] || ''
|
20
|
+
|
21
|
+
# Services to hide
|
22
|
+
services_blacklist = (ENV['EXCLUDE_SERVICES'] || 'consul-agent-http,mesos-slave,mesos-agent-watcher,mesos-exporter-slave').split(',')
|
23
|
+
# Compute the health of a Service
|
24
|
+
def compute_state(node)
|
25
|
+
states = ['passing', []]
|
26
|
+
node['Checks'].each do |chk|
|
27
|
+
st = chk['Status']
|
28
|
+
states[1] << st
|
29
|
+
states[0] = st if st == 'critical' || (st == 'warning' && states[0] == 'passing')
|
30
|
+
end
|
31
|
+
states
|
32
|
+
end
|
33
|
+
def compute_attributes(node)
|
34
|
+
w = 100
|
35
|
+
node['Service']['Tags'].each do |tag|
|
36
|
+
match = /^weight-([1-9][0-9])*$/.match(tag)
|
37
|
+
w = match[1].to_i if match
|
38
|
+
end
|
39
|
+
attributes = ""
|
40
|
+
states = compute_state(node)
|
41
|
+
attributes = "#{attributes} disabled" if states[0] == 'critical'
|
42
|
+
if states[0] == 'warning'
|
43
|
+
w = w / 8
|
44
|
+
end
|
45
|
+
attributes = "#{attributes} weight #{w}" if w.positive?
|
46
|
+
end
|
47
|
+
backends = {}
|
48
|
+
all_kv = {}
|
49
|
+
services(tag: service_tag_filter).each do |service_name, tags|
|
50
|
+
if !services_blacklist.include?(service_name) && tags.include?(instance_must_tag)
|
51
|
+
the_backends = []
|
52
|
+
kv_data = kv("#{kv_root}/#{service_name}/network-service").get_value_json
|
53
|
+
all_kv[service_name] = kv_data if kv_data
|
54
|
+
service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |node|
|
55
|
+
tags_of_instance = node['Service']['Tags']
|
56
|
+
if tags_of_instance.include?(instance_must_tag) && !tags_of_instance.include?(instance_exclude_tag)
|
57
|
+
the_backends << node if node['Service']['Port']
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# We add the backend ONLY if at least one valid instance does exists
|
61
|
+
backends[service_name] = the_backends
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@all_kv = all_kv
|
66
|
+
def find_alternative_fqdns(service_name)
|
67
|
+
json_kv = @all_kv[service_name]
|
68
|
+
return nil unless json_kv
|
69
|
+
return nil unless json_kv['alternative_fqdn']
|
70
|
+
# Add spaces before
|
71
|
+
" #{json_kv['alternative_fqdn'].join(' ')}"
|
72
|
+
end
|
73
|
+
%>global
|
74
|
+
log 127.0.0.1 local0 info
|
75
|
+
maxconn 262144
|
76
|
+
user haproxy
|
77
|
+
group haproxy
|
78
|
+
nbproc 1
|
79
|
+
daemon
|
80
|
+
stats socket /var/lib/haproxy/stats level admin mode 644 expose-fd listeners
|
81
|
+
stats timeout 2m
|
82
|
+
tune.bufsize 33792
|
83
|
+
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
84
|
+
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
|
85
|
+
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
86
|
+
ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
|
87
|
+
ssl-server-verify required
|
88
|
+
|
89
|
+
defaults
|
90
|
+
log global
|
91
|
+
mode http
|
92
|
+
retries 3
|
93
|
+
timeout connect 10s
|
94
|
+
timeout client 30s
|
95
|
+
timeout server 30s
|
96
|
+
timeout http-keep-alive 10s
|
97
|
+
timeout http-request 10s
|
98
|
+
timeout queue 1s
|
99
|
+
timeout check 5s
|
100
|
+
option httplog
|
101
|
+
option dontlognull
|
102
|
+
option redispatch
|
103
|
+
option prefer-last-server
|
104
|
+
option dontlog-normal
|
105
|
+
option http-keep-alive
|
106
|
+
option forwardfor except 127.0.0.0/8
|
107
|
+
balance roundrobin
|
108
|
+
maxconn 262134
|
109
|
+
http-reuse safe
|
110
|
+
default-server inter 5s fastinter 1s fall 3 slowstart 20s
|
111
|
+
|
112
|
+
listen stats
|
113
|
+
bind *:8080
|
114
|
+
stats enable
|
115
|
+
stats uri /haproxy_stats
|
116
|
+
|
117
|
+
# ==== Managed by consul-templaterb ====
|
118
|
+
|
119
|
+
frontend fe_main # HTTP(S) Service
|
120
|
+
bind *:80 name http
|
121
|
+
|
122
|
+
# Monitoring
|
123
|
+
monitor-uri /delivery/monitor/mesos-haproxy/lb-check
|
124
|
+
errorfile 200 /etc/haproxy/200-criteo-ok.txt
|
125
|
+
|
126
|
+
# Adding a header indicating client side is using HTTPS
|
127
|
+
acl http ssl_fc,not
|
128
|
+
acl https ssl_fc
|
129
|
+
http-request set-header X-Forwarded-Protocol https if https
|
130
|
+
|
131
|
+
# Disable CONNECT globally (identified as vulnerability by audit tools such as Qualys)
|
132
|
+
acl ::disabled_http_methods method CONNECT
|
133
|
+
http-request block if ::disabled_http_methods
|
134
|
+
|
135
|
+
# Consul-agent ACL
|
136
|
+
acl consul-agent-http-acl hdr_dom(host) -i consul-agent-http.lb-ty5.crto.in consul-agent-http.lb-ty5.central.criteo.prod
|
137
|
+
use_backend bestatic_consul-agent-http if consul-agent-http-acl
|
138
|
+
|
139
|
+
# ACLs, HTTP Host header based, following the pattern <consul_app_name>.<fqdn_suffix>
|
140
|
+
<% backends.each_pair do |service_name, nodes|
|
141
|
+
%>
|
142
|
+
acl <%= service_name %>-acl hdr_beg(host) -i <%= service_name %>.<%= optional_dns_suffix %><%= find_alternative_fqdns(service_name)%>
|
143
|
+
use_backend be_<%= service_name %> if <%= service_name%>-acl
|
144
|
+
<% end %>
|
145
|
+
|
146
|
+
# Backends
|
147
|
+
backend bestatic_consul-agent-http
|
148
|
+
http-request deny if !METH_GET # Deny writes
|
149
|
+
server srv0 127.0.0.1:8500
|
150
|
+
|
151
|
+
<% backends.each_pair do |service_name, nodes|
|
152
|
+
%>
|
153
|
+
backend be_<%= service_name %>
|
154
|
+
<% if all_kv[service_name] %>
|
155
|
+
# data2: <%= all_kv[service_name] %>
|
156
|
+
<% end %>
|
157
|
+
mode http
|
158
|
+
balance leastconn
|
159
|
+
<% nodes.each_with_index do |node, idx|
|
160
|
+
%> server srv<%= idx %> <%= node['Node']['Address']%>:<%= node['Service']['Port'] %><%= compute_attributes(node) %>
|
161
|
+
<% end
|
162
|
+
end
|
163
|
+
%>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
<% require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'date'
|
4
|
+
@current_time = Time.now.utc
|
5
|
+
%>
|
6
|
+
<%= render_file 'common/header.html.erb' %>
|
7
|
+
<main role="main" class="container">
|
8
|
+
<div>
|
9
|
+
<h1>Show all choregraphie information</h1>
|
10
|
+
<div>This page only show choregraphie when at least one holder exists.</div>
|
11
|
+
<%
|
12
|
+
def display_holder(holder, value)
|
13
|
+
begin
|
14
|
+
holder_date = Time.parse(value)
|
15
|
+
status = 'success'
|
16
|
+
diff = (@current_time - holder_date).round(0)
|
17
|
+
status = 'warning' if diff > 3600
|
18
|
+
status = 'danger' if diff > 7200
|
19
|
+
diff_txt = "#{diff % 3600} seconds"
|
20
|
+
diff_txt = "#{(diff % 86400) / 3600} hours, #{diff_txt}" if diff > 3600
|
21
|
+
diff_txt = "#{diff / 86400} days, #{diff_txt}" if diff > 86400
|
22
|
+
rescue StandardError => e
|
23
|
+
status = 'info'
|
24
|
+
holder_date = "Cannot parse date: #{e}"
|
25
|
+
diff_txt = "Error Parsing date #{value}"
|
26
|
+
end
|
27
|
+
["<li class=\"list-group-item list-group-item-#{status}\">#{holder}: #{holder_date} : #{diff_txt} ago", status]
|
28
|
+
end
|
29
|
+
%>
|
30
|
+
|
31
|
+
<div id="accordion">
|
32
|
+
<% kv('choregraphie', recurse:true).each do |tuple| %>
|
33
|
+
<!-- <%= tuple['Key'] %> -->
|
34
|
+
<%
|
35
|
+
key = tuple['Key'].gsub('/', '-')
|
36
|
+
if tuple['Value'].nil?
|
37
|
+
json = []
|
38
|
+
holders = []
|
39
|
+
%>
|
40
|
+
<div class="alert alert-warning" role="alert">
|
41
|
+
Invalid Choregraphie data: <%= tuple %>
|
42
|
+
</div>
|
43
|
+
<%
|
44
|
+
else
|
45
|
+
json = JSON.parse(Base64.decode64(tuple['Value']))
|
46
|
+
holders = json['holders']
|
47
|
+
end
|
48
|
+
%>
|
49
|
+
<% if holders.count > 0 %>
|
50
|
+
|
51
|
+
<div class="card">
|
52
|
+
<div class="card-header" id="heading-<%= key %>">
|
53
|
+
<span class="badge badge-pill badge-primary float-right"><%= holders.count%>/<%= json['concurrency'] %></span>
|
54
|
+
<h5 class="mb-0">
|
55
|
+
<a href="#<%= key %>" class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-<%= key %>" aria-expanded="true" aria-controls="collapse-<%= key %>">
|
56
|
+
<%= tuple['Key'] %>
|
57
|
+
</a>
|
58
|
+
</h5>
|
59
|
+
</div>
|
60
|
+
<%
|
61
|
+
text_result = ''
|
62
|
+
clazz = 'collapse'
|
63
|
+
holders.each_pair do |key,value|
|
64
|
+
if value.is_a?(Hash)
|
65
|
+
text_result+= "<li><u>#{key}:</u><ul class=\"list-group\">"
|
66
|
+
value.each_pair do |k, v|
|
67
|
+
res, status = display_holder(k, v)
|
68
|
+
clazz = 'collapse show' unless status == 'success'
|
69
|
+
text_result += res
|
70
|
+
end
|
71
|
+
text_result += '</ul></li>'
|
72
|
+
else
|
73
|
+
res, status = display_holder(key, value)
|
74
|
+
clazz = 'collapse show' unless status == 'success'
|
75
|
+
text_result << res
|
76
|
+
end
|
77
|
+
end
|
78
|
+
%>
|
79
|
+
<div id="collapse-<%= key %>" class="<%= clazz %>" aria-labelledby="heading-<%= key %>" data-parent="#accordion">
|
80
|
+
<div class="card-body">
|
81
|
+
<pre class="pre-scrollable"><code><%= JSON.pretty_generate(json) %></code></pre>
|
82
|
+
<ul class="list-group">
|
83
|
+
<%= text_result %>
|
84
|
+
</ul>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
<% end %>
|
89
|
+
<% end %>
|
90
|
+
</div>
|
91
|
+
<%= render_file 'common/footer.html.erb' %>
|
@@ -0,0 +1,127 @@
|
|
1
|
+
<%
|
2
|
+
# This template can be configure the following way with environment variables
|
3
|
+
# Environment variables to filter services/instances
|
4
|
+
# SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
|
5
|
+
# INSTANCE_MUST_TAG: Second level of filtering (optional, default to SERVICES_TAG_FILTER)
|
6
|
+
# INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary)
|
7
|
+
# EXCLUDE_SERVICES: comma-separated services to exclude (default: consul-agent-http,mesos-slave,mesos-agent-watcher)
|
8
|
+
# Environment variables to configure HaProxy
|
9
|
+
# PORT0 : HaProxy main port (default to 8000)
|
10
|
+
# PORT1 : HaProxy admin port (default to 8001)
|
11
|
+
# HAPROXY_ADMIN_PORT: Port to listen
|
12
|
+
# HAPROXY_ADMIN_USER_PASSWORD: User:Password to access to stats (default: none)
|
13
|
+
# HAPROXY_SOCKET_FILE: HaProxy socket to control HaProxy
|
14
|
+
|
15
|
+
service_tag_filter = ENV['SERVICES_TAG_FILTER'] || 'http'
|
16
|
+
instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
|
17
|
+
instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG'] || 'canary'
|
18
|
+
|
19
|
+
# Services to hide
|
20
|
+
services_blacklist = (ENV['EXCLUDE_SERVICES'] || 'consul-agent-http,mesos-slave,mesos-agent-watcher,mesos-exporter-slave').split(',')
|
21
|
+
# Compute the health of a Service
|
22
|
+
def compute_state(node)
|
23
|
+
states = ['passing', []]
|
24
|
+
node['Checks'].each do |chk|
|
25
|
+
st = chk['Status']
|
26
|
+
states[1] << st
|
27
|
+
if st == 'critical'
|
28
|
+
states[0] = st
|
29
|
+
elsif st == 'warning' && states[0] == 'passing'
|
30
|
+
states[0] = st
|
31
|
+
end
|
32
|
+
end
|
33
|
+
states
|
34
|
+
end
|
35
|
+
def compute_attributes(node)
|
36
|
+
w = 100
|
37
|
+
node['Service']['Tags'].each do |tag|
|
38
|
+
match = /^weight-([1-9][0-9])*$/.match(tag)
|
39
|
+
w = match[1].to_i if match
|
40
|
+
end
|
41
|
+
attributes = ""
|
42
|
+
states = compute_state(node)
|
43
|
+
attributes = "#{attributes} disabled" if states[0] == 'critical'
|
44
|
+
if states[0] == 'warning'
|
45
|
+
w = w / 8
|
46
|
+
end
|
47
|
+
attributes = "#{attributes} weight #{w}" if w.positive?
|
48
|
+
end
|
49
|
+
backends = {}
|
50
|
+
services(tag: service_tag_filter).each do |service_name, tags|
|
51
|
+
if !services_blacklist.include?(service_name) && tags.include?(instance_must_tag)
|
52
|
+
the_backends = []
|
53
|
+
service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |node|
|
54
|
+
tags_of_instance = node['Service']['Tags']
|
55
|
+
if tags_of_instance.include?(instance_must_tag) && !tags_of_instance.include?(instance_exclude_tag)
|
56
|
+
the_backends << node if node['Service']['Port']
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# We add the backend ONLY if at least one valid instance does exists
|
60
|
+
backends[service_name] = the_backends
|
61
|
+
end
|
62
|
+
end
|
63
|
+
%>
|
64
|
+
# This HaProxy configuration is generated by consul-templaterb
|
65
|
+
# Service/Instances filtering
|
66
|
+
# Service tag MUST be <%= service_tag_filter %>
|
67
|
+
# Instance tag MUST be <%= instance_must_tag %>
|
68
|
+
# Instance tag excluded: <%= instance_exclude_tag %>
|
69
|
+
|
70
|
+
# Found <%= backends.keys.count %> different services with <%= backends.values.flatten.count %> nodes
|
71
|
+
|
72
|
+
global
|
73
|
+
maxconn 1024
|
74
|
+
<%
|
75
|
+
socket_file = ENV['HAPROXY_SOCKET_FILE']
|
76
|
+
if socket_file
|
77
|
+
%>
|
78
|
+
stats socket <%= socket_file %> mode 600 level admin
|
79
|
+
<% end %>
|
80
|
+
|
81
|
+
defaults
|
82
|
+
timeout connect 1000
|
83
|
+
timeout client 5000
|
84
|
+
timeout server 15000
|
85
|
+
<% backends.each_pair do |service_name, nodes|
|
86
|
+
%>
|
87
|
+
backend backend_http__<%= service_name %>
|
88
|
+
mode http
|
89
|
+
balance leastconn
|
90
|
+
<% nodes.each do |node|
|
91
|
+
%> server <%= node['Node']['Node']%>_<%= node['Service']['Port'] %> <%= node['Node']['Address']%>:<%= node['Service']['Port'] %><%= compute_attributes(node) %>
|
92
|
+
<% end
|
93
|
+
end
|
94
|
+
%>
|
95
|
+
frontend fontend_http
|
96
|
+
mode http
|
97
|
+
bind *:<%= ENV['PORT0'] || 8000 %>
|
98
|
+
option httplog
|
99
|
+
log 127.0.0.1:534 local5
|
100
|
+
option dontlognull
|
101
|
+
option forwardfor
|
102
|
+
<% backends.each_pair do |service_name, nodes|
|
103
|
+
%>
|
104
|
+
acl host__<%= service_name %> hdr_beg(host) -i <%= service_name %>.
|
105
|
+
use_backend backend_http__<%= service_name %> if host__<%= service_name%>
|
106
|
+
<% end %>
|
107
|
+
|
108
|
+
listen stats
|
109
|
+
bind :<%= ENV['PORT1'] || 8001 %>
|
110
|
+
mode http
|
111
|
+
log global
|
112
|
+
maxconn 10
|
113
|
+
timeout client 100s
|
114
|
+
timeout server 100s
|
115
|
+
timeout connect 100s
|
116
|
+
timeout queue 100s
|
117
|
+
stats enable
|
118
|
+
stats hide-version
|
119
|
+
stats refresh 30s
|
120
|
+
stats show-node
|
121
|
+
stats uri /haproxy?stats
|
122
|
+
<%
|
123
|
+
user_password = ENV['HAPROXY_ADMIN_USER_PASSWORD']
|
124
|
+
if user_password
|
125
|
+
%>
|
126
|
+
stats auth <%= user_password %>
|
127
|
+
<% end %>
|