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.
- checksums.yaml +7 -0
 - data/.gitignore +25 -0
 - data/.gitreview +5 -0
 - data/.rspec +2 -0
 - data/.rubocop.yml +43 -0
 - data/.ruby_app +0 -0
 - data/.travis.yml +13 -0
 - data/Gemfile +5 -0
 - data/LICENSE.txt +201 -0
 - data/README.md +270 -0
 - data/Rakefile +6 -0
 - data/bin/consul-templaterb +246 -0
 - data/consul-templaterb.gemspec +37 -0
 - data/lib/consul/async/consul_endpoint.rb +279 -0
 - data/lib/consul/async/consul_template.rb +323 -0
 - data/lib/consul/async/consul_template_engine.rb +57 -0
 - data/lib/consul/async/consul_template_render.rb +80 -0
 - data/lib/consul/async/process_handler.rb +64 -0
 - data/lib/consul/async/utilities.rb +17 -0
 - data/lib/consul/async/version.rb +5 -0
 - data/samples/checks.html.erb +96 -0
 - data/samples/common/footer.html.erb +10 -0
 - data/samples/common/header.html.erb +51 -0
 - data/samples/consul_template.html.erb +94 -0
 - data/samples/consul_template.json.erb +77 -0
 - data/samples/consul_template.txt.erb +45 -0
 - data/samples/consul_template.xml.erb +70 -0
 - data/samples/criteo/haproxy.cfg.erb +163 -0
 - data/samples/criteo_choregraphies.html.erb +91 -0
 - data/samples/ha_proxy.cfg.erb +127 -0
 - data/samples/keys.html.erb +38 -0
 - data/samples/nodes.html.erb +17 -0
 - data/samples/services.html.erb +89 -0
 - metadata +189 -0
 
| 
         @@ -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,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 %>">🔗</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 %>
         
     |