From a5f285c51eab07b70f6f709f1f93d047b09b17f6 Mon Sep 17 00:00:00 2001 From: Damian Dabrowski Date: Thu, 19 Jan 2023 22:41:25 +0100 Subject: [PATCH] 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 --- defaults/main.yml | 118 +++++++------- doc/source/configure-haproxy.rst | 149 +++++++++--------- examples/playbook.yml | 23 ++- ...rated-haproxy-config-b38d200ee0baaeac.yaml | 8 + tasks/haproxy_service_config.yml | 56 ++++--- tasks/main.yml | 2 +- templates/service.j2 | 138 ++++++++-------- 7 files changed, 249 insertions(+), 245 deletions(-) create mode 100644 releasenotes/notes/separated-haproxy-config-b38d200ee0baaeac.yaml diff --git a/defaults/main.yml b/defaults/main.yml index b8ced74..240c002 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -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: # diff --git a/doc/source/configure-haproxy.rst b/doc/source/configure-haproxy.rst index ea2cf86..51b57ad 100644 --- a/doc/source/configure-haproxy.rst +++ b/doc/source/configure-haproxy.rst @@ -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' diff --git a/examples/playbook.yml b/examples/playbook.yml index eb67de6..90912d8 100644 --- a/examples/playbook.yml +++ b/examples/playbook.yml @@ -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' diff --git a/releasenotes/notes/separated-haproxy-config-b38d200ee0baaeac.yaml b/releasenotes/notes/separated-haproxy-config-b38d200ee0baaeac.yaml new file mode 100644 index 0000000..b5878cf --- /dev/null +++ b/releasenotes/notes/separated-haproxy-config-b38d200ee0baaeac.yaml @@ -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. + diff --git a/tasks/haproxy_service_config.yml b/tasks/haproxy_service_config.yml index e7ee560..4dd67fd 100644 --- a/tasks/haproxy_service_config.yml +++ b/tasks/haproxy_service_config.yml @@ -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 diff --git a/tasks/main.yml b/tasks/main.yml index fc17faa..ac1a3c0 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -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 diff --git a/templates/service.j2 b/templates/service.j2 index 543d97f..22ffe47 100644 --- a/templates/service.j2 +++ b/templates/service.j2 @@ -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 %}