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.
@@ -1,265 +1,251 @@
1
- class ConsulNodes {
2
- constructor(ressourceURL, refresh) {
3
- this.ressourceURL = ressourceURL;
4
- this.fetchRessource();
5
- this.instanceFilter = $("#instance-filter");
6
- var filter = new URL(location.href).searchParams.get('filter');
7
- if (filter!=null && filter!='') {
8
- this.instanceFilter.val(filter);
9
- };
10
- this.instanceFilter.keyup(debounce(this.filterInstances, 400));
11
- this.refresh = parseInt(refresh);
12
- this.filterStatus = null;
13
- this.maxDisplayed = 100;
14
- this.displayedCount = 0;
15
- this.servicesStatus = {};
16
- window.setTimeout(function(){
17
- if (filter!=null && filter!='') {
18
- consulNodes.instanceFilter.val(filter);
19
- console.log(this.instanceFilter.value)
20
- consulNodes.filterInstances();
21
- }
22
- }, 100);
23
- }
24
-
25
- fetchRessource() {
26
- $.ajax({url: this.ressourceURL, cache: false, dataType: "json", sourceObject: this, success: function(result){
27
- consulNodes.initRessource(result);
28
- }});
29
- }
30
-
31
- initRessource(data) {
32
- this.data = data;
33
- this.displayInstances(this.data['nodes']);
34
- console.log('Data generated at: ' + data['generated_at']);
35
- }
1
+ class ConsulNodesManager extends ConsulUIManager {
2
+ constructor(resourceURL) {
3
+ super(resourceURL);
4
+ this.mainSelector = new NodeMainSelector(
5
+ $("#instances-list"),
6
+ $("#instance-filter"),
7
+ $("#instance-counter"),
8
+ $("#max-display-selector"),
9
+ "node_filter",
10
+ "node_status_filter"
11
+ );
12
+ this.fetchResource();
13
+ }
36
14
 
37
- onClickFilter(source) {
38
- var status = $(source).attr('status');
39
- this.filterStatus = (this.filterStatus == status) ? null : status;
40
- this.filterInstances();
41
- }
15
+ async initResource(data) {
16
+ this.mainSelector.initSelector(data["nodes"]);
17
+ }
18
+ }
42
19
 
43
- updateURL() {
44
- var newUrl = new URL(location.href);
45
- if (consulNodes.instanceFilter.val()!='') {
46
- newUrl.searchParams.set('filter', consulNodes.instanceFilter.val());
47
- } else {
48
- newUrl.searchParams.delete('filter')
20
+ class NodeMainSelector extends MainSelector {
21
+ constructor(listElement, filterElement, counterElement, maxDisplayed, URLLabelFilter, URLLabelStatus) {
22
+ super(listElement, filterElement, counterElement, maxDisplayed, URLLabelFilter, URLLabelStatus);
23
+ this.passingStatusButtonElement = $("#service-status-passing");
24
+ this.warningStatusButtonElement = $("#service-status-warning");
25
+ this.criticalStatusButtonElement = $("#service-status-critical");
26
+ this.totalStatusButtonElement = $("#service-status-total");
27
+ this.initStatusButtons();
49
28
  }
50
- window.history.pushState({},"",newUrl);
51
- }
52
29
 
53
- filterInstances() {
54
- updateFilterDisplay(consulNodes.filterStatus);
55
- consulNodes.updateURL();
56
- consulNodes.displayedCount = 0;
57
- consulNodes.servicesStatus = {};
58
- var filter = new RegExp(consulNodes.instanceFilter.val());
59
- $('#instances-list').children('div').each(function() {
60
- var status = $(this).attr('status');
61
- var limitNotReached = (consulNodes.displayedCount < consulNodes.maxDisplayed);
30
+ initStatusButtons() {
31
+ var obj = this;
32
+ this.passingStatusButtonElement.get(0).addEventListener("click", function () {
33
+ obj.onClickFilter(this, "passing");
34
+ });
35
+ this.warningStatusButtonElement.get(0).addEventListener("click", function () {
36
+ obj.onClickFilter(this, "warning");
37
+ });
38
+ this.criticalStatusButtonElement.get(0).addEventListener("click", function () {
39
+ obj.onClickFilter(this, "critical");
40
+ });
41
+ this.totalStatusButtonElement.get(0).addEventListener("click", function () {
42
+ obj.onClickFilter(this, null);
43
+ });
44
+ }
62
45
 
63
- if(nodeMatcher(this, filter)) {
64
- if (consulNodes.filterStatus == null || consulNodes.filterStatus == status) {
65
- if (limitNotReached) {
66
- $(this).removeClass('d-none');
67
- $(this).addClass('d-flex');
68
- consulNodes.displayedCount++;
69
- }
70
- var state = this.getAttribute('status');
71
- consulNodes.servicesStatus[state] = (consulNodes.servicesStatus[state] || 0) + 1;
72
- consulNodes.servicesStatus['total'] = (consulNodes.servicesStatus['total'] || 0) + 1;
73
- updateStatusItem(consulNodes.servicesStatus);
74
- } else {
75
- $(this).removeClass('d-flex');
76
- $(this).addClass('d-none');
46
+ elementGenerator(node) {
47
+ var element = document.createElement('div');
48
+ element.setAttribute('class', 'list-group-item');
49
+
50
+ var sidebar = document.createElement('div');
51
+ sidebar.setAttribute('class', 'status-sidebar');
52
+
53
+ var state = getGeneralNodeStatus(node['Service']);
54
+ switch (state)  {
55
+ case 'passing':
56
+ sidebar.classList.add('bg-success');
57
+ break;
58
+ case 'warning':
59
+ sidebar.classList.add('bg-warning');
60
+ break;
61
+ case 'critical':
62
+ sidebar.classList.add('bg-danger');
63
+ break;
77
64
  }
78
- } else {
79
- $(this).removeClass('d-flex');
80
- $(this).addClass('d-none');
81
- }
82
- })
83
- }
84
65
 
85
- // taken from https://www.consul.io/docs/internals/coordinates.html#working-with-coordinates
86
- compute_dist(a, b) {
87
- var sumsq = 0.0
88
- for (var i = 0; i < a.Vec.length; i++) {
89
- var diff = a.Vec[i] - b.Vec[i]
90
- sumsq += diff * diff
66
+ var content = document.createElement('div');
67
+ content.setAttribute('class', 'instance-content');
68
+ var contentHead = document.createElement('div');
69
+ contentHead.setAttribute('class', 'instance-content-header');
70
+ contentHead.appendChild(nodeNameGenator(node['Node']['Name'], node['Node']['Address']));
71
+ contentHead.appendChild(nodeAddressGenator(node['Node']['Address']));
72
+ contentHead.appendChild(nodeMetaGenerator(node['Node']['Meta']));
73
+ content.appendChild(contentHead);
74
+ var distances = document.createElement('div');
75
+ var distancesRefresh = document.createElement("button");
76
+ distancesRefresh.appendChild(document.createTextNode("Show/Hide Node Latency"));
77
+ distancesRefresh.setAttribute("class", "distancesButton");
78
+ distances.appendChild(distancesRefresh);
79
+ var distancesContent = document.createElement("div");
80
+ distances.appendChild(distancesContent);
81
+
82
+ var distancesContentToUpdate = distancesContent;
83
+ var obj = this
84
+ distancesRefresh.addEventListener("click", function () {
85
+ if (distancesContentToUpdate.children.length == 0) {
86
+ var x = obj.compute_all_distances(node['Node']['Name']);
87
+ var dl = document.createElement(dl);
88
+ dl.className = 'row';
89
+ for (var i in x) {
90
+ var dt = document.createElement("dt");
91
+ dt.appendChild(document.createTextNode(i));
92
+ dt.className = 'col-sm-4';
93
+ dl.appendChild(dt);
94
+ var dd = document.createElement("dd");
95
+ dd.appendChild(document.createTextNode(x[i]));
96
+ dd.className = 'col-sm-8';
97
+ dl.appendChild(dd);
98
+ }
99
+ distancesContentToUpdate.appendChild(dl);
100
+ } else {
101
+ distancesContentToUpdate.innerHTML = '';
102
+ }
103
+ });
104
+ content.appendChild(distances);
105
+ var nodesChecks = document.createElement('div');
106
+ nodesChecks.setAttribute('class', 'nodes-checks');
107
+ nodesChecks.appendChild(checksStatusGenerator(node, node['Node']['Name']));
108
+ content.appendChild(nodesChecks);
109
+
110
+ content.appendChild(servicesGenerator(node['Service']));
111
+ content.appendChild(tagsGenerator(getTagsNode(node)));
112
+
113
+ sidebar.setAttribute('status', state);
114
+ element.appendChild(sidebar)
115
+ element.appendChild(content)
116
+ return element
91
117
  }
92
- var rtt = Math.sqrt(sumsq) + a.Height + b.Height
93
118
 
94
- // Apply the adjustment components, guarding against negatives.
95
- var adjusted = rtt + a.Adjustment + b.Adjustment
96
- if (adjusted > 0.0) {
97
- rtt = adjusted
119
+ updateStatusCounters() {
120
+ updateStatusItem(this.selectorStatus);
98
121
  }
99
122
 
100
- // Go's times are natively nanoseconds, so we convert from seconds.
101
- const secondsToNanoseconds = 1.0e9
102
- return rtt
103
- }
123
+ getStatus(node) {
124
+ return getGeneralNodeStatus(node.Service)
125
+ }
104
126
 
105
- compute_all_distances(instances, node) {
106
- const asc = function(arr) { return arr.sort((a, b) => a - b); }
107
- // sample standard deviation
108
- const std = function (arr) {
109
- const mu = mean(arr);
110
- const diffArr = arr.map(a => (a - mu) ** 2);
111
- return Math.sqrt(sum(diffArr) / (arr.length - 1));
112
- };
127
+ matchElement(node, filter) {
128
+ if (
129
+ this.statusFilter != null &&
130
+ this.getStatus(node) != this.statusFilter
131
+ ) {
132
+ return false;
133
+ }
113
134
 
114
- const quantile = function(sorted, q) {
115
- //const sorted = asc(arr);
116
- const pos = ((sorted.length) - 1) * q;
117
- //console.log("pos", pos, "for", q);
118
- const base = Math.floor(pos);
119
- const rest = pos - base;
120
- if ((sorted[base + 1] !== undefined)) {
121
- return sorted[base] + rest * (sorted[base + 1] - sorted[base]);
122
- } else {
123
- return sorted[base];
124
- }
125
- };
135
+ if (node.Node.Name.match(filter)) {
136
+ return true;
137
+ }
126
138
 
127
- var sum = 0;
128
- var count = 0;
129
- var ret = {
130
- min: 3600,
131
- min_node: null,
132
- max: 0,
133
- max_node: null,
134
- };
135
- var all_values = [];
136
- var myCoords = instances[node]['Coord']
137
- if (myCoords == null) {
138
- console.log("Coords are not defined for ", node)
139
- return null;
140
- } else {
141
- for (var key in instances) {
142
- var instance = instances[key];
143
- if (key != node && instance != null && instance['Coord'] != null) {
144
- count++
145
- var coord = instance['Coord'];
146
- if (coord != null) {
147
- const rtt = this.compute_dist(myCoords, coord);
148
- all_values.push(rtt);
149
- if (rtt < ret.min) {
150
- ret.min = rtt;
151
- ret.min_node = key
139
+ if (node.Node.Address.match(filter)) {
140
+ return true;
141
+ }
142
+
143
+ var tags = getTagsNode(node)
144
+ for (var i in tags) {
145
+ if (tags[i].match(filter)) {
146
+ return true;
152
147
  }
153
- if (rtt > ret.max) {
154
- ret.max = rtt;
155
- ret.max_node = key;
148
+ }
149
+
150
+ for (var key in node.Node.Meta) {
151
+ if ((key + ":" + node.Node.Meta[key]).match(filter)) {
152
+ return true;
156
153
  }
157
- sum += rtt;
158
- }
159
154
  }
160
- }
161
- }
162
- all_values = all_values.sort();
163
- ret.avg = sum / count;
164
- ret.q50 = quantile(all_values, .50);
165
- ret.q90 = quantile(all_values, .90);
166
- ret.q99 = quantile(all_values, .99);
167
- ret.q999 = quantile(all_values, .999);
168
- ret.q9999 = quantile(all_values, .9999);
169
- return ret;
170
- }
171
155
 
172
- displayInstances(instances) {
173
- $("#instances-list").html("");
156
+ return false;
157
+ }
174
158
 
175
- // var serviceStatus = buildServiceStatus(service);
176
- this.displayedCount = 0;
177
- var nodesInfo = this;
178
- for (var key in instances) {
179
- var instance = instances[key];
159
+ // taken from https://www.consul.io/docs/internals/coordinates.html#working-with-coordinates
160
+ compute_dist(a, b) {
161
+ var sumsq = 0.0
162
+ for (var i = 0; i < a.Vec.length; i++) {
163
+ var diff = a.Vec[i] - b.Vec[i]
164
+ sumsq += diff * diff
165
+ }
166
+ var rtt = Math.sqrt(sumsq) + a.Height + b.Height
180
167
 
181
- var instanceHtml = document.createElement('div');
182
- if(this.displayedCount > this.maxDisplayed) {
183
- instanceHtml.setAttribute('class','list-group-item d-none');
184
- } else {
185
- instanceHtml.setAttribute('class','list-group-item');
186
- }
168
+ // Apply the adjustment components, guarding against negatives.
169
+ var adjusted = rtt + a.Adjustment + b.Adjustment
170
+ if (adjusted > 0.0) {
171
+ rtt = adjusted
172
+ }
187
173
 
188
- var sidebar = document.createElement('div');
189
- sidebar.setAttribute('class','status-sidebar');
190
- var state = getGeneralNodeStatus(instance['Service']);
191
- switch(state) {
192
- case 'passing': sidebar.classList.add('bg-success'); break;
193
- case 'warning': sidebar.classList.add('bg-warning'); break;
194
- case 'critical': sidebar.classList.add('bg-danger'); break;
195
- }
196
- this.servicesStatus[state] = (this.servicesStatus[state] || 0) + 1;
197
- this.servicesStatus['total'] = (this.servicesStatus['total'] || 0) + 1;
174
+ // Go's times are natively nanoseconds, so we convert from seconds.
175
+ const secondsToNanoseconds = 1.0e9
176
+ return rtt
177
+ }
198
178
 
199
- var content = document.createElement('div');
200
- content.setAttribute('class','instance-content');
201
- var contentHead = document.createElement('div');
202
- contentHead.setAttribute('class','instance-content-header');
203
- contentHead.appendChild(nodeNameGenator(instance['Node']['Name'],instance['Node']['Address']));
204
- contentHead.appendChild(nodeAddressGenator(instance['Node']['Address']));
205
- contentHead.appendChild(nodeMetaGenerator(instance['Node']['Meta']));
206
- content.appendChild(contentHead);
207
- var distances = document.createElement('div');
208
- var distancesRefresh = document.createElement("button");
209
- distancesRefresh.appendChild(document.createTextNode("Show/Hide Node Latency"));
210
- distancesRefresh.setAttribute("class", "distancesButton");
211
- distances.appendChild(distancesRefresh);
212
- var distancesContent = document.createElement("div");
213
- distances.appendChild(distancesContent);
214
- (function() {
215
- var nodeName = instance['Node']['Name'];
216
- var distancesContentToUpdate = distancesContent;
217
- var buttonToHide = $(distancesRefresh);
218
- $(distancesRefresh).click(function(){
219
- if (distancesContentToUpdate.children.length == 0){
220
- var x = nodesInfo.compute_all_distances(instances, nodeName);
221
- var dl = document.createElement(dl);
222
- dl.className = 'row';
223
- for (var i in x) {
224
- var dt = document.createElement("dt");
225
- dt.appendChild(document.createTextNode(i));
226
- dt.className = 'col-sm-4';
227
- dl.appendChild(dt);
228
- var dd = document.createElement("dd");
229
- dd.appendChild(document.createTextNode(x[i]));
230
- dd.className = 'col-sm-8';
231
- dl.appendChild(dd);
179
+ compute_all_distances(node) {
180
+ const asc = function (arr) {
181
+ return arr.sort((a, b) => a - b);
232
182
  }
233
- distancesContentToUpdate.appendChild(dl);
234
- } else {
235
- distancesContentToUpdate.innerHTML = '';
236
- }
237
- });
238
- })();
239
- content.appendChild(distances);
240
- //distances.appendChild()
241
- var nodesChecks = document.createElement('div');
242
- nodesChecks.setAttribute('class','nodes-checks');
243
- nodesChecks.appendChild(checksStatusGenerator(instance, instance['Node']['Name']));
244
- content.appendChild(nodesChecks);
245
-
246
- content.appendChild(servicesGenerator(instance['Service']));
247
- content.appendChild(tagsGenerator(getTagsNode(instance)));
248
-
249
- instanceHtml.setAttribute('status', state);
250
- instanceHtml.appendChild(sidebar)
251
- instanceHtml.appendChild(content)
252
-
253
- $("#instances-list").append(instanceHtml);
254
-
255
- this.displayedCount++;
183
+ // sample standard deviation
184
+ const std = function (arr) {
185
+ const mu = mean(arr);
186
+ const diffArr = arr.map(a => (a - mu) ** 2);
187
+ return Math.sqrt(sum(diffArr) / (arr.length - 1));
188
+ };
189
+
190
+ const quantile = function (sorted, q) {
191
+ //const sorted = asc(arr);
192
+ const pos = ((sorted.length) - 1) * q;
193
+ //console.log("pos", pos, "for", q);
194
+ const base = Math.floor(pos);
195
+ const rest = pos - base;
196
+ if ((sorted[base + 1] !== undefined)) {
197
+ return sorted[base] + rest * (sorted[base + 1] - sorted[base]);
198
+ } else {
199
+ return sorted[base];
200
+ }
201
+ };
202
+
203
+ var sum = 0;
204
+ var count = 0;
205
+ var ret = {
206
+ min: 3600,
207
+ min_node: null,
208
+ max: 0,
209
+ max_node: null,
210
+ };
211
+ var all_values = [];
212
+ var myCoords = this.data[node]['Coord']
213
+ if (myCoords == null) {
214
+ console.log("Coords are not defined for ", node)
215
+ return null;
216
+ } else {
217
+ for (var key in this.data) {
218
+ var instance = this.data[key];
219
+ if (key != node && instance != null && instance['Coord'] != null) {
220
+ count++
221
+ var coord = instance['Coord'];
222
+ if (coord != null) {
223
+ const rtt = this.compute_dist(myCoords, coord);
224
+ all_values.push(rtt);
225
+ if (rtt < ret.min) {
226
+ ret.min = rtt;
227
+ ret.min_node = key
228
+ }
229
+ if (rtt > ret.max) {
230
+ ret.max = rtt;
231
+ ret.max_node = key;
232
+ }
233
+ sum += rtt;
234
+ }
235
+ }
236
+ }
237
+ }
238
+ all_values = all_values.sort();
239
+ ret.avg = sum / count;
240
+ ret.q50 = quantile(all_values, .50);
241
+ ret.q90 = quantile(all_values, .90);
242
+ ret.q99 = quantile(all_values, .99);
243
+ ret.q999 = quantile(all_values, .999);
244
+ ret.q9999 = quantile(all_values, .9999);
245
+ return ret;
256
246
  }
257
247
 
258
- resizeInstances();
259
- $('#instances-list .list-group-item').resize(resizeInstances);
260
- this.filterInstances();
261
- }
262
248
  }
263
249
 
264
- $( window ).resize(resizeInstances);
265
- resizeInstances();
250
+ $(window).resize(resizeInstances);
251
+ resizeInstances();