diff --git a/REFERENCE.md b/REFERENCE.md
index 9f9e414ae..04ad69c2e 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -254,6 +254,11 @@ The following parameters are available in the `rabbitmq` class:
* [`package_name`](#-rabbitmq--package_name)
* [`port`](#-rabbitmq--port)
* [`python_package`](#-rabbitmq--python_package)
+* [`quorum_membership_reconciliation_enabled`](#-rabbitmq--quorum_membership_reconciliation_enabled)
+* [`quorum_membership_reconciliation_auto_remove`](#-rabbitmq--quorum_membership_reconciliation_auto_remove)
+* [`quorum_membership_reconciliation_interval`](#-rabbitmq--quorum_membership_reconciliation_interval)
+* [`quorum_membership_reconciliation_trigger_interval`](#-rabbitmq--quorum_membership_reconciliation_trigger_interval)
+* [`quorum_membership_reconciliation_target_group_size`](#-rabbitmq--quorum_membership_reconciliation_target_group_size)
* [`repos_ensure`](#-rabbitmq--repos_ensure)
* [`service_ensure`](#-rabbitmq--service_ensure)
* [`service_manage`](#-rabbitmq--service_manage)
@@ -799,6 +804,55 @@ Name of the package required by rabbitmqadmin.
Default value: `'python'`
+##### `quorum_membership_reconciliation_enabled`
+
+Data type: `Optional[Boolean]`
+
+Enables or disables continuous membership reconciliation.
+This REQUIRES RabbitMQ 3.13 or higher to be set to true. More information on this configuration
+can be found here: https://www.rabbitmq.com/docs/quorum-queues
+
+Default value: `undef`
+
+##### `quorum_membership_reconciliation_auto_remove`
+
+Data type: `Optional[Boolean]`
+
+Enables or disables automatic removal of member nodes that are no longer part of the cluster,
+but still a member of the quorum queue.
+Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+
+Default value: `undef`
+
+##### `quorum_membership_reconciliation_interval`
+
+Data type: `Optional[Integer]`
+
+The default evaluation interval in milliseconds.
+Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+
+Default value: `undef`
+
+##### `quorum_membership_reconciliation_trigger_interval`
+
+Data type: `Optional[Integer]`
+
+The reconciliation delay in milliseconds, used when a trigger event occurs,
+for example, a node is added or removed from the cluster or an applicable policy changes.
+This delay will be applied only once, then the regular interval will be used again.
+Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+
+Default value: `undef`
+
+##### `quorum_membership_reconciliation_target_group_size`
+
+Data type: `Optional[Integer]`
+
+Controls the target group size for a quorum queue
+Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+
+Default value: `undef`
+
##### `repos_ensure`
Data type: `Boolean`
diff --git a/manifests/config.pp b/manifests/config.pp
index 5f7062900..4abfa78d1 100644
--- a/manifests/config.pp
+++ b/manifests/config.pp
@@ -3,94 +3,99 @@
#
# @api private
class rabbitmq::config {
- $admin_enable = $rabbitmq::admin_enable
- $management_enable = $rabbitmq::management_enable
- $use_config_file_for_plugins = $rabbitmq::use_config_file_for_plugins
- $plugins = $rabbitmq::plugins
- $cluster_node_type = $rabbitmq::cluster_node_type
- $cluster_nodes = $rabbitmq::cluster_nodes
- $config = $rabbitmq::config
- $config_cluster = $rabbitmq::config_cluster
- $config_cowboy_opts = $rabbitmq::config_cowboy_opts
- $config_path = $rabbitmq::config_path
- $config_ranch = $rabbitmq::config_ranch
- $config_stomp = $rabbitmq::config_stomp
- $stomp_ensure = $rabbitmq::stomp_ensure
- $config_shovel = $rabbitmq::config_shovel
- $config_shovel_statics = $rabbitmq::config_shovel_statics
- $default_user = $rabbitmq::default_user
- $default_pass = $rabbitmq::default_pass
- $env_config = $rabbitmq::env_config
- $env_config_path = $rabbitmq::env_config_path
- $erlang_cookie = $rabbitmq::erlang_cookie
- $interface = $rabbitmq::interface
- $management_port = $rabbitmq::management_port
- $management_ssl = $rabbitmq::management_ssl
- $management_hostname = $rabbitmq::management_hostname
- $node_ip_address = $rabbitmq::node_ip_address
- $rabbitmq_user = $rabbitmq::rabbitmq_user
- $rabbitmq_group = $rabbitmq::rabbitmq_group
- $rabbitmq_home = $rabbitmq::rabbitmq_home
- $port = $rabbitmq::port
- $tcp_keepalive = $rabbitmq::tcp_keepalive
- $tcp_backlog = $rabbitmq::tcp_backlog
- $tcp_sndbuf = $rabbitmq::tcp_sndbuf
- $tcp_recbuf = $rabbitmq::tcp_recbuf
- $heartbeat = $rabbitmq::heartbeat
- $service_name = $rabbitmq::service_name
- $ssl = $rabbitmq::ssl
- $ssl_only = $rabbitmq::ssl_only
- $ssl_cacert = $rabbitmq::ssl_cacert
- $ssl_cert = $rabbitmq::ssl_cert
- $ssl_key = $rabbitmq::ssl_key
- $ssl_depth = $rabbitmq::ssl_depth
- $ssl_cert_password = $rabbitmq::ssl_cert_password
- $ssl_port = $rabbitmq::ssl_port
- $ssl_interface = $rabbitmq::ssl_interface
- $ssl_management_port = $rabbitmq::ssl_management_port
- $ssl_management_cacert = $rabbitmq::ssl_management_cacert
- $ssl_management_cert = $rabbitmq::ssl_management_cert
- $ssl_management_key = $rabbitmq::ssl_management_key
- $ssl_management_verify = $rabbitmq::ssl_management_verify
- $ssl_management_fail_if_no_peer_cert = $rabbitmq::ssl_management_fail_if_no_peer_cert
- $ssl_stomp_port = $rabbitmq::ssl_stomp_port
- $ssl_verify = $rabbitmq::ssl_verify
- $ssl_fail_if_no_peer_cert = $rabbitmq::ssl_fail_if_no_peer_cert
- $ssl_client_renegotiation = $rabbitmq::ssl_client_renegotiation
- $ssl_secure_renegotiate = $rabbitmq::ssl_secure_renegotiate
- $ssl_reuse_sessions = $rabbitmq::ssl_reuse_sessions
- $ssl_honor_cipher_order = $rabbitmq::ssl_honor_cipher_order
- $ssl_dhfile = $rabbitmq::ssl_dhfile
- $ssl_versions = $rabbitmq::ssl_versions
- $ssl_ciphers = $rabbitmq::ssl_ciphers
- $ssl_crl_check = $rabbitmq::ssl_crl_check
- $ssl_crl_cache_hash_dir = $rabbitmq::ssl_crl_cache_hash_dir
- $ssl_crl_cache_http_timeout = $rabbitmq::ssl_crl_cache_http_timeout
- $stomp_port = $rabbitmq::stomp_port
- $stomp_ssl_only = $rabbitmq::stomp_ssl_only
- $ldap_auth = $rabbitmq::ldap_auth
- $ldap_server = $rabbitmq::ldap_server
- $ldap_user_dn_pattern = $rabbitmq::ldap_user_dn_pattern
- $ldap_other_bind = $rabbitmq::ldap_other_bind
- $ldap_use_ssl = $rabbitmq::ldap_use_ssl
- $ldap_port = $rabbitmq::ldap_port
- $ldap_log = $rabbitmq::ldap_log
- $ldap_config_variables = $rabbitmq::ldap_config_variables
- $wipe_db_on_cookie_change = $rabbitmq::wipe_db_on_cookie_change
- $config_variables = $rabbitmq::config_variables
- $config_kernel_variables = $rabbitmq::config_kernel_variables
- $config_management_variables = $rabbitmq::config_management_variables
- $config_additional_variables = $rabbitmq::config_additional_variables
- $auth_backends = $rabbitmq::auth_backends
- $cluster_partition_handling = $rabbitmq::cluster_partition_handling
- $file_limit = $rabbitmq::file_limit
- $oom_score_adj = $rabbitmq::oom_score_adj
- $collect_statistics_interval = $rabbitmq::collect_statistics_interval
- $ipv6 = $rabbitmq::ipv6
- $inetrc_config = $rabbitmq::inetrc_config
- $inetrc_config_path = $rabbitmq::inetrc_config_path
- $ssl_erl_dist = $rabbitmq::ssl_erl_dist
- $loopback_users = $rabbitmq::loopback_users
+ $admin_enable = $rabbitmq::admin_enable
+ $management_enable = $rabbitmq::management_enable
+ $use_config_file_for_plugins = $rabbitmq::use_config_file_for_plugins
+ $plugins = $rabbitmq::plugins
+ $cluster_node_type = $rabbitmq::cluster_node_type
+ $cluster_nodes = $rabbitmq::cluster_nodes
+ $config = $rabbitmq::config
+ $config_cluster = $rabbitmq::config_cluster
+ $config_cowboy_opts = $rabbitmq::config_cowboy_opts
+ $config_path = $rabbitmq::config_path
+ $config_ranch = $rabbitmq::config_ranch
+ $config_stomp = $rabbitmq::config_stomp
+ $stomp_ensure = $rabbitmq::stomp_ensure
+ $config_shovel = $rabbitmq::config_shovel
+ $config_shovel_statics = $rabbitmq::config_shovel_statics
+ $default_user = $rabbitmq::default_user
+ $default_pass = $rabbitmq::default_pass
+ $env_config = $rabbitmq::env_config
+ $env_config_path = $rabbitmq::env_config_path
+ $erlang_cookie = $rabbitmq::erlang_cookie
+ $interface = $rabbitmq::interface
+ $management_port = $rabbitmq::management_port
+ $management_ssl = $rabbitmq::management_ssl
+ $management_hostname = $rabbitmq::management_hostname
+ $node_ip_address = $rabbitmq::node_ip_address
+ $quorum_membership_reconciliation_enabled = $rabbitmq::quorum_membership_reconciliation_enabled
+ $quorum_membership_reconciliation_auto_remove = $rabbitmq::quorum_membership_reconciliation_auto_remove
+ $quorum_membership_reconciliation_interval = $rabbitmq::quorum_membership_reconciliation_interval
+ $quorum_membership_reconciliation_trigger_interval = $rabbitmq::quorum_membership_reconciliation_trigger_interval
+ $quorum_membership_reconciliation_target_group_size = $rabbitmq::quorum_membership_reconciliation_target_group_size
+ $rabbitmq_user = $rabbitmq::rabbitmq_user
+ $rabbitmq_group = $rabbitmq::rabbitmq_group
+ $rabbitmq_home = $rabbitmq::rabbitmq_home
+ $port = $rabbitmq::port
+ $tcp_keepalive = $rabbitmq::tcp_keepalive
+ $tcp_backlog = $rabbitmq::tcp_backlog
+ $tcp_sndbuf = $rabbitmq::tcp_sndbuf
+ $tcp_recbuf = $rabbitmq::tcp_recbuf
+ $heartbeat = $rabbitmq::heartbeat
+ $service_name = $rabbitmq::service_name
+ $ssl = $rabbitmq::ssl
+ $ssl_only = $rabbitmq::ssl_only
+ $ssl_cacert = $rabbitmq::ssl_cacert
+ $ssl_cert = $rabbitmq::ssl_cert
+ $ssl_key = $rabbitmq::ssl_key
+ $ssl_depth = $rabbitmq::ssl_depth
+ $ssl_cert_password = $rabbitmq::ssl_cert_password
+ $ssl_port = $rabbitmq::ssl_port
+ $ssl_interface = $rabbitmq::ssl_interface
+ $ssl_management_port = $rabbitmq::ssl_management_port
+ $ssl_management_cacert = $rabbitmq::ssl_management_cacert
+ $ssl_management_cert = $rabbitmq::ssl_management_cert
+ $ssl_management_key = $rabbitmq::ssl_management_key
+ $ssl_management_verify = $rabbitmq::ssl_management_verify
+ $ssl_management_fail_if_no_peer_cert = $rabbitmq::ssl_management_fail_if_no_peer_cert
+ $ssl_stomp_port = $rabbitmq::ssl_stomp_port
+ $ssl_verify = $rabbitmq::ssl_verify
+ $ssl_fail_if_no_peer_cert = $rabbitmq::ssl_fail_if_no_peer_cert
+ $ssl_client_renegotiation = $rabbitmq::ssl_client_renegotiation
+ $ssl_secure_renegotiate = $rabbitmq::ssl_secure_renegotiate
+ $ssl_reuse_sessions = $rabbitmq::ssl_reuse_sessions
+ $ssl_honor_cipher_order = $rabbitmq::ssl_honor_cipher_order
+ $ssl_dhfile = $rabbitmq::ssl_dhfile
+ $ssl_versions = $rabbitmq::ssl_versions
+ $ssl_ciphers = $rabbitmq::ssl_ciphers
+ $ssl_crl_check = $rabbitmq::ssl_crl_check
+ $ssl_crl_cache_hash_dir = $rabbitmq::ssl_crl_cache_hash_dir
+ $ssl_crl_cache_http_timeout = $rabbitmq::ssl_crl_cache_http_timeout
+ $stomp_port = $rabbitmq::stomp_port
+ $stomp_ssl_only = $rabbitmq::stomp_ssl_only
+ $ldap_auth = $rabbitmq::ldap_auth
+ $ldap_server = $rabbitmq::ldap_server
+ $ldap_user_dn_pattern = $rabbitmq::ldap_user_dn_pattern
+ $ldap_other_bind = $rabbitmq::ldap_other_bind
+ $ldap_use_ssl = $rabbitmq::ldap_use_ssl
+ $ldap_port = $rabbitmq::ldap_port
+ $ldap_log = $rabbitmq::ldap_log
+ $ldap_config_variables = $rabbitmq::ldap_config_variables
+ $wipe_db_on_cookie_change = $rabbitmq::wipe_db_on_cookie_change
+ $config_variables = $rabbitmq::config_variables
+ $config_kernel_variables = $rabbitmq::config_kernel_variables
+ $config_management_variables = $rabbitmq::config_management_variables
+ $config_additional_variables = $rabbitmq::config_additional_variables
+ $auth_backends = $rabbitmq::auth_backends
+ $cluster_partition_handling = $rabbitmq::cluster_partition_handling
+ $file_limit = $rabbitmq::file_limit
+ $oom_score_adj = $rabbitmq::oom_score_adj
+ $collect_statistics_interval = $rabbitmq::collect_statistics_interval
+ $ipv6 = $rabbitmq::ipv6
+ $inetrc_config = $rabbitmq::inetrc_config
+ $inetrc_config_path = $rabbitmq::inetrc_config_path
+ $ssl_erl_dist = $rabbitmq::ssl_erl_dist
+ $loopback_users = $rabbitmq::loopback_users
if $ssl_only {
$default_ssl_env_variables = {}
diff --git a/manifests/init.pp b/manifests/init.pp
index 5382d9d8e..6254cf404 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -240,6 +240,25 @@
# The RabbitMQ port.
# @param python_package
# Name of the package required by rabbitmqadmin.
+# @param quorum_membership_reconciliation_enabled
+# Enables or disables continuous membership reconciliation.
+# This REQUIRES RabbitMQ 3.13 or higher to be set to true. More information on this configuration
+# can be found here: https://www.rabbitmq.com/docs/quorum-queues
+# @param quorum_membership_reconciliation_auto_remove
+# Enables or disables automatic removal of member nodes that are no longer part of the cluster,
+# but still a member of the quorum queue.
+# Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+# @param quorum_membership_reconciliation_interval
+# The default evaluation interval in milliseconds.
+# Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+# @param quorum_membership_reconciliation_trigger_interval
+# The reconciliation delay in milliseconds, used when a trigger event occurs,
+# for example, a node is added or removed from the cluster or an applicable policy changes.
+# This delay will be applied only once, then the regular interval will be used again.
+# Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
+# @param quorum_membership_reconciliation_target_group_size
+# Controls the target group size for a quorum queue
+# Important Note: This only takes affect if quorum_membership_reconciliation_enabled is set to true.
# @param repos_ensure
# Ensure that a repo with the official (and newer) RabbitMQ package is configured, along with its signing key.
# Defaults to false (use system packages). This does not ensure that soft dependencies are present.
@@ -381,6 +400,11 @@
Optional[Variant[Numeric, String[1]]] $package_apt_pin = undef,
String $package_ensure = 'installed',
Optional[String] $package_gpg_key = undef,
+ Optional[Boolean] $quorum_membership_reconciliation_enabled = undef,
+ Optional[Boolean] $quorum_membership_reconciliation_auto_remove = undef,
+ Optional[Integer] $quorum_membership_reconciliation_interval = undef,
+ Optional[Integer] $quorum_membership_reconciliation_trigger_interval = undef,
+ Optional[Integer] $quorum_membership_reconciliation_target_group_size = undef,
Optional[String] $repo_gpg_key = undef,
Variant[String, Array] $package_name = 'rabbitmq',
Optional[String] $package_source = undef,
diff --git a/spec/classes/rabbitmq_spec.rb b/spec/classes/rabbitmq_spec.rb
index 6479c6cd3..9273b7f9a 100644
--- a/spec/classes/rabbitmq_spec.rb
+++ b/spec/classes/rabbitmq_spec.rb
@@ -1788,12 +1788,83 @@
describe 'rabbitmq-heartbeat options' do
let(:params) { { heartbeat: 60 } }
- it 'sets heartbeat paramter in config file' do
+ it 'sets heartbeat parameter in config file' do
is_expected.to contain_file('rabbitmq.config'). \
with_content(%r{\{heartbeat, 60\}})
end
end
+ # Ensure that whenever Param quorum_membership_reconciliation_enabled is unset - none of the
+ # other quorum_membership_reconciliation paramaters are set at all
+ # This ensures full backward compatibility with PRE RabbitMQ 3.13
+ describe 'rabbitmq-quorum_membership_reconciliation_enabled undef options' do
+ let(:params) { { quorum_membership_reconciliation_enabled: :undef } }
+
+ it 'sets quorum_membership_reconciliation_enabled parameter undef in config file' do
+ is_expected.to contain_file('rabbitmq.config'). \
+ without_content(%r{\{quorum_membership_reconciliation_enabled, }). \
+ without_content(%r{\{quorum_membership_reconciliation_auto_remove, }). \
+ without_content(%r{\{quorum_membership_reconciliation_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_trigger_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_target_group_size, })
+ end
+ end
+
+ # Ensure that whenever Param quorum_membership_reconciliation_enabled is false - none of the
+ # other quorum_membership_reconciliation paramaters are set at all
+ # This ensures full backward compatibility with PRE RabbitMQ 3.13
+ describe 'rabbitmq-quorum_membership_reconciliation_enabled false options' do
+ let(:params) { { quorum_membership_reconciliation_enabled: false } }
+
+ it 'sets quorum_membership_reconciliation_enabled parameter false in config file' do
+ is_expected.to contain_file('rabbitmq.config'). \
+ without_content(%r{\{quorum_membership_reconciliation_enabled, }). \
+ without_content(%r{\{quorum_membership_reconciliation_auto_remove, }). \
+ without_content(%r{\{quorum_membership_reconciliation_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_trigger_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_target_group_size, })
+ end
+ end
+
+ # Ensure that whenever Param quorum_membership_reconciliation_enabled is true - the defaults
+ # of all other quorum_membership_reconciliation parameters ensure they are UNSET until
+ # explicitly set.
+ describe 'rabbitmq-quorum_membership_reconciliation_enabled true options' do
+ let(:params) { { quorum_membership_reconciliation_enabled: true } }
+
+ it 'sets quorum_membership_reconciliation_enabled parameter true in config file' do
+ is_expected.to contain_file('rabbitmq.config'). \
+ with_content(%r{\{quorum_membership_reconciliation_enabled, true\}}). \
+ without_content(%r{\{quorum_membership_reconciliation_auto_remove, }). \
+ without_content(%r{\{quorum_membership_reconciliation_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_trigger_interval, }). \
+ without_content(%r{\{quorum_membership_reconciliation_target_group_size, })
+ end
+ end
+
+ # Ensure that whenever Param quorum_membership_reconciliation_enabled is true
+ # and the other parameters are set - they pass as expected.
+ describe 'rabbitmq-quorum_membership_reconciliation_enabled true options' do
+ let(:params) do
+ {
+ quorum_membership_reconciliation_enabled: true,
+ quorum_membership_reconciliation_auto_remove: true,
+ quorum_membership_reconciliation_interval: 36_000,
+ quorum_membership_reconciliation_trigger_interval: 3_600,
+ quorum_membership_reconciliation_target_group_size: 2
+ }
+ end
+
+ it 'sets quorum_membership_reconciliation_enabled parameter true in config file' do
+ is_expected.to contain_file('rabbitmq.config'). \
+ with_content(%r{\{quorum_membership_reconciliation_enabled, true\}}). \
+ with_content(%r{\{quorum_membership_reconciliation_auto_remove, true\}}). \
+ with_content(%r{\{quorum_membership_reconciliation_interval, 36000\}}). \
+ with_content(%r{\{quorum_membership_reconciliation_trigger_interval, 3600\}}). \
+ with_content(%r{\{quorum_membership_reconciliation_target_group_size, 2\}})
+ end
+ end
+
context 'delete_guest_user' do
describe 'should do nothing by default' do
it { is_expected.not_to contain_rabbitmq_user('guest') }
diff --git a/templates/rabbitmq.config.epp b/templates/rabbitmq.config.epp
index be71d1187..7f93431e9 100644
--- a/templates/rabbitmq.config.epp
+++ b/templates/rabbitmq.config.epp
@@ -25,6 +25,21 @@
{cluster_nodes, {[], <%= $rabbitmq::config::cluster_node_type %>}},
<%- } -%>
{cluster_partition_handling, <%= $rabbitmq::config::cluster_partition_handling %>},
+<% } -%>
+<% if $rabbitmq::config::quorum_membership_reconciliation_enabled {-%>
+ {quorum_membership_reconciliation_enabled, <%= $rabbitmq::config::quorum_membership_reconciliation_enabled %>},
+ <%- unless $rabbitmq::config::quorum_membership_reconciliation_auto_remove =~ Undef {-%>
+ {quorum_membership_reconciliation_auto_remove, <%= $rabbitmq::config::quorum_membership_reconciliation_auto_remove %>},
+ <%- } -%>
+ <%- unless $rabbitmq::config::quorum_membership_reconciliation_interval =~ Undef {-%>
+ {quorum_membership_reconciliation_interval, <%= $rabbitmq::config::quorum_membership_reconciliation_interval %>},
+ <%- } -%>
+ <%- unless $rabbitmq::config::quorum_membership_reconciliation_trigger_interval =~ Undef {-%>
+ {quorum_membership_reconciliation_trigger_interval, <%= $rabbitmq::config::quorum_membership_reconciliation_trigger_interval %>},
+ <%- } -%>
+ <%- unless $rabbitmq::config::quorum_membership_reconciliation_target_group_size =~ Undef {-%>
+ {quorum_membership_reconciliation_target_group_size, <%= $rabbitmq::config::quorum_membership_reconciliation_target_group_size %>},
+ <%- } -%>
<% } -%>
{tcp_listen_options, [
<%- unless $rabbitmq::config::config_ranch {-%>