consul-templaterb 1.18.5 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ node ; Status
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
+ node_filter = Regexp.new(ENV['CONSUL_NODE_FILTER'] || '.*')
11
+ dc_filter = Regexp.new(ENV['CONSUL_DC_FILTER'] || '.*')
12
+ datacenters.each do |dc|
13
+ next unless dc_filter.match(dc)
14
+ nodes(dc: dc).each do |node|
15
+ #warn node.inspect
16
+ next unless node_filter.match(node['Node'])
17
+ checks_for_node(node['Node'], dc: dc).each do |check|
18
+ if check['Status'] != 'passing' && check['CheckID'] == '_node_maintenance'
19
+ %>"<%= check['Node'] %>" ; "<%= check['Notes'] %>"
20
+ <%
21
+ end
22
+ end
23
+ end
24
+ end
25
+ %>
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.18.5
4
+ version: 1.19.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-09-30 00:00:00.000000000 Z
11
+ date: 2019-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -192,9 +192,6 @@ files:
192
192
  - lib/consul/async/vault_endpoint.rb
193
193
  - lib/consul/async/version.rb
194
194
  - samples/all_services.txt.erb
195
- - samples/checks.html.erb
196
- - samples/common/footer.html.erb
197
- - samples/common/header.html.erb
198
195
  - samples/consul-ui/README.md
199
196
  - samples/consul-ui/common/header.html.erb
200
197
  - samples/consul-ui/consul-keys-ui.html.erb
@@ -210,6 +207,7 @@ files:
210
207
  - samples/consul-ui/js/nodes.js
211
208
  - samples/consul-ui/js/service.js
212
209
  - samples/consul-ui/js/timeline.js
210
+ - samples/consul-ui/js/types.js
213
211
  - samples/consul-ui/js/utils.js
214
212
  - samples/consul-ui/ringbuffer.rb
215
213
  - samples/consul-ui/timeline.json.erb
@@ -221,23 +219,20 @@ files:
221
219
  - samples/consul_template.xml.erb
222
220
  - samples/consul_template_broken.txt.erb
223
221
  - samples/criteo/haproxy.cfg.erb
224
- - samples/criteo_choregraphies.txt.erb
225
222
  - samples/debug/compare_connect_services.txt.erb
226
223
  - samples/ha_proxy.cfg.erb
227
224
  - samples/haproxy_dns.cfg.erb
228
225
  - samples/hosts.erb
229
226
  - samples/hosts_per_services.erb
230
- - samples/keys.html.erb
231
227
  - samples/kv_yaml_to_json.json.erb
232
228
  - samples/list_ruby_versions_from_rubygems.txt.erb
233
229
  - samples/metrics.erb
234
- - samples/nodes.html.erb
235
230
  - samples/prometheus_consul_coordinates.erb
236
231
  - samples/render_template_from_kv.erb
237
232
  - samples/sample_keys.html.erb
238
233
  - samples/service_checks_metrics.erb
239
- - samples/services.html.erb
240
234
  - samples/tools/find_all_failing_services.txt.erb
235
+ - samples/tools/find_all_maintenance_nodes.txt.erb
241
236
  - samples/tools/find_all_nodes_without_id.txt.erb
242
237
  - samples/vault-ldap.txt.erb
243
238
  homepage: https://rubygems.org/gems/consul-templaterb
@@ -1,130 +0,0 @@
1
- <%= render_file('common/header.html.erb', title: 'Consul Checks') %>
2
- <%
3
- # This template can be configure the following way with environment variables
4
- # Environment variables to filter services/instances
5
- # SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
6
- services_tag_filter = ENV['SERVICES_TAG_FILTER']
7
- def status_to_class(status)
8
- if status == 'passing'
9
- 'success'
10
- elsif status == 'warning'
11
- 'warning'
12
- elsif status == 'critical'
13
- 'danger'
14
- else
15
- 'info'
16
- end
17
- end
18
- %>
19
- <style>
20
- .check {
21
- transition: opacity 1s ease-out;
22
- }
23
- </style>
24
- <script>//<!--
25
- function updateStates() {
26
- states = ['passing', 'warning', 'critical']
27
- stylesheet = document.getElementById('css-states');
28
- txt = "";
29
- for (var i in states) {
30
- var s = states[i];
31
- is_checked = document.getElementById('show_'+s).checked
32
- var to_append = "." + s + " { ";
33
- if (is_checked) {
34
- to_append += "display: block"
35
- } else {
36
- to_append += "display:none"
37
- }
38
- to_append += " }\r\n"
39
- txt += to_append;
40
- }
41
- stylesheet.textContent = txt;
42
- }
43
- //->
44
- </script>
45
- <div class="container-fluid">
46
- <div class="row">
47
- <nav class="col-2">
48
- <ul>
49
- <%
50
- all_services = services(tag: services_tag_filter)
51
- all_services.each do |service_name, tags|
52
- %>
53
- <li><a title="<%= tags.sort.join(', ') %>" href="#service_<%= service_name %>"><%= service_name %></a></li>
54
- <% end %>
55
- </ul>
56
- </nav>
57
- <main class="col-10">
58
- <div class="float-right">
59
- <span class="state-selector">
60
- <input id="show_passing" type="checkbox" class="checks-visibility" value="passing" checked="checked" onchange="updateStates()"/>
61
- <label for="show_passing"><span class="badge badge-success">Passing</span></label>
62
- </span>
63
- <span class="state-selector">
64
- <input id="show_warning" type="checkbox" class="checks-visibility" value="warning" checked="checked" onchange="updateStates()"/>
65
- <label for="show_warning"><span class="badge badge-warning">Warning</span></label>
66
- </span>
67
- <span class="state-selector">
68
- <input id="show_critical" type="checkbox" class="checks-visibility" value="critical" checked="checked" onchange="updateStates()"/>
69
- <label for="show_critical"><span class="badge badge-danger">Critical</span></label>
70
- </span>
71
- </div>
72
-
73
- <h1 id="services">Services <%= services_tag_filter ? " tag: #{services_tag_filter}" : 'No filtering' %></h1>
74
- <% all_services.each do |service_name, tags|
75
- passing = 0
76
- warning = 0
77
- critical = 0
78
- service_state = 'passing'
79
- sum = 0
80
- checks_for_service(service_name).each do |check|
81
- st = check['Status']
82
- sum += 1
83
- case st
84
- when 'warning'
85
- warning += 1
86
- when 'passing'
87
- passing += 1
88
- else
89
- critical += 1
90
- end
91
- end
92
- service_state = 'warning' if warning > 0
93
- service_state = 'critical' if critical > 0
94
- %>
95
- <div class="service <%= service_state %>" id="service_<%= service_name %>">
96
- <h2 class="service-name text-<%= status_to_class(service_state) %>">Service <%= service_name %>
97
- <span class="float-right">
98
- <span class="badge badge-pill badge-success"><%= passing > 0 ? passing : nil %></span>
99
- <span class="badge badge-pill badge-warning"><%= warning > 0 ? warning : nil %></span>
100
- <span class="badge badge-pill badge-danger"><%= critical > 0 ? critical : nil %></span>
101
- </span>
102
- </h2>
103
- <% if sum > 0
104
- %><div class="progress">
105
- <div title="<%= "#{passing} / #{sum}" %>" class="progress-bar bg-success" role="progressbar" style="width:<%= (100.0 * passing / sum).round(2) %>%" aria-valuenow="<%= passing %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
106
- <div title="<%= "#{warning} / #{sum}" %>" class="progress-bar bg-warning" role="progressbar" style="width:<%= (100.0 * warning / sum).round(2) %>%" aria-valuenow="<%= warning %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
107
- <div title="<%= "#{critical} / #{sum}" %>" class="progress-bar bg-danger" role="progressbar" style="width:<%= (100.0 * critical / sum).round(2) %>%" aria-valuenow="<%= critical %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
108
- </div>
109
- <% end %>
110
- <div class="list-group">
111
- <% checks_for_service(service_name).each do |check| %>
112
- <div class="list-group-item check <%= check['Status'] %>" id="<%= check['Node'] + check['CheckID'] %>">
113
- <div class="d-flex align-items-center justify-content-between">
114
- <h5>
115
- <%= check['Name'] %> / <%= check['Node'] %>
116
- </h5>
117
- <span class="badge badge-pill badge-<%= status_to_class(check['Status']) %>"><%= check['Status'] %></span>
118
- </div>
119
- <p><%= ERB::Util.html_escape(check['Notes']) %></p>
120
- <code><%= ERB::Util.html_escape(check['Output']) %></code>
121
- </div>
122
- <% end %>
123
- </div>
124
- </div>
125
- <% end %>
126
- </main>
127
- </div>
128
- </div>
129
- <script>updateStates();</script>
130
- <%= render_file('common/footer.html.erb') %>
@@ -1,8 +0,0 @@
1
- <!-- Bootstrap core JavaScript
2
- ================================================== -->
3
- <!-- Latest compiled and minified JavaScript -->
4
- <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
5
- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
6
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
7
- </body>
8
- </html>
@@ -1,45 +0,0 @@
1
- <%
2
- # This template can be configure the following way with environment variables
3
- # CONSUL_TOOLS_SUFFIX: suffix for the address of consul tools
4
- # CONSUL_TOOLS_PREFIX: prefix for the address of consul tools
5
- # CONSUL_TOOLS: comma sperated list of consul tools
6
- tools = (ENV['CONSUL_TOOLS'] || 'criteo_choregraphies,checks,services,nodes,keys').split(",")
7
- suffix = ENV['CONSUL_TOOLS_PREFIX'] || '.html'
8
- prefix = ENV['CONSUL_TOOLS_SUFFIX'] || ''
9
- %><!DOCTYPE html>
10
- <html lang="en">
11
- <head>
12
- <meta charset="utf-8"/>
13
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
14
- <meta name="description" content="Display Consul information"/>
15
- <meta name="author" content="Criteo"/>
16
- <meta http-equiv="refresh" content="<%= param('refresh', ENV['REFRESH'] || '600') %>"/>
17
- <title><%= param('title', 'Consul Real Time information') %></title>
18
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
19
- <style>
20
- body {
21
- padding-top: 5rem;
22
- }
23
- .check {
24
- transition: opacity 1s ease-out;
25
- }
26
- </style>
27
- <style id="css-states">
28
- </style>
29
- </head>
30
- <body>
31
- <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
32
- <a class="navbar-brand" href="#">Consul</a>
33
- <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
34
- <span class="navbar-toggler-icon"></span>
35
- </button>
36
- <div class="collapse navbar-collapse" id="navbarsExampleDefault">
37
- <ul class="navbar-nav mr-auto">
38
- <% tools.each do |tool| %>
39
- <li class="nav-item">
40
- <a class="nav-link" href="<%= prefix + tool + suffix %>"><%= tool.gsub('_', ' ') %></a>
41
- </li>
42
- <% end %>
43
- </ul>
44
- </div>
45
- </nav>
@@ -1,49 +0,0 @@
1
- <%
2
- require 'base64'
3
- require 'json'
4
- require 'date'
5
- @current_time = Time.now.utc
6
- def display_holder(holder, value)
7
- begin
8
- holder_date = Time.parse(value)
9
- status = 'success'
10
- diff = (@current_time - holder_date).round(0)
11
- status = 'warning' if diff > 3600
12
- status = 'danger' if diff > 7200
13
- diff_txt = "#{diff % 3600} seconds"
14
- diff_txt = "#{(diff % 86400) / 3600} hours, #{diff_txt}" if diff > 3600
15
- diff_txt = "#{diff / 86400} days, #{diff_txt}" if diff > 86400
16
- rescue StandardError => e
17
- status = 'info'
18
- holder_date = "Cannot parse date: #{e}"
19
- diff_txt = "Error Parsing date #{value}"
20
- end
21
- [holder, holder_date, "#{diff_txt} ago", status]
22
- end
23
-
24
- datacenters.each do |dc|
25
- kv('choregraphie', dc:dc, recurse:true).each do |tuple|
26
- ckey = tuple['Key'].gsub('/', '-')
27
- if tuple['Value'].nil?
28
- json = []
29
- holders = []
30
- else
31
- json = JSON.parse(Base64.decode64(tuple['Value']))
32
- holders = json['holders']
33
- end
34
- if holders.count > 0
35
- holders.each_pair do |key,value|
36
- if value.is_a?(Hash)
37
- value.each_pair do |k, v|
38
- host, holder_date, diff_txt, status = display_holder(k, v)
39
- end
40
- else
41
- host, holder_date, diff_txt, status = display_holder(key, value)
42
- end
43
- %><%= "#{host} ; #{dc} ; #{holder_date} ; #{status} ; #{ckey} ; #{diff_txt}" %>
44
- <%
45
- end
46
- end
47
- end
48
- end
49
- %>
@@ -1,42 +0,0 @@
1
- <%= render_file('common/header.html.erb', title: 'Keys') %>
2
- <% path = ENV['kv_path'] || '' %>
3
- <% require 'base64'
4
- require 'json'
5
- require 'date'
6
- %>
7
- <main class="container">
8
- <div>
9
- <h1>Show all keys <%= path == '' ? '' : "under hierarchy #{path}" %></h1>
10
- <div id="accordion">
11
- <!-- LastModified: <%= kv(path, recurse:true).endpoint.stats.last_modified %> -->
12
- <%
13
- kv(path, recurse:true).each do |tuple|
14
- key = tuple['Key']
15
- val = "NO_VALUE"
16
- if !tuple['Value'].nil?
17
- begin
18
- val = Base64.decode64(tuple['Value'])
19
- rescue StdError => e
20
- val = "#{e.inspect} for tuple['Value']"
21
- end
22
- end
23
- %>
24
- <div class="card">
25
- <div class="card-header" id="heading-<%= key %>">
26
- <h5 class="mb-0">
27
- <a href="#<%= key %>" class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-<%= key %>" aria-expanded="true" aria-controls="collapse-<%= key %>">
28
- <%= key %>
29
- </a>
30
- </h5>
31
- <div id="collapse-<%= key %>" class="collapse" aria-labelledby="heading-<%= key %>" data-parent="#accordion">
32
- <div class="card-body">
33
- <pre class="pre-scrollable"><%= ERB::Util.html_escape(val) %></pre>
34
- </div>
35
- </div>
36
- </div>
37
- </div>
38
- <% end %>
39
- </div>
40
- </div>
41
- </main>
42
- <%= render_file 'common/footer.html.erb' %>
@@ -1,52 +0,0 @@
1
- <%= render_file('common/header.html.erb', title: 'Nodes') %><%
2
- service_tag_filter = ENV['SERVICES_TAG_FILTER'] || nil
3
- # Services to hide
4
- services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || 'lbl7.*,netsvc-probe.*,consul-probed.*').split(',')
5
- services_blacklist = services_blacklist_raw.map { |v| Regexp.new(v) }
6
-
7
- service_per_node = {}
8
- services.each do |service_name, tags|
9
- if !services_blacklist.any? {|r| r.match(service_name)}
10
- service(service_name, tag: service_tag_filter).sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
11
- node_services = service_per_node[snode['Node']['Node']] || []
12
- node_services.push(snode)
13
- service_per_node[snode['Node']['Node']] = node_services
14
- end
15
- end
16
- end %>
17
-
18
- <h1 id="nodes">List all nodes for DC, sorted by name</h1>
19
- <ul class="list-group">
20
- <% nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
21
- %><li id="node_<%= snode['ID'] %>" class="list-group-item">
22
- <a href="ssh://<%= snode['Address']%>"><%= snode['Address'] %></a> <%= snode['Node'] %><%
23
- snode['Meta'].each do |k,v|
24
- if v && !v.empty?
25
- %><span class="badge badge-pill badge-primary float-right"><%= k %>:&nbsp;<%= v%></span><%
26
- end
27
- end if snode['Meta']
28
- %><div><%
29
- if service_per_node.key?(snode['Node'])
30
- service_per_node[snode['Node']].each do |service|
31
- tags = service['Service']['Tags'].sort
32
- addr = service.service_address
33
- port_num = service['Service']['Port'].to_i
34
- port = port_num && port_num > 0 ? ":#{port_num}" : ''
35
- url = if tags.include? 'https'
36
- "https://#{addr}#{port}"
37
- elsif tags.include? 'http'
38
- "http://#{addr}#{port}"
39
- elsif tags.include? 'ftp'
40
- "ftp://#{addr}#{port}"
41
- else
42
- nil
43
- end
44
- %> <a class="badge badge-secondary" href='<%= url %>'>
45
- <%= service['Service']['Service'] %>: <%= port_num %>
46
- </a>
47
- <% end
48
- end
49
- %></div></li>
50
- <% end %>
51
- </ul>
52
- <%= render_file 'common/footer.html.erb' %>
@@ -1,134 +0,0 @@
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
- require 'base64'
6
- require 'json'
7
- require 'date'
8
-
9
- services_tag_filter = ENV['SERVICES_TAG_FILTER']
10
- def status_to_class(status)
11
- if status == 'passing'
12
- 'success'
13
- elsif status == 'warning'
14
- 'warning'
15
- elsif status == 'critical'
16
- 'danger'
17
- else
18
- 'info'
19
- end
20
- end
21
-
22
- def compute_node_status(snode)
23
- state = 'passing'
24
- return state unless snode['Checks']
25
- snode['Checks'].each do |c|
26
- case c['Status']
27
- when 'critical'
28
- return 'critical'
29
- when 'warning'
30
- state = 'warning'
31
- end
32
- end
33
- state
34
- end
35
-
36
- def compute_service_status(snodes)
37
- passing = 0
38
- warning = 0
39
- critical = 0
40
- sum = 0
41
- snodes.each do |snode|
42
- st = compute_node_status(snode)
43
- sum += 1
44
- case st
45
- when 'passing'
46
- passing += 1
47
- when 'warning'
48
- warning += 1
49
- else
50
- critical += 1
51
- end
52
- end
53
- [passing, warning, critical, sum]
54
- end
55
- %><%= render_file('common/header.html.erb', title: 'Services') %>
56
- <nav>
57
- <ul>
58
- <li><a href="#datacenters">DataCenters</a></li>
59
- <li><a href="#list_services">List of services</a></li>
60
- <li><a href="#services">Services with instances</a></li>
61
- </ul>
62
- </nav>
63
-
64
- <div class="container-fluid">
65
- <div class="row">
66
- <nav id="list_services" class="col-2">
67
- <ul>
68
- <%
69
- all_services = services(tag: services_tag_filter)
70
- all_services.each do |service_name, tags|
71
- %>
72
- <li><a title="<%= tags.sort.join(', ') %>" href="#service_<%= service_name %>"><%= service_name %></a></li>
73
- <% end %>
74
- </ul>
75
- </nav>
76
- <main class="col-10">
77
- <h1 id="datacenters">List of all datacenters</h1>
78
- <ul>
79
- <% datacenters.each do |dc| %>
80
- <li id="dc_<%=dc %>%"><%= dc %> with <%= services(dc:dc).keys.count %> services, <%= nodes(dc:dc).count %> nodes</li>
81
- <% end %>
82
- </ul>
83
- <h1 id="services">List all services instances sorted by node name</h1>
84
- <% services.each do |service_name, tags|
85
- service_group = service(service_name)
86
- nodes_sorted = service_group.sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }
87
- passing, warning, critical, sum = compute_service_status(nodes_sorted)
88
- service_state = 'passing'
89
- service_state = 'warning' if warning > 0
90
- service_state = 'critical' if critical > 0
91
- %>
92
- <div class="service <%= service_state %>" id="service_<%= service_name %>">
93
- <h2 class="text-<%= status_to_class(service_state) %>" title="<%= tags.join(', ') %>"><%= service_name %><a class="qlink" href="#service_<%= service_name %>">&#128279;</a></h2>
94
- <% if sum > 0
95
- %><div class="progress">
96
- <div title="<%= "#{passing} / #{sum}" %>" class="progress-bar bg-success" role="progressbar" style="width:<%= (100.0 * passing / sum).round(2) %>%" aria-valuenow="<%= passing %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
97
- <div title="<%= "#{warning} / #{sum}" %>" class="progress-bar bg-warning" role="progressbar" style="width:<%= (100.0 * warning / sum).round(2) %>%" aria-valuenow="<%= warning %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
98
- <div title="<%= "#{critical} / #{sum}" %>" class="progress-bar bg-danger" role="progressbar" style="width:<%= (100.0 * critical / sum).round(2) %>%" aria-valuenow="<%= critical %>" aria-valuemin="0" aria-valuemax="<%= sum %>"></div>
99
- </div>
100
- <% end %>
101
- <div class="list-group">
102
- <% nodes_sorted.each do |snode|
103
- tags = snode['Service']['Tags'].sort
104
- addr = snode.service_address
105
- port_num = snode['Service']['Port'].to_i
106
- port = port_num && port_num > 0 ? ":#{port_num}" : ''
107
- url = if tags.include? 'https'
108
- "https://#{addr}#{port}"
109
- elsif tags.include? 'http'
110
- "http://#{addr}#{port}"
111
- elsif tags.include? 'ftp'
112
- "ftp://#{addr}#{port}"
113
- else
114
- nil
115
- end
116
- %><div class="list-group-item check"><a <%= url ? "href=\"#{url}\"" : nil %>><%=
117
- snode['Node']['Node'] %><%= port %></a>
118
- <span class="tags"><%
119
- snode['Service']['Tags'].sort.each do |t|
120
- %><span class="badge badge-pill"><%= t %></span><%
121
- end
122
- %></span>
123
- <span class="float-right statuses"><%
124
- snode['Checks'].each do |c| %> <span title="<%= c['Name']%>" class="badge badge-pill badge-<%= status_to_class(c['Status']) %>"><%= c['Status']
125
- %></span><% end if snode['Checks'] %></span></div>
126
- <% end %>
127
- </div>
128
- </div>
129
- <% end
130
- %>
131
- </main>
132
- </div>
133
- </div>
134
- <%= render_file 'common/footer.html.erb' %>