consul-templaterb 1.0.3

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.
@@ -0,0 +1,64 @@
1
+ module Consul
2
+ module Async
3
+ class ProcessDoesNotExist < StandardError
4
+ end
5
+ class ProcessHandler
6
+ attr_reader :command, :sig_reload, :sig_term, :pid, :exit_status
7
+ def initialize(command, sig_reload: 'HUP', sig_term: 'TERM')
8
+ raise 'empty sig_term is not supported' unless sig_term
9
+ @command = command
10
+ @sig_reload = sig_reload
11
+ @sig_term = sig_term
12
+ @pid = nil
13
+ @exit_status = nil
14
+ end
15
+
16
+ def start
17
+ return pid unless pid.nil?
18
+ @pid = Process.spawn(command)
19
+ end
20
+
21
+ def reload
22
+ return if sig_reload.nil?
23
+ STDERR.puts "Sending SIG #{sig_reload} to #{pid}..."
24
+ begin
25
+ Process.kill(sig_reload, pid)
26
+ rescue Errno::ESRCH => e
27
+ STDERR.puts "*** Process #{pid} has already been killed: #{e.inspect}"
28
+ raise e
29
+ end
30
+ end
31
+
32
+ def kill
33
+ return exit_status if pid.nil?
34
+ the_pid = pid
35
+ @pid = nil
36
+ STDERR.puts "[KILL] Sending SIG #{sig_term} to #{the_pid}..."
37
+ begin
38
+ STDERR.puts "[KILL] waiting for #{the_pid}..."
39
+ Process.kill(sig_term, the_pid)
40
+ rescue Errno::ESRCH
41
+ STDERR.puts "[KILL] *** Process #{the_pid} has already been killed"
42
+ end
43
+ begin
44
+ _pid, @exit_status = Process.waitpid2 the_pid
45
+ rescue SystemCallError
46
+ STDERR.puts "[KILL] *** UNEXPECTED ERROR *** Failed to get return code for #{the_pid}"
47
+ end
48
+ exit_status
49
+ end
50
+
51
+ def process_status
52
+ raise ProcessDoesNotExist, 'No child process' if pid.nil?
53
+ begin
54
+ cpid, result = Process.waitpid2(pid, Process::WNOHANG)
55
+ raise ProcessDoesNotExist, "Unexpected PID: #{cpid}, was expecting #{pid}" unless cpid.nil? || cpid == pid
56
+ result
57
+ rescue Errno::ECHILD => e
58
+ e2 = ProcessDoesNotExist.new e
59
+ raise e2, "ChildProcess has been killed: #{e.message}", e.backtrace
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ module Consul
2
+ module Async
3
+ class Utilities
4
+ def self.bytes_to_h(bytes)
5
+ if bytes < 1024
6
+ "#{bytes} b"
7
+ elsif bytes < 1_048_576
8
+ "#{(bytes / 1024).round(2)} Kb"
9
+ elsif bytes < 1_073_741_824
10
+ "#{(bytes / 1_048_576.0).round(2)} Mb"
11
+ else
12
+ "#{(bytes / 1_073_741_824.0).round(2)} Gb"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module Consul
2
+ module Async
3
+ VERSION = '1.0.3'.freeze
4
+ end
5
+ end
@@ -0,0 +1,96 @@
1
+ <%
2
+ # This template can be configure the following way with environment variables
3
+ # Environment variables to filter services/instances
4
+ # SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
5
+ services_tag_filter = ENV['SERVICES_TAG_FILTER']
6
+ def status_to_class(status)
7
+ if status == 'passing'
8
+ 'success'
9
+ elsif status == 'warning'
10
+ 'warning'
11
+ elsif status == 'critical'
12
+ 'danger'
13
+ else
14
+ 'info'
15
+ end
16
+ end
17
+ %>
18
+ <%= render_file 'common/header.html.erb' %>
19
+ <style type="text/css">
20
+ .check {
21
+ transition: opacity 1s ease-out;
22
+ }
23
+ </style>
24
+ <script type="text/javascript">
25
+ function updateStates() {
26
+ states = ['passing', 'warning', 'critical']
27
+ stylesheet = document.getElementById('css-states');
28
+ txt = "";
29
+ for (var i in states) {
30
+ var s = states[i];
31
+ is_checked = document.getElementById('show_'+s).checked
32
+ var to_append = "." + s + " { ";
33
+ if (is_checked) {
34
+ to_append += "opacity: 1; height: auto;"
35
+ } else {
36
+ to_append += "opacity: 0; height: 0; overflow: hidden;"
37
+ }
38
+ to_append += " }\r\n"
39
+ txt += to_append;
40
+ }
41
+ stylesheet.textContent = txt;
42
+ }
43
+ </script>
44
+ <div class="container-fluid">
45
+ <div class="row">
46
+ <nav class="col-2">
47
+ <ul>
48
+ <%
49
+ all_services = services(tag: services_tag_filter)
50
+ all_services.each do |service_name, tags|
51
+ %>
52
+ <li><a href="#service_<%= service_name %>"><%= service_name %></a></li>
53
+ <% end %>
54
+ </ul>
55
+ </nav>
56
+ <main class="col-10">
57
+ <div class="float-right">
58
+ <div class="state-selector">
59
+ <input id="show_passing" type="checkbox" class="checks-visibility" value="passing" checked="checked" onchange="updateStates()"/>
60
+ <label for="show_passing"><span class="badge badge-success">Passing</span></label>
61
+ </div>
62
+ <div class="state-selector">
63
+ <input id="show_warning" type="checkbox" class="checks-visibility" value="warning" checked="checked" onchange="updateStates()"/>
64
+ <label for="show_warning"><span class="badge badge-warning">Warning</span></label>
65
+ </div>
66
+ <div class="state-selector">
67
+ <input id="show_critical" type="checkbox" class="checks-visibility" value="critical" checked="checked" onchange="updateStates()"/>
68
+ <label for="show_critical"><span class="badge badge-danger">Critical</span></label>
69
+ </div>
70
+ </div>
71
+
72
+ <h1 id="services">Services <%= services_tag_filter ? " tag: #{services_tag_filter}" : 'No filtering' %></h1>
73
+ <% all_services.each do |service_name, tags| %>
74
+ <div class="service" id="service_<%= service_name %>">
75
+ <h2>Service <%= service_name %></h2>
76
+ <div class="list-group">
77
+ <% checks_for_service(service_name).each do |check| %>
78
+ <div class="list-group-item check <%= check['Status'] %>" id="<%= check['CheckID'] %>">
79
+ <div class="d-flex align-items-center justify-content-between">
80
+ <h5>
81
+ <%= check['Name'] %> / <%= check['Node'] %>
82
+ </h5>
83
+ <span class="badge badge-pill badge-<%= status_to_class(check['Status']) %>"><%= check['Status'] %></span>
84
+ </div>
85
+ <p><%= ERB::Util.html_escape(check['Notes']) %></p>
86
+ <code><%= ERB::Util.html_escape(check['Output']) %></code>
87
+ </div>
88
+ <% end %>
89
+ </div>
90
+ </div>
91
+ <% end %>
92
+ </main>
93
+ </div>
94
+ </div>
95
+ <script type="text/javascript">updateStates();</script>
96
+ <%= render_file 'common/footer.html.erb' %>
@@ -0,0 +1,10 @@
1
+ </div>
2
+ </main>
3
+ <!-- Bootstrap core JavaScript
4
+ ================================================== -->
5
+ <!-- Latest compiled and minified JavaScript -->
6
+ <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
8
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,51 @@
1
+ <%
2
+ # This template can be configure the following way with environment variables
3
+ # CONSUL_TOOLS_SUFFIX: suffix for the address of consul tools
4
+ # CONSUL_TOOLS_PREFIX: prefix for the address of consul tools
5
+ # CONSUL_TOOLS: comma sperated list of consul tools
6
+ tools = (ENV['CONSUL_TOOLS'] || 'criteo_choregraphies,checks,services,nodes,keys').split(",")
7
+ suffix = ENV['CONSUL_TOOLS_PREFIX'] || '.html'
8
+ prefix = ENV['CONSUL_TOOLS_SUFFIX'] || ''
9
+ %>
10
+ <!DOCTYPE html>
11
+ <html lang="en">
12
+ <head>
13
+ <meta charset="utf-8">
14
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
15
+ <meta name="description" content="Display Consul information">
16
+ <meta name="author" content="Criteo">
17
+ <meta http-equiv="refresh" content="<%= ENV['REFRESH'] || '600' %>"/>
18
+
19
+ <title><%= ENV['TITLE'] || 'Consul Real Time information'%></title>
20
+
21
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
22
+ <style type="text/css">
23
+ body {
24
+ padding-top: 5rem;
25
+ }
26
+ .check {
27
+ transition: opacity 1s ease-out;
28
+ }
29
+ </style>
30
+ <style type="text/css" id="css-states">
31
+ </style>
32
+ </head>
33
+
34
+ <body>
35
+
36
+ <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
37
+ <a class="navbar-brand" href="#">Consul</a>
38
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
39
+ <span class="navbar-toggler-icon"></span>
40
+ </button>
41
+
42
+ <div class="collapse navbar-collapse" id="navbarsExampleDefault">
43
+ <ul class="navbar-nav mr-auto">
44
+ <% tools.each do |tool| %>
45
+ <li class="nav-item">
46
+ <a class="nav-link" href="<%= prefix + tool + suffix %>"><%= tool.gsub('_', ' ') %></a>
47
+ </li>
48
+ <% end %>
49
+ </ul>
50
+ </div>
51
+ </nav>
@@ -0,0 +1,94 @@
1
+ <!doctype html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8"/>
5
+ <meta http-equiv="refresh" content="300"/>
6
+ <title>Consul Full Info</title>
7
+ <style type="text/css">
8
+ .passing {
9
+ color:green;
10
+ }
11
+ .warning {
12
+ color: orange;
13
+ }
14
+ .critical {
15
+ color: red;
16
+ }
17
+ .qlink {
18
+ text-decoration: none;
19
+ }
20
+ </style>
21
+ </head>
22
+ <body>
23
+ <% require 'base64'
24
+ require 'json'
25
+ require 'date'
26
+ %>
27
+ <nav>
28
+ <ul>
29
+ <li><a href="#datacenters">DataCenters</a></li>
30
+ <li><a href="#list_services">List of services</a></li>
31
+ <li><a href="#services">Services with instances</a></li>
32
+ <li><a href="#nodes">All Nodes</a></li>
33
+ <li><a href="#kv">Key/Value Store</a></li>
34
+ </ul>
35
+ </nav>
36
+ <h1 id="datacenters">List of all datacenters</h1>
37
+ <ul>
38
+ <% datacenters.each do |dc| %>
39
+ <li id="dc_<%=dc %>%"><%= dc %> with <%= services(dc:dc).keys.count %> services, <%= nodes(dc:dc).count %> nodes</li>
40
+ <% end %>
41
+ </ul>
42
+
43
+ <h1 id="list_services">List of all services in current DC</h1>
44
+ <ul>
45
+ <% services.each do |service_name, tags|
46
+ %>
47
+ <li><a href="#service_<%= service_name %>"><%= service_name %></a> <%= tags.sort %></li>
48
+ <% end %>
49
+ </ul>
50
+
51
+ <h1 id="services">List all services instances sorted by node name</h1>
52
+ <% services.each do |service_name, tags|
53
+ %><h2 id="service_<%= service_name %>" title="<%= tags %>"><%= service_name %> <a class="qlink" href="#service_<%= service_name %>">&#128279;</a></h2>
54
+ <ul>
55
+ <% service(service_name).sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
56
+ tags = snode['Service']['Tags'].sort
57
+ addr = snode['Node']['Address']
58
+ port_num = snode['Service']['Port'].to_i
59
+ port = port_num && port_num > 0 ? ":#{port_num}" : ''
60
+ url = if tags.include? 'https'
61
+ "https://#{addr}#{port}"
62
+ elsif tags.include? 'http'
63
+ "http://#{addr}#{port}"
64
+ elsif tags.include? 'ftp'
65
+ "ftp://#{addr}#{port}"
66
+ else
67
+ nil
68
+ end
69
+ %><li><a <%= url ? "href=\"#{url}\"" : nil %>><%=
70
+ snode['Node']['Node'] %><%= port %></a>
71
+ <span class="tags"><%= snode['Service']['Tags'].sort %></tag>
72
+ <span class="statuses"><%
73
+ snode['Checks'].each do |c| %> <span title="<%= c['Name']%>" class="<%= c['Status'] %>"><%= c['Status']
74
+ %></span><% end if snode['Checks'] %></span></li>
75
+ <% end%>
76
+ </ul>
77
+ <% end%>
78
+
79
+
80
+ <h1 id="nodes">List all nodes for DC, sorted by name</h1>
81
+ <ul>
82
+ <% nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
83
+ %> <li id="node_#{snode['ID']"><%= snode['Address'].ljust(16) %> <%= snode['Node'] %></li>
84
+ <% end %>
85
+ </ul>
86
+
87
+ <h1 id="kv">KV of Current DC</h1>
88
+ <ul>
89
+ <% kv(keys:true).each do |key|
90
+ %><li id="kv_#{key}"><%= key %></li>
91
+ <% end %>
92
+ </ul>
93
+ </body>
94
+ </html>
@@ -0,0 +1,77 @@
1
+ <%
2
+ # This template can be configure the following way with environment variables
3
+ # Environment variables to filter services/instances
4
+ # SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
5
+ # INSTANCE_MUST_TAG: Second level of filtering (optional, default to SERVICES_TAG_FILTER)
6
+ # INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary)
7
+ # EXCLUDE_SERVICES: comma-separated services to exclude (default: consul-agent-http,mesos-slave,mesos-agent-watcher)
8
+
9
+ service_tag_filter = ENV['SERVICES_TAG_FILTER'] || 'http'
10
+ instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
11
+ instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG'] || 'canary'
12
+
13
+ # Services to hide
14
+ services_blacklist = (ENV['EXCLUDE_SERVICES'] || 'consul-agent-http,mesos-slave,mesos-agent-watcher,mesos-exporter-slave').split(',')
15
+ # Compute the health of a Service
16
+ def compute_state(snode)
17
+ states = ['passing', []]
18
+ snode['Checks'].each do |chk|
19
+ st = chk['Status']
20
+ states[1] << st
21
+ if st == 'critical'
22
+ states[0] = st
23
+ elsif st == 'warning' && states[0] == 'passing'
24
+ states[0] = st
25
+ end
26
+ end
27
+ states
28
+ end
29
+ def compute_attributes(snode)
30
+ w = 100
31
+ snode['Service']['Tags'].each do |tag|
32
+ match = /^weight-([1-9][0-9])*$/.match(tag)
33
+ w = match[1].to_i if match
34
+ end
35
+ attributes = ""
36
+ states = compute_state(snode)
37
+ attributes = "#{attributes} disabled" if states[0] == 'critical'
38
+ if states[0] == 'warning'
39
+ w = w / 8
40
+ end
41
+ attributes = "#{attributes} weight #{w}" if w.positive?
42
+ end
43
+ backends = {}
44
+ services(tag: service_tag_filter).each do |service_name, tags|
45
+ if !services_blacklist.include?(service_name) && tags.include?(instance_must_tag)
46
+ the_backends = []
47
+ service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
48
+ tags_of_instance = snode['Service']['Tags']
49
+ if tags_of_instance.include?(instance_must_tag) && !tags_of_instance.include?(instance_exclude_tag)
50
+ the_backends << snode if snode['Service']['Port']
51
+ end
52
+ end
53
+ # We add the backend ONLY if at least one valid instance does exists
54
+ backends[service_name] = the_backends
55
+ end
56
+ end
57
+ %><%
58
+ json_backends = {}
59
+ backends.each_pair do |service_name, nodes|
60
+ service = {
61
+ name: service_name,
62
+ count: nodes.count,
63
+ instances: []
64
+ }
65
+ json_backends[service_name] = service
66
+ nodes.each do |snode|
67
+ server = { frontend_id: "backend_http__#{service_name}",
68
+ id: snode['Service']['ID'],
69
+ addr: snode['Node']['Address'],
70
+ port: snode['Service']['Port'],
71
+ tags: snode['Service']['Tags'],
72
+ }
73
+ service[:instances] << server
74
+ end
75
+ end
76
+ json = { services: json_backends}
77
+ %><%= JSON.pretty_generate(json) %>
@@ -0,0 +1,45 @@
1
+ + List of all datacenters
2
+ -------------------------
3
+ <% datacenters. each do |dc| %>
4
+ * <%= dc %> with <%= services(dc:dc).keys.count %> services, <%= nodes(dc:dc).count %> nodes
5
+ <% end %>
6
+
7
+ ===========
8
+
9
+ + List of all services in current DC
10
+ ------------------------------------
11
+ <% services.each do |service_name, tags|
12
+ %> * <%= service_name %> [ <%= tags %> ]
13
+ <% end %>
14
+
15
+ ===========
16
+
17
+ + List all services instances with http tag on current DC, instances sorted by node name
18
+ ----------------------------------------------------------------------------------------
19
+ <% services.each do |service_name, tags|
20
+ if tags.include? 'http'
21
+ %> ++ Service <%= service_name %>
22
+ <% service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |snode|
23
+ %> * <%= service_name %> -> <%=
24
+ snode['Node']['Node'] %>:<%= snode['Service']['Port'] %> <%=
25
+ snode['Service']['Tags'] %> status: <%
26
+ snode['Checks'].each do |c| %> <%= c['Status']
27
+ %><% end if snode['Checks'] %>
28
+ <% end
29
+ end
30
+ end %>
31
+
32
+ ===========
33
+
34
+ + List all nodes for DC, sorted by name
35
+ ---------------------------------------
36
+ <% nodes.sort {|a,b| a['Node'] <=> b['Node'] }.each do |snode|
37
+ %> * <%= snode['Address'].ljust(16) %> <%= snode['Node'] %>
38
+ <% end %>
39
+
40
+ + KV of Current DC
41
+ ------------------
42
+
43
+ <% kv(keys:true).each do |key|
44
+ %> * <%= key %>
45
+ <% end %>