consul-templaterb 1.9.9 → 1.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bc60bdb2bf31bd1da18ee4623f62fdf7a664daa5f31a273712168591612a666
4
- data.tar.gz: 05dbb95ce7faba2da08b30cd6c7e8cdd96246d4e0bd4fd93996b279c9c2f6c61
3
+ metadata.gz: 9d389019e21022ecf1c1e1783133ff49379d6e97141cf5a083b2c9c805c013f7
4
+ data.tar.gz: 4860d2607e32173aae5e4e2aa606564bc1cc1ccec4876d2079c7f22404c2a4b0
5
5
  SHA512:
6
- metadata.gz: 11019612ceefc6258fe2d578bfedc836689c82c7e3118621298d7eaea21b22e65a48778422e378b50ac7799f733af8c4af1d3330356b8a0d0b10758f829725f4
7
- data.tar.gz: aa338fff43589ddbc32b6d8bc20982cbd58bf0f2fd556cc18c46865014592fdffb8b9ccd7f34d54a352b3476474ceb4edfd53b12785fa1a2e76c0f9836851a4b
6
+ metadata.gz: d092840b101377b92a526778b6b77aa73cac04f7f97526fcd8e8c52a54bb9e335e8644e4c18362fa07cba982f5edd748d47bd0d2440c7f3ad0b4c037ec9d5cbf
7
+ data.tar.gz: 8805e42b635107b8936daf0b71e1f789afa9da4b61fb88aca3c0d3f4192d5d5a03f997cda5df5e3526433e81de95d436e8c4dbc5290673d357b29a1753c6449b
data/.gitignore CHANGED
@@ -19,7 +19,9 @@ samples/consul-ui/common/*.html
19
19
  /samples/criteo/haproxy.cfg
20
20
  /samples/consul_template
21
21
  /samples/metrics
22
+ /samples/service_checks_metrics
22
23
  /samples/find_blocked_choregraphies
24
+ /samples/tools/*.txt
23
25
  /spec/consul/async/resources/templates/*.txt
24
26
  /spec/consul/async/resources/templates/*.result
25
27
  /out.txt
@@ -29,7 +31,7 @@ samples/consul-ui/common/*.html
29
31
  # Mac OS
30
32
  .DS_Store
31
33
 
32
- # IntelliJ project files
34
+ # IntelliJ project files
33
35
  *.iml
34
36
  *.iws
35
37
  *.ipr
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## (UNRELEASED)
4
4
 
5
+ IMPROVEMENTS:
6
+
7
+ ## 1.10.0 (February 27, 2019)
8
+
9
+ * new sample [samples/tools/find_all_failing_services.txt.erb](samples/tools/find_all_failing_services.txt.erb)
10
+ to find all failing service instances on all DCs very easily.
11
+ * Do not report timestamps in metrics.erb as it is toxic for Prometheus
12
+ * in metrics.erb, add all net_info statistics to observe consul-templaterb itself
13
+ * new flag -l <error|info|debug> to control verbosity of messages
14
+ * Now diplays Checks of a Node in Consul-UI
15
+
5
16
  ## 1.9.9 (January 18, 2019)
6
17
 
7
18
  IMPROVEMENTS:
data/README.md CHANGED
@@ -144,6 +144,7 @@ USAGE: consul-templaterb [[options]]
144
144
  -v, --version Show Version
145
145
  -g, --no-gzip-compression Disable GZIP compression in HTTP requests
146
146
  -c, --consul-addr=<address> Address of Consul, eg: http://localhost:8500
147
+ -l, --log-level=<log_level> Log level, default=info, any of none|error|info|debug
147
148
  --consul-token=<token> Use a token to connect to Consul
148
149
  -V, --vault-addr=<address> Address of Vault, eg: http://localhost:8200
149
150
  --vault-token=<token> Token used to authenticate against vault.
@@ -239,6 +240,7 @@ examples:
239
240
  9. [Export Consul Statistics to Prometheus](samples/metrics.erb) : count all services, their state,
240
241
  datacenters and nodes and export it to prometheus easily to trigger alerts.
241
242
  10. [List all services/Nodes with their statuses for all datacenters](samples/all_services.txt.erb)
243
+ 11. [Show all services/instances not passing on all DCs](samples/tools/find_all_failing_services.txt.erb)
242
244
 
243
245
  If you want to test it quickly, you might try with (assuming your consul agent is listening on
244
246
  `http://localhost:8500`):
@@ -2,6 +2,7 @@
2
2
  # This script can be launched to get a uniq id for this instance
3
3
  require 'consul/async/consul_template_engine'
4
4
  require 'consul/async/process_handler'
5
+ require 'consul/async/debug'
5
6
  require 'consul/async/version'
6
7
  require 'optparse'
7
8
  require 'optparse/uri'
@@ -97,6 +98,10 @@ optparse = OptionParser.new do |opts|
97
98
  options[:consul][:base_url] = consul_url
98
99
  end
99
100
 
101
+ opts.on('-l', '--log-level=<log_level>', String, "Log level, default=info, any of #{::Consul::Async::Debug.levels.join('|')}") do |log_level|
102
+ ::Consul::Async::Debug.level = log_level
103
+ end
104
+
100
105
  opts.on('--consul-token=<token>', String, 'Use a token to connect to Consul') do |consul_token|
101
106
  options[:consul][:token] = consul_token
102
107
  end
@@ -177,7 +182,7 @@ optparse = OptionParser.new do |opts|
177
182
  begin
178
183
  @programs[cmd].process_status
179
184
  rescue Consul::Async::ProcessDoesNotExist => e
180
- STDERR.puts "[ERROR] The process is dead, aborting run: #{e.inspect}"
185
+ STDERR.puts "[FATAL] The process is dead, aborting run: #{e.inspect}"
181
186
  template_manager.terminate
182
187
  EventMachine.stop
183
188
  end
@@ -193,16 +198,16 @@ optparse = OptionParser.new do |opts|
193
198
  mod = false
194
199
  results = results.map do |res|
195
200
  mod ||= res.modified
196
- STDERR.puts "[INFO] Hot reload of template #{res.template_file} with success" if res.hot_reloaded
201
+ ::Consul::Async::Debug.puts_info "Hot reload of template #{res.template_file} with success" if res.hot_reloaded
197
202
  "#{res.modified ? 'WRITTEN' : 'UNCHANGED'}[#{res.output_file}]"
198
203
  end.join(' ')
199
204
  if mod
200
- STDERR.puts("[INFO] File written: #{results} #{template_manager.net_info.inspect}")
205
+ ::Consul::Async::Debug.puts_info "File written: #{results} #{template_manager.net_info.inspect}"
201
206
  else
202
- STDERR.print "[DBUG] Files not changed #{results} #{template_manager.net_info.inspect}\r"
207
+ ::Consul::Async::Debug.print_debug "Files not changed #{results} #{template_manager.net_info.inspect}\r"
203
208
  end
204
209
  else
205
- STDERR.print "[DBUG] Still waiting for data #{template_manager.net_info.inspect}...\r"
210
+ ::Consul::Async::Debug.print_debug "Still waiting for data #{template_manager.net_info.inspect}...\r"
206
211
  end
207
212
  end
208
213
  end
@@ -286,7 +291,7 @@ template_manager = Consul::Async::EndPointsManager.new(consul_conf, vault_conf,
286
291
 
287
292
  ARGV.each do |tpl|
288
293
  dest = compute_default_output(tpl)
289
- puts "Using #{dest} output for #{tpl}"
294
+ ::Consul::Async::Debug.puts_info "Using #{dest} output for #{tpl}"
290
295
  consul_engine.add_template(tpl, dest)
291
296
  end
292
297
 
@@ -37,7 +37,7 @@ module Consul
37
37
  def ch(path, symbol)
38
38
  sub = @paths[path.to_sym]
39
39
  if sub && sub[symbol]
40
- STDERR.puts "[INFO] Overriding #{symbol}:=#{sub[symbol]} for #{path}"
40
+ ::Consul::Async::Debug.puts_debug "Overriding #{symbol}:=#{sub[symbol]} for #{path}"
41
41
  sub[symbol]
42
42
  else
43
43
  method(symbol).call
@@ -196,7 +196,7 @@ module Consul
196
196
 
197
197
  def _handle_error(http, consul_index)
198
198
  retry_in = _compute_retry_in([600, conf.retry_duration + 2**@consecutive_errors].min)
199
- STDERR.puts "[ERROR][#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
199
+ ::Consul::Async::Debug.puts_error "[#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
200
200
  @consecutive_errors += 1
201
201
  http_result = HttpResponse.new(http)
202
202
  EventMachine.add_timer(retry_in) do
@@ -257,7 +257,7 @@ module Consul
257
257
  http.errback do
258
258
  unless @stopping
259
259
  _handle_error(http, consul_index) do
260
- STDERR.puts "[RETRY][#{path}] (#{@consecutive_errors} errors) due to #{http.error}" if (@consecutive_errors % 10) == 1
260
+ ::Consul::Async::Debug.puts_error "[RETRY][#{path}] (#{@consecutive_errors} errors) due to #{http.error}" if (@consecutive_errors % 10) == 1
261
261
  end
262
262
  end
263
263
  end
@@ -215,21 +215,21 @@ module Consul
215
215
  if not_ready.count.positive?
216
216
  if @iteration - @last_debug_time > 1
217
217
  @last_debug_time = @iteration
218
- STDERR.print "[INFO] #{@last_debug} Waiting for data from #{not_ready.count}/#{not_ready.count + ready} endpoints: #{not_ready[0..2]}..."
218
+ ::Consul::Async::Debug.print_info "Waiting for data from #{not_ready.count}/#{not_ready.count + ready} endpoints: #{not_ready[0..2]}...\r"
219
219
  end
220
220
  return [false, false, nil]
221
221
  end
222
222
  if to_cleanup.count > 1
223
- STDERR.puts "[INFO] Cleaned up #{to_cleanup.count} endpoints: #{to_cleanup}"
223
+ ::Consul::Async::Debug.puts_info "Cleaned up #{to_cleanup.count} endpoints: #{to_cleanup}"
224
224
  to_cleanup.each do |to_remove|
225
225
  x = @endpoints.delete(to_remove)
226
226
  x.endpoint.terminate
227
227
  end
228
228
  end
229
229
  if last_result != data
230
- STDERR.print "[INFO] Write #{Utilities.bytes_to_h data.bytesize} bytes to #{file}, "\
230
+ ::Consul::Async::Debug.print_info "Write #{Utilities.bytes_to_h data.bytesize} bytes to #{file}, "\
231
231
  "netinfo=#{@net_info} aka "\
232
- "#{Utilities.bytes_to_h((net_info[:network_bytes] / (Time.now.utc - @start_time)).round(1))}/s ...\n"
232
+ "#{Utilities.bytes_to_h((net_info[:network_bytes] / (Time.now.utc - @start_time)).round(1))}/s ...\r"
233
233
  tmp_file = "#{file}.tmp"
234
234
  File.open(tmp_file, 'w') do |f|
235
235
  f.write data
@@ -248,7 +248,7 @@ module Consul
248
248
 
249
249
  def vault_setup_token_renew
250
250
  path = 'v1/auth/token/renew-self'
251
- STDERR.print '[INFO] Setting up vault token renewal'
251
+ ::Consul::Async::Debug.print_debug 'Setting up vault token renewal'
252
252
  VaultEndpoint.new(vault_conf, path, :POST, {}, {})
253
253
  end
254
254
 
@@ -260,7 +260,7 @@ module Consul
260
260
  tpl = @endpoints[fqdn]
261
261
  unless tpl
262
262
  tpl = yield
263
- STDERR.print "[INFO] path #{path.ljust(64)} #{query_params.inspect}\r"
263
+ ::Consul::Async::Debug.print_debug "path #{path.ljust(64)} #{query_params.inspect}\r"
264
264
  @endpoints[fqdn] = tpl
265
265
  tpl.endpoint.on_response do |result|
266
266
  @net_info[:success] += 1
@@ -20,6 +20,7 @@ module Consul
20
20
  @periodic_started = false
21
21
  @debug_memory = false
22
22
  @last_memory_state = build_memory_info
23
+ @start = Time.now
23
24
  end
24
25
 
25
26
  def build_memory_info
@@ -45,14 +46,15 @@ module Consul
45
46
  all_ready = results.reduce(true) { |a, e| a && e.ready? }
46
47
  if !@all_templates_rendered && all_ready
47
48
  @all_templates_rendered = true
48
- STDERR.puts "[INFO] First rendering of #{results.count} templates completed"
49
+ cur_time = Time.now
50
+ ::Consul::Async::Debug.puts_info "First rendering of #{results.count} templates completed in #{cur_time - @start}s at #{cur_time}. "
49
51
  end
50
52
  begin
51
53
  @template_callbacks.each do |c|
52
54
  c.call([all_ready, template_manager, results])
53
55
  end
54
56
  rescue StandardError => cbk_error
55
- STDERR.puts "[ERROR] callback error: #{cbk_error.inspect}"
57
+ ::Consul::Async::Debug.puts_error "callback error: #{cbk_error.inspect}"
56
58
  raise cbk_error
57
59
  end
58
60
  rescue Consul::Async::InvalidTemplateException => e
@@ -60,7 +62,7 @@ module Consul
60
62
  template_manager.terminate
61
63
  EventMachine.stop
62
64
  rescue StandardError => e
63
- STDERR.puts "[ERROR] Fatal error occured: #{e.inspect} - #{e.backtrace.join("\n\t")}"
65
+ STDERR.puts "[FATAL] Error occured: #{e.inspect} - #{e.backtrace.join("\n\t")}"
64
66
  template_manager.terminate
65
67
  EventMachine.stop
66
68
  end
@@ -0,0 +1,39 @@
1
+ module Consul
2
+ module Async
3
+ class Debug
4
+ def self.level
5
+ @level || 2
6
+ end
7
+
8
+ def self.levels
9
+ %w[none error info debug]
10
+ end
11
+
12
+ def self.level=(log_level)
13
+ lvl = levels.index(log_level)
14
+ raise "Log level #{log_level} unsupported, must be one of #{levels.inspect}" if lvl.nil?
15
+ @level = lvl
16
+ end
17
+
18
+ def self.puts_error(msg)
19
+ STDERR.puts "[ERROR] #{msg}" if level.positive?
20
+ end
21
+
22
+ def self.puts_info(msg)
23
+ STDERR.puts "[INFO] #{msg}" if level > 1
24
+ end
25
+
26
+ def self.print_info(msg)
27
+ STDERR.print "[INFO] #{msg}" if level > 1
28
+ end
29
+
30
+ def self.puts_debug(msg)
31
+ STDERR.puts "[DEBG] #{msg}" if level > 2
32
+ end
33
+
34
+ def self.print_debug(msg)
35
+ STDERR.print "[DEBG] #{msg}" if level > 2
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,6 @@
1
1
  require 'consul/async/utilities'
2
2
  require 'consul/async/stats'
3
+ require 'consul/async/debug'
3
4
  require 'em-http'
4
5
  require 'net/http'
5
6
  require 'thread'
@@ -34,7 +35,7 @@ module Consul
34
35
  def ch(path, symbol)
35
36
  sub = @paths[path.to_sym]
36
37
  if sub && sub[symbol]
37
- STDERR.puts "[INFO] Overriding #{symbol}:=#{sub[symbol]} for #{path}"
38
+ ::Consul::Async::Debug.puts_info "Overriding #{symbol}:=#{sub[symbol]} for #{path}"
38
39
  sub[symbol]
39
40
  else
40
41
  method(symbol).call
@@ -138,7 +139,7 @@ module Consul
138
139
  "[#{stats.body_bytes_human.ljust(8)}][#{stats.bytes_per_sec_human.ljust(9)}]"\
139
140
  " #{path.ljust(48)} idx:#{result.x_consul_index}, next in #{result.retry_in} s"
140
141
  end
141
- on_error { |http| STDERR.puts "[ERROR]: #{path}: #{http.error}" }
142
+ on_error { |http| ::Consul::Async::Debug.puts_error "#{path}: #{http.error}" }
142
143
  end
143
144
 
144
145
  def on_response(&block)
@@ -193,7 +194,7 @@ module Consul
193
194
 
194
195
  def _handle_error(http)
195
196
  retry_in = [conf.max_retry_duration, conf.retry_duration + 2**@consecutive_errors].min
196
- STDERR.puts "[ERROR][#{path}][#{http_method}] Code: #{http.response_header.status} #{_get_errors(http).join(' - ')} - Retry in #{retry_in}s #{stats.body_bytes_human}"
197
+ ::Consul::Async::Debug.puts_error "[#{path}][#{http_method}] Code: #{http.response_header.status} #{_get_errors(http).join(' - ')} - Retry in #{retry_in}s"
197
198
  @consecutive_errors += 1
198
199
  http_result = VaultHttpResponse.new(http, default_value)
199
200
  EventMachine.add_timer(retry_in) do
@@ -1,5 +1,5 @@
1
1
  module Consul
2
2
  module Async
3
- VERSION = '1.9.9'.freeze
3
+ VERSION = '1.10.0'.freeze
4
4
  end
5
5
  end
@@ -53,6 +53,8 @@
53
53
  node_data = {
54
54
  Node: node_node_data,
55
55
  Service: node_services_data,
56
+ # Only put Checks on a Node
57
+ checks: snode["Checks"].select{|c| c['ServiceID'].empty? }.map{|c| {output: c['Output'], notes: c['Notes'], name: c['Name'], checkid: c['CheckID'], status: c['Status']}},
56
58
  }
57
59
 
58
60
  service_per_node[snode['Node']['Node']] = node_data
@@ -98,6 +98,11 @@ class ConsulNodes {
98
98
  contentHead.appendChild(nodeAddressGenator(instance['Node']['Address']));
99
99
  contentHead.appendChild(nodeMetaGenator(instance['Node']['Meta']));
100
100
  content.appendChild(contentHead);
101
+ var nodesChecks = document.createElement('div');
102
+ nodesChecks.setAttribute('class','nodes-checks');
103
+ nodesChecks.appendChild(checksStatusGenerator(instance, instance['Node']['Name']));
104
+ content.appendChild(nodesChecks);
105
+
101
106
  content.appendChild(servicesGenerator(instance['Service']));
102
107
  content.appendChild(tagsGenerator(getTagsNode(instance)));
103
108
 
@@ -68,6 +68,14 @@ class ConsulService {
68
68
  if(this.refresh > 0) {
69
69
  setTimeout(this.fetchRessource, this.refresh * 1000);
70
70
  }
71
+
72
+ let urlServiceParam = new URL(location.href).searchParams.get('filter');
73
+ if (urlServiceParam === null) {
74
+ return
75
+ } else if (urlServiceParam) {
76
+ this.serviceFilter.val(urlServiceParam);
77
+ this.filterService()
78
+ }
71
79
  }
72
80
 
73
81
  reloadServiceList() {
@@ -251,7 +259,7 @@ class ConsulService {
251
259
  serviceHtml.appendChild(tagsGenerator(instance.tags));
252
260
  serviceHtml.appendChild(serviceMetaGenerator(instance.sMeta));
253
261
  serviceHtml.appendChild(connectGenerator(instance))
254
- serviceHtml.appendChild(checksStatusGenerator(instance));
262
+ serviceHtml.appendChild(checksStatusGenerator(instance, instance.name));
255
263
  serviceHtml.setAttribute('status', state);
256
264
  $("#instances-list").append(serviceHtml);
257
265
  }
@@ -227,7 +227,7 @@ function servicesGenerator(instanceServices) {
227
227
  return services;
228
228
  }
229
229
 
230
- function checksStatusGenerator(instance) {
230
+ function checksStatusGenerator(instance, prefix) {
231
231
  var instanceChecks = instance.checks;
232
232
  var checks = document.createElement('div');
233
233
  checks.className = 'checks';
@@ -236,7 +236,7 @@ function checksStatusGenerator(instance) {
236
236
 
237
237
  for (var checkKey in instanceChecks) {
238
238
  var checkInstance = instanceChecks[checkKey];
239
- var checkId = instance.name + '::' + checkInstance.checkid;
239
+ var checkId = prefix + '::' + checkInstance.checkid;
240
240
  var btn = 'btn-' + toCSSClass(instanceChecks[checkKey]['status'])
241
241
  var check = document.createElement('div');
242
242
 
data/samples/metrics.erb CHANGED
@@ -25,28 +25,39 @@
25
25
  'warning' => 0,
26
26
  'critical' => 0,
27
27
  }
28
- service(service_name).each do |snode|
28
+ srv = service(service_name)
29
+ srv.each do |snode|
29
30
  state = snode.status
30
31
  res[state] += 1
31
32
  end
32
33
  backends[service_name] = {
33
34
  state: res,
34
- stats: service(service_name).endpoint.stats,
35
+ stats: srv.endpoint.stats,
35
36
  }
36
37
  end
37
38
  end
38
39
  %>
39
40
  # HELP consul_datacenters_count A gauge of number of datacenters available
40
41
  # TYPE consul_nodes_count gauge
41
- consul_datacenters_count <%= datacenters().count %> <%= datacenters().endpoint.stats.last_success_or_error.to_i * 1000 %>
42
+ consul_datacenters_count <%= datacenters().count %>
42
43
 
43
44
  # HELP consul_nodes_count A gauge of number of nodes in the cluster
44
45
  # TYPE consul_nodes_count gauge
45
- consul_nodes_count <%= nodes().count %> <%= nodes().endpoint.stats.last_success_or_error.to_i * 1000 %>
46
+ consul_nodes_count <%= nodes().count %>
46
47
 
47
48
  # HELP consul_services_count A gauge of the number of services
48
49
  # TYPE consul_services_count gauge
49
- consul_services_count <%= service_count %> <%= services(tag: service_tag_filter).endpoint.stats.last_success_or_error.to_i * 1000 %>
50
+ consul_services_count <%= service_count %>
51
+
52
+ <%
53
+ %i[success errors bytes_read changes network_bytes].each do |sym|
54
+ %>
55
+ # HELP consul_net_info_<%= sym.to_s %> consul-templaterb global stats for <%= sym.to_s %>
56
+ # TYPE consul_net_info_<%= sym.to_s %> counter
57
+ consul_net_info_<%= sym.to_s %> <%= @net_info[sym] %>
58
+ <%
59
+ end
60
+ %>
50
61
 
51
62
  # HELP consul_service_count A gauge of number instances of service with their current state
52
63
  # TYPE consul_service_count gauge
@@ -0,0 +1,34 @@
1
+ # A template for exporting metrics for prometheus using consul-templaterb
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
7
+ # EXCLUDE_SERVICES: comma-separated services regexps to exclude (example: lbl7.*,netsvc-probe.*,consul-probed.*)
8
+
9
+
10
+ # HELP consul_service_check_count The number of service check for each service
11
+ # TYPE consul_service_check_count gauge
12
+ # HELP consul_node_check_count The number of node check for each service
13
+ # TYPE consul_node_check_count gauge
14
+
15
+ <%
16
+ service_tag_filter = ENV['SERVICES_TAG_FILTER'] || nil
17
+ instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
18
+ instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG']
19
+
20
+ # Services to hide
21
+ services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || 'lbl7.*,netsvc-probe.*,consul-probed.*').split(',')
22
+ services_blacklist = services_blacklist_raw.map { |v| Regexp.new(v) }
23
+
24
+
25
+ services().each do |service_name, tags|
26
+ if !services_blacklist.any? {|r| r.match(service_name)} && (instance_must_tag.nil? || tags.include?(instance_must_tag))
27
+ service(service_name).each do |snode|
28
+ %>consul_service_check_count{service="<%= service_name %>", node="<%= snode['Node']['Node'] %>"} <%= snode['Checks'].select{|chk| chk['ServiceID'] != ""}.length %>
29
+ consul_node_check_count{service="<%= service_name %>", node="<%= snode['Node']['Node'] %>"} <%= snode['Checks'].select{|chk| chk['ServiceID'] == ""}.length %>
30
+ <%
31
+ end
32
+ end
33
+ end
34
+ %>
@@ -0,0 +1,25 @@
1
+ service_name ; service_status ; node ; service_address ; non_passing_checks
2
+ <%
3
+ # find all the failing services.
4
+ # Usage: consul-templaterb --once samples/tools/find_all_failing_services.txt.erb
5
+ #
6
+ # Environment variables:
7
+ # * `CONSUL_SERVICE_FILTER` : regexp to filter services `.*` by default
8
+ # * `CONSUL_DC_FILTER`: regexp to filter datacenters `.*` by default
9
+
10
+ service_filter = Regexp.new(ENV['CONSUL_SERVICE_FILTER'] || '.*')
11
+ dc_filter = Regexp.new(ENV['CONSUL_DC_FILTER'] || '.*')
12
+ datacenters.each do |dc|
13
+ next unless dc_filter.match(dc)
14
+ services(dc: dc).each do |service_name, tags|
15
+ next unless service_filter.match(service_name)
16
+ service(service_name, dc: dc).each do |snode|
17
+ if snode.status != 'passing'
18
+ failing_checks = snode['Checks'].select{ |c| c['Status'] != 'passing' }.map { |c| c['Name'] || c['ID'] || c['CheckID']}
19
+ %><%= service_name %> ; <%= snode.status %> ; <%= snode['Node']['Node']%> ; <%= snode.service_address %> ; <%= failing_checks %>
20
+ <%
21
+ end
22
+ end
23
+ end
24
+ end
25
+ %>
@@ -0,0 +1,14 @@
1
+ <%
2
+ # find all nodes without ID
3
+ # Usage: consul-templaterb --once samples/tools/find_all_failing_services.txt.erb
4
+ #
5
+
6
+ datacenters.each do |dc|
7
+ nodes(dc:dc).each do |snode|
8
+ if snode['ID'] == ''
9
+ %><%= snode['Node'] %>; <%= snode.inspect %>
10
+ <%
11
+ end
12
+ end
13
+ end
14
+ %>
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.9.9
4
+ version: 1.10.0
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: 2019-01-18 00:00:00.000000000 Z
11
+ date: 2019-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -168,6 +168,7 @@ files:
168
168
  - lib/consul/async/consul_template.rb
169
169
  - lib/consul/async/consul_template_engine.rb
170
170
  - lib/consul/async/consul_template_render.rb
171
+ - lib/consul/async/debug.rb
171
172
  - lib/consul/async/process_handler.rb
172
173
  - lib/consul/async/stats.rb
173
174
  - lib/consul/async/utilities.rb
@@ -211,7 +212,10 @@ files:
211
212
  - samples/metrics.erb
212
213
  - samples/nodes.html.erb
213
214
  - samples/sample_keys.html.erb
215
+ - samples/service_checks_metrics.erb
214
216
  - samples/services.html.erb
217
+ - samples/tools/find_all_failing_services.txt.erb
218
+ - samples/tools/find_all_nodes_without_id.txt.erb
215
219
  - samples/vault-ldap.txt.erb
216
220
  homepage: https://rubygems.org/gems/consul-templaterb
217
221
  licenses:
@@ -236,7 +240,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
236
240
  - !ruby/object:Gem::Version
237
241
  version: '0'
238
242
  requirements: []
239
- rubygems_version: 3.0.2
243
+ rubyforge_project:
244
+ rubygems_version: 2.7.7
240
245
  signing_key:
241
246
  specification_version: 4
242
247
  summary: Implementation of Consul template using Ruby and .erb templating language