consul-templaterb 1.25.2 → 1.27.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 +7 -7
- data/.travis.yml +5 -5
- data/CHANGELOG.md +43 -0
- data/Dockerfile +1 -1
- data/INTERNALS.md +2 -0
- data/README.md +3 -1
- data/TemplateAPI.md +184 -164
- data/bin/consul-templaterb +30 -0
- data/docs/article-06_Template-based_discovery_with_consul-templaterb.md +124 -0
- data/docs/images/consul-templaterb.png +0 -0
- data/docs/images/consul-templaterb.svg +3 -0
- data/lib/consul/async/consul_endpoint.rb +28 -7
- data/lib/consul/async/consul_template.rb +56 -34
- data/lib/consul/async/json_endpoint.rb +15 -2
- data/lib/consul/async/vault_endpoint.rb +25 -6
- data/lib/consul/async/version.rb +1 -1
- data/samples/all_services.txt.erb +1 -1
- data/samples/all_services_multi_agents.txt.erb +69 -0
- data/samples/checks_in_warning_or_critical_state.yaml.erb +13 -0
- data/samples/consul-ui/README.md +19 -0
- data/samples/consul-ui/decorators.js.erb +2 -171
- data/samples/display_timestamped_changes.txt.erb +17 -0
- data/samples/find_all_invalid_dns_labels.json.erb +12 -0
- data/samples/find_nodes_in_catalog_but_not_in_members.json.erb +28 -0
- data/samples/metrics.erb +14 -0
- metadata +10 -2
@@ -9,7 +9,7 @@ module Consul
|
|
9
9
|
class JSONConfiguration
|
10
10
|
attr_reader :url, :retry_duration, :min_duration, :retry_on_non_diff,
|
11
11
|
:debug, :enable_gzip_compression, :request_method, :json_body,
|
12
|
-
:headers
|
12
|
+
:headers, :tls_cert_chain, :tls_private_key, :tls_verify_peer
|
13
13
|
def initialize(url:,
|
14
14
|
debug: { network: false },
|
15
15
|
retry_duration: 10,
|
@@ -18,7 +18,10 @@ module Consul
|
|
18
18
|
request_method: :get,
|
19
19
|
json_body: nil,
|
20
20
|
headers: {},
|
21
|
-
enable_gzip_compression: true
|
21
|
+
enable_gzip_compression: true,
|
22
|
+
tls_cert_chain: nil,
|
23
|
+
tls_private_key: nil,
|
24
|
+
tls_verify_peer: true)
|
22
25
|
@url = url
|
23
26
|
@debug = debug
|
24
27
|
@enable_gzip_compression = enable_gzip_compression
|
@@ -28,6 +31,9 @@ module Consul
|
|
28
31
|
@request_method = request_method
|
29
32
|
@json_body = json_body
|
30
33
|
@headers = headers
|
34
|
+
@tls_cert_chain = tls_cert_chain
|
35
|
+
@tls_private_key = tls_private_key
|
36
|
+
@tls_verify_peer = tls_verify_peer
|
31
37
|
end
|
32
38
|
|
33
39
|
def create(_url)
|
@@ -181,6 +187,13 @@ module Consul
|
|
181
187
|
connect_timeout: 5, # default connection setup timeout
|
182
188
|
inactivity_timeout: 60 # default connection inactivity (post-setup) timeout
|
183
189
|
}
|
190
|
+
unless conf.tls_cert_chain.nil?
|
191
|
+
options[:tls] = {
|
192
|
+
cert_chain_file: conf.tls_cert_chain,
|
193
|
+
private_key_file: conf.tls_private_key,
|
194
|
+
verify_peer: conf.tls_verify_peer
|
195
|
+
}
|
196
|
+
end
|
184
197
|
connection = {
|
185
198
|
conn: EventMachine::HttpRequest.new(conf.url, options)
|
186
199
|
}
|
@@ -10,7 +10,8 @@ module Consul
|
|
10
10
|
# Configuration for Vault Endpoints
|
11
11
|
class VaultConfiguration
|
12
12
|
attr_reader :base_url, :token, :token_renew, :retry_duration, :min_duration, :wait_duration, :max_retry_duration, :retry_on_non_diff,
|
13
|
-
:lease_duration_factor, :debug, :max_consecutive_errors_on_endpoint, :fail_fast_errors
|
13
|
+
:lease_duration_factor, :debug, :max_consecutive_errors_on_endpoint, :fail_fast_errors, :tls_cert_chain, :tls_private_key,
|
14
|
+
:tls_verify_peer
|
14
15
|
|
15
16
|
def initialize(base_url: 'http://localhost:8200',
|
16
17
|
debug: { network: false },
|
@@ -22,7 +23,10 @@ module Consul
|
|
22
23
|
max_retry_duration: 600,
|
23
24
|
paths: {},
|
24
25
|
max_consecutive_errors_on_endpoint: 10,
|
25
|
-
fail_fast_errors: false
|
26
|
+
fail_fast_errors: false,
|
27
|
+
tls_cert_chain: nil,
|
28
|
+
tls_private_key: nil,
|
29
|
+
tls_verify_peer: true)
|
26
30
|
@base_url = base_url
|
27
31
|
@token_renew = token_renew
|
28
32
|
@debug = debug
|
@@ -34,6 +38,9 @@ module Consul
|
|
34
38
|
@token = token
|
35
39
|
@max_consecutive_errors_on_endpoint = max_consecutive_errors_on_endpoint
|
36
40
|
@fail_fast_errors = fail_fast_errors
|
41
|
+
@tls_cert_chain = tls_cert_chain
|
42
|
+
@tls_private_key = tls_private_key
|
43
|
+
@tls_verify_peer = tls_verify_peer
|
37
44
|
end
|
38
45
|
|
39
46
|
def ch(path, symbol)
|
@@ -46,10 +53,15 @@ module Consul
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
49
|
-
def create(path)
|
56
|
+
def create(path, agent: nil)
|
50
57
|
return self unless @paths[path.to_sym]
|
51
58
|
|
52
|
-
|
59
|
+
base_url = ch(path, :base_url)
|
60
|
+
if agent
|
61
|
+
agent = "http://#{agent}" unless agent.start_with? 'http', 'https'
|
62
|
+
base_url = agent
|
63
|
+
end
|
64
|
+
VaultConfiguration.new(base_url: base_url,
|
53
65
|
debug: ch(path, :debug),
|
54
66
|
token: ch(path, :token),
|
55
67
|
retry_duration: ch(path, :retry_duration),
|
@@ -117,8 +129,8 @@ module Consul
|
|
117
129
|
class VaultEndpoint
|
118
130
|
attr_reader :conf, :path, :http_method, :queue, :stats, :last_result, :enforce_json_200, :start_time, :default_value, :query_params
|
119
131
|
|
120
|
-
def initialize(conf, path, http_method = 'GET', enforce_json_200 = true, query_params = {}, default_value = '{}', post_data = {})
|
121
|
-
@conf = conf.create(path)
|
132
|
+
def initialize(conf, path, http_method = 'GET', enforce_json_200 = true, query_params = {}, default_value = '{}', post_data = {}, agent: nil)
|
133
|
+
@conf = conf.create(path, agent: agent)
|
122
134
|
@default_value = default_value
|
123
135
|
@path = path
|
124
136
|
@http_method = http_method
|
@@ -221,6 +233,13 @@ module Consul
|
|
221
233
|
connect_timeout: 5, # default connection setup timeout
|
222
234
|
inactivity_timeout: 1 # default connection inactivity (post-setup) timeout
|
223
235
|
}
|
236
|
+
unless conf.tls_cert_chain.nil?
|
237
|
+
options[:tls] = {
|
238
|
+
cert_chain_file: conf.tls_cert_chain,
|
239
|
+
private_key_file: conf.tls_private_key,
|
240
|
+
verify_peer: conf.tls_verify_peer
|
241
|
+
}
|
242
|
+
end
|
224
243
|
connection = EventMachine::HttpRequest.new(conf.base_url, options)
|
225
244
|
cb = proc do |_|
|
226
245
|
http = connection.send(http_method.downcase, build_request) # Under the hood: c.send('get', {stuff}) === c.get({stuff})
|
data/lib/consul/async/version.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
require 'set'
|
10
10
|
|
11
11
|
# Services to hide
|
12
|
-
services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || '.*netsvc-probe.*,.*consul-probed.*').split(',')
|
12
|
+
services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || '.*netsvc-probe.*,.*consul-probed.*,.lbl7.*').split(',')
|
13
13
|
services_blacklist = services_blacklist_raw.map { |v| Regexp.new(v) }
|
14
14
|
|
15
15
|
num_services={}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
__________________________________________________________________
|
2
|
+
| DC | Services |______________Instances________________| Nodes |
|
3
|
+
| | | Passing | Warning | Critic | Total | |
|
4
|
+
|-------+----------+---------+---------+---------+---------+-------|
|
5
|
+
<%
|
6
|
+
# This template list all instances on all DCs
|
7
|
+
# And aggregates a list of Services, Services Instances/status
|
8
|
+
# And nodes.
|
9
|
+
require 'set'
|
10
|
+
|
11
|
+
|
12
|
+
def find_best_agent_for_dc(dc)
|
13
|
+
agent = service('consul-relay', passing: true, dc:dc).first
|
14
|
+
agent = service('consul-agent-http', passing: true, dc:dc).first unless agent
|
15
|
+
service('consul', passing: true, dc:dc).first unless agent
|
16
|
+
return nil unless agent
|
17
|
+
port = agent['Service']['Port'] || 8500
|
18
|
+
"http://#{agent.service_address}:#{port}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Services to hide
|
22
|
+
services_blacklist_raw = (ENV['EXCLUDE_SERVICES'] || '.*netsvc-probe.*,.*consul-probed.*').split(',')
|
23
|
+
services_blacklist = services_blacklist_raw.map { |v| Regexp.new(v) }
|
24
|
+
|
25
|
+
num_services={}
|
26
|
+
num_instances={}
|
27
|
+
all_states = ['passing', 'warning', 'critical', 'total']
|
28
|
+
distinct_services=Set.new
|
29
|
+
datacenters().each do |dc|
|
30
|
+
next unless find_best_agent_for_dc(dc)
|
31
|
+
num_services[dc] = 0
|
32
|
+
num_instances[dc] = {
|
33
|
+
'passing' => 0,
|
34
|
+
'warning' => 0,
|
35
|
+
'critical' => 0,
|
36
|
+
'total' => 0
|
37
|
+
}
|
38
|
+
services(dc:dc, agent: find_best_agent_for_dc(dc)).each do |service_name, tags|
|
39
|
+
next if services_blacklist.any? {|r| r.match(service_name)}
|
40
|
+
distinct_services.add(service_name)
|
41
|
+
num_services[dc]+=1
|
42
|
+
service(service_name, dc:dc, agent: find_best_agent_for_dc(dc)).each do |snode|
|
43
|
+
num_instances[dc][snode.status]+=1
|
44
|
+
num_instances[dc]['total']+=1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
num_instances_total={
|
49
|
+
'passing' => 0,
|
50
|
+
'warning' => 0,
|
51
|
+
'critical' => 0,
|
52
|
+
'total' => 0
|
53
|
+
}
|
54
|
+
num_nodes_total=0
|
55
|
+
num_services.each do |dc, num_services_for_dc|
|
56
|
+
all_states.each do |s|
|
57
|
+
num_instances_total[s] += num_instances[dc][s]
|
58
|
+
end
|
59
|
+
num_nodes=nodes(dc:dc, agent: find_best_agent_for_dc(dc)).count
|
60
|
+
num_nodes_total+=num_nodes
|
61
|
+
%>| <%= dc.rjust(5) %> | <%= num_services_for_dc.to_s.rjust(8) %> |<% all_states.each do |status|
|
62
|
+
%> <%= num_instances[dc][status].to_s.rjust(7) %> |<% end %> <%= num_nodes.to_s.rjust(5) %> |
|
63
|
+
<%
|
64
|
+
end
|
65
|
+
%>|-------+----------+---------+---------+---------+---------+-------|
|
66
|
+
| TOTAL | <%= distinct_services.count.to_s.rjust(8) %> |<% all_states.each do |status|
|
67
|
+
%> <%= num_instances_total[status].to_s.rjust(7) %> |<%
|
68
|
+
end %> <%= num_nodes_total.to_s.rjust(5) %> |
|
69
|
+
'_______|__________|_________|_________|_________|_________|_______'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%=
|
2
|
+
# This sample displays checks for the whole cluster
|
3
|
+
# in warning or critical state
|
4
|
+
# API available with Consul 1.7+
|
5
|
+
res = []
|
6
|
+
checks_in_state('warning').each do |c|
|
7
|
+
res << c
|
8
|
+
end
|
9
|
+
checks_in_state('critical').each do |c|
|
10
|
+
res << c
|
11
|
+
end
|
12
|
+
YAML.dump({'warning_or_critical_checks' => res})
|
13
|
+
%>
|
data/samples/consul-ui/README.md
CHANGED
@@ -50,6 +50,25 @@ The content is statically created, so you can serve it using any HTTP server ver
|
|
50
50
|
For development, you might use `python -m SimpleHTTPServer` in order to server the result
|
51
51
|
on your browser.
|
52
52
|
|
53
|
+
### Running it in production
|
54
|
+
|
55
|
+
Whatever your solution, be sure to have a index.html, so read next below on
|
56
|
+
how generating an index.html.
|
57
|
+
|
58
|
+
#### Running with web server
|
59
|
+
|
60
|
+
You can run it with your favoite web server, at Criteo we run it with nginx
|
61
|
+
which handles nicely cache and offer good performance.
|
62
|
+
|
63
|
+
In that case, consul-templaterb can start nginx with `--exec` or you can run it
|
64
|
+
as a daemon, in which case, consul-templaterb only generate the files.
|
65
|
+
|
66
|
+
#### Run it in Consul
|
67
|
+
|
68
|
+
You can run consul with `-ui-dir=/path/to/directory/of/consul-ui`, in such case
|
69
|
+
reaching consul on poort 8500 will redirect to the /ui/ path, displaying the UI
|
70
|
+
of your choice on http://consul-agent.example.org:8500/ui/.
|
71
|
+
|
53
72
|
### Generating index.html
|
54
73
|
|
55
74
|
By default, the command `consul-templaterb -c http://localhost:8500 samples/consul-ui/*.erb``
|
@@ -1,18 +1,5 @@
|
|
1
|
-
//
|
1
|
+
// Use this file to configure custom decorators for your Consul-UI
|
2
2
|
var httpRegexp = new RegExp('^http[s]?://[^ ]+$');
|
3
|
-
var dc = "<%= ENV['CRITEO_DC'] || 'par'%>";
|
4
|
-
var env = "<%= ENV['CRITEO_ENV'] || 'preprod'%>";
|
5
|
-
|
6
|
-
var availability_url = 'https://grafana.crto.in/d/xFX5gCnWz/service-availability?var-datacenter=' + dc + '&var-service=';
|
7
|
-
if (env == 'preprod') {
|
8
|
-
availability_url = 'https://grafana.preprod.crto.in/d/E0ANGjnZz/service-availability?var-datacenter=' + dc + '&var-service=';
|
9
|
-
}
|
10
|
-
var swagger_url = 'https://swaggercatalogapp.' + dc + '.' + env + '.crto.in/explore/swagger?key=';
|
11
|
-
var slack_url = 'https://criteo.slack.com/app_redirect?channel=';
|
12
|
-
|
13
|
-
var rackguru_url = 'https://rackguru.' + env + '.crto.in/serial/';
|
14
|
-
|
15
|
-
var asapi_url = 'https://idm.' + env + '.crto.in/tool/multiGroupInfo/'
|
16
3
|
|
17
4
|
function url_decorator(key, value) {
|
18
5
|
var e = document.createElement('a');
|
@@ -26,27 +13,7 @@ function usefullLinksGenerator(instance, serviceName, node_meta_info) {
|
|
26
13
|
top.className = 'instance-links';
|
27
14
|
|
28
15
|
var usefullLinks = [
|
29
|
-
{
|
30
|
-
title: "Trigger security scan",
|
31
|
-
iconClassName: "fas fa-shield-alt",
|
32
|
-
href: "https://security.crto.in/#/scan/?ip=" + instance.addr
|
33
|
-
},
|
34
|
-
{
|
35
|
-
title: "Availability Graph",
|
36
|
-
iconClassName: "fas fa-chart-area",
|
37
|
-
href: availability_url + serviceName
|
38
|
-
},
|
39
16
|
];
|
40
|
-
if (node_meta_info!= null) {
|
41
|
-
var serial = node_meta_info['serial_number'];
|
42
|
-
if (serial != null) {
|
43
|
-
usefullLinks.push({
|
44
|
-
title: "RackGuru",
|
45
|
-
iconClassName: "fas fa-server",
|
46
|
-
href: rackguru_url + serial
|
47
|
-
});
|
48
|
-
}
|
49
|
-
}
|
50
17
|
var first = true;
|
51
18
|
for (let usefullLink of usefullLinks) {
|
52
19
|
link = document.createElement('a');
|
@@ -134,19 +101,6 @@ function groups_decorator(instance, key, value, serviceName) {
|
|
134
101
|
return span;
|
135
102
|
}
|
136
103
|
|
137
|
-
/**
|
138
|
-
* Decorates with a slack channel link
|
139
|
-
*/
|
140
|
-
function slack_channel(instance, key, value, serviceName) {
|
141
|
-
var sName = value;
|
142
|
-
if (sName.startsWith('#')) {
|
143
|
-
sName = sName.substring(1);
|
144
|
-
}
|
145
|
-
return build_link(slack_url + encodeURIComponent(sName), '#'+ sName);
|
146
|
-
}
|
147
|
-
|
148
|
-
const start_regexp = /(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z/
|
149
|
-
|
150
104
|
function decorateIsoDate(value, formated) {
|
151
105
|
const parsed = Date.parse(formated);
|
152
106
|
if (isNaN(parsed)) {
|
@@ -163,55 +117,6 @@ function decorateIsoDate(value, formated) {
|
|
163
117
|
// This is the list of function called
|
164
118
|
// When a service meta is found
|
165
119
|
var registered_decorators = {
|
166
|
-
alert_availability_slack_channel: slack_channel,
|
167
|
-
gerrit_repository: function(instance, key, value, serviceName) {
|
168
|
-
return build_link('https://review.crto.in/#/q/' + value, value);
|
169
|
-
},
|
170
|
-
version: function(instance, key, value, serviceName) {
|
171
|
-
var asInt = parseInt(value);
|
172
|
-
if (asInt < 10000) {
|
173
|
-
return document.createTextNode(value);
|
174
|
-
}
|
175
|
-
if (instance.sMeta['CRITEO_APP_POOL'] != null) {
|
176
|
-
return build_link("https://devtools.crto.in/log.html?moab=cs&im=nb-to&range=100%2C" + asInt, value);
|
177
|
-
} else {
|
178
|
-
var tUrl = "https://devtools.crto.in/log.html?moab=j&im=nb-to&range=100%2C" + asInt;
|
179
|
-
if (instance.sMeta['jvm_artifact'] != null) {
|
180
|
-
tUrl += '&with-dependencies=true&artifacts=' + encodeURIComponent(instance.sMeta['jvm_artifact']);
|
181
|
-
}
|
182
|
-
return build_link(tUrl, value);
|
183
|
-
}
|
184
|
-
},
|
185
|
-
MESOS_TERM_DEBUG_GRANTED_TO: groups_decorator,
|
186
|
-
OWNERS: groups_decorator,
|
187
|
-
marathon_app_id: function(instance, key, value, serviceName) {
|
188
|
-
var app_name = value;
|
189
|
-
if (app_name[0] != '/') {
|
190
|
-
app_name = '/' + app_name;
|
191
|
-
}
|
192
|
-
if (instance.sMeta && instance.sMeta['marathon_ui']) {
|
193
|
-
return build_link(instance.sMeta['marathon_ui'] + '/#/apps/' + encodeURIComponent(app_name), value);
|
194
|
-
} else {
|
195
|
-
// non decorated value
|
196
|
-
return document.createTextNode(value);
|
197
|
-
}
|
198
|
-
},
|
199
|
-
marathon_app_version: function(instance, key, value, serviceName) {
|
200
|
-
return decorateIsoDate(value, value);
|
201
|
-
},
|
202
|
-
slack_channel: slack_channel,
|
203
|
-
start: function(instance, key, value, serviceName) {
|
204
|
-
const reg = start_regexp.exec(value);
|
205
|
-
if (reg != null) {
|
206
|
-
var formated = reg[1] + '-' + reg[2] + '-' + reg[3] + 'T' + reg[4] + ':' + reg[5] + ':' + reg[6] + 'Z';
|
207
|
-
return decorateIsoDate(value, formated);
|
208
|
-
} else {
|
209
|
-
return document.createTextNode(value);
|
210
|
-
}
|
211
|
-
},
|
212
|
-
swagger_key: function(instance, key, value, serviceName) {
|
213
|
-
return build_link(swagger_url + encodeURIComponent(value), value);
|
214
|
-
},
|
215
120
|
}
|
216
121
|
|
217
122
|
function service_meta_semantics_decorator(instance, key, value, serviceName) {
|
@@ -286,85 +191,11 @@ function nodeMetaGenerator(nodeMetaTags, serviceMetaIfAny) {
|
|
286
191
|
* it does not have to return anything.
|
287
192
|
*/
|
288
193
|
function navBarDecorator(navbar) {
|
289
|
-
if (typeof consulManager === 'undefined') {
|
290
|
-
// Timepicker is not supported on this page
|
291
|
-
return;
|
292
|
-
}
|
293
|
-
var timepicker_container = document.createElement('div');
|
294
|
-
timepicker_container.innerHTML = `
|
295
|
-
<div class="row">
|
296
|
-
<button type="button" disabled class="btn btn-secondary" data-toggle="tooltip" data-html="true" title="Data returned is the closest available to request" id="currently-displayed-data-date">
|
297
|
-
Pick a date to see data from the past
|
298
|
-
</button>
|
299
|
-
<div class="col-sm-14">
|
300
|
-
<div class="form-group">
|
301
|
-
<div class="input-group date" id="datetimepicker1" data-target-input="nearest">
|
302
|
-
<input type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1"/>
|
303
|
-
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
|
304
|
-
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
|
305
|
-
</div>
|
306
|
-
</div>
|
307
|
-
</div>
|
308
|
-
</div>
|
309
|
-
</div>
|
310
|
-
`;
|
311
|
-
|
312
|
-
navbar.appendChild(timepicker_container);
|
313
|
-
var script= document.createElement('script');
|
314
|
-
script.type='text/javascript';
|
315
|
-
// TODO(g.seux): extract code to another file and set "source" on script element
|
316
|
-
script.innerHTML = `
|
317
|
-
$('#datetimepicker1').datetimepicker({
|
318
|
-
format: 'DD/MM/YYYY HH:mm:ss Z', // default format does not allow to select seconds
|
319
|
-
sideBySide: true, // display date+time on the same widget
|
320
|
-
useCurrent: true // by default, select current date
|
321
|
-
});
|
322
|
-
$("#datetimepicker1").on("change.datetimepicker", function (e) {
|
323
|
-
console.log("Will fetch data from date " + e.date);
|
324
|
-
console.log("will clean existing data");
|
325
|
-
consulManager.clean().then(function(result) {
|
326
|
-
switch(consulManager.constructor.name) {
|
327
|
-
case "ConsulServiceManager":
|
328
|
-
backup_type = 'consul_services';
|
329
|
-
break;
|
330
|
-
case "ConsulKeysManager":
|
331
|
-
backup_type = 'consul_keys'
|
332
|
-
break;
|
333
|
-
case "ConsulNodesManager":
|
334
|
-
backup_type = 'consul_nodes'
|
335
|
-
break;
|
336
|
-
default:
|
337
|
-
console.log("Unknown " + consulManager.constructor.name + " type");
|
338
|
-
}
|
339
|
-
if (e.date) {
|
340
|
-
console.log("Will replace data by closest snapshot to " + e.date);
|
341
|
-
var target_url = "https://consul-info-timeline-history.<%= ENV['CRITEO_DC'] %>.<%= ENV['CRITEO_ENV']%>.crto.in/backup/" + backup_type + "/" + e.date / 1000;
|
342
|
-
} else {
|
343
|
-
console.log("Will restore to local version");
|
344
|
-
var target_url = defaultConsulManager.resourceURL;
|
345
|
-
}
|
346
|
-
if (typeof(defaultConsulManager) == 'undefined') {
|
347
|
-
// store first manager to be able to restore it
|
348
|
-
defaultConsulManager = consulManager
|
349
|
-
}
|
350
|
-
consulManager = new consulManager.constructor(target_url);
|
351
|
-
});
|
352
|
-
});
|
353
|
-
`;
|
354
|
-
navbar.appendChild(script);
|
355
194
|
}
|
356
195
|
|
357
|
-
|
358
196
|
/**
|
359
197
|
* fetchedResponseDecorator is called with http response when a resource is fetched by any instance of ConsulUIManager
|
360
198
|
* it does not have to return anything.
|
361
199
|
*/
|
362
200
|
async function fetchedResponseDecorator(httpResponse) {
|
363
|
-
|
364
|
-
current_date_display = $('#currently-displayed-data-date');
|
365
|
-
if (data_date > 0) {
|
366
|
-
current_date_display.html("Data is a snapshot from: " + moment.unix(data_date).format('DD/MM/YYYY HH:mm:ss Z'));
|
367
|
-
} else {
|
368
|
-
current_date_display.html("Pick a date to see data from the past");
|
369
|
-
}
|
370
|
-
}
|
201
|
+
}
|