Merge "haproxy: frontend/backend syntax in config" into stable/wallaby

This commit is contained in:
Zuul 2021-09-20 14:05:23 +00:00 committed by Gerrit Code Review
commit 00f205b36f
8 changed files with 724 additions and 283 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,
}
}
}

View File

@ -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.

View File

@ -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|

View File

@ -152,6 +152,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: