consul-templaterb 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 [](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
|