Simplify haproxy_service_configs structure

For historical reasons the ``haproxy_service_configs`` variable was
a list of nested mappings with only single valid key for the top
level mapping.

There have been no use-cases for extra keys, so this patch simplifies
the code by removing one level of nesting.

Change-Id: I50c17b7020a459ab8a88b004cc8828cac857f1c9
This commit is contained in:
Damian Dabrowski 2023-01-19 22:41:25 +01:00
parent d548b7e5ff
commit a5f285c51e
7 changed files with 249 additions and 245 deletions

View File

@ -52,73 +52,67 @@ haproxy_frontend_redirect_extra_raw: "{{ haproxy_frontend_extra_raw }}"
haproxy_service_configs: []
# Example:
# haproxy_service_configs:
# - service:
# haproxy_service_name: haproxy_all
# haproxy_backend_nodes: "{{ groups['haproxy_all'][0] }}"
# # haproxy_backup_nodes: "{{ groups['haproxy_all'][1:] }}"
# haproxy_port: 80
# haproxy_balance_type: http
# haproxy_backend_options:
# - "forwardfor"
# - "httpchk"
# - "httplog"
# haproxy_backend_server_options:
# - "inter 3000" # a contrived example, there are many server config options possible
# haproxy_acls:
# allow_list:
# rule: "src 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8"
# backend_name: "mybackend"
# haproxy_frontend_acls:
# letsencrypt-acl:
# rule: "path_beg /.well-known/acme-challenge/"
# backend_name: letsencrypt
# haproxy_stick_table:
# - "stick-table type ipv6 size 256k expire 10s store http_err_rate(10s)"
# - "http-request track-sc0 src"
# - "http-request deny deny_status 429 if { sc_http_err_rate(0) gt 20 } !{ src 10.0.0.0/8 } !{ src 172.16.0.0/12 } !{ src 192.168.0.0/16 }"
# - service:
# - haproxy_service_name: haproxy_all
# haproxy_backend_nodes: "{{ groups['haproxy_all'][0] }}"
# # haproxy_backup_nodes: "{{ groups['haproxy_all'][1:] }}"
# haproxy_port: 80
# haproxy_balance_type: http
# haproxy_backend_options:
# - "forwardfor"
# - "httpchk"
# - "httplog"
# haproxy_backend_server_options:
# - "inter 3000" # a contrived example, there are many server config options possible
# haproxy_acls:
# allow_list:
# rule: "src 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8"
# backend_name: "mybackend"
# haproxy_frontend_acls:
# letsencrypt-acl:
# rule: "path_beg /.well-known/acme-challenge/"
# backend_name: letsencrypt
# haproxy_stick_table:
# - "stick-table type ipv6 size 256k expire 10s store http_err_rate(10s)"
# - "http-request track-sc0 src"
# - "http-request deny deny_status 429 if { sc_http_err_rate(0) gt 20 } !{ src 10.0.0.0/8 } !{ src 172.16.0.0/12 } !{ src 192.168.0.0/16 }"
# # https://www.haproxy.com/blog/haproxy-exposes-a-prometheus-metrics-endpoint/
# haproxy_service_name: prometheus-metrics
# haproxy_port: 8404
# haproxy_bind:
# - '127.0.0.1'
# haproxy_allowlist_networks: "{{ haproxy_allowlist_networks }}"
# haproxy_frontend_only: True
# haproxy_balance_type: "http"
# haproxy_frontend_raw:
# - 'http-request use-service prometheus-exporter if { path /metrics }'
# haproxy_service_enabled: True
# haproxy_default_backend: other_backend
# - haproxy_service_name: prometheus-metrics
# haproxy_port: 8404
# haproxy_bind:
# - '127.0.0.1'
# haproxy_allowlist_networks: "{{ haproxy_allowlist_networks }}"
# haproxy_frontend_only: True
# haproxy_balance_type: "http"
# haproxy_frontend_raw:
# - 'http-request use-service prometheus-exporter if { path /metrics }'
# haproxy_service_enabled: True
# HAProxy maps (unrelated keys are omitted but are required as the previous service example)
# Example:
# haproxy_service_configs:
# - service:
# state: present # state 'absent' will remove map entries defined in this service
# haproxy_service_enabled: true # haproxy_service_enabled 'false' will remove map entries defined in this service
# haproxy_service_name: "one"
# haproxy_maps:
# - 'use_backend %[req.hdr(host),lower,map(/etc/haproxy/route.map)]'
# haproxy_map_entries:
# - name: 'route' # this service contributes entries to the map called 'route'
# order: 10 # prefix the name of the map fragment wih this string to control ordering of the assembled map
# entries:
# - compute.example.com nova-api
# - dashboard.example.com horizon
# - service: # this service has no map definitions
# haproxy_service_name: "two"
# - service:
# haproxy_service_name: "three"
# haproxy_map_entries:
# - name: 'route' # this service contributes to the map called 'route'
# entries:
# - s3.example.com radosgw
# - sso.example.com keycloak
# - name: 'rate' # and also to the map called 'rate'
# state: present # individual map entries can be removed with state 'absent'
# entries:
# - /api/foo 20
# - /api/bar 40
# - state: present # state 'absent' will remove map entries defined in this service
# haproxy_service_enabled: true # haproxy_service_enabled 'false' will remove map entries defined in this service
# haproxy_service_name: "one"
# haproxy_maps:
# - 'use_backend %[req.hdr(host),lower,map(/etc/haproxy/route.map)]'
# haproxy_map_entries:
# - name: 'route' # this service contributes entries to the map called 'route'
# order: 10 # prefix the name of the map fragment wih this string to control ordering of the assembled map
# entries:
# - compute.example.com nova-api
# - dashboard.example.com horizon
# - haproxy_service_name: "two"
# - haproxy_service_name: "three"
# haproxy_map_entries:
# - name: 'route' # this service contributes to the map called 'route'
# entries:
# - s3.example.com radosgw
# - sso.example.com keycloak
# - name: 'rate' # and also to the map called 'rate'
# state: present # individual map entries can be removed with state 'absent'
# entries:
# - /api/foo 20
# - /api/bar 40
#
# Results:
#

View File

@ -186,36 +186,34 @@ certificates are renewed.
haproxy_service_configs:
# the external facing service which serves the apache test site, with a acl for LE requests
- service:
haproxy_service_name: test
haproxy_redirect_http_port: 80 #redirect port 80 to port ssl
haproxy_redirect_scheme: "https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }" #redirect all non-ssl traffic to ssl except acme-challenge
haproxy_port: 443
haproxy_frontend_acls: #use a frontend ACL specify the backend to use for acme-challenge
letsencrypt-acl:
rule: "path_beg /.well-known/acme-challenge/"
backend_name: letsencrypt
haproxy_ssl: True
haproxy_backend_nodes: #apache is running on locally on 127.0.0.1:80 serving a dummy site
- name: local-test-service
ip_addr: 127.0.0.1
haproxy_balance_type: http
haproxy_backend_port: 80
haproxy_backend_options:
- "httpchk HEAD /" # request to use for health check for the example service
- haproxy_service_name: test
haproxy_redirect_http_port: 80 #redirect port 80 to port ssl
haproxy_redirect_scheme: "https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }" #redirect all non-ssl traffic to ssl except acme-challenge
haproxy_port: 443
haproxy_frontend_acls: #use a frontend ACL specify the backend to use for acme-challenge
letsencrypt-acl:
rule: "path_beg /.well-known/acme-challenge/"
backend_name: letsencrypt
haproxy_ssl: True
haproxy_backend_nodes: #apache is running on locally on 127.0.0.1:80 serving a dummy site
- name: local-test-service
ip_addr: 127.0.0.1
haproxy_balance_type: http
haproxy_backend_port: 80
haproxy_backend_options:
- "httpchk HEAD /" # request to use for health check for the example service
# an internal only service for acme-challenge whose backend is certbot on the haproxy host
- service:
haproxy_service_name: letsencrypt
haproxy_backend_nodes:
- name: localhost
ip_addr: {{ ansible_host }} #certbot binds to the internal IP
backend_rise: 1 #quick rise and fall time for multinode deployment to succeed
backend_fall: 2
haproxy_bind:
- 127.0.0.1 #bind to 127.0.0.1 as the local internal address will be used by certbot
haproxy_port: 8888 #certbot is configured with http-01-port to be 8888
haproxy_balance_type: http
- haproxy_service_name: letsencrypt
haproxy_backend_nodes:
- name: localhost
ip_addr: {{ ansible_host }} #certbot binds to the internal IP
backend_rise: 1 #quick rise and fall time for multinode deployment to succeed
backend_fall: 2
haproxy_bind:
- 127.0.0.1 #bind to 127.0.0.1 as the local internal address will be used by certbot
haproxy_port: 8888 #certbot is configured with http-01-port to be 8888
haproxy_balance_type: http
It is possible to use an HA configuration of HAProxy with certificates
@ -269,19 +267,18 @@ An example HTTP service could look like:
.. code-block:: yaml
haproxy_extra_services:
- service:
haproxy_service_name: extra-web-service
haproxy_backend_nodes: "{{ groups['service_group'] | default([]) }}"
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10000
haproxy_balance_type: http
# If backend connections should be secured with SSL (default False)
haproxy_backend_ssl: True
haproxy_backend_ca: /path/to/ca/cert.pem
# Or to use system CA for validation
# haproxy_backend_ca: True
# Or if certificate validation should be disabled
# haproxy_backend_ca: False
- haproxy_service_name: extra-web-service
haproxy_backend_nodes: "{{ groups['service_group'] | default([]) }}"
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10000
haproxy_balance_type: http
# If backend connections should be secured with SSL (default False)
haproxy_backend_ssl: True
haproxy_backend_ca: /path/to/ca/cert.pem
# Or to use system CA for validation
# haproxy_backend_ca: True
# Or if certificate validation should be disabled
# haproxy_backend_ca: False
Additionally, you can specify haproxy services that are not managed
in the Ansible inventory by manually specifying their hostnames/IP Addresses:
@ -289,18 +286,17 @@ in the Ansible inventory by manually specifying their hostnames/IP Addresses:
.. code-block:: yaml
haproxy_extra_services:
- service:
haproxy_service_name: extra-non-inventory-service
haproxy_backend_nodes:
- name: nonInvHost01
ip_addr: 172.0.1.1
- name: nonInvHost02
ip_addr: 172.0.1.2
- name: nonInvHost03
ip_addr: 172.0.1.3
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10001
haproxy_balance_type: http
- haproxy_service_name: extra-non-inventory-service
haproxy_backend_nodes:
- name: nonInvHost01
ip_addr: 172.0.1.1
- name: nonInvHost02
ip_addr: 172.0.1.2
- name: nonInvHost03
ip_addr: 172.0.1.3
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10001
haproxy_balance_type: http
Adding additional global VIP addresses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -355,14 +351,13 @@ Here is an example that shows how to achieve the goal
.. code-block:: yaml
- service:
haproxy_service_name: influxdb-relay
haproxy_acls:
write_queries:
rule: "path_sub -i write"
read_queries:
rule: "path_sub -i query"
backend_name: "influxdb"
- haproxy_service_name: influxdb-relay
haproxy_acls:
write_queries:
rule: "path_sub -i write"
read_queries:
rule: "path_sub -i query"
backend_name: "influxdb"
This will add two acl rules ``path_sub -i write`` and ``path_sub -i query`` to
the front end and use the backend specified in the rule. If no backend is specified
@ -374,12 +369,11 @@ backend service does not require its own corresponding front-end, the
.. code-block:: yaml
- service:
haproxy_service_name: influxdb
haproxy_backend_only: true # Directed by the 'influxdb-relay' service above
haproxy_backend_nodes:
- name: influxdb-service
ip_addr: 10.100.10.10
- haproxy_service_name: influxdb
haproxy_backend_only: true # Directed by the 'influxdb-relay' service above
haproxy_backend_nodes:
- name: influxdb-service
ip_addr: 10.100.10.10
Adding prometheus metrics to haproxy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -391,14 +385,13 @@ option:
.. code-block:: yaml
- service:
haproxy_service_name: prometheus-metrics
haproxy_port: 8404
haproxy_bind:
- '127.0.0.1'
haproxy_whitelist_networks: "{{ haproxy_whitelist_networks }}"
haproxy_frontend_only: True
haproxy_frontend_raw:
- 'http-request use-service prometheus-exporter if { path /metrics }'
haproxy_service_enabled: True
haproxy_balance_type: 'http'
- haproxy_service_name: prometheus-metrics
haproxy_port: 8404
haproxy_bind:
- '127.0.0.1'
haproxy_whitelist_networks: "{{ haproxy_whitelist_networks }}"
haproxy_frontend_only: True
haproxy_frontend_raw:
- 'http-request use-service prometheus-exporter if { path /metrics }'
haproxy_service_enabled: True
haproxy_balance_type: 'http'

View File

@ -6,15 +6,14 @@
- { role: "haproxy_server", tags: [ "haproxy-server" ] }
vars:
haproxy_service_configs:
- service:
haproxy_service_name: group_name
haproxy_backend_nodes: "{{ groups['group_name'][0] }}"
haproxy_backup_nodes: "{{ groups['group_name'][1:] }}"
haproxy_port: 80
haproxy_balance_type: http
haproxy_backend_options:
- "forwardfor"
- "httpchk"
- "httplog"
haproxy_backend_arguments:
- 'http-check expect string OK'
- haproxy_service_name: group_name
haproxy_backend_nodes: "{{ groups['group_name'][0] }}"
haproxy_backup_nodes: "{{ groups['group_name'][1:] }}"
haproxy_port: 80
haproxy_balance_type: http
haproxy_backend_options:
- "forwardfor"
- "httpchk"
- "httplog"
haproxy_backend_arguments:
- 'http-check expect string OK'

View File

@ -0,0 +1,8 @@
---
deprecations:
- |
``haproxy_service_configs`` format was simplified.
Now it's just a list of dicts. Usage of ``service`` key
in ``haproxy_service_configs`` elements is deprecated and will be
removed in 2023.2 release.

View File

@ -21,29 +21,39 @@
- name: Create haproxy service config files
template:
src: service.j2
dest: "/etc/haproxy/conf.d/{{ item.service.haproxy_service_name }}"
with_items: "{{ haproxy_service_configs }}"
dest: "/etc/haproxy/conf.d/{{ service.haproxy_service_name }}"
# NOTE(damiandabrowski): Deprecated haproxy_service_configs format
# conversion will be removed in 2024.1.
# loop: "{{ haproxy_service_configs }}"
loop: "{{ haproxy_service_configs[0].service is defined | ternary(haproxy_service_configs | map(attribute='service'), haproxy_service_configs) | list }}"
loop_control:
loop_var: service
when:
- (item.service.haproxy_backend_nodes is defined and
item.service.haproxy_backend_nodes | length > 0) or
(item.service.haproxy_backup_nodes is defined and
item.service.haproxy_backup_nodes | length > 0) or
item.service.haproxy_frontend_only | default('False')
- (item.service.haproxy_service_enabled | default('True')) | bool
- (item.service.state is not defined or item.service.state != 'absent')
- (service.haproxy_backend_nodes is defined and
service.haproxy_backend_nodes | length > 0) or
(service.haproxy_backup_nodes is defined and
service.haproxy_backup_nodes | length > 0) or
service.haproxy_frontend_only | default('False')
- (service.haproxy_service_enabled | default('True')) | bool
- (service.state is not defined or service.state != 'absent')
notify: Regenerate haproxy configuration
tags:
- haproxy-service-config
- name: Remove haproxy service config files for absent services
file:
path: "/etc/haproxy/conf.d/{{ item.service.haproxy_service_name }}"
path: "/etc/haproxy/conf.d/{{ service.haproxy_service_name }}"
state: absent
notify: Regenerate haproxy configuration
with_items: "{{ haproxy_service_configs }}"
# NOTE(damiandabrowski): Deprecated haproxy_service_configs format
# conversion will be removed in 2024.1.
# loop: "{{ haproxy_service_configs }}"
loop: "{{ haproxy_service_configs[0].service is defined | ternary(haproxy_service_configs | map(attribute='service'), haproxy_service_configs) | list }}"
loop_control:
loop_var: service
when:
- ((item.service.haproxy_service_enabled | default('True')) | bool) is falsy or
(item.service.state is defined and item.service.state == 'absent')
- ((service.haproxy_service_enabled | default('True')) | bool) is falsy or
(service.state is defined and service.state == 'absent')
tags:
- haproxy-service-config
@ -55,20 +65,20 @@
file:
state: directory
path: "/etc/haproxy/map.conf.d/{{ item }}"
with_items: "{{ haproxy_service_configs | selectattr('service.haproxy_map_entries', 'defined') | map(attribute='service.haproxy_map_entries') | flatten | map(attribute='name') | unique }}"
with_items: "{{ haproxy_service_configs | selectattr('haproxy_map_entries', 'defined') | map(attribute='haproxy_map_entries') | flatten | map(attribute='name') | unique }}"
# create map entries when the service is enabled and an existing map fragment is not absent
- name: Create haproxy map files
vars:
map_file: "/etc/haproxy/map.conf.d/{{ item.1.name }}/{{ item.1.order | default('00') }}-{{ item.0.service.haproxy_service_name }}.map"
map_file: "/etc/haproxy/map.conf.d/{{ item.1.name }}/{{ item.1.order | default('00') }}-{{ item.0.haproxy_service_name }}.map"
template:
src: map.j2
dest: "{{ map_file }}"
with_subelements:
- "{{ haproxy_service_configs | selectattr('service.haproxy_map_entries', 'defined') }}"
- service.haproxy_map_entries
- "{{ haproxy_service_configs | selectattr('haproxy_map_entries', 'defined') }}"
- haproxy_map_entries
when:
- (item.0.service.haproxy_service_enabled | default(True)) | bool
- (item.0.haproxy_service_enabled | default(True)) | bool
- item.1.state | default('present') != 'absent'
notify: regenerate maps
register: map_create
@ -77,13 +87,13 @@
- name: Delete unused map entries
file:
state: absent
path: "/etc/haproxy/map.conf.d/{{ item.1.name }}/{{ item.1.order | default('00') }}-{{ item.0.service.haproxy_service_name }}.map"
path: "/etc/haproxy/map.conf.d/{{ item.1.name }}/{{ item.1.order | default('00') }}-{{ item.0.haproxy_service_name }}.map"
when:
- (item.0.service.haproxy_service_enabled | default('True')) | bool is falsy or
(item.0.service.state is defined and item.0.service.state == 'absent') or
- (item.0.haproxy_service_enabled | default('True')) | bool is falsy or
(item.0.state is defined and item.0.state == 'absent') or
(item.1.state | default('present') == 'absent')
with_subelements:
- "{{ haproxy_service_configs | selectattr('service.haproxy_map_entries', 'defined') }}"
- service.haproxy_map_entries
- "{{ haproxy_service_configs | selectattr('haproxy_map_entries', 'defined') }}"
- haproxy_map_entries
notify: regenerate maps
register: map_delete

View File

@ -59,7 +59,7 @@
tags:
- haproxy_server-config
# NOTE(jrosser) we must reload the haproxy config before doing the first time certbot setup to ensure the letsencypt backend is configured
# NOTE(jrosser) we must reload the haproxy config before doing the first time certbot setup to ensure the letsencypt backend is configured
- meta: flush_handlers
- include_tasks: haproxy_ssl_letsencrypt.yml

View File

@ -1,24 +1,24 @@
# {{ ansible_managed }}
{% set request_option = item.service.haproxy_balance_type | default("http") -%}
{% if item.service.haproxy_backend_port is not defined %}
{% set haproxy_backend_port = item.service.haproxy_port %}
{% set request_option = service.haproxy_balance_type | default("http") -%}
{% if service.haproxy_backend_port is not defined %}
{% set haproxy_backend_port = service.haproxy_port %}
{% else %}
{% set haproxy_backend_port = item.service.haproxy_backend_port %}
{% set haproxy_backend_port = service.haproxy_backend_port %}
{% endif -%}
{% if item.service.haproxy_check_port is not defined %}
{% if service.haproxy_check_port is not defined %}
{% set haproxy_check_port = haproxy_backend_port %}
{% else %}
{% set haproxy_check_port = item.service.haproxy_check_port %}
{% set haproxy_check_port = service.haproxy_check_port %}
{% endif -%}
{% if item.service.haproxy_bind is defined %}
{% set vip_binds = item.service.haproxy_bind %}
{% if service.haproxy_bind is defined %}
{% set vip_binds = service.haproxy_bind %}
{% else %}
{% set vip_binds = haproxy_tls_vip_binds + extra_lb_vip_addresses %}
{% endif %}
{% if not item.service.haproxy_backend_only | default(false) %}
{% if not service.haproxy_backend_only | default(false) %}
{% for vip_bind in vip_binds %}
{% if vip_bind is not string and vip_bind is mapping %}
{% set vip_address = vip_bind['address'] %}
@ -27,17 +27,17 @@
{% set vip_address = vip_bind %}
{% set vip_interface = '' %}
{% endif %}
{% if item.service.haproxy_redirect_http_port is defined and item.service.haproxy_ssl %}
{% if (loop.index == 1 or item.service.haproxy_ssl_all_vips | default(false) | bool) %}
{% if service.haproxy_redirect_http_port is defined and service.haproxy_ssl %}
{% if (loop.index == 1 or service.haproxy_ssl_all_vips | default(false) | bool) %}
frontend {{ item.service.haproxy_service_name }}-redirect-front-{{ loop.index }}
bind {{ vip_address }}:{{ item.service.haproxy_redirect_http_port }}{{ (vip_interface is truthy) | ternary(' interface ' ~ vip_interface, '') }}
frontend {{ service.haproxy_service_name }}-redirect-front-{{ loop.index }}
bind {{ vip_address }}:{{ service.haproxy_redirect_http_port }}{{ (vip_interface is truthy) | ternary(' interface ' ~ vip_interface, '') }}
mode http
redirect scheme {{ item.service.haproxy_redirect_scheme | default('https if !{ ssl_fc }') }}
{% if item.service.haproxy_frontend_acls is defined %}
{% for key, value in item.service.haproxy_frontend_acls.items() %}
redirect scheme {{ service.haproxy_redirect_scheme | default('https if !{ ssl_fc }') }}
{% if service.haproxy_frontend_acls is defined %}
{% for key, value in service.haproxy_frontend_acls.items() %}
acl {{ key }} {{ value.rule }}
use_backend {{ value.backend_name | default(item.service.haproxy_service_name) }}-back if {{ key }}
use_backend {{ value.backend_name | default(service.haproxy_service_name) }}-back if {{ key }}
{% endfor %}
{% for entry in haproxy_frontend_redirect_extra_raw %}
{{ entry }}
@ -48,66 +48,66 @@ bind {{ vip_address }}:{{ item.service.haproxy_redirect_http_port }}{{ (vip_inte
{# TODO: remove if and section inside if after HTTPS upgrade #}
{# During an upgrade of internal frontends from HTTP to HTTPS, need to accept both HTTP and HTTPS until client config has been changed #}
{% if (item.service.haproxy_tcp_upgrade_frontend | default(false)) and (item.service.haproxy_ssl_all_vips | default(false)) %}
{% if (service.haproxy_tcp_upgrade_frontend | default(false)) and (service.haproxy_ssl_all_vips | default(false)) %}
{% include 'service-redirect.j2' %}
{% else %}
frontend {{ item.service.haproxy_service_name }}-front-{{ loop.index }}
bind {{ vip_address }}:{{ item.service.haproxy_port }}{{ (vip_interface is truthy) | ternary(' interface ' ~ vip_interface, '') }} {% if (item.service.haproxy_ssl | default(false) | bool) and (loop.index == 1 or vip_address in extra_lb_tls_vip_addresses or (item.service.haproxy_ssl_all_vips | default(false) | bool and vip_address not in extra_lb_vip_addresses)) %}ssl crt {{ haproxy_ssl_cert_path }}/haproxy_{{ ansible_facts['hostname'] }}-{{ (vip_interface is truthy) | ternary(vip_address ~ '-' ~ vip_interface, vip_address) }}.pem {% endif %}
frontend {{ service.haproxy_service_name }}-front-{{ loop.index }}
bind {{ vip_address }}:{{ service.haproxy_port }}{{ (vip_interface is truthy) | ternary(' interface ' ~ vip_interface, '') }} {% if (service.haproxy_ssl | default(false) | bool) and (loop.index == 1 or vip_address in extra_lb_tls_vip_addresses or (service.haproxy_ssl_all_vips | default(false) | bool and vip_address not in extra_lb_vip_addresses)) %}ssl crt {{ haproxy_ssl_cert_path }}/haproxy_{{ haproxy_host | default(ansible_facts['hostname']) }}-{{ (vip_interface is truthy) | ternary(vip_address ~ '-' ~ vip_interface, vip_address) }}.pem {% endif %}
{% if request_option == "http" %}
option httplog
option forwardfor except 127.0.0.0/8
{% if item.service.haproxy_http_keepalive_mode is defined %}
option {{ item.service.haproxy_http_keepalive_mode }}
{% if service.haproxy_http_keepalive_mode is defined %}
option {{ service.haproxy_http_keepalive_mode }}
{% endif %}
{% elif request_option == "tcp" %}
option tcplog
{% endif %}
{% if item.service.haproxy_timeout_client is defined %}
timeout client {{ item.service.haproxy_timeout_client }}
{% if service.haproxy_timeout_client is defined %}
timeout client {{ service.haproxy_timeout_client }}
{% endif %}
{% if item.service.haproxy_allowlist_networks is defined %}
acl allow_list src 127.0.0.1/8 {{ item.service.haproxy_allowlist_networks | join(' ') }}
{% if service.haproxy_allowlist_networks is defined %}
acl allow_list src 127.0.0.1/8 {{ service.haproxy_allowlist_networks | join(' ') }}
tcp-request content accept if allow_list
tcp-request content reject
{% endif %}
{% if item.service.haproxy_acls is defined %}
{% for key, value in item.service.haproxy_acls.items() %}
{% if service.haproxy_acls is defined %}
{% for key, value in service.haproxy_acls.items() %}
acl {{ key }} {{ value.rule }}
{% if not item.service.haproxy_frontend_only | default(false) %}
use_backend {{ value.backend_name | default(item.service.haproxy_service_name) }}-back if {{ key }}
{% if not service.haproxy_frontend_only | default(false) %}
use_backend {{ value.backend_name | default(service.haproxy_service_name) }}-back if {{ key }}
{% endif %}
{% endfor %}
{% endif %}
{% for entry in item.service.haproxy_maps | default([]) %}
{% for entry in service.haproxy_maps | default([]) %}
{{ entry }}
{% endfor %}
{% if (item.service.haproxy_ssl | default(false) | bool) and request_option == 'http' and (loop.index == 1 or vip_address in extra_lb_tls_vip_addresses or (item.service.haproxy_ssl_all_vips | default(false) | bool and vip_address not in extra_lb_vip_addresses)) %}
{% if (service.haproxy_ssl | default(false) | bool) and request_option == 'http' and (loop.index == 1 or vip_address in extra_lb_tls_vip_addresses or (service.haproxy_ssl_all_vips | default(false) | bool and vip_address not in extra_lb_vip_addresses)) %}
http-request add-header X-Forwarded-Proto https
{% endif %}
mode {{ item.service.haproxy_balance_type }}
{% if (not item.service.haproxy_frontend_only | default(false)) or ((item.service.haproxy_default_backend is defined) and (item.service.haproxy_default_backend | length > 0)) %}
default_backend {{ item.service.haproxy_default_backend | default(item.service.haproxy_service_name) }}-back
mode {{ service.haproxy_balance_type }}
{% if (not service.haproxy_frontend_only | default(false)) or ((service.haproxy_default_backend is defined) and (service.haproxy_default_backend | length > 0)) %}
default_backend {{ service.haproxy_default_backend | default(service.haproxy_service_name) }}-back
{% endif %}
{% for entry in (item.service.haproxy_frontend_raw|default([])) + haproxy_frontend_extra_raw %}
{% for entry in (service.haproxy_frontend_raw|default([])) + haproxy_frontend_extra_raw %}
{{ entry }}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% if not item.service.haproxy_frontend_only | default(false) %}
{% set backend_options = item.service.haproxy_backend_options|default([]) %}
{% set backend_arguments = item.service.haproxy_backend_arguments|default([]) %}
{% if not service.haproxy_frontend_only | default(false) %}
{% set backend_options = service.haproxy_backend_options|default([]) %}
{% set backend_arguments = service.haproxy_backend_arguments|default([]) %}
backend {{ item.service.haproxy_service_name }}-back
mode {{ item.service.haproxy_balance_type }}
balance {{ item.service.haproxy_balance_alg|default("leastconn") }}
{% if item.service.haproxy_timeout_server is defined %}
timeout server {{ item.service.haproxy_timeout_server }}
backend {{ service.haproxy_service_name }}-back
mode {{ service.haproxy_balance_type }}
balance {{ service.haproxy_balance_alg|default("leastconn") }}
{% if service.haproxy_timeout_server is defined %}
timeout server {{ service.haproxy_timeout_server }}
{% endif %}
{% if (item.service.haproxy_stick_table_enabled | default(true) | bool) %}
{% set stick_table = item.service.haproxy_stick_table|default( haproxy_stick_table | default([])) %}
{% if (service.haproxy_stick_table_enabled | default(true) | bool) %}
{% set stick_table = service.haproxy_stick_table|default( haproxy_stick_table | default([])) %}
{% for entry in stick_table %}
{{ entry }}
{% endfor %}
@ -121,13 +121,13 @@ backend {{ item.service.haproxy_service_name }}-back
{% for argument in backend_arguments %}
{{ argument }}
{% endfor %}
{% set backend_httpcheck_options = item.service.haproxy_backend_httpcheck_options|default([]) %}
{% set backend_httpcheck_options = service.haproxy_backend_httpcheck_options|default([]) %}
{% for option in backend_httpcheck_options %}
http-check {{ option }}
{% endfor %}
{% for host_name in item.service.haproxy_backend_nodes %}
{% for host_name in service.haproxy_backend_nodes %}
{% if hostvars[host_name] is defined %}
{% set ip_addr = hostvars[host_name]['ansible_host'] %}
{% endif %}
@ -139,24 +139,24 @@ backend {{ item.service.haproxy_service_name }}-back
{% set _ = entry.append("port") %}
{% set _ = entry.append(haproxy_check_port | string) %}
{% set _ = entry.append("inter") %}
{% set _ = entry.append(item.service.interval|default(haproxy_interval) | string) %}
{% set _ = entry.append(service.interval|default(haproxy_interval) | string) %}
{% set _ = entry.append("rise") %}
{% set _ = entry.append(item.service.backend_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append(service.backend_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append("fall") %}
{% set _ = entry.append(item.service.backend_fall|default(haproxy_fall | string)) %}
{% if item.service.haproxy_backend_ssl | default(False) %}
{% set _ = entry.append(service.backend_fall|default(haproxy_fall | string)) %}
{% if service.haproxy_backend_ssl | default(False) %}
{% set _ = entry.append("ssl") %}
{% if item.service.haproxy_backend_ssl_check | default(item.service.haproxy_backend_ssl) %}
{% if service.haproxy_backend_ssl_check | default(service.haproxy_backend_ssl) %}
{% set _ = entry.append("check-ssl") %}
{% endif %}
{% if item.service.haproxy_backend_ca %}
{% if service.haproxy_backend_ca %}
{% set _ = entry.append("ca-file") %}
{% set _ = entry.append(item.service.haproxy_backend_ca is string | ternary(item.service.haproxy_backend_ca, haproxy_system_ca)) %}
{% set _ = entry.append(service.haproxy_backend_ca is string | ternary(service.haproxy_backend_ca, haproxy_system_ca)) %}
{% else %}
{% set _ = entry.append("verify none") %}
{% endif %}
{% endif %}
{% set backend_server_options = item.service.haproxy_backend_server_options|default([]) %}
{% set backend_server_options = service.haproxy_backend_server_options|default([]) %}
{% for option in backend_server_options %}
{% set _ = entry.append(option) %}
{% endfor %}
@ -167,7 +167,7 @@ backend {{ item.service.haproxy_service_name }}-back
{{ entry | join(' ') }}
{# TODO: remove if and section inside if after HTTPS upgrade #}
{# During an upgrade of backends from HTTP to HTTPS, need to uses both HTTP and HTTPS backends until backends have been changed #}
{% if item.service.haproxy_tcp_upgrade_backend | default(false) and item.service.haproxy_backend_ssl | default(false) %}
{% if service.haproxy_tcp_upgrade_backend | default(false) and service.haproxy_backend_ssl | default(false) %}
{% set entry = [] %}
{% set _ = entry.append("server") %}
{% set _ = entry.append((host_name.name | default(host_name)) + "-http" | string) %}
@ -176,12 +176,12 @@ backend {{ item.service.haproxy_service_name }}-back
{% set _ = entry.append("port") %}
{% set _ = entry.append(haproxy_check_port | string) %}
{% set _ = entry.append("inter") %}
{% set _ = entry.append(item.service.interval|default(haproxy_interval) | string) %}
{% set _ = entry.append(service.interval|default(haproxy_interval) | string) %}
{% set _ = entry.append("rise") %}
{% set _ = entry.append(item.service.backend_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append(service.backend_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append("fall") %}
{% set _ = entry.append(item.service.backend_fall|default(haproxy_fall | string)) %}
{% set backend_server_options = item.service.haproxy_backend_server_options|default([]) %}
{% set _ = entry.append(service.backend_fall|default(haproxy_fall | string)) %}
{% set backend_server_options = service.haproxy_backend_server_options|default([]) %}
{% for option in backend_server_options %}
{% set _ = entry.append(option) %}
{% endfor %}
@ -193,7 +193,7 @@ backend {{ item.service.haproxy_service_name }}-back
{% endif %}
{% endfor %}
{% for host_name in item.service.haproxy_backup_nodes|default([]) %}
{% for host_name in service.haproxy_backup_nodes|default([]) %}
{% if hostvars[host_name] is defined %}
{% set ip_addr = hostvars[host_name]['ansible_host'] %}
{% endif %}
@ -207,23 +207,23 @@ backend {{ item.service.haproxy_service_name }}-back
{% set _ = entry.append("inter") %}
{% set _ = entry.append(haproxy_interval | string) %}
{% set _ = entry.append("rise") %}
{% set _ = entry.append(item.service.backup_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append(service.backup_rise|default(haproxy_rise | string)) %}
{% set _ = entry.append("fall") %}
{% set _ = entry.append(item.service.backup_fall|default(haproxy_fall | string)) %}
{% set _ = entry.append(service.backup_fall|default(haproxy_fall | string)) %}
{% set _ = entry.append("backup") %}
{% if item.service.haproxy_backend_ssl | default(False) %}
{% if service.haproxy_backend_ssl | default(False) %}
{% set _ = entry.append("ssl") %}
{% if item.service.haproxy_backend_ssl_check | default(item.service.haproxy_backend_ssl) %}
{% if service.haproxy_backend_ssl_check | default(service.haproxy_backend_ssl) %}
{% set _ = entry.append("check-ssl") %}
{% endif %}
{% if item.service.haproxy_backend_ca %}
{% if service.haproxy_backend_ca %}
{% set _ = entry.append("ca-file") %}
{% set _ = entry.append(item.service.haproxy_backend_ca is string | ternary(item.service.haproxy_backend_ca, haproxy_system_ca)) %}
{% set _ = entry.append(service.haproxy_backend_ca is string | ternary(service.haproxy_backend_ca, haproxy_system_ca)) %}
{% else %}
{% set _ = entry.append("verify none") %}
{% endif %}
{% endif %}
{% set backend_server_options = item.service.haproxy_backend_server_options|default([]) %}
{% set backend_server_options = service.haproxy_backend_server_options|default([]) %}
{% for option in backend_server_options %}
{% set _ = entry.append(option) %}
{% endfor %}