consul-templaterb 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +13 -1
- data/Gemfile +1 -1
- data/README.md +45 -83
- data/TemplateAPI.md +84 -0
- data/bin/consul-templaterb +9 -11
- data/consul-templaterb.gemspec +1 -0
- data/lib/consul/async/consul_template.rb +24 -8
- data/lib/consul/async/consul_template_engine.rb +6 -1
- data/lib/consul/async/consul_template_render.rb +2 -1
- data/lib/consul/async/version.rb +1 -1
- data/samples/checks.html.erb +54 -19
- data/samples/common/footer.html.erb +0 -2
- data/samples/common/header.html.erb +9 -14
- data/samples/consul_template.html.erb +6 -6
- data/samples/criteo_choregraphies.html.erb +4 -2
- data/samples/keys.html.erb +7 -5
- data/samples/nodes.html.erb +4 -7
- data/samples/services.html.erb +109 -46
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49568fc4a6f043e390484820ea383914a31d35c99149669a4b77772bfeed0504
|
4
|
+
data.tar.gz: f56e6cd3882cb1154219c3c56da2ae9b484e9c6196c685980c296e713c6f9650
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e241be76b837635ef83dff4ec76191bba016cdb7e040b4c17325458465d6b10ae5a8430527484be30a2b0bf05d0a86350e970742b570766d14578a621f817fb
|
7
|
+
data.tar.gz: 9f4ccd3d0222a28abf6bcb89b46e101c627d736c73b6451a39f9bb4507e68713b1a88abfaf66d4e5a152de09d84b55ac486af2f2a692967a26762bb62129fd84
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
## (UNRELEASED)
|
2
2
|
|
3
|
+
## 1.0.8 (March 18, 2018)
|
4
|
+
|
5
|
+
IMPROVEMENTS:
|
6
|
+
|
7
|
+
* More clever behaviour regarding processes on First completed rendering phase
|
8
|
+
* All samples/*.html.erb templates are w3c compatibles without errors
|
9
|
+
* Look and features improvements for samples/*.html.erb
|
10
|
+
* Added optional parameters to sub-template in `render_file`
|
11
|
+
* Added `param(name, default_value)` to retrieve parameter from sub-template
|
12
|
+
* Use `CONSUL_HTTP_TOKEN` if present in environment variables to get the token
|
13
|
+
* Added [TemplateAPI.md](TemplateAPI.md] for documenting functions
|
14
|
+
|
3
15
|
## 1.0.7 (March 16, 2018)
|
4
16
|
|
5
17
|
BUG FIXES:
|
@@ -14,7 +26,7 @@ IMPROVEMENTS:
|
|
14
26
|
|
15
27
|
IMPROVEMENTS:
|
16
28
|
|
17
|
-
* Adds http
|
29
|
+
* Adds `http://` to Consul URL if missing since `$CONSUL_HTTP_ADDR` environment
|
18
30
|
variable might not have it
|
19
31
|
* Updated gem description with more accurate information
|
20
32
|
* samples: removed KV/nodes from services.html.erb
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# consul-templaterb [![Build Status](https://api.travis-ci.org/criteo/consul-templaterb.svg?branch=master)](https://travis-ci.org/criteo/consul-templaterb)
|
2
2
|
|
3
|
-
|
3
|
+
The ruby GEM [consul-templaterb](https://rubygems.org/gems/consul-templaterb)
|
4
|
+
is both a library and an executable that allows to generate files
|
4
5
|
using data from Consul (Discovery and Key/Value Store) easily using ruby's
|
5
6
|
erb templates. It also support launching programs and baby-sitting processes
|
6
7
|
when rendering the files, thus notifying programs when data do change.
|
@@ -9,8 +10,9 @@ It is intended for user accustomed to expressiveness or Ruby templating (ERB),
|
|
9
10
|
allowing for more flexibility and features than Go templates.
|
10
11
|
|
11
12
|
It also allows to use all of ruby language, especially useful for generating
|
12
|
-
files in several formats (JSON,
|
13
|
-
|
13
|
+
files in several formats ([JSON](samples/consul_template.json.erb),
|
14
|
+
[XML](samples/consul_template.xml.erb)) for which text substitutions are hard
|
15
|
+
to get right (escaping, attributes encoding...).
|
14
16
|
|
15
17
|
It also focuses on good performance and lightweight usage of bandwidth,
|
16
18
|
especially for very large clusters and watching lots of services.
|
@@ -19,6 +21,9 @@ For complicated rendering of templates and large Consul Clusters, it usually
|
|
19
21
|
renders faster with a more predictable way the template than the original
|
20
22
|
consul-template.
|
21
23
|
|
24
|
+
It provides a very [simple API](TemplateAPI.md) to write your own templates
|
25
|
+
with fully [working examples](samples/).
|
26
|
+
|
22
27
|
## Differences with HashiCorp's consul-template
|
23
28
|
|
24
29
|
[Hashicorp's Consul Template](https://github.com/hashicorp/consul-template)
|
@@ -45,13 +50,16 @@ Compared to consul-template, consul-templaterb offers the following features:
|
|
45
50
|
|
46
51
|
* Hot-Reload of template files
|
47
52
|
* Bandwidth limitation per endpoint (will soon support dynamic bandwidth limiter)
|
48
|
-
* Supports
|
53
|
+
* Supports launch and supervision of multiple child processes
|
54
|
+
* Supports launching commands when files do change on disk (reload commands...)
|
49
55
|
* Supports all Ruby features (ex: base64, real JSON/XML generation...)
|
50
56
|
* Information about bandwidth
|
51
57
|
|
52
|
-
The executable supports
|
53
|
-
|
54
|
-
|
58
|
+
The executable supports semantics and command line flags and options similar to
|
59
|
+
HashiCorp's Consul-template, so many flags you might use in consul-template will
|
60
|
+
work in a similar way. It also supports the same environment variable
|
61
|
+
`CONSUL_HTTP_ADDR` to find the Consul Agent to query and 'CONSUL_HTTP_TOKEN' to
|
62
|
+
get the token.
|
55
63
|
|
56
64
|
## Installation
|
57
65
|
|
@@ -96,6 +104,7 @@ installed:
|
|
96
104
|
|
97
105
|
```shell
|
98
106
|
$ gem contents consul-templaterb|grep samples
|
107
|
+
[...]
|
99
108
|
```
|
100
109
|
|
101
110
|
Will output the path where the samples are being installed, you can copy the directory
|
@@ -103,11 +112,16 @@ somewhere and then issue the command:
|
|
103
112
|
|
104
113
|
```shell
|
105
114
|
$ consul-templaterb samples/*.html.erb
|
115
|
+
Using samples/checks.html output for samples/checks.html.erb
|
116
|
+
[...]
|
106
117
|
```
|
107
118
|
|
108
119
|
It will render a full web site you may browse to look in real time the status of your
|
109
120
|
Consul Cluster.
|
110
121
|
|
122
|
+
You can now have a look to the [API Documentation](TemplateAPI.md) to modify existing
|
123
|
+
templates or write your owns, it is very easy!
|
124
|
+
|
111
125
|
## Usage of consul-templaterb
|
112
126
|
|
113
127
|
### Show help
|
@@ -168,8 +182,8 @@ meaning that if 2 results of templates are modified at the same time, the signal
|
|
168
182
|
sent only once (it is helpful for instance if your app is using several configurations
|
169
183
|
files that must be consistent all together).
|
170
184
|
|
171
|
-
Signals can be customized per process. Two signals are supported with options
|
172
|
-
|
185
|
+
Signals can be customized per process. Two signals are supported with options `--sig-reload` and
|
186
|
+
`--sig-term`. When the option is added, the next `--exec` options to start a process will use the
|
173
187
|
given signal. By default, HUP will be sent to reload events (you can use NONE to avoid sending any
|
174
188
|
reload signal), TERM will be used when leaving consul-templaterb.
|
175
189
|
|
@@ -189,90 +203,36 @@ by consul-templaterb.
|
|
189
203
|
|
190
204
|
### Samples
|
191
205
|
|
192
|
-
Have a look into the [samples/](samples/) directory to browse example files
|
206
|
+
Have a look into the [samples/](samples/) directory to browse example files which contains those
|
207
|
+
examples:
|
208
|
+
|
209
|
+
1. [List all nodes on Cluster](samples/nodes.html.erb)
|
210
|
+
2. [Show all services in Cluster](samples/services.html.erb)
|
211
|
+
3. [Show all Service Checks and their output](samples/checks.html.erb)
|
212
|
+
4. [Show all Key/Values nicely](samples/keys.html.erb)
|
213
|
+
5. [Show Choregraphies - work on content of K/V with JSON](samples/criteo_choregraphies.html.erb)
|
214
|
+
6. [Services in XML](samples/consul_template.xml.erb)
|
215
|
+
7. [Services in JSON](samples/consul_template.json.erb)
|
216
|
+
8. [Generate HaProxy Configuration](samples/ha_proxy.cfg.erb)
|
193
217
|
|
194
218
|
If you want to test it quickly, you might try with (assuming you consul agent is listening on
|
195
|
-
http://localhost:8500):
|
219
|
+
`http://localhost:8500`):
|
196
220
|
|
197
|
-
```
|
221
|
+
```shell
|
198
222
|
$ be bin/consul-templaterb -c 'http://localhost:8500' samples/*.html.erb
|
223
|
+
[...]
|
199
224
|
```
|
200
225
|
|
201
226
|
It will generate a full website in samples/ directory with lots of Consul information ready to
|
202
227
|
use (website updated automagically when values to change).
|
203
228
|
|
204
|
-
|
205
|
-
|
206
|
-
Here are the various functions you might use in your templates.
|
207
|
-
|
208
|
-
For each function, mandatory arguments are specified at the beginning while optional ones are marked with `[]`.
|
209
|
-
Most of them support the optional dc attribute to access data from another datacenter. If the `dc`
|
210
|
-
attribute is not specified, the function will output data from the current datacenter.
|
211
|
-
|
212
|
-
To ease template development, `consul-templaterb` supports HOT reload of templates, thus it is possible to
|
213
|
-
develop the templates interactively. While developing, it is possible to use the switch `--hot-reload=keep`,
|
214
|
-
thus the application will display a warning if the template is invalid and won't stop
|
215
|
-
(`--hot-reload=die` is the default, thus if the hot-reloaded template has issue, the application will die).
|
216
|
-
|
217
|
-
### datacenters()
|
218
|
-
|
219
|
-
[Get the list of datacenters as string array](https://www.consul.io/api/catalog.html#list-datacenters).
|
220
|
-
|
221
|
-
### services([dc: datacenter], [tag: tagToFilterWith])
|
222
|
-
|
223
|
-
[List the services matching the optional tag filter](https://www.consul.io/api/catalog.html#list-services),
|
224
|
-
if tag is not specified, will match all the services. Note that this endpoint performs client side tag
|
225
|
-
filtering for services to ease templates development since this feature is not available on Consul's endpoint.
|
226
|
-
|
227
|
-
### service(serviceName, [dc: datacenter], [tag: tagToFilterWith], [passing: true])
|
228
|
-
|
229
|
-
[List the instances](https://www.consul.io/api/health.html#list-nodes-for-service) of a service having the given
|
230
|
-
optional tag. If no tag is specified, will return all instances of service. By default, it will return all the
|
231
|
-
well services that are passing or not. An optional argument passing might be used to retrieve only passing instances.
|
229
|
+
All templates are validated using the Travis CI, so all should be working for your Consul
|
230
|
+
Configuration.
|
232
231
|
|
233
|
-
|
234
|
-
|
235
|
-
[List all the nodes of selected datacenter](https://www.consul.io/api/catalog.html#list-nodes). No filtering is
|
236
|
-
applied.
|
237
|
-
|
238
|
-
### node(nodeNameOrId, [dc: datacenter])
|
239
|
-
|
240
|
-
[List all the services of a given Node](https://www.consul.io/api/catalog.html#list-services-for-node) using its
|
241
|
-
name or its ID. If DC is specified, will lookup for given node in another datacenter.
|
242
|
-
|
243
|
-
### checks_for_service(name, dc: nil, passing: false, tag: nil)
|
244
|
-
|
245
|
-
[Find all the checks](https://www.consul.io/api/health.html#list-checks-for-service) of a given service.
|
246
|
-
|
247
|
-
### kv(name = nil, dc: nil, keys: nil, recurse: false)
|
248
|
-
|
249
|
-
[Read keys from KV Store](https://www.consul.io/api/kv.html#read-key). It can be used for both listing the keys and
|
250
|
-
getting the values. See the file in samples [keys.html.erb](samples/keys.html.erb) for a working example.
|
251
|
-
|
252
|
-
### agent_metrics()
|
253
|
-
|
254
|
-
[Get the metrics of Consul Agent](https://www.consul.io/api/agent.html#view-metrics). Since this endpoint does
|
255
|
-
not support blocking queries, data will be refreshed every few seconds, but will not use blocking queries
|
256
|
-
mechanism.
|
257
|
-
|
258
|
-
### agent_self()
|
259
|
-
|
260
|
-
[Get the configuration of Consul Agent](https://www.consul.io/api/agent.html#read-configuration).
|
261
|
-
Since this endpoint does not support blocking queries, data will be refreshed every few seconds,
|
262
|
-
but will not use blocking queries mechanism.
|
263
|
-
|
264
|
-
### render_file RELATIVE_PATH_TO_ERB_FILE
|
265
|
-
|
266
|
-
This allow to include a template file into another one. Beware, it does not check for infinite recursion!
|
267
|
-
The template can be either a static file either another template. The file has to be a valid template, but
|
268
|
-
can also be raw text (if it is a valid template) and is resolved with a relative path regarding the file
|
269
|
-
including it.
|
270
|
-
|
271
|
-
Example:
|
232
|
+
## Template development
|
272
233
|
|
273
|
-
|
274
|
-
|
275
|
-
```
|
234
|
+
Please look at [the template API](TemplateAPI.md) to have a list of all functions you might use for your
|
235
|
+
templates. Also have a look to [samples/](samples/) directory to have full working examples.
|
276
236
|
|
277
237
|
## Development
|
278
238
|
|
@@ -292,6 +252,8 @@ Here are the known bugs of the application:
|
|
292
252
|
on very large clusters or when watching thousands of individual KV keys.
|
293
253
|
* [ ] render_file might create an infinite recursion if a template includes itself indirectly.
|
294
254
|
|
255
|
+
Please consult [CHANGELOG.md](CHANGELOG.md) for fixed bugs.
|
256
|
+
|
295
257
|
## TODO
|
296
258
|
|
297
259
|
* [ ] Hashi's Vault support
|
data/TemplateAPI.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Template API for writting templates
|
2
|
+
|
3
|
+
Here are the various functions you might use in your templates.
|
4
|
+
|
5
|
+
For each function, mandatory arguments are specified at the beginning while optional ones are marked with `[]`.
|
6
|
+
Most of them support the optional dc attribute to access data from another datacenter. If the `dc`
|
7
|
+
attribute is not specified, the function will output data from the current datacenter.
|
8
|
+
|
9
|
+
To ease template development, `consul-templaterb` supports HOT reload of templates, thus it is possible to
|
10
|
+
develop the templates interactively. While developing, it is possible to use the switch `--hot-reload=keep`,
|
11
|
+
thus the application will display a warning if the template is invalid and won't stop
|
12
|
+
(`--hot-reload=die` is the default, thus if the hot-reloaded template has issue, the application will die).
|
13
|
+
|
14
|
+
Have a look to [samples/](samples/) directory to start writing your own templates.
|
15
|
+
|
16
|
+
## datacenters()
|
17
|
+
|
18
|
+
[Get the list of datacenters as string array](https://www.consul.io/api/catalog.html#list-datacenters).
|
19
|
+
|
20
|
+
## services([dc: datacenter], [tag: tagToFilterWith])
|
21
|
+
|
22
|
+
[List the services matching the optional tag filter](https://www.consul.io/api/catalog.html#list-services),
|
23
|
+
if tag is not specified, will match all the services. Note that this endpoint performs client side tag
|
24
|
+
filtering for services to ease templates development since this feature is not available on Consul's endpoint.
|
25
|
+
|
26
|
+
## service(serviceName, [dc: datacenter], [tag: tagToFilterWith], [passing: true])
|
27
|
+
|
28
|
+
[List the instances](https://www.consul.io/api/health.html#list-nodes-for-service) of a service having the given
|
29
|
+
optional tag. If no tag is specified, will return all instances of service. By default, it will return all the
|
30
|
+
well services that are passing or not. An optional argument passing might be used to retrieve only passing instances.
|
31
|
+
|
32
|
+
## nodes([dc: datacenter])
|
33
|
+
|
34
|
+
[List all the nodes of selected datacenter](https://www.consul.io/api/catalog.html#list-nodes). No filtering is
|
35
|
+
applied.
|
36
|
+
|
37
|
+
## node(nodeNameOrId, [dc: datacenter])
|
38
|
+
|
39
|
+
[List all the services of a given Node](https://www.consul.io/api/catalog.html#list-services-for-node) using its
|
40
|
+
name or its ID. If DC is specified, will lookup for given node in another datacenter.
|
41
|
+
|
42
|
+
## checks_for_service(name, dc: nil, passing: false, tag: nil)
|
43
|
+
|
44
|
+
[Find all the checks](https://www.consul.io/api/health.html#list-checks-for-service) of a given service.
|
45
|
+
|
46
|
+
## kv(name = nil, dc: nil, keys: nil, recurse: false)
|
47
|
+
|
48
|
+
[Read keys from KV Store](https://www.consul.io/api/kv.html#read-key). It can be used for both listing the keys and
|
49
|
+
getting the values. See the file in samples [keys.html.erb](samples/keys.html.erb) for a working example.
|
50
|
+
|
51
|
+
## agent_metrics()
|
52
|
+
|
53
|
+
[Get the metrics of Consul Agent](https://www.consul.io/api/agent.html#view-metrics). Since this endpoint does
|
54
|
+
not support blocking queries, data will be refreshed every few seconds, but will not use blocking queries
|
55
|
+
mechanism.
|
56
|
+
|
57
|
+
## agent_self()
|
58
|
+
|
59
|
+
[Get the configuration of Consul Agent](https://www.consul.io/api/agent.html#read-configuration).
|
60
|
+
Since this endpoint does not support blocking queries, data will be refreshed every few seconds,
|
61
|
+
but will not use blocking queries mechanism.
|
62
|
+
|
63
|
+
## render_file(relative_path_to_erb_file, [params={}])
|
64
|
+
|
65
|
+
This allow to include a template file into another one. Beware, it does not check for infinite recursion!
|
66
|
+
The template can be either a static file either another template. The file has to be a valid template, but
|
67
|
+
can also be raw text (if it is a valid template) and is resolved with a relative path regarding the file
|
68
|
+
including it.
|
69
|
+
|
70
|
+
Example:
|
71
|
+
|
72
|
+
```erb
|
73
|
+
<%= render_file('common/header.html.erb', title: 'My Title') %>
|
74
|
+
```
|
75
|
+
|
76
|
+
Will render header.html.erb with parameter title = 'My Title'. `title` can then be accessed within
|
77
|
+
the template using `param('title', 'My default Value')` in the `header.html.erb` file.
|
78
|
+
|
79
|
+
## param(parameter_name, [default_value: nil])
|
80
|
+
|
81
|
+
Can be used within a template to access a parameter. Parameters can be specified with `render_file`
|
82
|
+
directive. Optional value `default_value` allow to get a value if parameter has not been set.
|
83
|
+
|
84
|
+
See [samples/common/header.html.erb](samples/common/header.html.erb) for example of usage.
|
data/bin/consul-templaterb
CHANGED
@@ -22,7 +22,7 @@ options = {
|
|
22
22
|
network: false
|
23
23
|
},
|
24
24
|
base_url: ENV['CONSUL_HTTP_ADDR'] || 'http://localhost:8500',
|
25
|
-
token: nil,
|
25
|
+
token: ENV['CONSUL_HTTP_TOKEN'] || nil,
|
26
26
|
retry_duration: 10, # On error, retry after n seconds
|
27
27
|
min_duration: 5, # On sucess and when differences are found
|
28
28
|
retry_on_non_diff: 3, # On success but when there are not differences
|
@@ -113,16 +113,14 @@ optparse = OptionParser.new do |opts|
|
|
113
113
|
sig_term = cur_sig_term
|
114
114
|
consul_engine.add_template_callback do |all_ready, template_manager, results|
|
115
115
|
if all_ready
|
116
|
-
modified = results.reduce(false) { |a, e| a ||
|
117
|
-
if
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
end
|
125
|
-
elsif !@programs[cmd].nil?
|
116
|
+
modified = results.reduce(false) { |a, e| a || e.modified }
|
117
|
+
if @programs[cmd].nil?
|
118
|
+
STDERR.puts "[EXEC] Starting process: #{cmd}... on_reload=#{sig_reload ? sig_reload : 'NONE'} on_term=#{sig_term}"
|
119
|
+
@programs[cmd] = Consul::Async::ProcessHandler.new(cmd, sig_reload: sig_reload, sig_term: sig_term)
|
120
|
+
@programs[cmd].start
|
121
|
+
else
|
122
|
+
# At least one template has been modified
|
123
|
+
@programs[cmd].reload if modified
|
126
124
|
begin
|
127
125
|
@programs[cmd].process_status
|
128
126
|
rescue Consul::Async::ProcessDoesNotExist => e
|
data/consul-templaterb.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
end
|
27
27
|
spec.bindir = 'bin'
|
28
28
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
29
|
+
spec.extra_rdoc_files = ['README.md', 'TemplateAPI.md']
|
29
30
|
spec.require_paths = ['lib']
|
30
31
|
|
31
32
|
spec.require_paths = ['lib']
|
@@ -24,6 +24,10 @@ module Consul
|
|
24
24
|
errors: 0,
|
25
25
|
bytes_read: 0
|
26
26
|
}
|
27
|
+
@context = {
|
28
|
+
current_erb_path: nil,
|
29
|
+
params: {}
|
30
|
+
}
|
27
31
|
end
|
28
32
|
|
29
33
|
# https://www.consul.io/api/health.html#list-nodes-for-service
|
@@ -79,6 +83,14 @@ module Consul
|
|
79
83
|
create_if_missing(path, query_params) { ConsulAgentMetrics.new(ConsulEndpoint.new(conf, path, true, query_params, default_value)) }
|
80
84
|
end
|
81
85
|
|
86
|
+
# Return a param of template
|
87
|
+
def param(key, default_value = nil)
|
88
|
+
v = @context[:params][key]
|
89
|
+
v = @context[:params][key.to_sym] unless v
|
90
|
+
v = default_value unless v
|
91
|
+
v
|
92
|
+
end
|
93
|
+
|
82
94
|
# https://www.consul.io/api/catalog.html#list-services
|
83
95
|
def services(dc: nil, tag: nil)
|
84
96
|
path = '/v1/catalog/services'
|
@@ -107,18 +119,22 @@ module Consul
|
|
107
119
|
create_if_missing(path, query_params) { ConsulTemplateKV.new(ConsulEndpoint.new(conf, path, true, query_params, default_value), name) }
|
108
120
|
end
|
109
121
|
|
110
|
-
|
111
|
-
|
122
|
+
# render a relative file with the given params accessible from template
|
123
|
+
def render_file(path, params = {})
|
124
|
+
new_path = File.expand_path(path, File.dirname(@context[:current_erb_path]))
|
112
125
|
raise "render_file ERROR: #{path} is resolved as #{new_path}, but the file does not exists" unless File.exist? new_path
|
113
|
-
render(File.read(new_path), new_path)
|
126
|
+
render(File.read(new_path), new_path, params)
|
114
127
|
end
|
115
128
|
|
116
|
-
def render(tpl, tpl_file_path)
|
129
|
+
def render(tpl, tpl_file_path, params = {})
|
117
130
|
# Ugly, but allow to use render_file well to support stack of calls
|
118
|
-
old_value = @
|
119
|
-
@
|
131
|
+
old_value = @context
|
132
|
+
@context = {
|
133
|
+
current_erb_path: tpl_file_path,
|
134
|
+
params: params
|
135
|
+
}
|
120
136
|
result = ERB.new(tpl).result(binding)
|
121
|
-
@
|
137
|
+
@context = old_value
|
122
138
|
result
|
123
139
|
rescue StandardError => e
|
124
140
|
e2 = InvalidTemplateException.new e
|
@@ -141,7 +157,7 @@ module Consul
|
|
141
157
|
end
|
142
158
|
if not_ready.count.positive?
|
143
159
|
STDERR.print "[INFO] Waiting for data from #{not_ready.count}/#{not_ready.count + ready} endpoints: #{not_ready[0..2]}..."
|
144
|
-
return [false, false,
|
160
|
+
return [false, false, nil]
|
145
161
|
end
|
146
162
|
if to_cleanup.count > 1
|
147
163
|
STDERR.puts "[INFO] Cleaned up #{to_cleanup.count} endpoints: #{to_cleanup}"
|
@@ -14,6 +14,7 @@ module Consul
|
|
14
14
|
@templates = []
|
15
15
|
@template_callbacks = []
|
16
16
|
@hot_reload_failure = 'die'
|
17
|
+
@all_templates_rendered = false
|
17
18
|
end
|
18
19
|
|
19
20
|
def add_template_callback(&block)
|
@@ -36,12 +37,16 @@ module Consul
|
|
36
37
|
begin
|
37
38
|
results = template_renders.map(&:run)
|
38
39
|
all_ready = results.reduce(true) { |a, e| a && e.ready? }
|
40
|
+
if !@all_templates_rendered && all_ready
|
41
|
+
@all_templates_rendered = true
|
42
|
+
STDERR.puts "[INFO] First rendering of #{results.count} templates completed"
|
43
|
+
end
|
39
44
|
begin
|
40
45
|
@template_callbacks.each do |c|
|
41
46
|
c.call([all_ready, template_manager, results])
|
42
47
|
end
|
43
48
|
rescue StandardError => cbk_error
|
44
|
-
STDERR.puts "
|
49
|
+
STDERR.puts "[ERROR] callback error: #{cbk_error.inspect}"
|
45
50
|
raise cbk_error
|
46
51
|
end
|
47
52
|
rescue StandardError => e
|
@@ -58,7 +58,8 @@ module Consul
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def write
|
61
|
-
success, modified,
|
61
|
+
success, modified, last_res = @template_manager.write(@output_file, @template, @last_result, template_file)
|
62
|
+
@last_result = last_res if last_res
|
62
63
|
[success, modified, @last_result]
|
63
64
|
end
|
64
65
|
|
data/lib/consul/async/version.rb
CHANGED
data/samples/checks.html.erb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
<%= render_file('common/header.html.erb', title: 'Consul Checks') %>
|
1
2
|
<%
|
2
3
|
# This template can be configure the following way with environment variables
|
3
4
|
# Environment variables to filter services/instances
|
@@ -14,13 +15,13 @@
|
|
14
15
|
'info'
|
15
16
|
end
|
16
17
|
end
|
17
|
-
|
18
|
-
<style
|
18
|
+
%>
|
19
|
+
<style>
|
19
20
|
.check {
|
20
21
|
transition: opacity 1s ease-out;
|
21
22
|
}
|
22
23
|
</style>
|
23
|
-
<script
|
24
|
+
<script>//<!--
|
24
25
|
function updateStates() {
|
25
26
|
states = ['passing', 'warning', 'critical']
|
26
27
|
stylesheet = document.getElementById('css-states');
|
@@ -30,15 +31,16 @@
|
|
30
31
|
is_checked = document.getElementById('show_'+s).checked
|
31
32
|
var to_append = "." + s + " { ";
|
32
33
|
if (is_checked) {
|
33
|
-
to_append += "
|
34
|
+
to_append += "display: block"
|
34
35
|
} else {
|
35
|
-
to_append += "
|
36
|
+
to_append += "display:none"
|
36
37
|
}
|
37
38
|
to_append += " }\r\n"
|
38
39
|
txt += to_append;
|
39
40
|
}
|
40
41
|
stylesheet.textContent = txt;
|
41
42
|
}
|
43
|
+
//->
|
42
44
|
</script>
|
43
45
|
<div class="container-fluid">
|
44
46
|
<div class="row">
|
@@ -48,33 +50,66 @@
|
|
48
50
|
all_services = services(tag: services_tag_filter)
|
49
51
|
all_services.each do |service_name, tags|
|
50
52
|
%>
|
51
|
-
<li><a href="#service_<%= service_name %>"><%= service_name %></a></li>
|
53
|
+
<li><a title="<%= tags.sort.join(', ') %>" href="#service_<%= service_name %>"><%= service_name %></a></li>
|
52
54
|
<% end %>
|
53
55
|
</ul>
|
54
56
|
</nav>
|
55
57
|
<main class="col-10">
|
56
58
|
<div class="float-right">
|
57
|
-
<
|
59
|
+
<span class="state-selector">
|
58
60
|
<input id="show_passing" type="checkbox" class="checks-visibility" value="passing" checked="checked" onchange="updateStates()"/>
|
59
61
|
<label for="show_passing"><span class="badge badge-success">Passing</span></label>
|
60
|
-
</
|
61
|
-
<
|
62
|
+
</span>
|
63
|
+
<span class="state-selector">
|
62
64
|
<input id="show_warning" type="checkbox" class="checks-visibility" value="warning" checked="checked" onchange="updateStates()"/>
|
63
65
|
<label for="show_warning"><span class="badge badge-warning">Warning</span></label>
|
64
|
-
</
|
65
|
-
<
|
66
|
+
</span>
|
67
|
+
<span class="state-selector">
|
66
68
|
<input id="show_critical" type="checkbox" class="checks-visibility" value="critical" checked="checked" onchange="updateStates()"/>
|
67
69
|
<label for="show_critical"><span class="badge badge-danger">Critical</span></label>
|
68
|
-
</
|
69
|
-
|
70
|
+
</span>
|
71
|
+
</div>
|
70
72
|
|
71
73
|
<h1 id="services">Services <%= services_tag_filter ? " tag: #{services_tag_filter}" : 'No filtering' %></h1>
|
72
|
-
<% all_services.each do |service_name, tags|
|
73
|
-
|
74
|
-
|
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 %>
|
75
110
|
<div class="list-group">
|
76
111
|
<% checks_for_service(service_name).each do |check| %>
|
77
|
-
<div class="list-group-item check <%= check['Status'] %>" id="<%= check['CheckID'] %>">
|
112
|
+
<div class="list-group-item check <%= check['Status'] %>" id="<%= check['Node'] + check['CheckID'] %>">
|
78
113
|
<div class="d-flex align-items-center justify-content-between">
|
79
114
|
<h5>
|
80
115
|
<%= check['Name'] %> / <%= check['Node'] %>
|
@@ -91,5 +126,5 @@
|
|
91
126
|
</main>
|
92
127
|
</div>
|
93
128
|
</div>
|
94
|
-
<script
|
95
|
-
<%= render_file
|
129
|
+
<script>updateStates();</script>
|
130
|
+
<%= render_file('common/footer.html.erb') %>
|
@@ -9,35 +9,30 @@
|
|
9
9
|
%><!DOCTYPE html>
|
10
10
|
<html lang="en">
|
11
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="<%= ENV['REFRESH'] || '600' %>"/>
|
17
|
-
|
18
|
-
<title><%= ENV['TITLE'] || 'Consul Real Time information'%></title>
|
19
|
-
|
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>
|
20
18
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
21
|
-
<style
|
19
|
+
<style>
|
22
20
|
body {
|
23
|
-
|
21
|
+
padding-top: 5rem;
|
24
22
|
}
|
25
23
|
.check {
|
26
24
|
transition: opacity 1s ease-out;
|
27
25
|
}
|
28
26
|
</style>
|
29
|
-
<style
|
27
|
+
<style id="css-states">
|
30
28
|
</style>
|
31
29
|
</head>
|
32
|
-
|
33
30
|
<body>
|
34
|
-
|
35
31
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
|
36
32
|
<a class="navbar-brand" href="#">Consul</a>
|
37
33
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
38
34
|
<span class="navbar-toggler-icon"></span>
|
39
35
|
</button>
|
40
|
-
|
41
36
|
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
42
37
|
<ul class="navbar-nav mr-auto">
|
43
38
|
<% tools.each do |tool| %>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<!doctype html>
|
2
|
-
<html lang="
|
2
|
+
<html lang="en">
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8"/>
|
5
5
|
<meta http-equiv="refresh" content="300"/>
|
6
6
|
<title>Consul Full Info</title>
|
7
|
-
<style
|
7
|
+
<style>
|
8
8
|
.passing {
|
9
9
|
color:green;
|
10
10
|
}
|
@@ -50,7 +50,7 @@
|
|
50
50
|
|
51
51
|
<h1 id="services">List all services instances sorted by node name</h1>
|
52
52
|
<% services.each do |service_name, tags|
|
53
|
-
%><h2 id="service_<%= service_name %>" title="<%= tags %>"><%= service_name %> <a class="qlink" href="#service_<%= service_name %>">🔗</a></h2>
|
53
|
+
%><h2 id="service_<%= service_name %>" title="<%= tags.join(', ') %>"><%= service_name %> <a class="qlink" href="#service_<%= service_name %>">🔗</a></h2>
|
54
54
|
<ul>
|
55
55
|
<% service(service_name).sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
|
56
56
|
tags = snode['Service']['Tags'].sort
|
@@ -68,7 +68,7 @@
|
|
68
68
|
end
|
69
69
|
%><li><a <%= url ? "href=\"#{url}\"" : nil %>><%=
|
70
70
|
snode['Node']['Node'] %><%= port %></a>
|
71
|
-
<span class="tags"><%= snode['Service']['Tags'].sort %></
|
71
|
+
<span class="tags"><%= snode['Service']['Tags'].sort %></span>
|
72
72
|
<span class="statuses"><%
|
73
73
|
snode['Checks'].each do |c| %> <span title="<%= c['Name']%>" class="<%= c['Status'] %>"><%= c['Status']
|
74
74
|
%></span><% end if snode['Checks'] %></span></li>
|
@@ -80,14 +80,14 @@
|
|
80
80
|
<h1 id="nodes">List all nodes for DC, sorted by name</h1>
|
81
81
|
<ul>
|
82
82
|
<% nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
|
83
|
-
%> <li id="node_
|
83
|
+
%> <li id="node_<%= snode['ID'] %>"><%= snode['Address'].ljust(16) %> <%= snode['Node'] %></li>
|
84
84
|
<% end %>
|
85
85
|
</ul>
|
86
86
|
|
87
87
|
<h1 id="kv">KV of Current DC</h1>
|
88
88
|
<ul>
|
89
89
|
<% kv(keys:true).each do |key|
|
90
|
-
%><li id="kv_
|
90
|
+
%><li id="kv_<%= key %>"><%= key %></li>
|
91
91
|
<% end %>
|
92
92
|
</ul>
|
93
93
|
</body>
|
@@ -2,8 +2,8 @@
|
|
2
2
|
require 'json'
|
3
3
|
require 'date'
|
4
4
|
@current_time = Time.now.utc
|
5
|
-
%><%= render_file
|
6
|
-
<main
|
5
|
+
%><%= render_file('common/header.html.erb', title: 'Choregraphies', refresh: 30) %>
|
6
|
+
<main class="container">
|
7
7
|
<div>
|
8
8
|
<h1>Show all choregraphie information</h1>
|
9
9
|
<div>This page only show choregraphie when at least one holder exists.</div>
|
@@ -87,4 +87,6 @@
|
|
87
87
|
<% end %>
|
88
88
|
<% end %>
|
89
89
|
</div>
|
90
|
+
</div>
|
91
|
+
</main>
|
90
92
|
<%= render_file 'common/footer.html.erb' %>
|
data/samples/keys.html.erb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
<%= render_file
|
2
|
-
<% path = ENV['kv_path'] || '
|
1
|
+
<%= render_file('common/header.html.erb', title: 'Keys') %>
|
2
|
+
<% path = ENV['kv_path'] || '' %>
|
3
3
|
<% require 'base64'
|
4
4
|
require 'json'
|
5
5
|
require 'date'
|
6
6
|
%>
|
7
|
-
<main
|
7
|
+
<main class="container">
|
8
8
|
<div>
|
9
|
-
<h1>Show all keys under hierarchy
|
9
|
+
<h1>Show all keys <%= path == '' ? '' : "under hierarchy #{path}" %></h1>
|
10
10
|
<div id="accordion">
|
11
11
|
<% kv(path, recurse:true).each do |tuple|
|
12
12
|
key = tuple['Key']
|
@@ -28,11 +28,13 @@
|
|
28
28
|
</h5>
|
29
29
|
<div id="collapse-<%= key %>" class="collapse" aria-labelledby="heading-<%= key %>" data-parent="#accordion">
|
30
30
|
<div class="card-body">
|
31
|
-
<pre class="pre-scrollable"><%= val %></pre>
|
31
|
+
<pre class="pre-scrollable"><%= ERB::Util.html_escape(val) %></pre>
|
32
32
|
</div>
|
33
33
|
</div>
|
34
34
|
</div>
|
35
35
|
</div>
|
36
36
|
<% end %>
|
37
37
|
</div>
|
38
|
+
</div>
|
39
|
+
</main>
|
38
40
|
<%= render_file 'common/footer.html.erb' %>
|
data/samples/nodes.html.erb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
|
-
<%= render_file
|
1
|
+
<%= render_file('common/header.html.erb', title: 'Nodes') %>
|
2
2
|
<h1 id="nodes">List all nodes for DC, sorted by name</h1>
|
3
3
|
<ul>
|
4
4
|
<% nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
|
5
|
-
|
5
|
+
%><li id="node_<%= snode['ID'] %>"><a href="ssh://<%= snode['Address']%>"><%= snode['Address'] %></a> <%= snode['Node'] %><%
|
6
6
|
snode['Meta'].each do |k,v|
|
7
7
|
if v && !v.empty?
|
8
|
-
|
9
|
-
<span class="badge badge-pill badge-primary float-right"><%= k %>: <%= v%></span>
|
10
|
-
<%
|
8
|
+
%><span class="badge badge-pill badge-primary float-right"><%= k %>: <%= v%></span><%
|
11
9
|
end
|
12
10
|
end if snode['Meta']
|
13
|
-
|
14
|
-
</li>
|
11
|
+
%></li>
|
15
12
|
<% end %>
|
16
13
|
</ul>
|
17
14
|
<%= render_file 'common/footer.html.erb' %>
|
data/samples/services.html.erb
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
# This template can be configure the following way with environment variables
|
3
3
|
# Environment variables to filter services/instances
|
4
4
|
# SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
|
5
|
+
require 'base64'
|
6
|
+
require 'json'
|
7
|
+
require 'date'
|
8
|
+
|
5
9
|
services_tag_filter = ENV['SERVICES_TAG_FILTER']
|
6
10
|
def status_to_class(status)
|
7
11
|
if status == 'passing'
|
@@ -14,11 +18,41 @@
|
|
14
18
|
'info'
|
15
19
|
end
|
16
20
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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') %>
|
22
56
|
<nav>
|
23
57
|
<ul>
|
24
58
|
<li><a href="#datacenters">DataCenters</a></li>
|
@@ -26,46 +60,75 @@
|
|
26
60
|
<li><a href="#services">Services with instances</a></li>
|
27
61
|
</ul>
|
28
62
|
</nav>
|
29
|
-
<h1 id="datacenters">List of all datacenters</h1>
|
30
|
-
<ul>
|
31
|
-
<% datacenters.each do |dc| %>
|
32
|
-
<li id="dc_<%=dc %>%"><%= dc %> with <%= services(dc:dc).keys.count %> services, <%= nodes(dc:dc).count %> nodes</li>
|
33
|
-
<% end %>
|
34
|
-
</ul>
|
35
|
-
|
36
|
-
<h1 id="list_services">List of all services in current DC</h1>
|
37
|
-
<ul>
|
38
|
-
<% services.each do |service_name, tags|
|
39
|
-
%>
|
40
|
-
<li><a href="#service_<%= service_name %>"><%= service_name %></a> <%= tags.sort %></li>
|
41
|
-
<% end %>
|
42
|
-
</ul>
|
43
63
|
|
44
|
-
<
|
45
|
-
|
46
|
-
|
47
|
-
<ul>
|
48
|
-
<%
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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 %>">🔗</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['Node']['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>
|
71
134
|
<%= render_file 'common/footer.html.erb' %>
|
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.0.
|
4
|
+
version: 1.0.8
|
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: 2018-03-
|
11
|
+
date: 2018-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -129,7 +129,9 @@ email:
|
|
129
129
|
executables:
|
130
130
|
- consul-templaterb
|
131
131
|
extensions: []
|
132
|
-
extra_rdoc_files:
|
132
|
+
extra_rdoc_files:
|
133
|
+
- README.md
|
134
|
+
- TemplateAPI.md
|
133
135
|
files:
|
134
136
|
- ".gitignore"
|
135
137
|
- ".gitreview"
|
@@ -142,6 +144,7 @@ files:
|
|
142
144
|
- LICENSE.txt
|
143
145
|
- README.md
|
144
146
|
- Rakefile
|
147
|
+
- TemplateAPI.md
|
145
148
|
- bin/consul-templaterb
|
146
149
|
- consul-templaterb.gemspec
|
147
150
|
- lib/consul/async/consul_endpoint.rb
|