<%
# This template can be configure the following way with environment variables
# Environment variables to filter services/instances
#   SERVICES_TAG_FILTER: basic tag filter for service (default HTTP)
#   INSTANCE_MUST_TAG: Second level of filtering (optional, default to SERVICES_TAG_FILTER)
#   INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary)
#   EXCLUDE_SERVICES: comma-separated services to exclude (default: consul-agent-http,mesos-slave,mesos-agent-watcher)
# Environment variables to configure HaProxy
#   PORT0 : HaProxy main port (default to 8000)
#   PORT1 : HaProxy admin port (default to 8001)
#   HAPROXY_ADMIN_PORT: Port to listen
#   HAPROXY_ADMIN_USER_PASSWORD: User:Password to access to stats (default: none)
#   HAPROXY_SOCKET_FILE: HaProxy socket to control HaProxy

  service_tag_filter = ENV['SERVICES_TAG_FILTER'] || 'http'
  instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter
  instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG'] || 'canary'

  # Services to hide
  services_blacklist = (ENV['EXCLUDE_SERVICES'] || 'consul-agent-http,mesos-slave,mesos-agent-watcher,mesos-exporter-slave').split(',')
  # Compute the health of a Service
  def compute_state(node)
    states = ['passing', []]
    node['Checks'].each do |chk|
      st = chk['Status']
      states[1] << st
      if st == 'critical'
        states[0] = st
      elsif st == 'warning' && states[0] == 'passing'
        states[0] = st
      end
    end
    states
  end
  def compute_attributes(node)
    w = 100
    node['Service']['Tags'].each do |tag|
      match = /^weight-([1-9][0-9])*$/.match(tag)
      w = match[1].to_i if match
    end
    attributes = ""
    states = compute_state(node)
    attributes = "#{attributes} disabled" if states[0] == 'critical'
    if states[0] == 'warning'
      w = w / 8
    end
    attributes = "#{attributes} weight #{w}" if w.positive?
  end
  backends = {}
  services(tag: service_tag_filter).each do |service_name, tags|
    if !services_blacklist.include?(service_name) && tags.include?(instance_must_tag)
      the_backends = []
      service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |node|
        tags_of_instance = node['Service']['Tags']
        if tags_of_instance.include?(instance_must_tag) && !tags_of_instance.include?(instance_exclude_tag)
          the_backends << node if node['Service']['Port']
        end
      end
      # We add the backend ONLY if at least one valid instance does exists
      backends[service_name] = the_backends
    end
  end
%>
# This HaProxy configuration is generated by consul-templaterb
# Service/Instances filtering
# Service tag MUST be <%= service_tag_filter %>
# Instance tag MUST be <%= instance_must_tag %>
# Instance tag excluded: <%= instance_exclude_tag %>

# Found <%= backends.keys.count %> different services with <%= backends.values.flatten.count %> nodes

global
  maxconn 1024
<%
  socket_file = ENV['HAPROXY_SOCKET_FILE']
  if socket_file
%>
  stats socket <%= socket_file %> mode 600 level admin
<% end %>

defaults
  timeout connect 1000
  timeout client 5000
  timeout server 15000
<% backends.each_pair do |service_name, nodes|
%>
backend backend_http__<%= service_name %>
  mode http
  balance leastconn
<%   nodes.each do |node|
  %>  server <%= node['Node']['Node']%>_<%= node['Service']['Port'] %> <%= node['Node']['Address']%>:<%= node['Service']['Port'] %><%= compute_attributes(node) %>
<%   end
   end
%>
frontend fontend_http
   mode http
   bind *:<%= ENV['PORT0'] || 8000 %>
   option httplog
   log 127.0.0.1:534 local5
   option  dontlognull
   option forwardfor
<% backends.each_pair do |service_name, nodes|
%>
   acl host__<%= service_name %> hdr_beg(host) -i <%= service_name %>.
   use_backend backend_http__<%= service_name %> if host__<%= service_name%>
<% end %>

listen stats
  bind    :<%= ENV['PORT1'] || 8001 %>
  mode            http
  log             global
  maxconn 10
  timeout client  100s
  timeout server  100s
  timeout connect 100s
  timeout queue   100s
  stats enable
  stats hide-version
  stats refresh 30s
  stats show-node
  stats uri  /haproxy?stats
<%
   user_password = ENV['HAPROXY_ADMIN_USER_PASSWORD']
   if user_password
%>
  stats auth <%= user_password %>
<% end %>