consul-templaterb 1.28.1 → 1.31.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -2
- data/bin/consul-templaterb +5 -0
- data/lib/consul/async/consul_endpoint.rb +28 -2
- data/lib/consul/async/version.rb +1 -1
- data/samples/consul-ui/.preferences.rb.samples +1 -0
- data/samples/consul-ui/README.md +6 -0
- data/samples/consul-ui/consul_services.json.erb +14 -1
- data/samples/consul-ui/decorators.js.erb +7 -0
- data/samples/consul-ui/js/nodes.js +1 -1
- data/samples/consul-ui/js/service.js +1 -1
- data/samples/consul-ui/js/timeline.js +1 -1
- data/samples/consul-ui/js/utils.js +8 -5
- data/samples/consul-ui/timeline.json.erb +4 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5d188151cdf2f004d4993cc5620ad86ce8632e2de820ca6498d37ce8acbd4c9
|
4
|
+
data.tar.gz: 6469c2b6d1a9032bb16fdfbe53b062a2271e3a787dcc0f52bb0e749c081081e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 498a5282930d98afe30840f8f167559783aafa7d17b9a902ff8950dac5727d8496c666d0dea01d10ac59cfe4e845ca5664ded482b16641d4723f3edd5fa9053a
|
7
|
+
data.tar.gz: a2526b83b9083275b6d1057948d80457f8ea4aede46201b15408fe331a329430d6785f8372339b8c2e139da2f1fe96c13a699d4b6c936f98d411c26b797413c2
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,41 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
## (
|
3
|
+
## 1.31.1 (Jan 25, 2021)
|
4
4
|
|
5
|
-
|
5
|
+
IMPROVEMENTS:
|
6
|
+
|
7
|
+
* Use Node.Meta.fqdn to display node names in timeline if set
|
8
|
+
|
9
|
+
## 1.31.0 (Jan 18, 2021)
|
10
|
+
|
11
|
+
IMPROVEMENTS:
|
12
|
+
|
13
|
+
* Do not apply penalty on unmodified services not changing much (Will improve streaming performance)
|
14
|
+
|
15
|
+
## 1.30.0 (Dec 18, 2020)
|
16
|
+
|
17
|
+
IMPROVEMENTS:
|
18
|
+
|
19
|
+
* Allow customization to sort nodes in service view in Consul-UI ([#71](https://github.com/criteo/consul-templaterb/pull/71))
|
20
|
+
|
21
|
+
NEW FEATURES:
|
22
|
+
|
23
|
+
* Auto-detection of rate-limit on Consul Side (introduced in Consul 1.6.2+), this feature
|
24
|
+
will work only Consul 1.9+ (see [Consul #7527](https://github.com/hashicorp/consul/issues/7527)).
|
25
|
+
|
26
|
+
## 1.29.0 (Oct 6, 2020)
|
27
|
+
|
28
|
+
IMPROVEMENTS:
|
29
|
+
|
30
|
+
* When no template has been specified, stop early with an error message
|
31
|
+
|
32
|
+
## 1.28.2 (Oct 5, 2020)
|
33
|
+
|
34
|
+
NEW FEATURES:
|
35
|
+
|
36
|
+
* Added new decorator to compute node names in consul-ui ([#70](https://github.com/criteo/consul-templaterb/pull/70))
|
37
|
+
|
38
|
+
## 1.28.1 (Sept 30, 2020)
|
6
39
|
|
7
40
|
IMPROVEMENTS:
|
8
41
|
|
data/bin/consul-templaterb
CHANGED
@@ -375,6 +375,11 @@ ARGV.each do |tpl|
|
|
375
375
|
consul_engine.add_template(tpl, dest)
|
376
376
|
end
|
377
377
|
|
378
|
+
if consul_engine.templates.count.zero?
|
379
|
+
puts 'You must specify at least one template as arg or using -t'
|
380
|
+
exit 255
|
381
|
+
end
|
382
|
+
|
378
383
|
template_manager = Consul::Async::EndPointsManager.new(consul_conf, vault_conf, consul_engine.templates, options[:erb][:trim_mode])
|
379
384
|
|
380
385
|
Signal.trap('USR1', 'IGNORE') unless Gem.win_platform?
|
@@ -225,9 +225,34 @@ module Consul
|
|
225
225
|
retry_in / 2 + Consul::Async::Utilities.random.rand(retry_in)
|
226
226
|
end
|
227
227
|
|
228
|
+
# rubocop:disable Style/ClassVars
|
229
|
+
def _last_429
|
230
|
+
@@_last_429 ||= { count: 0 }
|
231
|
+
end
|
232
|
+
# rubocop:enable Style/ClassVars
|
233
|
+
|
228
234
|
def _handle_error(http, consul_index)
|
229
235
|
retry_in = _compute_retry_in([600, conf.retry_duration + 2**@consecutive_errors].min)
|
230
|
-
|
236
|
+
if http.response_header.status == 429
|
237
|
+
_last_429
|
238
|
+
retry_in = 60 + Consul::Async::Utilities.random.rand(180) if retry_in < 60
|
239
|
+
_last_429[:time] = Time.now.utc
|
240
|
+
_last_429[:count] += 1
|
241
|
+
if (_last_429[:count] % 10) == 1
|
242
|
+
if _last_429[:count] == 1
|
243
|
+
::Consul::Async::Debug.puts_error "Rate limiting detected on Consul side (HTTP 429)!\n\n" \
|
244
|
+
"******************************* CONFIGURATION ISSUE DETECTED *******************************\n" \
|
245
|
+
"* Too many simultaneous connections for Consul agent #{conf.base_url}\n" \
|
246
|
+
"* You should tune 'limits.http_max_conns_per_client' to a higher value.\n" \
|
247
|
+
"* This program will behave badly until you change this.\n" \
|
248
|
+
"* See https://www.consul.io/docs/agent/options.html#http_max_conns_per_client for more info\n" \
|
249
|
+
"********************************************************************************************\n\n"
|
250
|
+
end
|
251
|
+
::Consul::Async::Debug.puts_error "[#{path}] Too many conns to #{conf.base_url}, errors=#{_last_429[:count]} - Retry in #{retry_in}s #{stats.body_bytes_human}"
|
252
|
+
end
|
253
|
+
else
|
254
|
+
::Consul::Async::Debug.puts_error "[#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
|
255
|
+
end
|
231
256
|
@consecutive_errors += 1
|
232
257
|
http_result = HttpResponse.new(http)
|
233
258
|
EventMachine.add_timer(retry_in) do
|
@@ -272,11 +297,12 @@ module Consul
|
|
272
297
|
end
|
273
298
|
new_content = http_result.response.freeze
|
274
299
|
modified = @last_result.fake? || @last_result.data != new_content
|
275
|
-
if n_consul_index
|
300
|
+
if n_consul_index.nil?
|
276
301
|
retry_in = modified ? conf.missing_index_retry_time_on_diff : conf.missing_index_retry_time_on_unchanged
|
277
302
|
n_consul_index = consul_index
|
278
303
|
else
|
279
304
|
retry_in = modified ? conf.min_duration : conf.retry_on_non_diff
|
305
|
+
retry_in = 0.1 if retry_in < (Time.now - @last_result.last_update)
|
280
306
|
end
|
281
307
|
retry_in = _compute_retry_in(retry_in)
|
282
308
|
retry_in = 0.1 if retry_in < 0.1
|
data/lib/consul/async/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
SORT_CONSUL_SERVICE_NODES = -> (nodes) { nodes.sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] } }
|
data/samples/consul-ui/README.md
CHANGED
@@ -94,3 +94,9 @@ This app supports the following environment variables:
|
|
94
94
|
* `EXCLUDE_SERVICES`: comma-separated services to exclude (default: lbl7.*,netsvc-probe.*,consul-probed.*)
|
95
95
|
* `CONSUL_TIMELINE_BUFFER`: number of entries to keep in the timeline. 1000 by default.
|
96
96
|
* `CONSUL_TIMELINE_BLACKLIST`: regexp of services to hide from timeline
|
97
|
+
|
98
|
+
### Preferences
|
99
|
+
|
100
|
+
Some templates allows you to override some behavior through `.preferences.rb` file.
|
101
|
+
In order to do that, rename `.preferences.rb.samples` file to `.preferences.rb`
|
102
|
+
and update lambda defined inside to match targeted behavior.
|
@@ -6,6 +6,19 @@
|
|
6
6
|
# INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary)
|
7
7
|
# EXCLUDE_SERVICES: comma-separated services regexps to exclude (default: lbl7.*,netsvc-probe.*,consul-probed.*)
|
8
8
|
|
9
|
+
unless @sort_consul_service_nodes
|
10
|
+
begin
|
11
|
+
target_dir = File.split(File.expand_path(template_info['source']))[0]
|
12
|
+
target = File.join(target_dir, '.preferences.rb')
|
13
|
+
load "#{target}"
|
14
|
+
STDERR.puts "Using #{target} file."
|
15
|
+
@sort_consul_service_nodes = SORT_CONSUL_SERVICE_NODES
|
16
|
+
rescue LoadError
|
17
|
+
STDERR.puts 'Couldn\'t find .preferences.rb file ; default configuration will be used.'
|
18
|
+
@sort_consul_service_nodes = -> (nodes) { nodes.sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] } }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
9
22
|
service_tag_filter = ENV['SERVICES_TAG_FILTER'] || nil
|
10
23
|
instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
|
11
24
|
instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG']
|
@@ -20,7 +33,7 @@
|
|
20
33
|
if !services_blacklist.any? {|r| r.match(service_name)} && (instance_must_tag.nil? || tags.include?(instance_must_tag))
|
21
34
|
tags_per_service[service_name] = tags.sort
|
22
35
|
the_backends = []
|
23
|
-
service(service_name).
|
36
|
+
@sort_consul_service_nodes.call(service(service_name)).each do |snode|
|
24
37
|
tags_of_instance = snode['Service']['Tags'].sort
|
25
38
|
if (instance_must_tag.nil? || tags_of_instance.include?(instance_must_tag)) && !tags_of_instance.include?(instance_exclude_tag)
|
26
39
|
the_backends << snode if snode['Service']['Port']
|
@@ -36,6 +36,13 @@ function usefullLinksGenerator(instance, serviceName, node_meta_info) {
|
|
36
36
|
return top;
|
37
37
|
}
|
38
38
|
|
39
|
+
/**
|
40
|
+
* createNodeDisplayElement resolves and displays the node name.
|
41
|
+
*/
|
42
|
+
function createNodeDisplayElement(nodeName, nodemeta) {
|
43
|
+
return document.createTextNode(nodeName);
|
44
|
+
}
|
45
|
+
|
39
46
|
/**
|
40
47
|
* serviceInstanceDecorator is called to decorate an instance.
|
41
48
|
*/
|
@@ -71,7 +71,7 @@ class NodeMainSelector extends MainSelector {
|
|
71
71
|
content.setAttribute('class', 'instance-content');
|
72
72
|
var contentHead = document.createElement('div');
|
73
73
|
contentHead.setAttribute('class', 'instance-content-header');
|
74
|
-
contentHead.appendChild(nodeNameGenator(node['Node']
|
74
|
+
contentHead.appendChild(nodeNameGenator(node['Node']));
|
75
75
|
contentHead.appendChild(nodeAddressGenator(node['Node']['Address']));
|
76
76
|
contentHead.appendChild(nodeMetaGenerator(node['Node']['Meta']));
|
77
77
|
content.appendChild(contentHead);
|
@@ -304,8 +304,8 @@ class ServiceMainSelector extends MainSelector {
|
|
304
304
|
element.setAttribute("class", "list-group-item service-instance");
|
305
305
|
var state = nodeState(instance.checks);
|
306
306
|
element.appendChild(weightsGenerator(instance.weights, state));
|
307
|
-
element.appendChild(serviceTitleGenerator(instance, serviceName));
|
308
307
|
var node_info = this.nodes[instance.name];
|
308
|
+
element.appendChild(serviceTitleGenerator(instance, serviceName, node_info));
|
309
309
|
if (node_info != null) {
|
310
310
|
node_info = node_info.meta;
|
311
311
|
element.appendChild(nodeMetaGenerator(node_info, instance.sMeta));
|
@@ -434,7 +434,7 @@ class ServiceTimeline {
|
|
434
434
|
}
|
435
435
|
var text = e.instance;
|
436
436
|
if (e.instance_info && e.instance_info.node) {
|
437
|
-
text = e.instance_info.
|
437
|
+
text = e.instance_info.fqdn;
|
438
438
|
if (e.instance_info.port > 0) {
|
439
439
|
text += ":" + e.instance_info.port
|
440
440
|
}
|
@@ -63,7 +63,7 @@ function nodeState(checks) {
|
|
63
63
|
|
64
64
|
supported_protocols = ['https', 'http', 'sftp', 'ftp', 'ssh', 'telnet']
|
65
65
|
|
66
|
-
function serviceTitleGenerator(instance, serviceName) {
|
66
|
+
function serviceTitleGenerator(instance, serviceName, node_info) {
|
67
67
|
var protocol = null;
|
68
68
|
for (i in supported_protocols) {
|
69
69
|
var protoc = supported_protocols[i]
|
@@ -86,7 +86,10 @@ function serviceTitleGenerator(instance, serviceName) {
|
|
86
86
|
instanceLink.setAttribute('target', '_blank');
|
87
87
|
}
|
88
88
|
|
89
|
-
|
89
|
+
var nodemeta = (node_info != null) ? node_info.meta : null;
|
90
|
+
instanceLink.appendChild(createNodeDisplayElement(instance.name, nodemeta));
|
91
|
+
instanceLink.appendChild(document.createTextNode(appendPort));
|
92
|
+
|
90
93
|
const nodeInfo = document.createElement('a');
|
91
94
|
nodeInfo.appendChild(document.createTextNode('\u24D8'));
|
92
95
|
nodeInfo.setAttribute('title', 'Click to see details of Node: ' + instance.name +
|
@@ -103,7 +106,7 @@ function serviceTitleGenerator(instance, serviceName) {
|
|
103
106
|
return htmlTitle;
|
104
107
|
}
|
105
108
|
|
106
|
-
function nodeNameGenator(
|
109
|
+
function nodeNameGenator(node) {
|
107
110
|
var protocol = 'ssh://'
|
108
111
|
|
109
112
|
var htmlTitle = document.createElement('h5');
|
@@ -111,10 +114,10 @@ function nodeNameGenator(nodename, nodeaddr) {
|
|
111
114
|
var instanceLink = document.createElement('a');
|
112
115
|
instanceLink.setAttribute('class', 'instance-name');
|
113
116
|
if (protocol != null) {
|
114
|
-
instanceLink.setAttribute('href', protocol +
|
117
|
+
instanceLink.setAttribute('href', protocol + node['Address']);
|
115
118
|
instanceLink.setAttribute('target', '_blank');
|
116
119
|
}
|
117
|
-
instanceLink.appendChild(
|
120
|
+
instanceLink.appendChild(createNodeDisplayElement(node['Name'], node['Meta']));
|
118
121
|
htmlTitle.appendChild(instanceLink);
|
119
122
|
|
120
123
|
return htmlTitle;
|
@@ -41,10 +41,12 @@ cur_state = services.map do |service_name, _tags|
|
|
41
41
|
mindex = chk['ModifyIndex'] || 0
|
42
42
|
mod_index = mindex if mod_index < mindex
|
43
43
|
end
|
44
|
-
|
44
|
+
node_name = instance['Node']['Node']
|
45
|
+
["#{node_name}:#{instance['Service']['ID']}",
|
45
46
|
{
|
46
47
|
'address' => instance.service_address,
|
47
|
-
'node' =>
|
48
|
+
'node' => node_name,
|
49
|
+
'fqdn' => instance.node_meta['fqdn'] || node_name,
|
48
50
|
'port' => instance['Service']['Port'],
|
49
51
|
'idx' => mod_index || cur_index,
|
50
52
|
'status' => instance.status,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consul-templaterb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.31.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SRE Core Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -181,6 +181,7 @@ files:
|
|
181
181
|
- samples/all_services_multi_agents.txt.erb
|
182
182
|
- samples/all_templates.erb
|
183
183
|
- samples/checks_in_warning_or_critical_state.yaml.erb
|
184
|
+
- samples/consul-ui/.preferences.rb.samples
|
184
185
|
- samples/consul-ui/README.md
|
185
186
|
- samples/consul-ui/common/footer.html.erb
|
186
187
|
- samples/consul-ui/common/header.html.erb
|