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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca62994383929bd3874db5527f85efeaaf184fdb83b8f3b17e05fbadbfbbc90a
4
- data.tar.gz: e878ff880557ffdfd8db6e5cb900a19e8191d4db11ba28fa0b4e7bbe9b1b9240
3
+ metadata.gz: f5d188151cdf2f004d4993cc5620ad86ce8632e2de820ca6498d37ce8acbd4c9
4
+ data.tar.gz: 6469c2b6d1a9032bb16fdfbe53b062a2271e3a787dcc0f52bb0e749c081081e4
5
5
  SHA512:
6
- metadata.gz: 62afc852ef61329a30bba3a67f43ed372130d9a87cd1afce559b5f88f9aa0a6db336c84c63b173eaa96896e8c9088686cfa37f10d540cd91c80ca2fb976b00b3
7
- data.tar.gz: 4a02aa15f2d4f95e5d144e916bf6a51190a90756e134456aece5b4afbf7ba106e150faeb8cf7b0e09ff27f1f61b237c47dd11f236299d922a519e91b019e3705
6
+ metadata.gz: 498a5282930d98afe30840f8f167559783aafa7d17b9a902ff8950dac5727d8496c666d0dea01d10ac59cfe4e845ca5664ded482b16641d4723f3edd5fa9053a
7
+ data.tar.gz: a2526b83b9083275b6d1057948d80457f8ea4aede46201b15408fe331a329430d6785f8372339b8c2e139da2f1fe96c13a699d4b6c936f98d411c26b797413c2
@@ -1,8 +1,41 @@
1
1
  # CHANGELOG
2
2
 
3
- ## (UNRELEASED)
3
+ ## 1.31.1 (Jan 25, 2021)
4
4
 
5
- ## 1.28.1 (Sept 30,, 2020)
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
 
@@ -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
- ::Consul::Async::Debug.puts_error "[#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
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 == consul_index || n_consul_index.nil?
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
@@ -1,5 +1,5 @@
1
1
  module Consul
2
2
  module Async
3
- VERSION = '1.28.1'.freeze
3
+ VERSION = '1.31.1'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1 @@
1
+ SORT_CONSUL_SERVICE_NODES = -> (nodes) { nodes.sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] } }
@@ -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).sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
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']['Name'], node['Node']['Address']));
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.node;
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
- instanceLink.appendChild(document.createTextNode(instance.name + appendPort));
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(nodename, nodeaddr) {
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 + nodeaddr);
117
+ instanceLink.setAttribute('href', protocol + node['Address']);
115
118
  instanceLink.setAttribute('target', '_blank');
116
119
  }
117
- instanceLink.appendChild(document.createTextNode(nodename));
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
- ["#{instance['Node']['Node']}:#{instance['Service']['ID']}",
44
+ node_name = instance['Node']['Node']
45
+ ["#{node_name}:#{instance['Service']['ID']}",
45
46
  {
46
47
  'address' => instance.service_address,
47
- 'node' => instance['Node']['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.28.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: 2020-09-29 00:00:00.000000000 Z
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