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 {-%>