Add support for haproxy map files
HAProxy supports the use of map files for selecting backends, or a number of other functions. See [1] and [2]. This patch adds the key `maps` for each service definition allowing fragments of a complete map to be defined across all the services, with each service contributing some elements to the overall map file. The service enabled/disabled and state flags are observed to add and remove entries from the map file, and individual map entries can also be marked as present/absent to make inclusion conditional. [1] https://www.haproxy.com/blog/introduction-to-haproxy-maps/ [2] https://www.haproxy.com/documentation/hapee/latest/configuration/map-files/syntax/ Change-Id: I755c18a4d33ee69c42d68a50daa63614a2b2feb7
This commit is contained in:
parent
56fef3de83
commit
d548b7e5ff
|
@ -90,6 +90,48 @@ haproxy_service_configs: []
|
|||
# haproxy_service_enabled: True
|
||||
# haproxy_default_backend: other_backend
|
||||
|
||||
# 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
|
||||
#
|
||||
# Results:
|
||||
#
|
||||
# /etc/haproxy/route.map
|
||||
# s3.example.com radosgw
|
||||
# sso.example.com keycloak
|
||||
# compute.example.com nova-api
|
||||
# dashboard.example.com horizon
|
||||
#
|
||||
# /etc/haproxy/rate.map
|
||||
# /api/foo 20
|
||||
# /api/bar 40
|
||||
|
||||
galera_monitoring_user: monitoring
|
||||
haproxy_bind_on_non_local: False
|
||||
|
||||
|
|
|
@ -25,6 +25,15 @@
|
|||
listen:
|
||||
- cert installed
|
||||
|
||||
- name: regenerate maps
|
||||
vars:
|
||||
all_changed_results: "{{ (map_create.results + map_delete.results) | select('changed') }}"
|
||||
assemble:
|
||||
src: "/etc/haproxy/map.conf.d/{{ item }}"
|
||||
dest: "/etc/haproxy/{{ item }}.map"
|
||||
notify: Reload haproxy
|
||||
with_items: "{{ all_changed_results | map(attribute='item') | flatten | selectattr('name', 'defined') | map(attribute='name') | unique }}"
|
||||
|
||||
- name: Regenerate haproxy configuration
|
||||
assemble:
|
||||
src: "/etc/haproxy/conf.d"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
A new key `haproxy_map_entries` is now able to be configured for each
|
||||
haproxy service definition to allow arbitrary entries to be placed in
|
||||
any number of haproxy map files which may then be referenced in other
|
||||
directives in the haproxy config file such as ``use_backend`` or
|
||||
``http-request``. The complete map files are constructed from the
|
||||
fragments defined across all the service definitions and are assembled
|
||||
into a complete map file in alphanumeric sort order, or optionally with
|
||||
a user defined ordering.
|
|
@ -13,6 +13,11 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Service frontends and backends assembled from fragments into haproxy.conf
|
||||
###########################################################################
|
||||
|
||||
- name: Create haproxy service config files
|
||||
template:
|
||||
src: service.j2
|
||||
|
@ -41,3 +46,44 @@
|
|||
(item.service.state is defined and item.service.state == 'absent')
|
||||
tags:
|
||||
- haproxy-service-config
|
||||
|
||||
###########################################################################
|
||||
# Map files assembled from fragments from each service into <map-name>.map
|
||||
###########################################################################
|
||||
|
||||
- name: Create haproxy map fragment directories
|
||||
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 }}"
|
||||
|
||||
# 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"
|
||||
template:
|
||||
src: map.j2
|
||||
dest: "{{ map_file }}"
|
||||
with_subelements:
|
||||
- "{{ haproxy_service_configs | selectattr('service.haproxy_map_entries', 'defined') }}"
|
||||
- service.haproxy_map_entries
|
||||
when:
|
||||
- (item.0.service.haproxy_service_enabled | default(True)) | bool
|
||||
- item.1.state | default('present') != 'absent'
|
||||
notify: regenerate maps
|
||||
register: map_create
|
||||
|
||||
# remove map entries when the service is not enabled, the service is absent or the map is absent
|
||||
- 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"
|
||||
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.1.state | default('present') == 'absent')
|
||||
with_subelements:
|
||||
- "{{ haproxy_service_configs | selectattr('service.haproxy_map_entries', 'defined') }}"
|
||||
- service.haproxy_map_entries
|
||||
notify: regenerate maps
|
||||
register: map_delete
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{% for m in item.1.entries %}
|
||||
{{ m }}
|
||||
{% endfor %}
|
|
@ -79,6 +79,9 @@ frontend {{ item.service.haproxy_service_name }}-front-{{ loop.index }}
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% for entry in item.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)) %}
|
||||
http-request add-header X-Forwarded-Proto https
|
||||
{% endif %}
|
||||
|
|
Loading…
Reference in New Issue