haproxy: frontend/backend syntax in config
Ability to generate haproxy config with the frontend/backend sections rather than the old listen section. This allows the generation of complex configs, such as for example giving priority to local backends when routing traffic. Make the new syntax configurable via a new hiera key `haproxy_backend_syntax`. The frontend and backend config of each service can be further tweaked via additional keys tripleo::haproxy::<service>::frontend_options and tripleo::haproxy::<service>::backend_options By default, keep the current 'listen' syntax. Tested with capability disabled, the haproxy config generated for undercloud and ha overcloud doesn't change. Tested with capability enabled, tempest smoke test passed. Closes-Bug: #1941617 Change-Id: Ieb36f90c6709934aa3aa6668d3929bff872c30f5
This commit is contained in:
parent
688a80c255
commit
7a6c5281e0
|
@ -0,0 +1,30 @@
|
|||
# This function merges two hashes and concatenate the values of
|
||||
# identical keys
|
||||
#
|
||||
# Example:
|
||||
# $frontend = { 'option' => [ 'tcpka', 'tcplog' ],
|
||||
# 'timeout client' => '90m' }
|
||||
# $backend = { 'option' => [ 'httpchk' ],
|
||||
# 'timeout server' => '90m' }
|
||||
#
|
||||
# Using this function:
|
||||
# $merge = merge_hash_values($frontend, $backend)
|
||||
#
|
||||
# Would return:
|
||||
# $merge = { 'option' => [ 'tcpka', 'tcplog', 'httpchk' ],
|
||||
# 'timeout client' => '90m',
|
||||
# 'timeout server' => '90m' }
|
||||
#
|
||||
|
||||
Puppet::Functions.create_function(:'merge_hash_values') do
|
||||
dispatch :merge_hash_values do
|
||||
param 'Hash', :hash1
|
||||
param 'Hash', :hash2
|
||||
return_type 'Hash'
|
||||
end
|
||||
|
||||
def merge_hash_values(hash1, hash2)
|
||||
hh = hash1.merge(hash2) {|k, v1, v2| (v2 + v1).uniq()}
|
||||
return hh
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,11 @@
|
|||
# Options for the balancer member, specified after the server declaration.
|
||||
# These should go in the member's configuration block.
|
||||
#
|
||||
# [*use_backend_syntax*]
|
||||
# (optional) When set to true, generate a config with frontend and
|
||||
# backend sections, otherwise use listen sections.
|
||||
# Defaults to hiera('haproxy_backend_syntax', false)
|
||||
#
|
||||
# [*haproxy_port*]
|
||||
# An alternative port, on which haproxy will listen for incoming requests.
|
||||
# Defaults to service_port.
|
||||
|
@ -65,6 +70,14 @@
|
|||
# HAproxy terms, the frontend).
|
||||
# defaults to {'option' => []}
|
||||
#
|
||||
# [*frontend_options*]
|
||||
# Options specified for the frontend service's configuration block
|
||||
# defaults to {'option' => []}
|
||||
#
|
||||
# [*backend_options*]
|
||||
# Options specified for the service's backend configuration block
|
||||
# defaults to {'option' => []}
|
||||
#
|
||||
# [*public_ssl_port*]
|
||||
# The port used for the public proxy endpoint if it differs from the default
|
||||
# one. This is used only if SSL is enabled, and it's used in order to avoid
|
||||
|
@ -119,6 +132,7 @@ define tripleo::haproxy::endpoint (
|
|||
$internal_ip,
|
||||
$service_port,
|
||||
$member_options,
|
||||
$use_backend_syntax = hiera('haproxy_backend_syntax', false),
|
||||
$haproxy_port = undef,
|
||||
$base_service_name = undef,
|
||||
$ip_addresses = hiera("${name}_node_ips", undef),
|
||||
|
@ -129,6 +143,12 @@ define tripleo::haproxy::endpoint (
|
|||
$listen_options = {
|
||||
'option' => [],
|
||||
},
|
||||
$frontend_options = {
|
||||
'option' => [],
|
||||
},
|
||||
$backend_options = {
|
||||
'option' => [],
|
||||
},
|
||||
$public_ssl_port = undef,
|
||||
$public_certificate = undef,
|
||||
$use_internal_certificates = false,
|
||||
|
@ -160,6 +180,8 @@ define tripleo::haproxy::endpoint (
|
|||
}
|
||||
# Let users override the options on a per-service basis
|
||||
$custom_options = hiera("tripleo::haproxy::${name}::options", undef)
|
||||
$custom_frontend_options = hiera("tripleo::haproxy::${name}::frontend_options", undef)
|
||||
$custom_backend_options = hiera("tripleo::haproxy::${name}::backend_options", undef)
|
||||
$custom_bind_options_public = delete(any2array(hiera("tripleo::haproxy::${name}::public_bind_options", undef)), undef).flatten()
|
||||
$custom_bind_options_internal = delete(any2array(hiera("tripleo::haproxy::${name}::internal_bind_options", undef)), undef).flatten()
|
||||
if $public_virtual_ip {
|
||||
|
@ -173,13 +195,16 @@ define tripleo::haproxy::endpoint (
|
|||
'option' => 'forwardfor',
|
||||
}
|
||||
$listen_options_precookie = merge($tls_listen_options, $listen_options, $custom_options)
|
||||
$frontend_options_precookie = merge($tls_listen_options, $frontend_options, $custom_frontend_options)
|
||||
} else {
|
||||
$listen_options_precookie = merge($listen_options, $custom_options)
|
||||
$frontend_options_precookie = merge($frontend_options, $custom_frontend_options)
|
||||
}
|
||||
$public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${public_ssl_port}"),
|
||||
union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate], $custom_bind_options_public))
|
||||
} else {
|
||||
$listen_options_precookie = merge($listen_options, $custom_options)
|
||||
$frontend_options_precookie = merge($frontend_options, $custom_frontend_options)
|
||||
$public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${haproxy_port_real}"),
|
||||
union($haproxy_listen_bind_param, $custom_bind_options_public))
|
||||
}
|
||||
|
@ -187,14 +212,17 @@ define tripleo::haproxy::endpoint (
|
|||
# internal service only
|
||||
$public_bind_opts = {}
|
||||
$listen_options_precookie = merge($listen_options, $custom_options)
|
||||
$frontend_options_precookie = merge($frontend_options, $custom_frontend_options)
|
||||
}
|
||||
if $sticky_sessions {
|
||||
$cookie_options = {
|
||||
'cookie' => "${session_cookie} insert indirect nocache",
|
||||
}
|
||||
$listen_options_real = merge($listen_options_precookie, $cookie_options)
|
||||
$frontend_options_real = merge($frontend_options_precookie, $cookie_options)
|
||||
} else {
|
||||
$listen_options_real = $listen_options_precookie
|
||||
$frontend_options_real = $frontend_options_precookie
|
||||
}
|
||||
if $use_internal_certificates {
|
||||
if !$service_network {
|
||||
|
@ -231,22 +259,45 @@ define tripleo::haproxy::endpoint (
|
|||
'acl' => "acl Auth${name} http_auth(${authorized_userlist})",
|
||||
'http-request' => "auth realm ${name} if !Auth${name}",
|
||||
}
|
||||
Haproxy::Listen[$name] {
|
||||
require => Tripleo::Haproxy::Userlist[$authorized_userlist],
|
||||
if $use_backend_syntax {
|
||||
Haproxy::Frontend[$name] {
|
||||
require => Tripleo::Haproxy::Userlist[$authorized_userlist],
|
||||
}
|
||||
} else {
|
||||
Haproxy::Listen[$name] {
|
||||
require => Tripleo::Haproxy::Userlist[$authorized_userlist],
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$access_rules = {}
|
||||
}
|
||||
|
||||
$_real_options = merge($listen_options_real, $access_rules)
|
||||
$_real_frontend_options = merge($frontend_options_real, $access_rules,
|
||||
{ 'default_backend' => "${name}_be" })
|
||||
|
||||
$bind_opts = merge($internal_bind_opts, $public_bind_opts)
|
||||
|
||||
haproxy::listen { "${name}":
|
||||
bind => $bind_opts,
|
||||
collect_exported => false,
|
||||
mode => $mode,
|
||||
options => $_real_options,
|
||||
if $use_backend_syntax {
|
||||
haproxy::frontend { "${name}":
|
||||
bind => $bind_opts,
|
||||
collect_exported => false,
|
||||
mode => $mode,
|
||||
options => $_real_frontend_options,
|
||||
}
|
||||
haproxy::backend { "${name}_be":
|
||||
mode => $mode,
|
||||
options => merge($backend_options, $custom_backend_options),
|
||||
}
|
||||
$listening_service = "${name}_be"
|
||||
} else {
|
||||
haproxy::listen { "${name}":
|
||||
bind => $bind_opts,
|
||||
collect_exported => false,
|
||||
mode => $mode,
|
||||
options => $_real_options,
|
||||
}
|
||||
$listening_service = "${name}"
|
||||
}
|
||||
if $sticky_sessions {
|
||||
hash(zip($ip_addresses_real, $server_names_real)).each | $ip, $server | {
|
||||
|
@ -254,7 +305,7 @@ define tripleo::haproxy::endpoint (
|
|||
# which is a reserved character to reference manifests
|
||||
$non_colon_ip = regsubst($ip, ':', '-', 'G')
|
||||
haproxy::balancermember { "${name}_${non_colon_ip}_${server}":
|
||||
listening_service => $name,
|
||||
listening_service => $listening_service,
|
||||
ports => $service_port_real,
|
||||
ipaddresses => $ip,
|
||||
server_names => $server,
|
||||
|
@ -263,7 +314,7 @@ define tripleo::haproxy::endpoint (
|
|||
}
|
||||
} else {
|
||||
haproxy::balancermember { "${name}":
|
||||
listening_service => $name,
|
||||
listening_service => $listening_service,
|
||||
ports => $service_port_real,
|
||||
ipaddresses => $ip_addresses_real,
|
||||
server_names => $server_names_real,
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
# If this service is internal only this should be ommitted.
|
||||
# Defaults to undef.
|
||||
#
|
||||
# [*use_backend_syntax*]
|
||||
# (optional) When set to true, generate a config with frontend and
|
||||
# backend sections, otherwise use listen sections.
|
||||
# Defaults to hiera('haproxy_backend_syntax', false)
|
||||
#
|
||||
# [*haproxy_listen_bind_param*]
|
||||
# A list of params to be added to the HAProxy listener bind directive.
|
||||
# Defaults to undef.
|
||||
|
@ -77,6 +82,7 @@ class tripleo::haproxy::horizon_endpoint (
|
|||
$server_names,
|
||||
$member_options,
|
||||
$public_virtual_ip,
|
||||
$use_backend_syntax = hiera('haproxy_backend_syntax', false),
|
||||
$haproxy_listen_bind_param = undef,
|
||||
$public_certificate = undef,
|
||||
$use_internal_certificates = false,
|
||||
|
@ -86,6 +92,8 @@ class tripleo::haproxy::horizon_endpoint (
|
|||
) {
|
||||
# Let users override the options on a per-service basis
|
||||
$custom_options = hiera('tripleo::haproxy::horizon::options', undef)
|
||||
$custom_frontend_options = hiera('tripleo::haproxy::horizon::frontend_options', undef)
|
||||
$custom_backend_options = hiera('tripleo::haproxy::horizon::backend_options', undef)
|
||||
$custom_bind_options_public = delete(any2array(hiera('tripleo::haproxy::horizon::public_bind_options', undef)), undef).flatten()
|
||||
$custom_bind_options_internal = delete(any2array(hiera('tripleo::haproxy::horizon::internal_bind_options', undef)), undef).flatten()
|
||||
# service exposed to the public network
|
||||
|
@ -120,26 +128,30 @@ class tripleo::haproxy::horizon_endpoint (
|
|||
"${public_virtual_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_public),
|
||||
"${public_virtual_ip}:443" => union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate], $custom_bind_options_public),
|
||||
}
|
||||
$horizon_options = merge({
|
||||
'cookie' => 'SERVERID insert indirect nocache',
|
||||
$horizon_frontend_options = {
|
||||
'rsprep' => '^Location:\ http://(.*) Location:\ https://\1',
|
||||
# NOTE(jaosorior): We always redirect to https for the public_virtual_ip.
|
||||
'redirect' => 'scheme https code 301 if !{ ssl_fc }',
|
||||
'option' => [ 'forwardfor', 'httpchk' ],
|
||||
'option' => [ 'forwardfor' ],
|
||||
'http-request' => [
|
||||
'set-header X-Forwarded-Proto https if { ssl_fc }',
|
||||
'set-header X-Forwarded-Proto http if !{ ssl_fc }'],
|
||||
}, $custom_options)
|
||||
}
|
||||
} else {
|
||||
$horizon_bind_opts = {
|
||||
"${internal_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_internal),
|
||||
"${public_virtual_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_public),
|
||||
}
|
||||
$horizon_options = merge({
|
||||
'cookie' => 'SERVERID insert indirect nocache',
|
||||
'option' => [ 'forwardfor', 'httpchk' ],
|
||||
}, $custom_options)
|
||||
$horizon_frontend_options = {
|
||||
'option' => [ 'forwardfor' ],
|
||||
}
|
||||
}
|
||||
$horizon_backend_options = {
|
||||
'cookie' => 'SERVERID insert indirect nocache',
|
||||
'option' => [ 'httpchk' ],
|
||||
}
|
||||
$horizon_options = merge_hash_values($horizon_backend_options,
|
||||
$horizon_frontend_options)
|
||||
|
||||
if $use_internal_certificates {
|
||||
# Use SSL port if TLS in the internal network is enabled.
|
||||
|
@ -148,18 +160,33 @@ class tripleo::haproxy::horizon_endpoint (
|
|||
$backend_port = '80'
|
||||
}
|
||||
|
||||
haproxy::listen { 'horizon':
|
||||
bind => $horizon_bind_opts,
|
||||
options => $horizon_options,
|
||||
mode => 'http',
|
||||
collect_exported => false,
|
||||
if $use_backend_syntax {
|
||||
haproxy::frontend { 'horizon':
|
||||
bind => $horizon_bind_opts,
|
||||
options => merge($horizon_frontend_options,
|
||||
{ default_backend => 'horizon_be' },
|
||||
$custom_frontend_options),
|
||||
mode => 'http',
|
||||
collect_exported => false,
|
||||
}
|
||||
haproxy::backend { 'horizon_be':
|
||||
options => merge($horizon_backend_options, $custom_backend_options),
|
||||
mode => 'http',
|
||||
}
|
||||
} else {
|
||||
haproxy::listen { 'horizon':
|
||||
bind => $horizon_bind_opts,
|
||||
options => merge($horizon_options, $custom_options),
|
||||
mode => 'http',
|
||||
collect_exported => false,
|
||||
}
|
||||
}
|
||||
hash(zip($ip_addresses, $server_names)).each | $ip, $server | {
|
||||
# We need to be sure the IP (IPv6) don't have colons
|
||||
# which is a reserved character to reference manifests
|
||||
$non_colon_ip = regsubst($ip, ':', '-', 'G')
|
||||
haproxy::balancermember { "horizon_${non_colon_ip}_${server}":
|
||||
listening_service => 'horizon',
|
||||
listening_service => 'horizon_be',
|
||||
ports => $backend_port,
|
||||
ipaddresses => $ip,
|
||||
server_names => $server,
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
# IP Address(es) on which the stats interface is listening on.
|
||||
# Can be a string or a list of ip addresses
|
||||
#
|
||||
# [*use_backend_syntax*]
|
||||
# (optional) When set to true, generate a config with frontend and
|
||||
# backend sections, otherwise use listen sections.
|
||||
# Defaults to hiera('haproxy_backend_syntax', false)
|
||||
#
|
||||
# [*port*]
|
||||
# Port on which to listen to for haproxy stats web interface
|
||||
# Defaults to '1993'
|
||||
|
@ -47,6 +52,7 @@
|
|||
class tripleo::haproxy::stats (
|
||||
$haproxy_listen_bind_param,
|
||||
$ip,
|
||||
$use_backend_syntax = hiera('haproxy_backend_syntax', false),
|
||||
$port = '1993',
|
||||
$password = undef,
|
||||
$certificate = undef,
|
||||
|
@ -66,12 +72,29 @@ class tripleo::haproxy::stats (
|
|||
} else {
|
||||
$stats_config = $stats_base
|
||||
}
|
||||
haproxy::listen { 'haproxy.stats':
|
||||
bind => $haproxy_stats_bind_opts,
|
||||
mode => 'http',
|
||||
options => {
|
||||
'stats' => $stats_config,
|
||||
},
|
||||
collect_exported => false,
|
||||
if $use_backend_syntax {
|
||||
haproxy::frontend { 'haproxy.stats':
|
||||
bind => $haproxy_stats_bind_opts,
|
||||
mode => 'http',
|
||||
options => {
|
||||
'stats' => $stats_config,
|
||||
},
|
||||
collect_exported => false,
|
||||
}
|
||||
haproxy::backend { 'haproxy.stats_be':
|
||||
mode => 'http',
|
||||
options => {
|
||||
'stats' => $stats_config,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
haproxy::listen { 'haproxy.stats':
|
||||
bind => $haproxy_stats_bind_opts,
|
||||
mode => 'http',
|
||||
options => {
|
||||
'stats' => $stats_config,
|
||||
},
|
||||
collect_exported => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Haproxy configuration file can now use the frontend and backend
|
||||
keywords to describe a service, rather than using the listen
|
||||
keyword. The new format can be enabled via hiera parameter
|
||||
`haproxy_backend_syntax`. When enabled, any frontend or backend
|
||||
configuration can be overriden on a per service-basis via new
|
||||
hiera keys `tripleo::haproxy::<service>::frontend_options` and
|
||||
`tripleo::haproxy::<service>::frontend_options`. The original
|
||||
hiera key `tripleo::haproxy::<service>::options` has no effect
|
||||
on the frontend and backend sections.
|
|
@ -75,6 +75,31 @@ describe 'tripleo::haproxy::endpoint' do
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with frontend/backend sections' do
|
||||
before :each do
|
||||
params.merge!({
|
||||
:use_backend_syntax => true,
|
||||
})
|
||||
end
|
||||
it 'should configure haproxy' do
|
||||
is_expected.to compile.with_all_deps
|
||||
is_expected.to contain_haproxy__frontend('neutron').with(
|
||||
:collect_exported => false,
|
||||
:bind => { "10.0.0.1:9696" => ["transparent"],
|
||||
"192.168.0.1:9696" => ["transparent"] },
|
||||
:options => {'option' => [],
|
||||
'timeout client' => '90m',
|
||||
'default_backend' => 'neutron_be',
|
||||
},
|
||||
)
|
||||
is_expected.to contain_haproxy__backend('neutron_be').with(
|
||||
:options => {'option' => [],
|
||||
'timeout server' => '90m',
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on_supported_os.each do |os, facts|
|
||||
|
|
|
@ -202,6 +202,10 @@ tripleo::dynamic_stuff::haproxy_endpoints:
|
|||
tripleo::haproxy::neutron::options:
|
||||
'timeout client': '90m'
|
||||
'timeout server': '90m'
|
||||
tripleo::haproxy::neutron::frontend_options:
|
||||
'timeout client': '90m'
|
||||
tripleo::haproxy::neutron::backend_options:
|
||||
'timeout server': '90m'
|
||||
|
||||
tripleo::haproxy_basic_auth::haproxy_endpoints:
|
||||
starwars:
|
||||
|
|
Loading…
Reference in New Issue