blob: 4600c4ae60f34f1b9280f1d03715577db64671ed [file] [log] [blame]
{%- from "haproxy/map.jinja" import proxy, invalid_section_options with context -%}
{% macro checktimeout(value) -%}
{% if value is number -%}{{ value }}ms{% else -%}{{ value }}{% endif %}
{%- endmacro -%}
global
{%- for param_name, param in proxy.global.items()|sort %} {# Iterate through all global parameters #}
{%- if param is iterable and param is not string and param|length > 0 %} {# Param is a list of values #}
{%- for value in param %} {# Iterate through list #}
{{ param_name|replace('_', '.') }} {{ value }} {# Add each value from list #}
{%- endfor %}
{%- elif param == true or param|lower == 'true' %} {# Param is boolean and true #}
{{ param_name|replace('_', '.') }} {# Add param name if value is true #}
{%- elif (param is string and param != '' and param|lower != 'false') or (param is number and param != false) %} {# Param is a string and is not empty or is a number #}
{{ param_name|replace('_', '.') }} {{ param }} {# Add a string value #}
{%- endif %}
{%- endfor %}
{%- if salt['pkg.version']('haproxy')[:3] >= '1.6' %}
# SSL options
ca-base /etc/haproxy/ssl
crt-base /etc/haproxy/ssl
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers {{ proxy.ssl_defaults.bind_ciphers }}
ssl-default-bind-options {{ proxy.ssl_defaults.bind_options }}
ssl-default-server-ciphers {{ proxy.ssl_defaults.server_ciphers }}
ssl-default-server-options {{ proxy.ssl_defaults.server_options }}
{%- endif %}
defaults
log global
mode http
maxconn {{ proxy.maxconn|default(8000) }}
{%- if proxy.get('forwardfor', {}).enabled|default(False) %}
option forwardfor{% if proxy.forwardfor.get('except', False) %} except {{proxy.forwardfor.except}}{% endif %}{% if proxy.forwardfor.get('header', False) %} header {{proxy.forwardfor.header}}{% endif %}{% if proxy.forwardfor.get('if-none') %} if-none{% endif %}
{%- endif %}
option redispatch
retries {{ proxy.retries|default(3) }}
stats enable
timeout http-request {{ checktimeout(proxy.get('timeout', {}).get('http-request','10s')) }}
timeout queue {{ checktimeout(proxy.get('timeout', {}).get('queue', '1m')) }}
timeout connect {{ checktimeout(proxy.get('timeout', {}).get('connect', '10s')) }}
timeout client {{ checktimeout(proxy.get('timeout', {}).get('client', '1m')) }}
timeout server {{ checktimeout(proxy.get('timeout', {}).get('server', '1m')) }}
timeout check {{ checktimeout(proxy.get('timeout', {}).get('check', '10s')) }}
{%- if proxy.get('listen') is mapping and proxy.listen.admin_page is defined and proxy.listen.admin_page.user is defined %}
userlist STATSUSERS
group admin users admin
user {{ proxy.listen.admin_page.user }} insecure-password {{ proxy.listen.admin_page.password }}
user stats insecure-password {{ proxy.listen.admin_page.password }}
{#
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.user is defined %}
user {{ listen.user }} insecure-password {{ listen.password }}
{%- endif %}
{%- endfor %}
#}
{%- endif %}
{% if proxy.get('userlist') is defined %}
{%- for userlist_name, userlist in proxy.get('userlist', {}).iteritems() %}
userlist {{ userlist.name|default(userlist_name) }}
{%- if userlist.groups is defined %}
{%- set groupNames = [] %}
{%- for group in userlist.groups %}
{%- do groupNames.append(group.name) %}
group {{ group.name }} {% if group.users is defined %} users {{ group.users|join(',') }} {% endif %}
{%- endfor %}
{% endif %}
{%- for user in userlist.users %}
{%- if user.get('insecure_password', False) %}
{%- set userPasswordField = 'insecure-password ' + user.password %}
{%- elif user.get('shadow_password', False) %}
{%- set userPasswordField = 'password ' + salt['shadow.gen_password'](user.password) %}
{%- else %}
{%- set userPasswordField = 'password ' + user.password %}
{%- endif %}
{%- if user.groups is defined %}
{%- set userGroupsField = 'groups ' + user.groups|join(',') %}
{%- elif userlist.groups is defined %}
{%- set userGroupsField = 'groups ' + groupNames|join(',') %}
{%- endif %}
user {{ user.name }} {{ userPasswordField }} {{ userGroupsField }}
{%- endfor %}
{%- endfor %}
{%- endif %}
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.get('enabled', True) %}
{%- if listen.get('format', 'listen') == 'listen' %}
listen {{ listen_name }}
{%- for bind in listen.binds %}
bind {{ bind.address }}:{{ bind.port }} {% if bind.get('ssl', {}).enabled|default(False) %}{% if bind.ssl.pem_file is defined %}ssl crt {{ bind.ssl.pem_file }}{% else %}ssl crt /etc/haproxy/ssl/{{ listen_name }}{% endif %}{% endif %}
{%- endfor %}
{%- if listen.bind_process is defined %}
bind-process {{ listen.bind_process }}
{%- endif %}
{%- if listen.get('type', None) == 'http' %}
mode http
balance {{ listen.get('balance', 'roundrobin') }}
option httplog
{%- elif listen.get('type', None) == 'rabbitmq' %}
balance {{ listen.get('balance', 'roundrobin') }}
mode tcp
option tcpka
timeout client 300s
timeout server 300s
{%- elif listen.get('type', None) == 'mysql' %}
balance {{ listen.get('balance', 'leastconn') }}
mode tcp
option httpchk
option tcplog
option clitcpka
option srvtcpka
timeout client 300s
timeout server 300s
{%- if listen.get('health-check', {}).get('mysql', {}).get('enabled', True) %}
# option conflict's with port check of clustercheck script, if enabled haproxy reports invalid reponse
option mysql-check user haproxy
{%- endif %}
{%- elif listen.get('type', None) == 'pgsql' %}
balance {{ listen.get('balance', 'leastconn') }}
mode tcp
option httpchk
option tcplog
option clitcpka
option srvtcpka
timeout client 28801s
timeout server 28801s
{%- if listen.get('health-check', {}).get('pgsql', {}).get('enabled', True) %}
option pgsql-check user postgres
{%- endif %}
{%- elif listen.get('type', None) == 'horizon' %}
balance {{ listen.get('balance', 'source') }}
capture cookie vgnvisitor= len 32
cookie SERVERID insert indirect nocache
mode http
option forwardfor
option httpchk
option httpclose
option httplog
rspidel ^Set-cookie:\ IP=
{%- elif listen.get('type', None) == 'general-service' %}
mode http
balance {{ listen.get('balance', 'roundrobin') }}
option httplog
{%- elif listen.get('type', None) == 'openstack-service' %}
# NOTE(vsaienko): by default haproxy uses OPTIONS method when doing check
# This is not guaranteed by openstack APIs, change it to GET instead
option httpchk GET /
option httplog
option httpclose
{%- elif listen.get('type', None) == 'heat' %}
balance source
option tcpka
option httpchk
option tcplog
{%- elif listen.get('type', None) == 'contrail-config' %}
mode http
stats enable
stats uri /
stats auth {{ listen.user }}:{{ listen.password }}
{%- elif listen.get('type', None) == 'contrail-api' %}
{%- for option in listen.get('options', []) %}
option {{ option }}
{%- endfor %}
balance {{ listen.get('balance', 'leastconn') }}
{%- elif listen.get('type', None) == 'contrail-analytics' %}
{%- for option in listen.get('options', []) %}
option {{ option }}
{%- endfor %}
balance {{ listen.get('balance', 'roundrobin') }}
option tcp-check
tcp-check connect port 6379
default-server error-limit 1 on-error mark-down
{%- elif listen.get('type', None) == 'stats' %}
mode http
stats enable
stats uri /
{%- if listen.user is defined %}
stats auth {{ listen.user }}:{{ listen.password }}
{%- endif %}
{%- elif listen.get('type', None) == 'admin' %}
mode http
acl AuthOkay_ReadOnly http_auth(STATSUSERS)
acl AuthOkay_Admin http_auth_group(STATSUSERS) {{ listen.user }}
stats enable
stats refresh 60s
stats uri /
stats http-request auth realm admin_page unless AuthOkay_ReadOnly
stats admin if AuthOkay_Admin
{%- else %}
{# no type specified #}
mode {{ listen.mode|default('tcp') }}
balance {{ listen.balance|default('roundrobin') }}
{%- for ttype, timeout in listen.get('timeout', {}).iteritems() %}
timeout {{ ttype }} {{ checktimeout(timeout) }}
{%- endfor %}
{%- for aclname, acl in listen.get('acl', {}).iteritems() %}
acl {{ aclname }} {{ acl }}
{%- endfor %}
{%- for capture in listen.get('capture', []) %}
capture {{ capture }}
{%- endfor %}
{%- for compression in listen.get('compression', []) %}
compression {{ compression }}
{%- endfor %}
{%- if listen.declare_capture is defined %}
declare capture {{ listen.declare_capture }}
{%- endif %}
{%- for email_alert in listen.get('email_alert', []) %}
email-alert {{ email_alert }}
{%- endfor %}
{%- if listen.errorfile is defined %}
{%- for errorfile_name, errorfile in listen.get('errorfile', {}).iteritems() %}
errorfile {{ errorfile.code }} {{ errorfile.file }}
{%- endfor %}
{%- endif %}
{%- if listen.max_keep_alive_queue is defined %}
max-keep-alive-queue {{ listen.max_keep_alive_queue }}
{%- endif %}
{%- if listen.maxconn is defined %}
maxconn {{ listen.maxconn }}
{%- endif %}
{%- for http_request in listen.get('http_request', []) %}
http-request {{ http_request.action }}{% if http_request.condition is defined %} {{ http_request.condition }}{% endif %}
{%- endfor %}
{%- for http_response in listen.get('http_response', []) %}
http-response {{ http_response.action }}{% if http_response.condition is defined %} {{ http_response.condition }}{% endif %}
{%- endfor %}
{%- for http_check in listen.get('http_check', []) %}
http-check {{ http_check.action }}
{%- endfor %}
{%- for option in listen.get('options', []) %}
option {{ option }}
{%- endfor %}
{%- for type, checks in listen.get('health-check', {}).iteritems() %}
{%- if checks.get('enabled', True) %}
{%- if type == 'http' and 'httpchk' not in listen.get('options', [])|join('|') %}
option httpchk
{%- endif %}
{%- if type == 'tcp' and 'tcp-check' not in listen.get('options', [])|join('|') %}
option tcp-check
{%- endif %}
{%- for option in checks.get('options', []) %}
{{ type }}-check {{ option }}
{%- endfor %}
{%- endif %}
{%- endfor %}
{%- for stick in listen.get('sticks', []) %}
{{ stick }}
{%- endfor %}
{%- for reqadd in listen.get('reqadd', []) %}
reqadd {{ reqadd }}
{%- endfor %}
{%- for reqirep in listen.get('reqirep', []) %}
reqirep {{ reqirep }}
{%- endfor %}
{%- for modify_header in listen.get('modify_headers', []) %}
{{ modify_header }}
{%- endfor %}
{%- if listen.retries is defined %}
retries {{ listen.retries }}
{%- endif %}
{%- for stat in listen.get('stats', []) %}
stats {{ stat }}
{%- endfor %}
{%- if listen.rate_limit_sessions is defined %}
rate-limit sessions {{ listen.rate_limit_sessions }}
{%- endif %}
{%- endif %}
{%- if listen.rate_limit is defined and listen.rate_limit.get('enabled', False) %}
{%- include "haproxy/files/_rate_limit.cfg" %}
{%- endif %}
{%- if listen.redirects is defined %}
{%- for redirect in listen.redirects %}
http-request redirect {% if redirect.code is defined %} code {{ redirect.code }} {% endif %} location {{ redirect.location }} {%- if redirect.condition_raw is defined %} {{ redirect.condition_raw }} {%- endif %}
{%- endfor %}
{%- else %}
{%- for server in listen.get('servers', []) %}
{%- set port_range_length=server.get('port_range_length', 1) %}
{%- set port_range_start_offset=server.get('port_range_start_offset', 0) %}
{%- for worker_port in range(port_range_start_offset, port_range_length) %}
server {{ server.name }}{% if worker_port > 0 %}p{{ worker_port }}{% endif %} {{ server.host }}:{{ server.port + worker_port }} {{ server.get('params', '') }}
{%- endfor %}
{%- endfor %}
{%- endif %}
{%- if listen.rate_limit is defined and listen.rate_limit.get('enabled', False) %}
backend {{ listen_name }}-rate_limit
{%- set stick_table_found = { 'val': false } %}
{%- for item in listen.get('sticks', []) if item.startswith('stick-table ') %}
{%- do stick_table_found.update({'val': true}) %}
{%- endfor %}
{%- if stick_table_found.val %}
stick-table type {{ listen.rate_limit.get('type', 'string') }} {%- if listen.rate_limit.len is defined and listen.rate_limit.type in ['string', 'binary'] %} len {{ listen.rate_limit.len }}{%- endif %} size {{ listen.rate_limit.get('size', '100k') }} store gpc0_rate({{ listen.rate_limit.get('duration', '60s') }})
{%- endif %}
timeout tarpit {{ checktimeout(listen.rate_limit.get('tarpit_timeout', '2s')) }}
errorfile 500 /etc/haproxy/errors/429.http11
http-request tarpit
{%- endif %}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- for listen_name, listen in proxy.get('listen', {}).iteritems() %}
{%- if listen.get('format', 'listen') == 'end' %}
frontend {{ listen_name }}
{%- for bind in listen.binds %}
bind {{ bind.address }}:{{ bind.port }} {% if bind.get('ssl', {}).enabled|default(False) %} {% if bind.ssl.pem_file is defined %}ssl crt {{ bind.ssl.pem_file }}{% else %}ssl crt /etc/haproxy/ssl/{{ listen_name }}{% endif %} {% endif %}
{% endfor %}
{% if listen.get('force_ssl') == true %}
redirect scheme https code 301 if !{ ssl_fc }
{% endif %}
{%- for redirect in listen.get('redirects', []) %}
{%- for condition in redirect.get('conditions', []) %}
redirect {% if redirect.code is defined %} code {{ redirect.code }} {% endif %} location {{ redirect.location }} if { {{ condition.type }} {{ condition.condition }} }
{%- endfor %}
{%- endfor %}
{#- Add options in the frontend section that make sense. #}
{%- for option in listen.get('options', []) %}
{%- if option not in invalid_section_options.frontend %}
option {{ option }}
{%- endif %}
{%- endfor %}
{%- for acl in listen.get('acls', []) %}
{%- for condition in acl.get('conditions', []) %}
acl {{ acl.name }} {{ condition.type }} {{ condition.condition }}
{%- endfor %}
{%- if listen_name == 'service_proxy' %}
use_backend {{ acl.backend|default(acl.name, true) }} if {{ acl.name }}
{% else %}
use_backend {{ acl.name }}-backend if {{ acl.name }}
{% endif %}
{%- endfor %}
{%- if listen.rate_limit is defined and listen.rate_limit.get('enabled', False) %}
{%- include "haproxy/files/_rate_limit.cfg" %}
{%- endif %}
default_backend {{ listen_name }}-backend
backend {{ listen_name }}-backend
{%- if listen.get('type', None) == 'http' %}
balance {{ listen.get('balance', 'roundrobin') }}
{%- endif %}
{#- Add options in the backend section that make sense. #}
{%- for option in listen.get('options', []) %}
{%- if option not in invalid_section_options.backend %}
option {{ option }}
{%- endif %}
{%- endfor %}
{%- for server in listen.get('servers', []) %}
server {{ server.get('name', server.host) }} {{ server.host }}:{{ server.port }} {{ server.get('params', '') }}
{%- endfor %}
{%- if listen_name != 'service_proxy' %}
{%- for acl in listen.get('acls', []) %}
backend {{ acl.name }}-backend
balance {{ acl.get('balance', 'roundrobin') }}
{%- for option in acl.get('options', []) %}
option {{ option }}
{%- endfor %}
{%- for server in acl.get('servers', []) %}
server {{ server.get('name', server.host) }} {{ server.host }}:{{ server.port }} {{ server.get('params', '') }}
{%- endfor %}
{%- endfor %}
{%- endif %}
{%- if listen.rate_limit is defined and listen.rate_limit.get('enabled', False) %}
backend {{ listen_name }}-rate_limit
timeout tarpit {{ checktimeout(listen.rate_limit.get('tarpit_timeout', '2s')) }}
errorfile 500 /etc/haproxy/errors/429.http11
http-request tarpit
{%- endif %}
{%- endif %}
{%- endfor %}