consul-templaterb 1.12.0 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +7 -0
- data/README.md +3 -4
- data/lib/consul/async/consul_endpoint.rb +7 -1
- data/lib/consul/async/version.rb +1 -1
- data/samples/consul-ui/consul_services.json.erb +6 -16
- data/samples/consul-ui/css/style.css +20 -2
- data/samples/consul-ui/js/nodes.js +1 -1
- data/samples/consul-ui/js/service.js +16 -7
- data/samples/consul-ui/js/utils.js +28 -40
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba3e953ddc4da2445e08a84bbd39c1a309855bac
|
4
|
+
data.tar.gz: '08c115b11cf6006014940030fea37f68c7ece703'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f778131a4db7c8ddf4464911a8969e8dfb841ad8cbdecca5e49a3d0d15887634915c4c5b68d80b59878e1fbd47c41fa99b8dfd75234bcc2808f47392b9a4ed42
|
7
|
+
data.tar.gz: 9d63155dad550910c3b6b7aec5f2ab677f62cfcf0996f16daf91c060d9528df40bdbe81fee86a8a62205d136219d99e6a83004146655eeecba776b543e13382e
|
data/.rubocop.yml
CHANGED
@@ -4,7 +4,7 @@ AllCops:
|
|
4
4
|
TargetRubyVersion: 2.4
|
5
5
|
|
6
6
|
Metrics/AbcSize:
|
7
|
-
Max:
|
7
|
+
Max: 82
|
8
8
|
|
9
9
|
Metrics/BlockLength:
|
10
10
|
Max: 145
|
@@ -22,13 +22,13 @@ Metrics/LineLength:
|
|
22
22
|
Max: 175
|
23
23
|
|
24
24
|
Metrics/MethodLength:
|
25
|
-
Max:
|
25
|
+
Max: 65
|
26
26
|
|
27
27
|
Metrics/ParameterLists:
|
28
28
|
Max: 12
|
29
29
|
|
30
30
|
Metrics/PerceivedComplexity:
|
31
|
-
Max:
|
31
|
+
Max: 23
|
32
32
|
|
33
33
|
Style/Documentation:
|
34
34
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## (UNRELEASED)
|
4
4
|
|
5
|
+
## 1.13.0 (April 10, 2019)
|
6
|
+
|
7
|
+
IMPROVEMENTS:
|
8
|
+
|
9
|
+
* On Windows, ensure a proper error message is displayed when watching more than 2048 endpoints
|
10
|
+
* consul-ui now allow better searches in instances, display node meta in service details, fixed display of tags on Ffx
|
11
|
+
|
5
12
|
## 1.12.0 (April 4, 2019)
|
6
13
|
|
7
14
|
NEW FEATURES:
|
data/README.md
CHANGED
@@ -110,13 +110,11 @@ You can now use it directly using the binary `consul-templaterb` in your path.
|
|
110
110
|
|
111
111
|
On Windows, a bug exists with Ruby greater than 2.4.
|
112
112
|
|
113
|
-
In order to make it work, use
|
113
|
+
In order to make it work, use this commands as explained in
|
114
114
|
https://github.com/oneclick/rubyinstaller2/issues/96#issuecomment-434619796
|
115
115
|
|
116
116
|
```
|
117
|
-
|
118
|
-
gem uninstall eventmachine
|
119
|
-
gem install eventmachine --platform ruby
|
117
|
+
gem install eventmachine consul-templaterb --platform ruby
|
120
118
|
```
|
121
119
|
|
122
120
|
### Playing with the samples templates
|
@@ -304,6 +302,7 @@ push git commits and tags, and push the `.gem` file to [rubygems.org](https://ru
|
|
304
302
|
Here are the known bugs of the application:
|
305
303
|
|
306
304
|
* [ ] `render_file` might create an infinite recursion if a template includes itself indirectly.
|
305
|
+
* [ ] On Windows, the consul-templaterb cannot work with more than 2048 endpoints watched (see https://github.com/oneclick/rubyinstaller/issues/104#issuecomment-7681074)
|
307
306
|
|
308
307
|
Please consult [CHANGELOG.md](CHANGELOG.md) for fixed bugs.
|
309
308
|
|
@@ -257,7 +257,13 @@ module Consul
|
|
257
257
|
http.errback do
|
258
258
|
unless @stopping
|
259
259
|
_handle_error(http, consul_index) do
|
260
|
-
|
260
|
+
if (@consecutive_errors % 10) == 1
|
261
|
+
add_msg = http.error
|
262
|
+
if Gem.win_platform? && http.error.include?('unable to create new socket: Too many open files')
|
263
|
+
add_msg += "\n *** Windows does not support more than 2048 watches, watch less endpoints ***"
|
264
|
+
end
|
265
|
+
::Consul::Async::Debug.puts_error "[RETRY][#{path}] (#{@consecutive_errors} errors) due to #{add_msg}"
|
266
|
+
end
|
261
267
|
end
|
262
268
|
end
|
263
269
|
end
|
data/lib/consul/async/version.rb
CHANGED
@@ -14,20 +14,6 @@
|
|
14
14
|
services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || 'lbl7.*,netsvc-probe.*,consul-probed.*').split(',')
|
15
15
|
services_blacklist = services_blacklist_raw.map { |v| Regexp.new(v) }
|
16
16
|
|
17
|
-
def compute_attributes(snode)
|
18
|
-
w = 100
|
19
|
-
snode['Service']['Tags'].each do |tag|
|
20
|
-
match = /^weight-([1-9][0-9])*$/.match(tag)
|
21
|
-
w = match[1].to_i if match
|
22
|
-
end
|
23
|
-
attributes = ""
|
24
|
-
node_status = snode.status
|
25
|
-
attributes = "#{attributes} disabled" if node_status == 'critical'
|
26
|
-
if node_status == 'warning'
|
27
|
-
w = w / 8
|
28
|
-
end
|
29
|
-
attributes = "#{attributes} weight #{w}" if w.positive?
|
30
|
-
end
|
31
17
|
backends = {}
|
32
18
|
tags_per_service = {}
|
33
19
|
services(tag: service_tag_filter).each do |service_name, tags|
|
@@ -45,6 +31,7 @@
|
|
45
31
|
end
|
46
32
|
end
|
47
33
|
%><%
|
34
|
+
all_nodes = {}
|
48
35
|
json_backends = {}
|
49
36
|
backends.each_pair do |service_name, nodes|
|
50
37
|
service = {
|
@@ -66,9 +53,12 @@
|
|
66
53
|
checks.push(check)
|
67
54
|
end
|
68
55
|
meta = snode['Service']['Meta']
|
56
|
+
node_meta = snode['Node']['Meta'] || {}
|
57
|
+
node_name = snode['Node']['Node']
|
58
|
+
all_nodes[node_name] = { meta: node_meta } if node_name
|
69
59
|
server = { frontend_id: "backend_http__#{service_name}",
|
70
60
|
id: snode['Service']['ID'],
|
71
|
-
name:
|
61
|
+
name: node_name,
|
72
62
|
sMeta: meta ? meta : {},
|
73
63
|
connect: snode['Service']['Connect'],
|
74
64
|
addr: snode.service_address,
|
@@ -83,5 +73,5 @@
|
|
83
73
|
end
|
84
74
|
end
|
85
75
|
json_datacenters = datacenters.to_a
|
86
|
-
json = { services: json_backends, datacenters: json_datacenters, generated_at: Time.now}
|
76
|
+
json = { nodes: all_nodes, services: json_backends, datacenters: json_datacenters, generated_at: Time.now}
|
87
77
|
%><%= JSON.pretty_generate(json) %>
|
@@ -3,6 +3,18 @@
|
|
3
3
|
box-shadow: none;
|
4
4
|
}
|
5
5
|
|
6
|
+
.btn-outline-danger::before, .btn-danger::before{
|
7
|
+
content: '✖ ';
|
8
|
+
}
|
9
|
+
|
10
|
+
.btn-outline-success::before, .btn-success::before{
|
11
|
+
content: '✔ ';
|
12
|
+
}
|
13
|
+
|
14
|
+
.btn-outline-warning::before, .btn-warning::before{
|
15
|
+
content: '⚠ ';
|
16
|
+
}
|
17
|
+
|
6
18
|
#service-wrapper, #instances-wrapper, #keys-wrapper {
|
7
19
|
overflow: scroll;
|
8
20
|
border-top-left-radius: 0px;
|
@@ -202,12 +214,18 @@ html, body {
|
|
202
214
|
.instance-content-header h5 {
|
203
215
|
margin-right: 10px;
|
204
216
|
}
|
205
|
-
|
206
|
-
|
217
|
+
.service-instance dt, .service-instance dl {
|
218
|
+
line-height: 1em;
|
219
|
+
}
|
220
|
+
.node-meta {
|
207
221
|
text-align: right;
|
208
222
|
flex: 2 0 0;
|
209
223
|
}
|
210
224
|
|
225
|
+
.service-instance .node-meta {
|
226
|
+
text-align: left;
|
227
|
+
}
|
228
|
+
|
211
229
|
#data-wrapper {
|
212
230
|
overflow: scroll;
|
213
231
|
}
|
@@ -96,7 +96,7 @@ class ConsulNodes {
|
|
96
96
|
contentHead.setAttribute('class','instance-content-header');
|
97
97
|
contentHead.appendChild(nodeNameGenator(instance['Node']['Name'],instance['Node']['Address']));
|
98
98
|
contentHead.appendChild(nodeAddressGenator(instance['Node']['Address']));
|
99
|
-
contentHead.appendChild(
|
99
|
+
contentHead.appendChild(nodeMetaGenerator(instance['Node']['Meta']));
|
100
100
|
content.appendChild(contentHead);
|
101
101
|
var nodesChecks = document.createElement('div');
|
102
102
|
nodesChecks.setAttribute('class','nodes-checks');
|
@@ -20,9 +20,9 @@ class ConsulService {
|
|
20
20
|
}, 100);
|
21
21
|
}
|
22
22
|
|
23
|
-
showTags(
|
23
|
+
showTags(enableTags) {
|
24
24
|
var stylesheet = document.getElementById('css-states');
|
25
|
-
stylesheet.textContent = '.service-tags { display: ' + (
|
25
|
+
stylesheet.textContent = '.service-tags { display: ' + (enableTags? 'block':'none') + '!important ;}';
|
26
26
|
}
|
27
27
|
|
28
28
|
showProxies(showProxies) {
|
@@ -239,10 +239,10 @@ class ConsulService {
|
|
239
239
|
this.selectedService = source.closest('li');
|
240
240
|
$(this.selectedService).addClass('active');
|
241
241
|
|
242
|
-
this.displayService(this.data.services[serviceName]);
|
242
|
+
this.displayService(this.data.services[serviceName], this.data.nodes);
|
243
243
|
}
|
244
244
|
|
245
|
-
displayService(service) {
|
245
|
+
displayService(service, nodes) {
|
246
246
|
var titleText = service['name'] + ' <a href="consul-timeline-ui.html?service=' + service['name'] + '">timeline</a>';
|
247
247
|
$("#service-title").html(titleText);
|
248
248
|
$("#instances-list").html("");
|
@@ -252,13 +252,22 @@ class ConsulService {
|
|
252
252
|
for (var key in service['instances']) {
|
253
253
|
var instance = service['instances'][key];
|
254
254
|
var serviceHtml = document.createElement('div');
|
255
|
-
serviceHtml.setAttribute('class','list-group-item');
|
255
|
+
serviceHtml.setAttribute('class','list-group-item service-instance');
|
256
256
|
var state = nodeState(instance.checks);
|
257
257
|
serviceHtml.appendChild(weightsGenerator(instance.weights, state));
|
258
258
|
serviceHtml.appendChild(serviceTitleGenerator(instance));
|
259
|
-
|
259
|
+
var node_info = nodes[instance.name];
|
260
|
+
if (node_info != null) {
|
261
|
+
node_info = node_info.meta;
|
262
|
+
serviceHtml.appendChild(nodeMetaGenerator(node_info));
|
263
|
+
serviceHtml.appendChild(document.createElement('hr'));
|
264
|
+
}
|
265
|
+
if (instance.tags && instance.tags.length > 0) {
|
266
|
+
serviceHtml.appendChild(tagsGenerator(instance.tags));
|
267
|
+
serviceHtml.appendChild(document.createElement('hr'));
|
268
|
+
}
|
260
269
|
serviceHtml.appendChild(serviceMetaGenerator(instance.sMeta));
|
261
|
-
serviceHtml.appendChild(connectGenerator(instance))
|
270
|
+
serviceHtml.appendChild(connectGenerator(instance));
|
262
271
|
serviceHtml.appendChild(checksStatusGenerator(instance, instance.name));
|
263
272
|
serviceHtml.setAttribute('status', state);
|
264
273
|
$("#instances-list").append(serviceHtml);
|
@@ -53,12 +53,12 @@ function serviceTitleGenerator(instance) {
|
|
53
53
|
|
54
54
|
var htmlTitle = document.createElement('h5');
|
55
55
|
htmlTitle.setAttribute('title', 'Node Name: ' + instance.name +
|
56
|
-
'\nAddress
|
56
|
+
'\nAddress: ' + instance.addr +
|
57
57
|
'\nService ID: ' + instance.id +
|
58
|
-
'\nService Port
|
58
|
+
'\nService Port: ' + instance.port);
|
59
59
|
|
60
|
+
htmlTitle.setAttribute('class', 'instance-name');
|
60
61
|
var instanceLink = document.createElement('a');
|
61
|
-
instanceLink.setAttribute('class', 'instance-name');
|
62
62
|
var appendPort = "";
|
63
63
|
if (instance.port > 0) {
|
64
64
|
appendPort = ':' + instance.port;
|
@@ -70,6 +70,8 @@ function serviceTitleGenerator(instance) {
|
|
70
70
|
|
71
71
|
instanceLink.appendChild(document.createTextNode(instance.name + appendPort));
|
72
72
|
htmlTitle.appendChild(instanceLink);
|
73
|
+
htmlTitle.appendChild(document.createTextNode(' '));
|
74
|
+
htmlTitle.appendChild(document.createTextNode(instance.addr));
|
73
75
|
|
74
76
|
return htmlTitle;
|
75
77
|
}
|
@@ -93,20 +95,21 @@ function nodeNameGenator(nodename, nodeaddr) {
|
|
93
95
|
|
94
96
|
function nodeAddressGenator(nodeaddr) {
|
95
97
|
var htmlAddress = document.createElement('h5');
|
96
|
-
htmlAddress.className = 'instance-addr';
|
98
|
+
htmlAddress.className = 'instance-addr lookup';
|
97
99
|
htmlAddress.appendChild(document.createTextNode(nodeaddr));
|
98
100
|
return htmlAddress;
|
99
101
|
}
|
100
102
|
|
101
|
-
function
|
103
|
+
function nodeMetaGenerator(nodeMetaTags) {
|
102
104
|
var metaTags = document.createElement('div');
|
103
|
-
metaTags.
|
105
|
+
metaTags.setAttribute('title', 'Node Meta')
|
106
|
+
metaTags.className = 'node-meta';
|
104
107
|
for (var tagKey in nodeMetaTags) {
|
105
108
|
if(!nodeMetaTags[tagKey]) {
|
106
109
|
continue;
|
107
110
|
}
|
108
111
|
var metaTag = document.createElement('span');
|
109
|
-
metaTag.setAttribute('class', 'badge badge-primary mx-1');
|
112
|
+
metaTag.setAttribute('class', 'badge badge-primary mx-1 lookup');
|
110
113
|
metaTag.appendChild(document.createTextNode(tagKey + ':' + nodeMetaTags[tagKey]));
|
111
114
|
metaTags.appendChild(metaTag);
|
112
115
|
}
|
@@ -117,11 +120,10 @@ function tagsGenerator(instanceTags) {
|
|
117
120
|
var tags = document.createElement('div');
|
118
121
|
|
119
122
|
tags.className = 'instance-tags';
|
120
|
-
tags.
|
121
|
-
tags.appendChild(document.createElement('br'));
|
123
|
+
tags.setAttribute('title', 'Tags of Service');
|
122
124
|
for (var tagKey in instanceTags) {
|
123
125
|
var tag = document.createElement('span');
|
124
|
-
tag.setAttribute('class', 'badge badge-secondary mx-1');
|
126
|
+
tag.setAttribute('class', 'badge badge-secondary mx-1 lookup');
|
125
127
|
tag.appendChild(document.createTextNode(instanceTags[tagKey]));
|
126
128
|
tags.appendChild(tag);
|
127
129
|
}
|
@@ -160,11 +162,11 @@ function serviceMetaGenerator(instanceMeta) {
|
|
160
162
|
container.className = 'row';
|
161
163
|
for (var meta in instanceMeta) {
|
162
164
|
var metaH = document.createElement('dt');
|
163
|
-
metaH.className = 'col-sm-4';
|
165
|
+
metaH.className = 'col-sm-4 lookup';
|
164
166
|
metaH.appendChild(document.createTextNode(meta));
|
165
167
|
container.appendChild(metaH);
|
166
168
|
var metaVH = document.createElement('dd');
|
167
|
-
metaVH.className = 'col-sm-8';
|
169
|
+
metaVH.className = 'col-sm-8 lookup';
|
168
170
|
metaVH.appendChild(document.createTextNode(instanceMeta[meta]));
|
169
171
|
container.appendChild(metaVH);
|
170
172
|
}
|
@@ -216,7 +218,7 @@ function servicesGenerator(instanceServices) {
|
|
216
218
|
var service = document.createElement('a');
|
217
219
|
var serviceName = instanceServices[serviceKey]['Service']['Service'];
|
218
220
|
var servicePort = instanceServices[serviceKey]['Service']['Port'];
|
219
|
-
service.setAttribute('class', 'btn btn-sm m-1');
|
221
|
+
service.setAttribute('class', 'btn btn-sm m-1 lookup');
|
220
222
|
service.setAttribute('target', '_blank');
|
221
223
|
nodeAddr = instanceServices[serviceKey]['Service']['Address'];
|
222
224
|
service.setAttribute('href', 'http://' + nodeAddr + ':' + servicePort);
|
@@ -231,8 +233,7 @@ function checksStatusGenerator(instance, prefix) {
|
|
231
233
|
var instanceChecks = instance.checks;
|
232
234
|
var checks = document.createElement('div');
|
233
235
|
checks.className = 'checks';
|
234
|
-
checks.
|
235
|
-
checks.appendChild(document.createElement('br'));
|
236
|
+
checks.setAttribute('title', 'Checks of Node/Service')
|
236
237
|
|
237
238
|
for (var checkKey in instanceChecks) {
|
238
239
|
var checkInstance = instanceChecks[checkKey];
|
@@ -354,19 +355,22 @@ function keyMatcher(service, regex) {
|
|
354
355
|
}
|
355
356
|
}
|
356
357
|
|
358
|
+
function hasMatches(instance, regex) {
|
359
|
+
var toLookup = instance.getElementsByClassName('lookup');
|
360
|
+
for (var i = 0 ; i < toLookup.length; i++) {
|
361
|
+
if(toLookup[i].innerHTML.match(regex)) {
|
362
|
+
return true;
|
363
|
+
}
|
364
|
+
}
|
365
|
+
return false;
|
366
|
+
}
|
367
|
+
|
357
368
|
function instanceMatcher(instance, regex) {
|
358
369
|
if(instance.getElementsByClassName('instance-name')[0].innerHTML.match(regex)) {
|
359
370
|
return true;
|
360
371
|
}
|
361
372
|
|
362
|
-
|
363
|
-
|
364
|
-
for (var i=0; i < tags.length; i++) {
|
365
|
-
if(tags[i].innerHTML.match(regex)) {
|
366
|
-
return true;
|
367
|
-
}
|
368
|
-
}
|
369
|
-
return false;
|
373
|
+
return hasMatches(instance, regex);
|
370
374
|
}
|
371
375
|
|
372
376
|
function nodeMatcher(instance, regex) {
|
@@ -375,23 +379,7 @@ function nodeMatcher(instance, regex) {
|
|
375
379
|
return true;
|
376
380
|
}
|
377
381
|
|
378
|
-
|
379
|
-
return true;
|
380
|
-
}
|
381
|
-
|
382
|
-
var metaTags = instance.getElementsByClassName('meta-tags')[0].getElementsByClassName('badge');
|
383
|
-
for (var i=0; i < metaTags.length; i++) {
|
384
|
-
if(metaTags[i].innerHTML.match(regex)) {
|
385
|
-
return true;
|
386
|
-
}
|
387
|
-
}
|
388
|
-
|
389
|
-
var services = instance.getElementsByClassName('instance-services')[0].getElementsByClassName('btn');
|
390
|
-
for (var i=0; i < services.length; i++) {
|
391
|
-
if(services[i].innerHTML.match(regex)) {
|
392
|
-
return true;
|
393
|
-
}
|
394
|
-
}
|
382
|
+
return hasMatches(instance, regex);
|
395
383
|
}
|
396
384
|
|
397
385
|
function getTagsNode(node) {
|
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.13.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-04-
|
11
|
+
date: 2019-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|