├── .rspec ├── templates └── default │ ├── doterlang.cookie.erb │ ├── systemd_limits.conf.erb │ ├── 90forceyes.erb │ ├── default.rabbitmq-server.erb │ ├── rabbitmq.upstart.conf.erb │ ├── rabbitmq-env.conf.erb │ └── rabbitmq.config.erb ├── test ├── cookbooks │ └── rabbitmq_test │ │ ├── README.md │ │ ├── metadata.rb │ │ └── recipes │ │ ├── cook-2151-3489.rb │ │ ├── cluster.rb │ │ ├── cook-openfiles.rb │ │ ├── mgmt_console.rb │ │ ├── default.rb │ │ └── lwrps.rb ├── integration │ ├── cluster │ │ └── default_spec.rb │ ├── lwrps │ │ └── default_spec.rb │ ├── management_plugin │ │ └── default_spec.rb │ ├── limits │ │ └── default_spec.rb │ └── default │ │ └── default_spec.rb └── erlang_package │ ├── latest_rpm │ └── default_spec.rb │ ├── pinned_rpm │ └── default_spec.rb │ ├── latest_deb │ └── default_spec.rb │ └── pinned_deb │ └── default_spec.rb ├── .gitignore ├── Berksfile ├── spec ├── plugins_spec.rb ├── vhosts_spec.rb ├── management_ui_spec.rb ├── users_spec.rb ├── spec_helper.rb ├── systemd_limits_spec.rb ├── policies_spec.rb ├── cluster_spec.rb ├── community_plugins_spec.rb ├── policy_spec.rb └── default_spec.rb ├── .kitchen.cloud.yml ├── libraries ├── helpers.rb └── default.rb ├── metadata.rb ├── recipes ├── mgmt_console.rb ├── user_management.rb ├── virtualhost_management.rb ├── policy_management.rb ├── plugin_management.rb ├── esl_erlang_package.rb ├── management_ui.rb ├── vhosts.rb ├── plugins.rb ├── policies.rb ├── community_plugins.rb ├── systemd_limits.rb ├── cluster.rb ├── users.rb ├── erlang_package.rb └── default.rb ├── Guardfile ├── .rubocop.yml ├── .travis.yml ├── Gemfile ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── Rakefile ├── resources ├── vhost.rb ├── erlang_apt_repository_on_cloudsmith.rb ├── erlang_zypper_repository_on_suse_factory.rb ├── plugin.rb ├── parameter.rb ├── erlang_yum_repository_on_cloudsmith.rb ├── policy.rb ├── erlang_package_from_cloudsmith.rb ├── user.rb └── cluster.rb ├── .kitchen.alphas.yml ├── TESTING.md ├── .kitchen.yml ├── CONTRIBUTING.md ├── LICENSE ├── .kitchen.dokken.yml └── attributes └── default.rb /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /templates/default/doterlang.cookie.erb: -------------------------------------------------------------------------------- 1 | <%= node['rabbitmq']['erlang_cookie'] %> 2 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/README.md: -------------------------------------------------------------------------------- 1 | This cookbook is used with test-kitchen to test the parent, rabbitmq cookbook. 2 | -------------------------------------------------------------------------------- /templates/default/systemd_limits.conf.erb: -------------------------------------------------------------------------------- 1 | [Service] 2 | <% node['rabbitmq']['systemd']['limits'].each do |limit, val| -%> 3 | Limit<%= limit.upcase %>=<%= val %> 4 | <% end -%> 5 | -------------------------------------------------------------------------------- /templates/default/90forceyes.erb: -------------------------------------------------------------------------------- 1 | APT::Get::Assume-Yes "<%= node['apt']['confd']['assume_yes'] ? true : false || false %>"; 2 | APT::Get::force-yes "<%= node['apt']['confd']['force-yes'] ? true : false || false %>"; 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | Berksfile.lock 3 | *~ 4 | *# 5 | .#* 6 | \#*# 7 | .*.sw[a-z] 8 | *.un~ 9 | .bundle 10 | .cache 11 | .kitchen 12 | .kitchen/* 13 | bin 14 | .kitchen.local.yml 15 | .coverage 16 | .direnv/ 17 | .envrc 18 | .ruby-version -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | source 'https://supermarket.chef.io' 3 | 4 | metadata 5 | 6 | group :integration do 7 | cookbook 'apt' 8 | cookbook 'minitest-handler' 9 | cookbook 'rabbitmq_test', :path => './test/cookbooks/rabbitmq_test' 10 | end 11 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | name 'rabbitmq_test' 3 | maintainer 'Chef Software, Inc.' 4 | maintainer_email 'cookbooks@chef.io' 5 | license 'Apache-2.0' 6 | description 'This cookbook is used with test-kitchen to test the parent, rabbitmq cookbook.' 7 | version '1.0.0' 8 | 9 | depends 'rabbitmq' 10 | -------------------------------------------------------------------------------- /test/integration/cluster/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe file('/var/lib/rabbitmq/.erlang.cookie') do 5 | it { should be_file } 6 | end 7 | 8 | describe file('/etc/rabbitmq/rabbitmq.config') do 9 | it { should be_file } 10 | skip(:content) { should match(/^\s+{cluster_nodes, {.*}},$/) } 11 | end 12 | -------------------------------------------------------------------------------- /spec/plugins_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::plugins' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | cached(:chef_run) do 8 | runner.converge(described_recipe) 9 | end 10 | 11 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 12 | 13 | it 'includes the `default` recipe' do 14 | expect(chef_run).to include_recipe('rabbitmq::default') 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/vhosts_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::vhosts' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | cached(:chef_run) do 8 | runner.converge(described_recipe) 9 | end 10 | 11 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 12 | 13 | it 'includes the `default` recipe' do 14 | expect(chef_run).to include_recipe('rabbitmq::default') 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/management_ui_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::mgmt_console' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | cached(:chef_run) do 8 | runner.converge(described_recipe) 9 | end 10 | 11 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 12 | 13 | it 'includes the `default` recipe' do 14 | expect(chef_run).to include_recipe('rabbitmq::default') 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/cook-2151-3489.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: cook-2151-3489 5 | # 6 | # This recipe exists to ensure that minitest tests are run. 7 | 8 | include_recipe 'rabbitmq::default' 9 | 10 | # HACK: Give rabbit time to spin up before the tests, it seems 11 | # to be responding that it has started before it really has 12 | execute 'sleep 10' do 13 | action :nothing 14 | subscribes :run, "service[#{node['rabbitmq']['service_name']}]", :delayed 15 | end 16 | -------------------------------------------------------------------------------- /templates/default/default.rabbitmq-server.erb: -------------------------------------------------------------------------------- 1 | ### 2 | # Generated by Chef 3 | ### 4 | 5 | # This file is sourced by /etc/init.d/rabbitmq-server. Its primary 6 | # reason for existing is to allow minor system and environment adjustment for the 7 | # rabbitmq-server process. 8 | # 9 | # On modern distributions system limits are managed by systemd, see rabbitmq:systemd_limits and 10 | # https://www.rabbitmq.com/networking.html#open-file-handle-limit. 11 | <% if node['rabbitmq']['open_file_limit'] -%>ulimit -n <%= node['rabbitmq']['open_file_limit'] %><% end %> 12 | -------------------------------------------------------------------------------- /test/integration/lwrps/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe command('curl -u guest:guest -H "Accept: application/json" -X GET "http://localhost:15672/api/overview"') do 5 | its(:exit_status) { should eq 0 } 6 | end 7 | 8 | describe command('rabbitmqctl list_policies -s') do 9 | its(:stdout) { should match(%r{{"max-length":1000}}) } 10 | end 11 | 12 | describe command('rabbitmqctl list_parameters -s -p sensu') do 13 | its(:stdout) { should match(%r{federation-upstream\s+sensu-dc-1\s+{"uri":"amqp:\/\/dc-cluster-node"}}) } 14 | end 15 | -------------------------------------------------------------------------------- /test/integration/management_plugin/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe package('rabbitmq-server') do 5 | it { should be_installed } 6 | end 7 | 8 | describe service('rabbitmq-server') do 9 | it { should be_running } 10 | end 11 | 12 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list -E | grep rabbitmq_management') do 13 | its(:exit_status) { should eq 0 } 14 | end 15 | 16 | describe port(5672) do 17 | it { should be_listening } 18 | end 19 | 20 | describe port(15672) do 21 | it { should be_listening } 22 | end 23 | -------------------------------------------------------------------------------- /.kitchen.cloud.yml: -------------------------------------------------------------------------------- 1 | --- 2 | provisioner: 3 | name: chef_zero 4 | require_chef_omnibus: latest 5 | client_rb: 6 | chef_license: accept 7 | 8 | platforms: 9 | - name: centos-7-x64 10 | driver: 11 | name: digitalocean 12 | 13 | - name: ubuntu-16-04-x64 14 | driver: 15 | name: digitalocean 16 | run_list: 17 | - recipe[apt] 18 | 19 | 20 | suites: 21 | - name: default 22 | run_list: 23 | - recipe[rabbitmq::default] 24 | 25 | - name: default-use-distro-version 26 | run_list: 27 | - recipe[rabbitmq::default] 28 | attributes: 29 | rabbitmq: 30 | use_distro_version: true 31 | excludes: ["centos-7-x64"] 32 | -------------------------------------------------------------------------------- /spec/users_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::users' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | cached(:chef_run) do 8 | runner.converge(described_recipe) 9 | end 10 | 11 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 12 | 13 | it 'includes the `default` recipe' do 14 | expect(chef_run).to include_recipe('rabbitmq::default') 15 | end 16 | 17 | it 'includes the `virtualhost_management` recipe' do 18 | expect(chef_run).to include_recipe('rabbitmq::vhosts') 19 | end 20 | 21 | it 'adds rabbitmq enabled users' do 22 | expect(chef_run).to add_rabbitmq_user('add-guest') 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /templates/default/rabbitmq.upstart.conf.erb: -------------------------------------------------------------------------------- 1 | description "Start rabbitmq on startup" 2 | start on started networking 3 | limit nofile <%= @max_file_descriptors %> <%= @max_file_descriptors %> 4 | 5 | respawn 6 | respawn limit 5 60 7 | 8 | env HOME="" 9 | env RABBITMQ_PID_FILE="/var/run/rabbitmq/pid" 10 | 11 | pre-start script 12 | PID_DIR=`dirname ${RABBITMQ_PID_FILE}` 13 | 14 | if [ ! -d ${PID_DIR} ]; 15 | then 16 | mkdir -p ${PID_DIR} 17 | chown -R rabbitmq:rabbitmq ${PID_DIR} 18 | chmod 755 ${PID_DIR} 19 | fi 20 | end script 21 | 22 | exec /usr/sbin/rabbitmq-server > /var/log/rabbitmq/startup.log \ 23 | 2> /var/log/rabbitmq/startup_err.log 24 | 25 | post-start exec /usr/sbin/rabbitmqctl wait $RABBITMQ_PID_FILE >/dev/null 2>&1 26 | -------------------------------------------------------------------------------- /libraries/helpers.rb: -------------------------------------------------------------------------------- 1 | module RabbitMQ 2 | module NodeHelpers 3 | require 'mixlib/shellout' 4 | 5 | def reset_current_node 6 | # stop rmq 7 | stop_rmq = Mixlib::ShellOut.new('rabbitmqctl stop_app') 8 | stop_rmq.run_command 9 | stop_rmq.error! 10 | # remove self from cluster 11 | reset_rmq = Mixlib::ShellOut.new('rabbitmqctl reset') 12 | reset_rmq.run_command 13 | reset_rmq.error! 14 | end 15 | 16 | def remove_remote_node_from_cluster(rmq_node) 17 | remove_from_cluster = Mixlib::ShellOut.new("rabbitmqctl forget_cluster_node #{rmq_node}") 18 | remove_from_cluster.run_command 19 | remove_from_cluster.error! 20 | end 21 | end 22 | end 23 | 24 | module RabbitMQCookbook 25 | module Helpers 26 | include RabbitMQ::NodeHelpers 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | name 'rabbitmq' 3 | maintainer 'VMware, Inc. and contributors' 4 | maintainer_email 'klishinm@vmware.com' 5 | license 'Apache-2.0' 6 | description 'Installs and configures RabbitMQ server' 7 | version '5.10.0' 8 | 9 | issues_url 'https://github.com/rabbitmq/chef-cookbook/issues' 10 | source_url 'https://github.com/rabbitmq/chef-cookbook' 11 | 12 | chef_version '>= 13.0' 13 | 14 | depends 'erlang' 15 | depends 'yum-epel' 16 | depends 'yum-erlang_solutions' 17 | depends 'dpkg_autostart' 18 | depends 'logrotate' 19 | 20 | supports 'amazon', '>= 2.0' 21 | supports 'centos', '>= 8.0' 22 | supports 'debian', '>= 10.0' 23 | supports 'fedora', '>= 32.0' 24 | supports 'opensuseleap' 25 | supports 'oracle' 26 | supports 'redhat' 27 | supports 'scientific' 28 | supports 'smartos' 29 | supports 'suse' 30 | supports 'ubuntu', '>= 18.04' 31 | -------------------------------------------------------------------------------- /test/integration/limits/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe package('rabbitmq-server') do 5 | it { should be_installed } 6 | end 7 | 8 | describe service('rabbitmq-server') do 9 | it { should be_running } 10 | end 11 | 12 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 13 | its(:exit_status) { should eq 0 } 14 | end 15 | describe file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf') do 16 | it { should be_file } 17 | its('owner') { should eq 'root' } 18 | its('group') { should eq 'root' } 19 | 20 | its('content') { should match(/LimitNOFILE=54000/) } 21 | end 22 | 23 | describe file('/etc/rabbitmq/rabbitmq.config') do 24 | it { should be_file } 25 | its('owner') { should eq 'root' } 26 | its('group') { should eq 'root' } 27 | end 28 | -------------------------------------------------------------------------------- /recipes/mgmt_console.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: mgmt_console 5 | # 6 | # Copyright 2012, Tacit Knowledge, Inc. 7 | # Copyright 2013-2018, Chef Software, Inc. 8 | # Copyright 2018-2019, VMware, Inc. or its affiliates 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | include_recipe 'rabbitmq::management_ui' 24 | -------------------------------------------------------------------------------- /recipes/user_management.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: user_management 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::users' 25 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | # guard 'kitchen' do 5 | # watch(%r{test/.+}) 6 | # watch(%r{^recipes/(.+)\.rb$}) 7 | # watch(%r{^attributes/(.+)\.rb$}) 8 | # watch(%r{^files/(.+)}) 9 | # watch(%r{^templates/(.+)}) 10 | # watch(%r{^providers/(.+)\.rb}) 11 | # watch(%r{^resources/(.+)\.rb}) 12 | # end 13 | 14 | # rubocop:disable all 15 | 16 | guard 'rubocop', :all_on_start => false do 17 | watch(%r{attributes/.+\.rb$}) 18 | watch(%r{providers/.+\.rb$}) 19 | watch(%r{recipes/.+\.rb$}) 20 | watch(%r{resources/.+\.rb$}) 21 | watch('metadata.rb') 22 | end 23 | 24 | guard :rspec, :cmd => 'bundle exec rspec', :all_on_start => false, :notification => false do 25 | watch(%r{^libraries/(.+)\.rb$}) 26 | watch(%r{^spec/(.+)_spec\.rb$}) 27 | watch(%r{^(recipes)/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } 28 | watch('spec/spec_helper.rb') { 'spec' } 29 | end 30 | -------------------------------------------------------------------------------- /test/erlang_package/latest_rpm/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe package('erlang') do 5 | it { should be_installed } 6 | end 7 | 8 | describe package('rabbitmq-server') do 9 | it { should be_installed } 10 | end 11 | 12 | describe service('rabbitmq-server') do 13 | it { should be_running } 14 | end 15 | 16 | describe command('erl') do 17 | it { should exist } 18 | end 19 | 20 | describe command('epmd') do 21 | it { should exist } 22 | end 23 | 24 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 25 | its(:exit_status) { should eq 0 } 26 | end 27 | 28 | describe command('HOSTNAME=$(hostname) rabbitmqctl ping') do 29 | its(:exit_status) { should eq 0 } 30 | end 31 | 32 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list') do 33 | its(:exit_status) { should eq 0 } 34 | end 35 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AsciiComments: 2 | Enabled: false 3 | 4 | Chef/Style/CommentFormat: 5 | Enabled: false 6 | 7 | Chef/Modernize/FoodcriticComments: 8 | Enabled: false 9 | 10 | Chef/Modernize/ExecuteSleep: 11 | Enabled: false 12 | 13 | Layout/ParameterAlignment: 14 | Enabled: false 15 | 16 | Layout/ElseAlignment: 17 | Enabled: false 18 | 19 | Layout/EndAlignment: 20 | Enabled: false 21 | 22 | Layout/IndentationWidth: 23 | Enabled: false 24 | 25 | Layout/LineLength: 26 | Max: 200 27 | 28 | Naming/FileName: 29 | Enabled: false 30 | 31 | Metrics/AbcSize: 32 | Max: 16 33 | 34 | Metrics/MethodLength: 35 | Max: 18 36 | 37 | Style/Encoding: 38 | Enabled: false 39 | 40 | Style/RegexpLiteral: 41 | Enabled: false 42 | 43 | Style/IfUnlessModifier: 44 | Enabled: false 45 | 46 | Style/HashSyntax: 47 | Enabled: false 48 | 49 | Style/TrailingCommaInHashLiteral: 50 | Enabled: false 51 | 52 | Style/WordArray: 53 | Enabled: false 54 | -------------------------------------------------------------------------------- /recipes/virtualhost_management.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: virtualhost_management 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::vhosts' 25 | -------------------------------------------------------------------------------- /recipes/policy_management.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: policy_management 5 | # 6 | # Author: Robert Choi 7 | # Copyright 2013 by Robert Choi 8 | # Copyright 2013, Chef Software, Inc. 9 | # Copyright 2019-2021, VMware, Inc or its affiliates. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::policies' 25 | -------------------------------------------------------------------------------- /recipes/plugin_management.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: plugin_management 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | # Backwards compatibility 25 | include_recipe 'rabbitmq::plugins' 26 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Encoding: utf-8 2 | # frozen_string_literal: true 3 | require 'chefspec' 4 | require 'chefspec/berkshelf' 5 | require 'fauxhai' 6 | 7 | require 'chef/application' 8 | 9 | # rubocop:disable all 10 | 11 | LOGLEVEL = :fatal 12 | SUSE_OPTS = { 13 | :platform => 'suse', 14 | :version => '12.5', 15 | :log_level => LOGLEVEL 16 | } 17 | REDHAT_OPTS = { 18 | :platform => 'redhat', 19 | :version => '8', 20 | :log_level => LOGLEVEL, 21 | :file_cache_path => '/tmp' 22 | } 23 | UBUNTU_OPTS = { 24 | :platform => 'ubuntu', 25 | :version => '18.04', 26 | :log_level => LOGLEVEL, 27 | :file_cache_path => '/tmp' 28 | } 29 | FEDORA_OPTS = { 30 | :platform => 'fedora', 31 | :version => '32', 32 | :log_level => LOGLEVEL, 33 | :file_cache_path => '/tmp' 34 | } 35 | 36 | # rubocop:enable all 37 | 38 | shared_context 'rabbitmq-stubs' do 39 | before do 40 | allow_any_instance_of(Chef::Config).to receive(:file_cache_path) 41 | .and_return('/tmp') 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/erlang_package/pinned_rpm/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe package('erlang') do 5 | it { should be_installed } 6 | its('version') { should match(/^(22|23)/) } 7 | end 8 | 9 | describe package('rabbitmq-server') do 10 | it { should be_installed } 11 | end 12 | 13 | describe service('rabbitmq-server') do 14 | it { should be_running } 15 | end 16 | 17 | describe command('erl') do 18 | it { should exist } 19 | end 20 | 21 | describe command('epmd') do 22 | it { should exist } 23 | end 24 | 25 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 26 | its(:exit_status) { should eq 0 } 27 | end 28 | 29 | describe command('HOSTNAME=$(hostname) rabbitmqctl ping') do 30 | its(:exit_status) { should eq 0 } 31 | end 32 | 33 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list') do 34 | its(:exit_status) { should eq 0 } 35 | end 36 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/cluster.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: cluster 5 | # 6 | # Copyright 2012, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # 2017, @rmoriz, this is broken and probably never worked 23 | node.override['rabbitmq']['cluster'] = true 24 | include_recipe 'rabbitmq::default' 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: bionic 2 | 3 | lang: ruby 4 | 5 | rvm: 6 | - 2.7 7 | 8 | before_install: 9 | - gem update bundler 10 | - bundle update --bundler 11 | 12 | env: 13 | - CHEF_LICENSE=accept 14 | 15 | cache: bundler 16 | 17 | services: docker 18 | 19 | # kitchen list -b | xargs -I {} echo "- INSTANCE={}" 20 | env: 21 | matrix: 22 | - INSTANCE=default-deb-debian-10 23 | - INSTANCE=default-deb-ubuntu-2004 24 | - INSTANCE=default-deb-ubuntu-1804 25 | - INSTANCE=default-rpm-centos-8 26 | - INSTANCE=system-limits-deb-ubuntu-1804 27 | - INSTANCE=lwrps 28 | - INSTANCE=cluster-deb-ubuntu-1804 29 | - INSTANCE=cluster-rpm 30 | - INSTANCE=default-force-yes 31 | - INSTANCE=default-force-yes-false 32 | 33 | before_script: 34 | - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER ) 35 | 36 | script: KITCHEN_LOCAL_YAML=.kitchen.dokken.yml kitchen test ${INSTANCE} 37 | 38 | matrix: 39 | include: 40 | script: bundle exec rake 41 | env: UNIT_AND_LINT=1 42 | -------------------------------------------------------------------------------- /recipes/esl_erlang_package.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: esl_erlang_package 5 | # 6 | # A convenience recipe for provisioning Erlang from 7 | # Erlang Solution. Identical to `recipe[erlang::esl]`. 8 | # Added to go with a recipe that provisions Erlang via RabbitMQ's own 9 | # packages. 10 | # 11 | # Copyright 2019-2021, VMware, Inc or its affiliates. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "License"); 14 | # you may not use this file except in compliance with the License. 15 | # You may obtain a copy of the License at 16 | # 17 | # https://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | # See the License for the specific language governing permissions and 23 | # limitations under the License. 24 | # 25 | 26 | include_recipe 'erlang::esl' 27 | -------------------------------------------------------------------------------- /spec/systemd_limits_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::systemd_limits' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | cached(:chef_run) do 8 | runner.converge(described_recipe) 9 | end 10 | let(:template) { chef_run.template('/etc/systemd/system/rabbitmq-server.service.d/limits.conf') } 11 | 12 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 13 | 14 | it 'includes the `default` recipe' do 15 | expect(chef_run).to include_recipe('rabbitmq::default') 16 | end 17 | 18 | it 'creates a limits file' do 19 | expect(chef_run).to create_template('/etc/systemd/system/rabbitmq-server.service.d/limits.conf') 20 | end 21 | 22 | it 'reloads systemd config' do 23 | expect(template).to notify('execute[systemctl daemon-reload]').to(:run).immediately 24 | end 25 | 26 | it 'reloads restarts the node' do 27 | expect(template).to notify('service[rabbitmq-server]').to(:restart).delayed 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | source 'https://rubygems.org' 3 | 4 | gem 'chef' 5 | gem 'berkshelf' 6 | gem 'github_changelog_generator' 7 | gem 'nokogiri', ">= 1.13.4" 8 | gem 'stove' 9 | 10 | group :lint do 11 | gem 'cookstyle' 12 | end 13 | 14 | group :unit do 15 | gem 'chefspec' 16 | end 17 | 18 | group :integration do 19 | gem 'kitchen-inspec', '~> 2.4' 20 | gem 'train', '~> 3.7' 21 | gem 'inspec', '~> 4.37' 22 | end 23 | 24 | group :kitchen_common do 25 | gem 'test-kitchen', '~> 2.12' 26 | end 27 | 28 | group :kitchen_vagrant do 29 | gem 'kitchen-vagrant', '~> 1.8' 30 | end 31 | 32 | group :kitchen_docker do 33 | gem 'kitchen-docker' 34 | end 35 | 36 | group :kitchen_dokken do 37 | gem 'kitchen-dokken', '~> 2.13' 38 | end 39 | 40 | group :kitchen_cloud do 41 | gem 'kitchen-ec2' 42 | gem 'kitchen-digitalocean' 43 | end 44 | 45 | group :development do 46 | gem 'ruby_gntp' 47 | gem 'growl' 48 | gem 'rb-fsevent' 49 | gem 'guard' 50 | gem 'guard-kitchen' 51 | gem 'guard-foodcritic' 52 | gem 'guard-rspec' 53 | gem 'guard-rubocop' 54 | gem 'rake' 55 | end 56 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/cook-openfiles.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: cook-openfiles 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | node.override['rabbitmq']['open_file_limit'] = 2048 20 | include_recipe 'rabbitmq::default' 21 | 22 | # HACK: Give rabbit time to spin up before the tests, it seems 23 | # # to be responding that it has started before it really has 24 | execute 'sleep 10' do 25 | action :nothing 26 | subscribes :run, "service[#{node['rabbitmq']['service_name']}]", :delayed 27 | end 28 | -------------------------------------------------------------------------------- /recipes/management_ui.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: mgmt_console 5 | # 6 | # Copyright 2012, Tacit Knowledge, Inc. 7 | # Copyright 2013-2018, Chef Software, Inc. 8 | # Copyright 2018-2019, VMware, Inc. or its affiliates 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | include_recipe 'rabbitmq::default' 24 | 25 | plugins = %w(rabbitmq_management) 26 | 27 | service_name = node['rabbitmq']['service_name'] 28 | 29 | plugins.each do |plugin| 30 | rabbitmq_plugin plugin do 31 | action :enable 32 | notifies :restart, "service[#{service_name}]", :immediately 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/mgmt_console.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: mgmt_console 5 | # 6 | # Copyright 2012-2013, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | include_recipe 'rabbitmq::mgmt_console' 23 | 24 | # HACK: Give rabbit time to spin up before the tests, it seems 25 | # to be responding that it has started before it really has 26 | execute 'sleep 10' do 27 | action :nothing 28 | subscribes :run, "service[#{node['rabbitmq']['service_name']}]", :delayed 29 | end 30 | -------------------------------------------------------------------------------- /recipes/vhosts.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: vhosts 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::default' 25 | 26 | node['rabbitmq']['virtualhosts'].each do |virtualhost| 27 | rabbitmq_vhost virtualhost do 28 | action :add 29 | end 30 | end 31 | 32 | node['rabbitmq']['disabled_virtualhosts'].each do |virtualhost| 33 | rabbitmq_vhost virtualhost do 34 | action :delete 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/policies_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::policies' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | let(:chef_run) do 8 | node.override['rabbitmq']['policies']['ha-all']['pattern'] = '^(?!amq\\.).*' 9 | node.override['rabbitmq']['policies']['ha-all']['params'] = { 'ha-mode' => 'all' } 10 | node.override['rabbitmq']['policies']['ha-all']['priority'] = 0 11 | node.override['rabbitmq']['policies']['ha-two']['pattern'] = '^two.' 12 | node.override['rabbitmq']['policies']['ha-two']['params'] = { 'ha-mode' => 'exactly', 'ha-params' => 2 } 13 | node.override['rabbitmq']['policies']['ha-two']['priority'] = 1 14 | runner.converge(described_recipe) 15 | end 16 | 17 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 18 | 19 | it 'includes the `default` recipe' do 20 | expect(chef_run).to include_recipe('rabbitmq::default') 21 | end 22 | 23 | it 'sets a rabbitmq policy ha-all' do 24 | expect(chef_run).to set_rabbitmq_policy('ha-all') 25 | end 26 | 27 | it 'sets a rabbitmq policy ha-two' do 28 | expect(chef_run).to set_rabbitmq_policy('ha-two') 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/cluster_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Spec:: cluster 5 | # 6 | # Author: Sunggun Yu 7 | # Copyright (C) 2015 Sunggun Yu 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | require 'spec_helper' 23 | 24 | describe 'rabbitmq::cluster' do 25 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 26 | let(:node) { runner.node } 27 | cached(:chef_run) do 28 | runner.converge('rabbitmq::cluster') 29 | end 30 | 31 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 32 | 33 | it 'includes the `default` recipe' do 34 | expect(chef_run).to include_recipe('rabbitmq::default') 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: default 5 | # 6 | # Copyright 2012-2017, Chef Software, Inc. 7 | # Copyright 2017-2019, VMware, Inc. or its affiliates 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | apt_update if platform_family?('debian') 23 | 24 | include_recipe 'rabbitmq::default' 25 | 26 | # HACK: Give rabbit time to spin up before the tests, it seems 27 | # to be responding that it has started before it really has 28 | execute 'sleep 15' do 29 | action :nothing 30 | subscribes :run, "service[#{node['rabbitmq']['service_name']}]", :delayed 31 | end 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for using RabbitMQ and for taking the time to report an 2 | issue. 3 | 4 | ## Does This Belong to GitHub or RabbitMQ Mailing List? 5 | 6 | *Important:* please first read the `CONTRIBUTING.md` document in the 7 | root of this repository. It will help you determine whether your 8 | feedback should be directed to the RabbitMQ mailing list [1] instead. 9 | 10 | ## Please Help Maintainers and Contributors Help You 11 | 12 | In order for the RabbitMQ team to investigate your issue, please provide 13 | **as much as possible** of the following details: 14 | 15 | * Cookbook version used 16 | * Operating system, version, and patch level 17 | * Node attributes 18 | * RabbitMQ version provisioned 19 | * Erlang version provisioned 20 | * RabbitMQ server and client application log files 21 | * Brief instructions that can be used to reproduce the issue e.g. with Vagrant and `chef-solo` 22 | 23 | This information **greatly speeds up issue investigation** (or makes it 24 | possible to investigate it at all). Please help project maintainers and 25 | contributors to help you by providing it! 26 | 27 | 1. https://groups.google.com/forum/#!forum/rabbitmq-users 28 | 2. https://github.com/rabbitmq/support-tools/blob/master/scripts/rabbitmq-collect-env 29 | -------------------------------------------------------------------------------- /recipes/plugins.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: plugins 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::default' 25 | 26 | node['rabbitmq']['enabled_plugins'].each do |plugin| 27 | rabbitmq_plugin plugin do 28 | action :enable 29 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 30 | end 31 | end 32 | 33 | node['rabbitmq']['disabled_plugins'].each do |plugin| 34 | rabbitmq_plugin plugin do 35 | action :disable 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/erlang_package/latest_deb/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | %w( 5 | erlang-asn1 erlang-crypto erlang-public-key erlang-ssl erlang-syntax-tools 6 | erlang-mnesia erlang-runtime-tools erlang-snmp erlang-os-mon erlang-parsetools 7 | erlang-inets erlang-tools erlang-eldap erlang-xmerl 8 | erlang-dev erlang-edoc erlang-eunit erlang-erl-docgen erlang-src 9 | ).each do |p| 10 | describe package(p) do 11 | it { should be_installed } 12 | end 13 | end 14 | 15 | describe package('rabbitmq-server') do 16 | it { should be_installed } 17 | end 18 | 19 | describe service('rabbitmq-server') do 20 | it { should be_running } 21 | end 22 | 23 | describe command('erl') do 24 | it { should exist } 25 | end 26 | 27 | describe command('epmd') do 28 | it { should exist } 29 | end 30 | 31 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 32 | its(:exit_status) { should eq 0 } 33 | end 34 | 35 | describe command('HOSTNAME=$(hostname) rabbitmqctl ping') do 36 | its(:exit_status) { should eq 0 } 37 | end 38 | 39 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list') do 40 | its(:exit_status) { should eq 0 } 41 | end 42 | -------------------------------------------------------------------------------- /spec/community_plugins_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::community_plugins' do 5 | let(:runner) { ChefSpec::ServerRunner.new(REDHAT_OPTS) } 6 | let(:node) { runner.node } 7 | let(:chef_run) do 8 | node.override['rabbitmq']['community_plugins'] = { 'rabbitmq_community_plugin' => 'http://sample.com/rabbitmq_community_plugin.ez' } 9 | runner.converge(described_recipe) 10 | end 11 | 12 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 13 | 14 | it 'includes the `default` recipe' do 15 | expect(chef_run).to include_recipe('rabbitmq::default') 16 | end 17 | 18 | plugins = { 'rabbitmq_community_plugin' => 'http://sample.com/rabbitmq_community_plugin.ez' } 19 | 20 | plugins.each do |plugin, download_url| 21 | it 'creates the remote files with attributes' do 22 | expect(chef_run).to create_remote_file("/usr/lib/rabbitmq/lib/rabbitmq_server-#{node['rabbitmq']['version']}/plugins/#{plugin}.ez").with( 23 | :source => download_url, 24 | :owner => 'rabbitmq', 25 | :group => 'rabbitmq', 26 | :mode => '644' 27 | ) 28 | end 29 | 30 | it 'enables community plugins' do 31 | expect(chef_run).to enable_rabbitmq_plugin(plugin) 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/erlang_package/pinned_deb/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | %w( 5 | erlang-asn1 erlang-crypto erlang-public-key erlang-ssl erlang-syntax-tools 6 | erlang-mnesia erlang-runtime-tools erlang-snmp erlang-os-mon erlang-parsetools 7 | erlang-inets erlang-tools erlang-eldap erlang-xmerl 8 | erlang-dev erlang-edoc erlang-eunit erlang-erl-docgen erlang-src 9 | ).each do |p| 10 | describe package(p) do 11 | it { should be_installed } 12 | its('version') { should match(/^1:2(3|4)/) } 13 | end 14 | end 15 | 16 | describe package('rabbitmq-server') do 17 | it { should be_installed } 18 | end 19 | 20 | describe service('rabbitmq-server') do 21 | it { should be_running } 22 | end 23 | 24 | describe command('erl') do 25 | it { should exist } 26 | end 27 | 28 | describe command('epmd') do 29 | it { should exist } 30 | end 31 | 32 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 33 | its(:exit_status) { should eq 0 } 34 | end 35 | 36 | describe command('HOSTNAME=$(hostname) rabbitmqctl ping') do 37 | its(:exit_status) { should eq 0 } 38 | end 39 | 40 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list') do 41 | its(:exit_status) { should eq 0 } 42 | end 43 | -------------------------------------------------------------------------------- /recipes/policies.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: policies 5 | # 6 | # Author: Robert Choi 7 | # Copyright 2013 by Robert Choi 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::default' 25 | 26 | node['rabbitmq']['policies'].each do |name, policy| 27 | rabbitmq_policy name do 28 | pattern policy['pattern'] 29 | definition policy['params'] 30 | priority policy['priority'] 31 | vhost policy['vhost'] 32 | apply_to policy['apply_to'] 33 | action :set 34 | end 35 | end 36 | 37 | node['rabbitmq']['disabled_policies'].each do |policy| 38 | rabbitmq_policy policy do 39 | action :clear 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | # frozen_string_literal: true 3 | 4 | # Style tests. cookstyle (rubocop) and Foodcritic 5 | namespace :style do 6 | begin 7 | require 'cookstyle' 8 | require 'rubocop/rake_task' 9 | 10 | desc 'Run Ruby style checks' 11 | RuboCop::RakeTask.new(:ruby) 12 | rescue LoadError => e 13 | puts ">>> Gem load error: #{e}, omitting style:ruby" unless ENV['CI'] 14 | end 15 | end 16 | 17 | desc 'Run all style checks' 18 | task :style => ['style:ruby'] 19 | 20 | # ChefSpec 21 | begin 22 | require 'rspec/core/rake_task' 23 | 24 | desc 'Run ChefSpec examples' 25 | RSpec::Core::RakeTask.new(:spec) 26 | rescue LoadError => e 27 | puts ">>> Gem load error: #{e}, omitting spec" unless ENV['CI'] 28 | end 29 | 30 | # Integration tests. Kitchen.ci 31 | namespace :integration do 32 | begin 33 | require 'kitchen/rake_tasks' 34 | 35 | desc 'Run kitchen integration tests' 36 | Kitchen::RakeTasks.new 37 | rescue StandardError => e 38 | puts ">>> Kitchen error: #{e}, omitting #{task.name}" unless ENV['CI'] 39 | end 40 | end 41 | 42 | namespace :supermarket do 43 | begin 44 | require 'stove/rake_task' 45 | 46 | desc 'Publish cookbook to Supermarket with Stove' 47 | Stove::RakeTask.new 48 | rescue LoadError => e 49 | puts ">>> Gem load error: #{e}, omitting #{task.name}" unless ENV['CI'] 50 | end 51 | end 52 | 53 | # Default 54 | task :default => %w(style spec) 55 | -------------------------------------------------------------------------------- /templates/default/rabbitmq-env.conf.erb: -------------------------------------------------------------------------------- 1 | ### 2 | # Generated by Chef 3 | ### 4 | 5 | <% if node['rabbitmq']['local_erl_networking'] -%> 6 | NODENAME=rabbit@localhost 7 | NODE_IP_ADDRESS=127.0.0.1 8 | export ERL_EPMD_ADDRESS=127.0.0.1 9 | <% elsif node['rabbitmq']['erl_networking_bind_address'] -%> 10 | NODENAME=<%= node['rabbitmq']['nodename'] %> 11 | NODE_IP_ADDRESS=<%= node['rabbitmq']['erl_networking_bind_address'] %> 12 | export ERL_EPMD_ADDRESS=<%= node['rabbitmq']['erl_networking_bind_address'] %> 13 | <% else -%> 14 | <% if node['rabbitmq']['address'] -%>NODE_IP_ADDRESS=<%= node['rabbitmq']['address'] %><% end %> 15 | <% if node['rabbitmq']['nodename'] -%>NODENAME=<%= node['rabbitmq']['nodename'] %><% end %> 16 | <% end -%> 17 | <% if node['rabbitmq']['port'] -%>NODE_PORT=<%= node['rabbitmq']['port'] %><% end %> 18 | <% if node['rabbitmq']['config'] -%>CONFIG_FILE=<%= @config_path %><% end %> 19 | <% if node['rabbitmq']['logdir'] -%>LOG_BASE=<%= node['rabbitmq']['logdir'] %><% end %> 20 | <% if node['rabbitmq']['mnesiadir'] -%>MNESIA_BASE=<%= node['rabbitmq']['mnesiadir'] %><% end %> 21 | <% if node['rabbitmq']['server_additional_erl_args'] -%>SERVER_ADDITIONAL_ERL_ARGS='<%= node['rabbitmq']['server_additional_erl_args'] %>'<% end %> 22 | <% if node['rabbitmq']['ctl_erl_args'] -%>CTL_ERL_ARGS='<%= node['rabbitmq']['ctl_erl_args'] %>'<% end %> 23 | <% if node['rabbitmq']['additional_env_settings'] -%> 24 | # Additional ENV settings 25 | <% node['rabbitmq']['additional_env_settings'].each do |line| -%> 26 | <%= line %> 27 | <% end -%> 28 | <% end -%> 29 | -------------------------------------------------------------------------------- /test/integration/default/default_spec.rb: -------------------------------------------------------------------------------- 1 | # The Inspec reference, with examples and extensive documentation, can be 2 | # found at https://inspec.io/docs/reference/resources/ 3 | 4 | describe package('rabbitmq-server') do 5 | it { should be_installed } 6 | end 7 | 8 | describe service('rabbitmq-server') do 9 | it { should be_running } 10 | end 11 | 12 | # make sure HOSTNAME is set which seems not to be the case with The 13 | # Centos 6 Docker image 14 | describe command('HOSTNAME=$(hostname) rabbitmqctl status') do 15 | its(:exit_status) { should eq 0 } 16 | end 17 | 18 | describe command('HOSTNAME=$(hostname) rabbitmq-diagnostics ping') do 19 | its(:exit_status) { should eq 0 } 20 | end 21 | 22 | describe command('HOSTNAME=$(hostname) rabbitmq-plugins list') do 23 | its(:exit_status) { should eq 0 } 24 | end 25 | 26 | describe port(5672) do 27 | it { should be_listening } 28 | end 29 | 30 | describe file('/var/lib/rabbitmq/mnesia') do 31 | it { should be_directory } 32 | its('mode') { should cmp '0775' } 33 | its('owner') { should eq 'rabbitmq' } 34 | its('group') { should eq 'rabbitmq' } 35 | end 36 | 37 | describe file('/etc/rabbitmq/rabbitmq-env.conf') do 38 | it { should be_file } 39 | its('owner') { should eq 'root' } 40 | its('group') { should eq 'root' } 41 | 42 | its('content') { should match(%r{CONFIG_FILE=/etc/rabbitmq/rabbitmq.config}) } 43 | end 44 | 45 | describe file('/etc/rabbitmq/rabbitmq.config') do 46 | it { should be_file } 47 | its('owner') { should eq 'root' } 48 | its('group') { should eq 'root' } 49 | end 50 | -------------------------------------------------------------------------------- /recipes/community_plugins.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: community_plugins 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::default' 25 | 26 | node['rabbitmq']['community_plugins'].each do |plugin, download_url| 27 | # This will only work for deb/rpm installations, such as Ubuntu, Fedora and CentOS 28 | # List of installation directory per installation method: https://www.rabbitmq.com/installing-plugins.html 29 | remote_file "/usr/lib/rabbitmq/lib/rabbitmq_server-#{node['rabbitmq']['version']}/plugins/#{plugin}.ez" do 30 | source download_url 31 | owner 'rabbitmq' 32 | group 'rabbitmq' 33 | mode '644' 34 | end 35 | 36 | rabbitmq_plugin plugin do 37 | action :enable 38 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /recipes/systemd_limits.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: systemd_limits 5 | # 6 | # Configures kernel limits on systemd-based distributions 7 | # using a systemd unit file. 8 | # For older distributions, use a separate cookbook such as 9 | # ulimit2. 10 | # 11 | # Copyright 2018-2021, VMware, Inc or its affiliates. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "License"); 14 | # you may not use this file except in compliance with the License. 15 | # You may obtain a copy of the License at 16 | # 17 | # https://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the License is distributed on an "AS IS" BASIS, 21 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | # See the License for the specific language governing permissions and 23 | # limitations under the License. 24 | # 25 | 26 | include_recipe 'rabbitmq::default' 27 | 28 | directory node['rabbitmq']['systemd_unit_root'] do 29 | owner 'root' 30 | group 'root' 31 | mode '775' 32 | recursive true 33 | end 34 | 35 | template "#{node['rabbitmq']['systemd_unit_root']}/limits.conf" do 36 | source 'systemd_limits.conf.erb' 37 | cookbook node['rabbitmq']['config-env_template_cookbook'] 38 | owner 'root' 39 | group 'root' 40 | mode '644' 41 | notifies :run, 'execute[systemctl daemon-reload]', :immediately 42 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 43 | end 44 | 45 | execute 'systemctl daemon-reload' do 46 | command 'systemctl daemon-reload' 47 | 48 | action :nothing 49 | retries 3 50 | retry_delay 3 51 | end 52 | -------------------------------------------------------------------------------- /recipes/cluster.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: cluster 5 | # 6 | # Author: Sunggun Yu 7 | # Copyright 2015 Sunggun Yu 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | require 'json' 24 | 25 | include_recipe 'rabbitmq::default' 26 | 27 | cluster_nodes = node['rabbitmq']['clustering']['cluster_nodes'] 28 | cluster_nodes = cluster_nodes.to_json 29 | 30 | auto_cluster_nodes = cluster_nodes 31 | static_cluster_nodes = cluster_nodes 32 | 33 | # Manual clustering 34 | unless node['rabbitmq']['clustering']['use_auto_clustering'] 35 | # Join in cluster 36 | rabbitmq_cluster auto_cluster_nodes do 37 | cluster_name node['rabbitmq']['clustering']['cluster_name'] 38 | action :join 39 | end 40 | end 41 | 42 | # Set cluster name : It will be skipped once same cluster name has been set in the cluster. 43 | rabbitmq_cluster static_cluster_nodes do 44 | cluster_name node['rabbitmq']['clustering']['cluster_name'] 45 | action [:set_cluster_name, :change_cluster_node_type] 46 | end 47 | -------------------------------------------------------------------------------- /recipes/users.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # frozen_string_literal: true 3 | # 4 | # Cookbook Name:: rabbitmq 5 | # Recipe:: users 6 | # 7 | # Copyright 2013, Grégoire Seux 8 | # Copyright 2013-2018, Chef Software, Inc. 9 | # Copyright 2018-2019, VMware, Inc. or its affiliates 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | include_recipe 'rabbitmq::default' 25 | include_recipe 'rabbitmq::vhosts' 26 | 27 | node['rabbitmq']['enabled_users'].each do |user| 28 | rabbitmq_user "add-#{user['name']}" do 29 | user user['name'] 30 | password user['password'] 31 | action :add 32 | 33 | notifies :set_tags, "rabbitmq_user[set-tags-#{user['name']}]", :immediately 34 | end 35 | rabbitmq_user "set-tags-#{user['name']}" do 36 | user user['name'] 37 | tag user['tag'] 38 | action :set_tags 39 | end 40 | user['rights'].each do |r| 41 | rabbitmq_user "set-perms-#{user['name']}-vhost-#{Array(r['vhost']).join().tr('/', '_')}" do 42 | user user['name'] 43 | vhost r['vhost'] if r['vhost'] 44 | permissions "#{r['conf']} #{r['write']} #{r['read']}" 45 | action :set_permissions 46 | end 47 | end 48 | end 49 | 50 | node['rabbitmq']['disabled_users'].each do |user| 51 | rabbitmq_user "delete-#{user}" do 52 | user user 53 | action :delete 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /resources/vhost.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: vhost 5 | # 6 | # Copyright 2011-201, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | unified_mode true if respond_to?(:unified_mode) 23 | 24 | property :vhost, String, name_property: true 25 | 26 | action_class do 27 | include RabbitMQ::CoreHelpers 28 | 29 | def vhost_exists?(name) 30 | cmd = "rabbitmqctl -q list_vhosts | grep ^#{name}$" 31 | cmd = Mixlib::ShellOut.new(cmd, :env => shell_environment) 32 | cmd.run_command 33 | Chef::Log.debug "rabbitmq_vhost_exists?: #{cmd}" 34 | Chef::Log.debug "rabbitmq_vhost_exists?: #{cmd.stdout}" 35 | !cmd.error? 36 | end 37 | end 38 | 39 | action :add do 40 | cmd = "rabbitmqctl -q add_vhost #{new_resource.vhost}" 41 | execute cmd do 42 | Chef::Log.debug "rabbitmq_vhost_add: #{cmd}" 43 | Chef::Log.info "Adding RabbitMQ vhost '#{new_resource.vhost}'." 44 | environment shell_environment 45 | not_if { vhost_exists?(new_resource.vhost) } 46 | end 47 | end 48 | 49 | action :delete do 50 | cmd = "rabbitmqctl -q delete_vhost #{new_resource.vhost}" 51 | execute cmd do 52 | Chef::Log.debug "rabbitmq_vhost_delete: #{cmd}" 53 | Chef::Log.info "Deleting RabbitMQ vhost '#{new_resource.vhost}'." 54 | environment shell_environment 55 | only_if { vhost_exists?(new_resource.vhost) } 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | 3 | Please describe the big picture of your changes here to communicate to the 4 | RabbitMQ team why we should accept this pull request. If it fixes a bug or 5 | resolves a feature request, be sure to link to that issue. 6 | 7 | A pull request that doesn't explain **why** the change was made has a much 8 | lower chance of being accepted. 9 | 10 | If English isn't your first language, don't worry about it and try to 11 | communicate the problem you are trying to solve to the best of your abilities. 12 | As long as we can understand the intent, it's all good. 13 | 14 | ## Types of Changes 15 | 16 | What types of changes does your code introduce to this project? 17 | _Put an `x` in the boxes that apply_ 18 | 19 | - [ ] Bug fix (non-breaking change which fixes issue #NNNN) 20 | - [ ] New feature (non-breaking change which adds functionality) 21 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 22 | - [ ] Documentation (correction or otherwise) 23 | - [ ] Cosmetics (whitespace, appearance) 24 | 25 | ## Checklist 26 | 27 | _Put an `x` in the boxes that apply. You can also fill these out after creating 28 | the PR. If you're unsure about any of them, don't hesitate to ask on the 29 | mailing list. We're here to help! This is simply a reminder of what we are 30 | going to look for before merging your code._ 31 | 32 | - [ ] I have read the `CONTRIBUTING.md` document 33 | - [ ] I have signed the CA (see https://cla.pivotal.io/sign/rabbitmq) 34 | - [ ] All tests pass locally with my changes 35 | - [ ] I have added tests that prove my fix is effective or that my feature works 36 | - [ ] I have added necessary documentation (if appropriate) 37 | - [ ] Any dependent changes have been merged and published in related repositories 38 | 39 | ## Further Comments 40 | 41 | If this is a relatively large or complex change, kick off the discussion by 42 | explaining why you chose the solution you did and what alternatives you 43 | considered, etc. 44 | -------------------------------------------------------------------------------- /resources/erlang_apt_repository_on_cloudsmith.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: erlang_apt_repository_on_cloudsmith 5 | # 6 | # Copyright 2019-2021, VMware, Inc. or its affiliates 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # https://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | 21 | unified_mode true if respond_to?(:unified_mode) 22 | 23 | default_action :add 24 | 25 | property :uri, String, default: '' 26 | property :distribution, String 27 | property :components, Array, default: ['erlang'] 28 | property :key, String, default: '' 29 | property :keyserver, String 30 | 31 | property :trusted, [true, false], default: false 32 | 33 | provides :erlang_repository, platform_family: %w(debian) 34 | 35 | action :add do 36 | package 'apt-transport-https' 37 | 38 | apt_repository(new_resource.name) do 39 | uri new_resource.uri 40 | distribution new_resource.distribution if new_resource.distribution 41 | components new_resource.components 42 | key new_resource.key 43 | keyserver new_resource.keyserver if new_resource.keyserver 44 | trusted new_resource.trusted 45 | 46 | action :add 47 | end 48 | 49 | apt_preference(new_resource.name) do 50 | glob 'erlang*' 51 | pin 'release o=cloudsmith' 52 | pin_priority '800' 53 | 54 | action :add 55 | end 56 | end 57 | 58 | action :remove do 59 | apt_repository(new_resource.name) do 60 | action :remove 61 | end 62 | 63 | apt_preference(new_resource.name) do 64 | action :remove 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /resources/erlang_zypper_repository_on_suse_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Provider:: erlang_yum_repository_on_cloudsmith 5 | # 6 | # Copyright 2019-2021, VMware, Inc. or its affiliates 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # https://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | 21 | unified_mode true if respond_to?(:unified_mode) 22 | 23 | provides :erlang_repository, platform_family: %w(suse) 24 | 25 | default_action :create 26 | 27 | property :baseurl, String, required: true 28 | 29 | property :gpgcheck, [true, false], default: true 30 | property :gpgkey, String 31 | property :gpgautoimportkeys, [true, false], default: true 32 | 33 | property :enabled, [true, false], default: true 34 | property :priority, Integer 35 | 36 | action :create do 37 | execute 'zypper refresh' do 38 | command 'zypper --gpg-auto-import-keys refresh' 39 | # triggered by a notification 40 | action :nothing 41 | end 42 | 43 | zypper_repository(new_resource.name) do 44 | description 'Erlang RPM packages from SUSE' 45 | 46 | baseurl new_resource.baseurl 47 | gpgcheck new_resource.gpgcheck 48 | gpgkey new_resource.gpgkey if new_resource.gpgkey 49 | gpgautoimportkeys new_resource.gpgautoimportkeys 50 | 51 | autorefresh true 52 | 53 | enabled new_resource.enabled 54 | priority new_resource.priority if new_resource.priority 55 | 56 | notifies :run, 'execute[zypper refresh]', :immediately 57 | 58 | action :create 59 | end 60 | end 61 | 62 | action :remove do 63 | zypper_repository(new_resource.name) do 64 | action :remove 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /resources/plugin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: plugin 5 | # 6 | # Copyright 2011-2019, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | unified_mode true if respond_to?(:unified_mode) 23 | 24 | default_action :enable 25 | 26 | property :plugin, String, name_property: true 27 | 28 | action_class do 29 | include RabbitMQ::CoreHelpers 30 | 31 | def plugin_enabled?(name) 32 | cmdstr = "/usr/lib/rabbitmq/bin/rabbitmq-plugins list -q -e '#{name}\\b'" 33 | cmd = Mixlib::ShellOut.new(cmdstr, :env => shell_environment) 34 | cmd.run_command 35 | Chef::Log.debug "rabbitmq_plugin_enabled?: #{cmdstr}" 36 | Chef::Log.debug "rabbitmq_plugin_enabled?: #{cmd.stdout}" 37 | cmd.error! 38 | cmd.stdout =~ /\b#{name}\b/ 39 | end 40 | end 41 | 42 | action :enable do 43 | execute "rabbitmq-plugins enable #{new_resource.plugin}" do 44 | command "/usr/lib/rabbitmq/bin/rabbitmq-plugins enable #{new_resource.plugin}" 45 | umask '0022' 46 | Chef::Log.info "Enabling RabbitMQ plugin '#{new_resource.plugin}'." 47 | environment shell_environment 48 | not_if { plugin_enabled?(new_resource.plugin) } 49 | end 50 | end 51 | 52 | action :disable do 53 | execute "rabbitmq-plugins disable #{new_resource.plugin}" do 54 | command "/usr/lib/rabbitmq/bin/rabbitmq-plugins disable #{new_resource.plugin}" 55 | umask '0022' 56 | Chef::Log.info "Disabling RabbitMQ plugin '#{new_resource.plugin}'." 57 | environment shell_environment 58 | only_if { plugin_enabled?(new_resource.plugin) } 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /resources/parameter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: parameter 5 | # 6 | # Author: Sean Porter 7 | # Copyright 2015 by Sean Porter 8 | # Copyright 2019-2021, VMware, Inc or its affiliates. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | unified_mode true if respond_to?(:unified_mode) 24 | 25 | default_action :set 26 | 27 | property :parameter, String, name_property: true 28 | property :component, String 29 | property :vhost, String, default: '/' 30 | property :parameters, [Hash, Array], default: {} 31 | 32 | action_class do 33 | include RabbitMQ::CoreHelpers 34 | 35 | def parameter_exists?(vhost, name) 36 | cmd = 'rabbitmqctl list_parameters -s' 37 | cmd += " -p #{Shellwords.escape vhost}" unless vhost.nil? 38 | cmd += " |grep '#{name}\\b'" 39 | 40 | cmd = Mixlib::ShellOut.new(cmd, :env => shell_environment) 41 | cmd.run_command 42 | !cmd.error? 43 | end 44 | end 45 | 46 | action :set do 47 | cmd = 'rabbitmqctl set_parameter -q' 48 | cmd += " -p #{new_resource.vhost}" 49 | cmd += " #{new_resource.component}" 50 | cmd += " #{new_resource.parameter}" 51 | 52 | cmd += " '" 53 | cmd += JSON.dump(new_resource.parameters) 54 | cmd += "'" 55 | 56 | parameter = "#{new_resource.component} #{new_resource.parameter}" 57 | 58 | execute "set_parameter #{parameter}" do 59 | command cmd 60 | environment shell_environment 61 | not_if { parameter_exists?(new_resource.vhost, new_resource.parameter) } 62 | end 63 | 64 | Chef::Log.info "Done setting RabbitMQ parameter #{parameter}." 65 | end 66 | 67 | action :clear do 68 | parameter = "#{new_resource.component} #{new_resource.parameter}" 69 | 70 | cmd = "rabbitmqctl clear_parameter #{parameter} -q -p #{new_resource.vhost}" 71 | execute "clear_parameter #{parameter}" do 72 | command cmd 73 | environment shell_environment 74 | only_if { parameter_exists?(new_resource.vhost, new_resource.parameter) } 75 | end 76 | 77 | Chef::Log.info "Done clearing RabbitMQ parameter #{parameter}." 78 | end 79 | -------------------------------------------------------------------------------- /resources/erlang_yum_repository_on_cloudsmith.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: erlang_yum_repository_on_cloudsmith 5 | # 6 | # Copyright 2019-2021, VMware, Inc. or its affiliates 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # https://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | 21 | unified_mode true if respond_to?(:unified_mode) 22 | 23 | provides :erlang_repository, platform_family: %w(rhel fedora amazon) 24 | 25 | default_action :create 26 | 27 | property :baseurl, String, required: true 28 | 29 | property :gpgcheck, [true, false], default: true 30 | property :gpgkey, String 31 | 32 | property :repo_gpgcheck, [true, false], default: true 33 | property :repositoryid, String 34 | property :enabled, [true, false], default: true 35 | property :priority, String 36 | 37 | property :proxy, String 38 | property :proxy_username, String 39 | property :proxy_password, String 40 | 41 | property :sslcacert, String 42 | property :sslclientcert, String 43 | property :sslclientkey, String 44 | property :sslverify, [true, false] 45 | 46 | property :timeout, String 47 | 48 | action :create do 49 | yum_repository(new_resource.name) do 50 | description 'Erlang RPM packages from Team RabbitMQ' 51 | 52 | baseurl new_resource.baseurl 53 | gpgcheck new_resource.gpgcheck 54 | gpgkey new_resource.gpgkey if new_resource.gpgkey 55 | 56 | repo_gpgcheck new_resource.repo_gpgcheck 57 | repositoryid new_resource.repositoryid if new_resource.repositoryid 58 | enabled new_resource.enabled 59 | priority new_resource.priority if new_resource.priority 60 | 61 | proxy new_resource.proxy if new_resource.proxy 62 | proxy_username new_resource.proxy_username if new_resource.proxy_username 63 | proxy_password new_resource.proxy_password if new_resource.proxy_password 64 | 65 | sslcacert new_resource.sslcacert if new_resource.sslcacert 66 | sslclientcert new_resource.sslclientcert if new_resource.sslclientcert 67 | sslclientkey new_resource.sslclientkey if new_resource.sslclientkey 68 | sslverify new_resource.sslverify if new_resource.sslverify 69 | 70 | timeout new_resource.timeout if new_resource.timeout 71 | 72 | action :create 73 | end 74 | end 75 | 76 | action :remove do 77 | yum_repository(new_resource.name) do 78 | action :remove 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /test/cookbooks/rabbitmq_test/recipes/lwrps.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq_test 4 | # Recipe:: lwrps 5 | # 6 | # Copyright 2013, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | include_recipe 'rabbitmq::default' 23 | 24 | # force the rabbitmq restart now, then start testing 25 | execute 'sleep 10' do 26 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]", :immediately 27 | end 28 | 29 | include_recipe 'rabbitmq::plugins' 30 | include_recipe 'rabbitmq::vhosts' 31 | include_recipe 'rabbitmq::policies' 32 | include_recipe 'rabbitmq::users' 33 | 34 | # can't verify it actually goes through without logging in, but at least exercise the code 35 | rabbitmq_user 'kitchen3' do 36 | password 'foobar' 37 | action :change_password 38 | end 39 | 40 | rabbitmq_user 'permissionless' do 41 | password 'permi$$ionless' 42 | action :add 43 | end 44 | 45 | rabbitmq_user 'permissionless' do 46 | action :clear_permissions 47 | end 48 | 49 | rabbitmq_user 'kitchen4' do 50 | password 'kitchen4' 51 | action :add 52 | end 53 | 54 | rabbitmq_user 'kitchen4' do 55 | password 'kitchen4' 56 | # see #565 57 | permissions "'.*' '^amq\\.default$' '.*'" 58 | action :set_permissions 59 | end 60 | 61 | # download the rabbitmqadmin util from management plugin 62 | # this tests an immediate notifies statement 63 | # see https://github.com/kennonkwok/rabbitmq/issues/141 64 | rabbitmq_plugin 'rabbitmq_management' do 65 | action :enable 66 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]", :immediately # must restart before we can download 67 | end 68 | 69 | rabbitmq_plugin 'rabbitmq_top' do 70 | action :disable 71 | end 72 | 73 | rabbitmq_policy 'queue_length_limit' do 74 | pattern 'limited.*' 75 | definition 'max-length' => 1000 76 | apply_to 'queues' 77 | action :set 78 | end 79 | 80 | rabbitmq_plugin 'rabbitmq_federation' do 81 | # this plugin does not work until we restart 82 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]", :immediately 83 | end 84 | 85 | rabbitmq_vhost 'sensu' 86 | 87 | rabbitmq_parameter 'sensu-dc-1' do 88 | vhost 'sensu' 89 | component 'federation-upstream' 90 | parameters 'uri' => 'amqp://dc-cluster-node' 91 | end 92 | -------------------------------------------------------------------------------- /resources/policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: policy 5 | # 6 | # Author: Robert Choi 7 | # Copyright 2013 by Robert Choi 8 | # Copyright 2019-2021, VMware, Inc or its affiliates. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | unified_mode true if respond_to?(:unified_mode) 24 | 25 | default_action :set 26 | 27 | property :policy, String, name_property: true 28 | property :pattern, String 29 | property :definition, Hash 30 | property :priority, Integer, default: 0 31 | property :apply_to, String, :equal_to => %w(all queues exchanges), default: 'all' 32 | property :vhost, String, default: '/' 33 | 34 | deprecated_property_alias 'parameters', 35 | 'definition', 36 | 'The \"parameters\" property has been renamed \"definition\". '\ 37 | 'Please update your cookbooks to use the new property name.' 38 | 39 | action_class do 40 | include RabbitMQ::CoreHelpers 41 | end 42 | 43 | load_current_value do |new_resource| 44 | p = get_policy(new_resource.policy, new_resource.vhost) 45 | 46 | current_value_does_not_exist! unless p 47 | 48 | pattern p['pattern'] 49 | definition p['definition'] 50 | apply_to p['apply-to'] 51 | priority p['priority'] 52 | end 53 | 54 | action :set do 55 | # These properties are only required for the :set action 56 | [:pattern, :definition].each do |prop| 57 | raise( 58 | Chef::Exceptions::ValidationFailed, 59 | "#{prop} is a required property" 60 | ) unless property_is_set?(prop) 61 | end 62 | 63 | converge_if_changed do 64 | cmd = "rabbitmqctl -q set_policy -p #{new_resource.vhost}" 65 | cmd += " --apply-to #{new_resource.apply_to}" 66 | cmd += " #{new_resource.policy}" 67 | cmd += " \"#{new_resource.pattern}\"" 68 | cmd += " '#{new_resource.definition.to_json}'" 69 | cmd += " --priority #{new_resource.priority}" 70 | 71 | execute "set_policy #{new_resource.policy} on vhost #{new_resource.vhost}" do 72 | command cmd 73 | environment shell_environment 74 | end 75 | end 76 | end 77 | 78 | action :clear do 79 | execute "clear_policy #{new_resource.policy} from vhost #{new_resource.vhost}" do 80 | command "rabbitmqctl clear_policy #{new_resource.policy} -p #{new_resource.vhost}" 81 | environment shell_environment 82 | only_if { get_policy(new_resource.policy, new_resource.vhost) } 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /.kitchen.alphas.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: dokken 3 | chef_version: latest 4 | privileged: true # because Docker and SystemD/Upstart 5 | volumes: 6 | - /sys/fs/cgroup:/sys/fs/cgroup 7 | 8 | transport: 9 | name: dokken 10 | 11 | provisioner: 12 | name: dokken 13 | 14 | verifier: 15 | root_path: '/opt/verifier' 16 | sudo: false 17 | 18 | platforms: 19 | - name: centos-8 20 | driver: 21 | image: dokken/centos-stream-8 22 | platform: rhel 23 | pid_one_command: /usr/lib/systemd/systemd 24 | intermediate_instructions: 25 | - RUN yum -y install sudo lsof which systemd-sysv initscripts openssl net-tools 26 | 27 | - name: fedora-34 28 | driver: 29 | image: dokken/fedora-34 30 | pid_one_command: /usr/lib/systemd/systemd 31 | intermediate_instructions: 32 | - RUN dnf -y install sudo 33 | 34 | - name: ubuntu-20.04 35 | driver: 36 | image: dokken/ubuntu-20.04 37 | pid_one_command: /bin/systemd 38 | intermediate_instructions: 39 | - ENV DEBIAN_FRONTEND noninteractive 40 | - RUN /usr/bin/apt-get update -y 41 | - RUN /usr/bin/apt-get install -y ca-certificates sudo apt-transport-https lsb-release procps net-tools 42 | 43 | - name: debian-10 44 | driver: 45 | image: dokken/debian-10 46 | pid_one_command: /bin/systemd 47 | intermediate_instructions: 48 | - ENV DEBIAN_FRONTEND noninteractive 49 | - RUN /usr/bin/apt-get update -y 50 | - RUN /usr/bin/apt-get install -y ca-certificates sudo apt-transport-https lsb-release procps net-tools 51 | 52 | # 53 | # Suites 54 | # 55 | 56 | suites: 57 | - name: default-deb-alpha 58 | run_list: 59 | - recipe[erlang::default] 60 | - recipe[rabbitmq::plugins] 61 | attributes: 62 | erlang: 63 | install_method: "esl" 64 | esl: 65 | version: "1:24.0.2-1" 66 | rabbitmq: 67 | # export RABBITMQ_VERSION="3.9.0~alpha.543" 68 | version: <%= ENV['RABBITMQ_VERSION'] %> 69 | deb_package_url: "https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server-all-dev/raw/versions/<%= ENV['RABBITMQ_VERSION'] %>" 70 | deb_package: "rabbitmq-server_<%= ENV['RABBITMQ_VERSION'].to_s.gsub(/\-alpha/, "~alpha") %>-1_all.deb" 71 | 72 | verifier: 73 | inspec_tests: 74 | - test/integration/default 75 | includes: ["ubuntu-20.04", "debian-10"] 76 | 77 | - name: default-rpm-el8-alpha 78 | run_list: 79 | - recipe[rabbitmq::erlang_package] 80 | - recipe[rabbitmq::plugins] 81 | attributes: 82 | rabbitmq: 83 | erlang: 84 | enabled: true 85 | # export RABBITMQ_VERSION="3.8.18-alpha.8" 86 | version: <%= ENV['RABBITMQ_VERSION'] %> 87 | 88 | rpm_package_url: "https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-server-all-dev/raw/versions/<%= ENV['RABBITMQ_VERSION'] %>/" 89 | rpm_package: "rabbitmq-server-<%= ENV['RABBITMQ_VERSION'].to_s.gsub(/\-alpha/, "~alpha") %>-1.el8.noarch.rpm" 90 | verifier: 91 | inspec_tests: 92 | - test/integration/default 93 | includes: ["centos-8", "fedora-34"] 94 | -------------------------------------------------------------------------------- /spec/policy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'rabbitmq_policy' do 4 | step_into :rabbitmq_policy 5 | 6 | platform 'ubuntu' 7 | 8 | context 'when policies do not exist' do 9 | before do 10 | shellout = double 11 | allow(Mixlib::ShellOut).to receive(:new).with( 12 | /rabbitmqctl list_policies/, { env: { 'HOME' => // } } 13 | ).and_return(shellout) 14 | allow(shellout).to receive(:run_command).and_return(shellout) 15 | allow(shellout).to receive(:stdout).and_return('[]') 16 | end 17 | 18 | recipe do 19 | rabbitmq_policy 'potato' do 20 | pattern '^(?!amq\\.).*' 21 | definition( 22 | 'ha-mode' => 'exactly', 23 | 'ha-params' => 2, 24 | 'ha-sync-mode' => 'automatic' 25 | ) 26 | action :set 27 | end 28 | 29 | rabbitmq_policy 'tomato' do 30 | action :clear 31 | end 32 | end 33 | 34 | it 'sets the policy' do 35 | is_expected.to run_execute('set_policy potato on vhost /').with( 36 | command: 'rabbitmqctl -q set_policy -p / --apply-to all potato "^(?!amq\\.).*" '\ 37 | '\'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}\' --priority 0' 38 | ) 39 | is_expected.to_not run_execute('clear_policy tomato from vhost /') 40 | end 41 | end 42 | 43 | context 'when policies already exist' do 44 | before do 45 | shellout = double 46 | allow(Mixlib::ShellOut).to receive(:new).with( 47 | /rabbitmqctl list_policies/, { env: { 'HOME' => // } } 48 | ).and_return(shellout) 49 | allow(shellout).to receive(:run_command).and_return(shellout) 50 | allow(shellout).to receive(:stdout).and_return( 51 | '[ 52 | { 53 | "name":"policy1", 54 | "pattern":"pattern1", 55 | "definition":{"key1":"val1"}, 56 | "apply-to":"all", 57 | "priority":0 58 | }, 59 | { 60 | "name":"policy2", 61 | "pattern":"pattern2", 62 | "definition":{"key2":"val2"}, 63 | "apply-to":"queues", 64 | "priority":1 65 | }, 66 | { 67 | "name":"policy3", 68 | "pattern":"pattern3", 69 | "definition":{"key3":"val3"}, 70 | "apply-to":"queues", 71 | "priority":2 72 | } 73 | ]' 74 | ) 75 | end 76 | 77 | recipe do 78 | rabbitmq_policy 'policy1' do 79 | pattern 'pattern1' 80 | definition('key1' => 'val1', 'extrakey' => 'extraval') 81 | apply_to 'all' 82 | priority 0 83 | action :set 84 | end 85 | 86 | rabbitmq_policy 'policy2' do 87 | pattern 'pattern2' 88 | definition('key2' => 'val2') 89 | apply_to 'queues' 90 | priority 1 91 | action :set 92 | end 93 | 94 | rabbitmq_policy 'policy3' do 95 | action :clear 96 | end 97 | end 98 | 99 | it 'amends only the policies that have changed' do 100 | is_expected.to run_execute('set_policy policy1 on vhost /').with( 101 | command: 'rabbitmqctl -q set_policy -p / --apply-to all policy1 "pattern1" '\ 102 | '\'{"key1":"val1","extrakey":"extraval"}\' --priority 0' 103 | ) 104 | is_expected.to_not run_execute('set_policy policy2 on vhost /') 105 | is_expected.to run_execute('clear_policy policy3 from vhost /') 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /recipes/erlang_package.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: erlang_package 5 | # 6 | # Provisions Erlang via RabbitMQ's own 7 | # packages for Debian and CentOS. 8 | # 9 | # Copyright 2019-2021, VMware, Inc or its affiliates. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | # 23 | 24 | node.default['erlang']['install_method'] = nil 25 | node.override['erlang']['install_method'] = nil 26 | 27 | # yum-erlang_solutions assumes that if it is loaded, you 28 | node.default['yum']['erlang_solutions']['enabled'] = false 29 | node.override['yum']['erlang_solutions']['enabled'] = false 30 | 31 | erlang_version = node['rabbitmq']['erlang']['version'] 32 | 33 | if platform_family?('debian') 34 | rabbitmq_erlang_apt_repository_on_cloudsmith 'rabbitmq_erlang_repo_on_cloudsmith' do 35 | uri node['rabbitmq']['erlang']['apt']['uri'] unless node['rabbitmq']['erlang']['apt']['uri'].nil? 36 | distribution node['rabbitmq']['erlang']['apt']['lsb_codename'] if node['rabbitmq']['erlang']['apt']['lsb_codename'] 37 | components node['rabbitmq']['erlang']['apt']['components'] 38 | key node['rabbitmq']['erlang']['apt']['key'] 39 | action :add 40 | end 41 | 42 | rabbitmq_erlang_package_from_cloudsmith 'rabbitmq_erlang' do 43 | use_hipe node['rabbitmq']['erlang']['hipe'] 44 | version erlang_version unless erlang_version.nil? 45 | 46 | options node['rabbitmq']['erlang']['apt']['install_options'] unless node['rabbitmq']['erlang']['apt']['install_options'].nil? 47 | retry_delay node['rabbitmq']['erlang']['retry_delay'] unless node['rabbitmq']['erlang']['retry_delay'].nil? 48 | end 49 | end 50 | 51 | if platform_family?('rhel') 52 | if node['platform_version'].to_i <= 5 53 | Chef::Log.fatal('RabbitMQ package repositories are not available for EL5') 54 | raise 55 | end 56 | end 57 | 58 | if platform_family?('rhel', 'fedora', 'amazon') 59 | rabbitmq_erlang_yum_repository_on_cloudsmith 'rabbitmq_erlang' do 60 | baseurl node['rabbitmq']['erlang']['yum']['baseurl'] 61 | gpgkey node['rabbitmq']['erlang']['yum']['gpgkey'] 62 | gpgcheck node['rabbitmq']['erlang']['yum']['gpgcheck'] 63 | repo_gpgcheck node['rabbitmq']['erlang']['yum']['repo_gpgcheck'] 64 | enabled true 65 | end 66 | 67 | rabbitmq_erlang_package_from_cloudsmith 'rabbitmq_erlang' do 68 | version erlang_version unless erlang_version.nil? 69 | 70 | retry_delay node['rabbitmq']['erlang']['retry_delay'] unless node['rabbitmq']['erlang']['retry_delay'].nil? 71 | end 72 | end 73 | 74 | if platform_family?('suse') 75 | rabbitmq_erlang_zypper_repository_on_suse_factory 'rabbitmq_erlang' do 76 | baseurl node['rabbitmq']['erlang']['zypper']['baseurl'] 77 | gpgkey node['rabbitmq']['erlang']['zypper']['gpgkey'] 78 | gpgcheck node['rabbitmq']['erlang']['zypper']['gpgcheck'] 79 | gpgautoimportkeys node['rabbitmq']['erlang']['zypper']['gpgautoimportkeys'] 80 | enabled true 81 | end 82 | 83 | rabbitmq_erlang_package_from_cloudsmith 'rabbitmq_erlang' do 84 | version erlang_version unless erlang_version.nil? 85 | 86 | retry_delay node['rabbitmq']['erlang']['retry_delay'] unless node['rabbitmq']['erlang']['retry_delay'].nil? 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /resources/erlang_package_from_cloudsmith.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: erlang_package_from_cloudsmith 5 | # 6 | # Copyright 2019-2021, VMware, Inc. or its affiliates 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # https://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | 21 | unified_mode true if respond_to?(:unified_mode) 22 | 23 | default_action :install 24 | 25 | property :version, String 26 | # HiPE's been deprecated since Erlang/OTP 22 and is going away in Erlang/OTP 24. 27 | # DO NOT USE. 28 | property :use_hipe, [true, false], default: false 29 | property :options, [String, Array] 30 | property :retries, Integer, default: 3 31 | property :retry_delay, Integer, default: 10 32 | 33 | provides :erlang_package_from_cloudsmith, platform_family: %w(debian rhel fedora) 34 | 35 | DEBIAN_PACKAGES = %w(erlang-base erlang-mnesia erlang-runtime-tools erlang-asn1 erlang-crypto erlang-public-key erlang-ssl 36 | erlang-syntax-tools erlang-snmp erlang-os-mon erlang-parsetools 37 | erlang-ftp erlang-tftp erlang-inets erlang-tools erlang-eldap erlang-xmerl 38 | erlang-dev erlang-edoc erlang-eunit erlang-erl-docgen erlang-src).freeze 39 | 40 | action :install do 41 | if platform_family?('debian') 42 | erlang_packages = DEBIAN_PACKAGES 43 | 44 | erlang_packages.each do |pkg| 45 | apt_preference "#{new_resource.name}-#{pkg}" do 46 | package_name pkg 47 | pin "version #{new_resource.version}" 48 | pin_priority '900' 49 | action :add 50 | not_if { new_resource.version.nil? } 51 | end 52 | end 53 | 54 | erlang_packages.each do |pkg| 55 | apt_package(pkg) do 56 | options new_resource.options if new_resource.options 57 | version new_resource.version if new_resource.version 58 | retries new_resource.retries 59 | retry_delay new_resource.retry_delay 60 | action :install 61 | notifies :reload, 'ohai[reload_packages]', :immediately 62 | end 63 | end 64 | end 65 | 66 | if platform_family?('rhel', 'fedora', 'amazon') 67 | package new_resource.name do 68 | package_name 'erlang' 69 | version new_resource.version if new_resource.version 70 | options '-y' 71 | retries new_resource.retries 72 | retry_delay new_resource.retry_delay 73 | 74 | notifies :reload, 'ohai[reload_packages]', :immediately 75 | end 76 | end 77 | end 78 | 79 | action :remove do 80 | if platform_family?('debian') 81 | erlang_packages = DEBIAN_PACKAGES 82 | 83 | erlang_packages.each do |p| 84 | apt_preference "#{new_resource.name}-#{p}" do 85 | action :remove 86 | only_if { new_resource.version } 87 | 88 | notifies :reload, 'ohai[reload_packages]', :immediately 89 | end 90 | end 91 | 92 | apt_package(erlang_packages) do 93 | options new_resource.options if new_resource.options 94 | # must provide an array of versions! 95 | version erlang_packages.map { new_resource.version } if new_resource.version 96 | retries new_resource.retries 97 | retry_delay new_resource.retry_delay 98 | action :remove 99 | 100 | notifies :reload, 'ohai[reload_packages]', :immediately 101 | end 102 | end 103 | 104 | if platform_family?('rhel', 'fedora') 105 | package new_resource.name do 106 | action :remove 107 | 108 | notifies :reload, 'ohai[reload_packages]', :immediately 109 | end 110 | end 111 | end 112 | -------------------------------------------------------------------------------- /libraries/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Library:: default 5 | # Author:: Jake Davis () 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | module RabbitMQ 21 | # module rabbit 22 | module CoreHelpers 23 | # This method does some of the yuckiness of formatting parameters properly 24 | # for rendering into the rabbit.config template. 25 | def format_kernel_parameters # rubocop:disable all 26 | rendered = [] # rubocop:enable all 27 | kernel = node['rabbitmq']['kernel'].dup 28 | 29 | # This parameter is special and needs commas instead of periods. 30 | rendered << "{inet_dist_use_interface, {#{kernel[:inet_dist_use_interface].tr('.', ',')}}}" if kernel[:inet_dist_use_interface] 31 | kernel.delete(:inet_dist_use_interface) 32 | 33 | # Otherwise, we can just render it nicely as Erlang wants. This 34 | # theoretically opens the door for arbitrary kernel_app parameters to be 35 | # declared. 36 | kernel.compact.each_pair do |param, val| 37 | rendered << " {#{param}, #{val}}" 38 | end 39 | 40 | rendered.join(",\n") 41 | end 42 | 43 | def get_policy(name, vhost) 44 | # Returns JSON of a policy in a vhost 45 | # Returns false if the policy does not exist 46 | cmd = "rabbitmqctl list_policies --vhost #{Shellwords.escape vhost} --formatter json" 47 | cmd = Mixlib::ShellOut.new(cmd, env: shell_environment).run_command 48 | pol = JSON.parse(cmd.stdout).select { |p| p['name'] == name }.first 49 | return false unless pol 50 | pol['definition'] = JSON.parse(pol['definition']) unless pol['definition'].is_a?(Hash) 51 | pol 52 | end 53 | 54 | def format_ssl_versions 55 | Array(node['rabbitmq']['ssl_versions']).map { |n| "'#{n}'" }.join(',') 56 | end 57 | 58 | def format_ssl_ciphers 59 | Array(node['rabbitmq']['ssl_ciphers']).join(',') 60 | end 61 | 62 | def shell_environment 63 | { 'HOME' => ENV.fetch('HOME', '/var/lib/rabbitmq') } 64 | end 65 | 66 | def use_distro_version? 67 | node['rabbitmq']['use_distro_version'] 68 | end 69 | 70 | def rabbitmq_version 71 | node['rabbitmq']['version'].to_s 72 | end 73 | 74 | def rabbitmq_38? 75 | rabbitmq_version =~ /^3.8/ 76 | end 77 | 78 | def rabbitmq_37? 79 | rabbitmq_version =~ /^3.7/ 80 | end 81 | 82 | def rabbitmq_36? 83 | rabbitmq_version =~ /^3.6/ 84 | end 85 | 86 | def installed_rabbitmq_version 87 | # output a rabbitmq-server version string excluding anything after the "-", 88 | # e.g. "3.7.13". This strips off development version qualifiers, package 89 | # revision and so on. 90 | node['packages']['rabbitmq-server']['version'][/[^-]+/] 91 | end 92 | 93 | def rabbitmq_config_file_path 94 | configured_path = node['rabbitmq']['config'] 95 | 96 | # 3.6.x does not support .config in RABBITMQ_CONFIG_FILE paths. MK. 97 | if ::File.extname(configured_path).empty? && !rabbitmq_36? && !use_distro_version? 98 | "#{configured_path}.config" 99 | else 100 | configured_path 101 | end 102 | end 103 | 104 | def manage_rabbitmq_service? 105 | node['rabbitmq']['manage_service'] 106 | end 107 | 108 | def service_control_init? 109 | node['init_package'] == 'init' && node['rabbitmq']['job_control'] == 'init' 110 | end 111 | 112 | def service_control_upstart? 113 | node['rabbitmq']['job_control'] == 'upstart' 114 | end 115 | 116 | def service_control_systemd? 117 | systemd? || node['rabbitmq']['job_control'] == 'systemd' 118 | end 119 | end 120 | end 121 | 122 | module Opscode 123 | module RabbitMQ 124 | include ::RabbitMQ::CoreHelpers 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing the Cookbook 2 | 3 | ## Bundler 4 | 5 | A Ruby environment with Bundler installed is a prerequisite for using 6 | the testing harness shipped with this cookbook. At the time of this 7 | writing, it works with Ruby 2.7+ and latest Bundler releases. All programs 8 | involved, with the exception of Vagrant, can be installed by cd'ing 9 | into the parent directory of this cookbook and running "bundle install" 10 | 11 | ## Rakefile 12 | 13 | The Rakefile ships with a number of tasks, each of which can be ran 14 | individually, or in groups. Typing "rake" by itself will perform style 15 | checks with Rubocop and Foodcritic, ChefSpec with rspec, and 16 | integration with Test Kitchen using the Vagrant driver by 17 | default.Alternatively, integration tests can be ran with Test Kitchen 18 | cloud drivers. 19 | 20 | ``` 21 | $ rake -T 22 | rake integration:cloud # Run Test Kitchen with cloud plugins 23 | rake integration:vagrant # Run Test Kitchen with Vagrant 24 | rake spec # Run ChefSpec examples 25 | rake style # Run all style checks 26 | rake style:ruby # Run Ruby style checks 27 | rake travis # Run all tests on Travis 28 | ``` 29 | 30 | ## Style Testing 31 | 32 | Ruby style tests can be performed by Cookstyle by issuing either 33 | ``` 34 | bundle exec cookstyle 35 | ``` 36 | or 37 | ``` 38 | rake style:ruby 39 | ``` 40 | 41 | ## Spec Testing 42 | 43 | Unit testing is done by running Rspec examples. Rspec will test any 44 | libraries, then test recipes using ChefSpec. This works by compiling a 45 | recipe (but not converging it), and allowing the user to make 46 | assertions about the resource_collection. 47 | 48 | ``` 49 | bundle exec rspec 50 | ``` 51 | 52 | will run the specs. 53 | 54 | 55 | ## Integration Testing 56 | 57 | Integration testing is performed by Test Kitchen. Test Kitchen will 58 | use either the Vagrant driver or various cloud drivers to instantiate 59 | machines and apply cookbooks. After a successful converge, tests are 60 | uploaded and ran out of band of Chef. Tests should be designed to 61 | ensure that a recipe has accomplished its goal. 62 | 63 | ### Using Docker 64 | 65 | Docker testing relies on Dokken. At the time of writing, Dokken 66 | is [only compatible with Docker Desktop `4.2.x`](https://github.com/test-kitchen/dokken-images/issues/57). 67 | 68 | To list available configurations that can be run, use 69 | 70 | ``` 71 | KITCHEN_LOCAL_YAML=".kitchen.dokken.yml" kitchen list 72 | ``` 73 | 74 | To run Kitchen tests in Docker, use 75 | 76 | ``` 77 | KITCHEN_LOCAL_YAML=".kitchen.dokken.yml" kitchen test default-deb --concurrency=2 78 | ``` 79 | 80 | where `default-deb` is a prefix of a group of configurations (they can be run in parallel 81 | if the `--concurrency` flag is used). 82 | 83 | To run all suites (this can take up to 90 minutes depending on the driver, 84 | hardware and concurrency rate): 85 | 86 | ``` 87 | export KI_DRIVER=dokken 88 | bundle exec kitchen test 89 | ``` 90 | This will run tels of suites on multiple operating systems (Debian, Ubuntu, CentOS 7, CentOS 6, 91 | and so on). 92 | 93 | ### Using Vagrant 94 | 95 | Integration tests can be performed on a local workstation using 96 | Virtualbox or VMWare. Detailed instructions for setting this up can be 97 | found at the [Bento](https://github.com/chef/bento) project web site. 98 | 99 | ``` 100 | kitchen test default-deb-ubuntu-2004 101 | ``` 102 | 103 | To run all suites (involves multiple operating systems: Ubuntu, Debian, CentOS 7, CentOS 6) 104 | 105 | ``` 106 | bundle exec kitchen test 107 | ``` 108 | 109 | or 110 | 111 | ``` 112 | rake integration:vagrant 113 | ``` 114 | 115 | ### Integration Testing using IaaS Providers 116 | 117 | Integration tests can be performed on cloud providers using 118 | Test Kitchen plugins. This cookbook ships a ```.kitchen.cloud.yml``` 119 | that references environmental variables present in the shell that 120 | ```kitchen test``` is ran from. These usually contain authentication 121 | tokens for driving IaaS APIs, as well as the paths to ssh private keys 122 | needed for Test Kitchen log into them after they've been created. 123 | 124 | Examples of environment variables being set in ```~/.bash_profile```: 125 | ``` 126 | # digital_ocean 127 | export DIGITAL_OCEAN_CLIENT_ID='your_bits_here' 128 | export DIGITAL_OCEAN_API_KEY='your_bits_here' 129 | export DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' 130 | 131 | # aws 132 | export AWS_ACCESS_KEY_ID='your_bits_here' 133 | export AWS_SECRET_ACCESS_KEY='your_bits_here' 134 | export AWS_KEYPAIR_NAME='your_bits_here' 135 | 136 | # joyent 137 | export SDC_CLI_ACCOUNT='your_bits_here' 138 | export SDC_CLI_IDENTITY='your_bits_here' 139 | export SDC_CLI_KEY_ID='your_bits_here' 140 | ``` 141 | 142 | Integration tests using cloud drivers can be performed with either 143 | ``` 144 | export KITCHEN_YAML=.kitchen.cloud.yml 145 | bundle exec kitchen test 146 | ``` 147 | or 148 | ``` 149 | rake integration:cloud 150 | ``` 151 | 152 | #### Digital Ocean Hint 153 | At the time of this writing, you cannot find the numerical values 154 | needed for your SSH_KEY_IDS from the GUI. Instead, you will need to 155 | access the API from the command line. 156 | 157 | curl -L 'https://api.digitalocean.com/ssh_keys/?client_id=your_bits_here&api_key=your_bits_here' 158 | 159 | #### Words about .travis.yml 160 | 161 | In order for Travis to perform integration tests on public cloud 162 | providers, two major things need to happen. First, the environment 163 | variables referenced by ```.kitchen.cloud.yml``` need to be made 164 | available. Second, the private half of the ssh keys needed to log into 165 | machines need to be dropped off on the machine. 166 | 167 | The first part is straightforward. The travis gem can encrypt 168 | environment variables against the public key on the Travis repository 169 | and add them to the .travis.yml. 170 | 171 | ``` 172 | gem install travis 173 | travis encrypt AWS_ACCESS_KEY_ID='your_bits_here' --add 174 | travis encrypt AWS_SECRET_ACCESS_'your_bits_here' --add 175 | travis encrypt AWS_KEYPAIR_NAME='your_bits_here' --add 176 | travis encrypt EC2_SSH_KEY_PATH='~/.ssh/id_ec2.pem' --add 177 | 178 | travis encrypt DIGITAL_OCEAN_CLIENT_ID='your_bits_here' --add 179 | travis encrypt DIGITAL_OCEAN_API_KEY='your_bits_here' --add 180 | travis encrypt DIGITAL_OCEAN_SSH_KEY_IDS='your_bits_here' --add 181 | travis encrypt DIGITAL_OCEAN_SSH_KEY_PATH='~/.ssh/id_do.pem' --add 182 | ``` 183 | 184 | The second part is a little more complicated. Travis ENV variables are 185 | restricted to 90 bytes, and will not fit an entire SSH key. This can 186 | be worked around by breaking them up into 90 byte chunks, stashing 187 | them into ENV variables, then digging them out in the 188 | ```before_install``` section of .travis.yml 189 | 190 | Here is an AWK script to do the encoding. 191 | ``` 192 | base64 ~/.ssh/travisci_cook_digitalocean.pem | \ 193 | awk '{ 194 | j=0; 195 | for( i=1; i> ~/.ssh/id_do.base64 215 | - cat ~/.ssh/id_do.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_do.pem 216 | - echo -n $EC2_KEY_CHUNK_{0..30} >> ~/.ssh/id_ec2.base64 217 | - cat ~/.ssh/id_ec2.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_ec2.pem 218 | ``` 219 | -------------------------------------------------------------------------------- /templates/default/rabbitmq.config.erb: -------------------------------------------------------------------------------- 1 | %%% 2 | %% Generated by Chef 3 | %%% 4 | 5 | [ 6 | {kernel, [ 7 | <%= @kernel %> 8 | ]}, 9 | <% if node['rabbitmq']['web_console_ssl'] -%> 10 | {rabbitmq_management, [ 11 | <% if node['rabbitmq']['management']['load_definitions'] %> 12 | {load_definitions, "<%= node['rabbitmq']['management']['definitions_file'] %>"}, 13 | <% end -%> 14 | {listener, [{port, <%= node['rabbitmq']['web_console_ssl_port'] %>}, 15 | <% if node['rabbitmq']['web_console_interface'] -%> 16 | {ip, "<%= node['rabbitmq']['web_console_interface'] %>"}, 17 | <% end -%> 18 | {ssl, true}, 19 | {ssl_opts, [{cacertfile,"<%= node['rabbitmq']['ssl_cacert'] %>"}, 20 | {certfile,"<%= node['rabbitmq']['ssl_cert'] %>"}, 21 | {keyfile,"<%= node['rabbitmq']['ssl_key'] %>"} 22 | <% if @ssl_versions -%>,{versions,[<%= @ssl_versions %>]}<% end -%> 23 | <% if @ssl_ciphers -%>,{ciphers,[<%= @ssl_ciphers %>]}<% end -%> 24 | ]} 25 | ]} 26 | ]}, 27 | <% else %> 28 | {rabbitmq_management, [ 29 | <% if node['rabbitmq']['management']['load_definitions'] %> 30 | {load_definitions, "<%= node['rabbitmq']['management']['definitions_file'] %>"}, 31 | <% end -%> 32 | {listener, [ 33 | {port, <%= node['rabbitmq']['web_console_port'] %>} 34 | <% if node['rabbitmq']['web_console_interface'] -%> 35 | ,{ip, "<%= node['rabbitmq']['web_console_interface'] %>"} 36 | <% end -%> 37 | ]} 38 | ]}, 39 | <% end %> 40 | <% if node['rabbitmq']['ssl'] && @ssl_versions -%> 41 | {ssl, [{versions, [<%= @ssl_versions %>]}]}, 42 | <% end %> 43 | {rabbit, [ 44 | {auth_backends, [<%= node['rabbitmq']['auth_backends'] %>]}, 45 | <% if node['rabbitmq']['clustering']['enable'] -%> 46 | <%if node['rabbitmq']['clustering']['use_auto_clustering'] -%> 47 | {cluster_nodes, {[<%= node['rabbitmq']['clustering']['cluster_nodes'].map { |n| "'#{n['name']}'"}.join(',') %>], disc}}, 48 | <% end %> 49 | {cluster_partition_handling,<%= node['rabbitmq']['clustering']['cluster_partition_handling'] %>}, 50 | <% end %> 51 | <% if node['rabbitmq']['ssl'] -%> 52 | <% if node['rabbitmq']['ssl_listen_interface'] %> 53 | {ssl_listeners, [{"<%= node['rabbitmq']['ssl_listen_interface'] %>", <%= node['rabbitmq']['ssl_port'] %>}]}, 54 | <% else %> 55 | {ssl_listeners, [<%= node['rabbitmq']['ssl_port'] %>]}, 56 | <% end %> 57 | {ssl_options, [{cacertfile,"<%= node['rabbitmq']['ssl_cacert'] %>"}, 58 | {certfile,"<%= node['rabbitmq']['ssl_cert'] %>"}, 59 | {keyfile,"<%= node['rabbitmq']['ssl_key'] %>"}, 60 | {verify,<%= node['rabbitmq']['ssl_verify'] %>}, 61 | {depth,<%= node['rabbitmq']['ssl_depth'] %>}, 62 | {fail_if_no_peer_cert,<%= node['rabbitmq']['ssl_fail_if_no_peer_cert'] %>} 63 | <% if @ssl_versions -%>,{versions,[<%= @ssl_versions %>]}<% end -%> 64 | <% if @ssl_ciphers -%>,{ciphers,[<%= @ssl_ciphers %>]}<% end -%> 65 | <% if node['rabbitmq']['ssl_secure_renegotiate'] -%>,{secure_renegotiate, <%= node['rabbitmq']['ssl_secure_renegotiate'] %>}<% end -%> 66 | <% if node['rabbitmq']['ssl_honor_cipher_order'] -%>,{honor_cipher_order, <%= node['rabbitmq']['ssl_honor_cipher_order'] %>}<% end -%> 67 | <% if node['rabbitmq']['ssl_honor_ecc_order'] -%>,{honor_ecc_order, <%= node['rabbitmq']['ssl_honor_ecc_order'] %>}<% end -%> 68 | ]}, 69 | <% end %> 70 | 71 | <% if node['rabbitmq']['tcp_listen_interface'] -%> 72 | {tcp_listeners, [{"<%= node['rabbitmq']['tcp_listen_interface'] %>", <%= node['rabbitmq']['port'] %>}]}, 73 | <% else %> 74 | {tcp_listeners, [<%= node['rabbitmq']['port'] %>]}, 75 | <% end -%> 76 | 77 | <% if node['rabbitmq']['tcp_listen'] -%> 78 | {tcp_listen_options, [binary, 79 | {packet, <%= node['rabbitmq']['tcp_listen_packet'] %>}, 80 | {reuseaddr, <%= node['rabbitmq']['tcp_listen_reuseaddr'] %>}, 81 | {backlog, <%= node['rabbitmq']['tcp_listen_backlog'] %>}, 82 | {nodelay, <%= node['rabbitmq']['tcp_listen_nodelay'] %>}, 83 | {exit_on_close, <%= node['rabbitmq']['tcp_listen_exit_on_close'] %>}, 84 | {keepalive, <%= node['rabbitmq']['tcp_listen_keepalive'] %>}, 85 | 86 | <% if node['rabbitmq']['tcp_listen_buffer'] -%> 87 | {buffer, <%= node['rabbitmq']['tcp_listen_buffer'] %>}, 88 | <% end -%> 89 | 90 | <% if node['rabbitmq']['tcp_listen_sndbuf'] -%> 91 | {sndbuf, <%= node['rabbitmq']['tcp_listen_sndbuf'] %>}, 92 | <% end -%> 93 | 94 | <% if node['rabbitmq']['tcp_listen_recbuf'] -%> 95 | {recbuf, <%= node['rabbitmq']['tcp_listen_recbuf'] %>}, 96 | <% end -%> 97 | 98 | {linger, {<%= node['rabbitmq']['tcp_listen_linger'] %>,<%= node['rabbitmq']['tcp_listen_linger_timeout'] %>}}]}, 99 | <% else -%> 100 | {tcp_listen_options, [binary]}, 101 | <% end %> 102 | 103 | <% if node['rabbitmq']['log_levels'] -%> 104 | {log_levels, [<%= node['rabbitmq']['log_levels'].map{ |key, value| "{ #{key}, #{value} }"}.join(', ') %>]}, 105 | <% end %> 106 | <% if node['rabbitmq']['disk_free_limit_relative'] -%> 107 | {disk_free_limit, {mem_relative, <%= node['rabbitmq']['disk_free_limit_relative'] %>}}, 108 | <% end %> 109 | <% if node['rabbitmq']['disk_free_limit'] %> 110 | <% if node['rabbitmq']['disk_free_limit'].is_a? String %> 111 | {disk_free_limit, "<%= node['rabbitmq']['disk_free_limit'] %>"}, 112 | <%elsif node['rabbitmq']['disk_free_limit'].is_a? Integer %> 113 | {disk_free_limit, <%= node['rabbitmq']['disk_free_limit'] %>}, 114 | <% end %> 115 | <% end %> 116 | <% if node['rabbitmq']['vm_memory_high_watermark'] -%> 117 | {vm_memory_high_watermark, <%= node['rabbitmq']['vm_memory_high_watermark'] %>}, 118 | <% end %> 119 | <% if node['rabbitmq']['channel_max'] -%> 120 | {channel_max, <%= node['rabbitmq']['channel_max'] %>}, 121 | <% end %> 122 | <% if node['rabbitmq']['loopback_users'] -%> 123 | {loopback_users, [<%= node['rabbitmq']['loopback_users'].map{|n| "<<\"#{n}\">>"}.join(',') %>]}, 124 | <% end %> 125 | 126 | {default_user, <<"<%= node['rabbitmq']['default_user'] %>">>}, 127 | {default_pass, <<"<%= node['rabbitmq']['default_pass'] %>">>}, 128 | {heartbeat, <%= node['rabbitmq']['heartbeat'] %>} 129 | 130 | <% if node['rabbitmq']['credit_flow_defaults'] -%> 131 | {credit_flow_default_credit, {<%= node['rabbitmq']['credit_flow_defaults']['initial'] %>, <%= node['rabbitmq']['credit_flow_defaults']['more_credit_after'] %>}}, 132 | <% end %> 133 | 134 | <% node['rabbitmq']['additional_rabbit_configs'].each do |key,value| -%> 135 | ,{<%= key %>, <%= value %>} 136 | <% end -%> 137 | ]} 138 | <%if node['rabbitmq']['ldap']['enabled']%> 139 | ,{rabbitmq_auth_backend_ldap, [ 140 | <% node['rabbitmq']['ldap']['conf'].each_with_index do |(key, value), index| -%> 141 | <%if index == 0%> 142 | {<%= key %>, <%= value %>} 143 | <%else%> 144 | ,{<%= key %>, <%= value %>} 145 | <%end%> 146 | <% end -%> 147 | ]} 148 | <% end %> 149 | <% node['rabbitmq']['conf'].each do |key,value| -%> 150 | ,{<%= key %>, <%= value %>} 151 | <% end -%> 152 | ]. 153 | -------------------------------------------------------------------------------- /resources/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: user 5 | # 6 | # Copyright 2011-2019, Chef Software, Inc. 7 | # Copyright 2019-2021, VMware, Inc or its affiliates. 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # https://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | unified_mode true if respond_to?(:unified_mode) 23 | 24 | default_action :add 25 | 26 | property :user, String, name_property: true 27 | property :password, String 28 | property :vhost, [String, Array], default: '/', coerce: proc { |x| [x].flatten } 29 | property :permissions, String 30 | property :tag, String 31 | 32 | action_class do 33 | include RabbitMQ::CoreHelpers 34 | 35 | def user_exists?(name) 36 | cmd = "rabbitmqctl -s list_users |grep '^#{name}\\s'" 37 | cmd = Mixlib::ShellOut.new(cmd, :env => shell_environment) 38 | cmd.run_command 39 | Chef::Log.debug "rabbitmq_user_exists?: #{cmd}" 40 | Chef::Log.debug "rabbitmq_user_exists?: #{cmd.stdout}" 41 | !cmd.error? 42 | end 43 | 44 | def user_has_tag?(name, tag) 45 | cmd = 'rabbitmqctl -s list_users' 46 | cmd = Mixlib::ShellOut.new(cmd, :env => shell_environment) 47 | cmd.run_command 48 | user_list = cmd.stdout 49 | tags = user_list.match(/^#{name}\s+\[(.*?)\]/)[1].split 50 | Chef::Log.debug "rabbitmq_user_has_tag?: #{cmd}" 51 | Chef::Log.debug "rabbitmq_user_has_tag?: #{cmd.stdout}" 52 | Chef::Log.debug "rabbitmq_user_has_tag?: #{name} has tags: #{tags}" 53 | if tag.nil? && tags.empty? 54 | true 55 | elsif tags.include?(tag) 56 | true 57 | else 58 | false 59 | end 60 | rescue RuntimeError 61 | false 62 | end 63 | 64 | # does the user have the rights listed on the vhost? 65 | # empty perm_list means we're checking for any permissions 66 | def user_has_expected_permissions?(name, vhost, perm_list = nil) 67 | cmd = "rabbitmqctl -s list_user_permissions #{name} | grep \"^#{vhost}\\s\"" 68 | cmd = Mixlib::ShellOut.new(cmd, :env => shell_environment) 69 | cmd.run_command 70 | Chef::Log.debug "rabbitmq_user_has_expected_permissions?: #{cmd}" 71 | Chef::Log.debug "rabbitmq_user_has_expected_permissions?: #{cmd.stdout}" 72 | Chef::Log.debug "rabbitmq_user_has_expected_permissions?: #{cmd.exitstatus}" 73 | # no permissions found and none expected 74 | if perm_list.nil? && cmd.stdout.empty? 75 | Chef::Log.debug 'rabbitmq_user_has_expected_permissions?: no permissions found' 76 | return true 77 | end 78 | # existing match search 79 | if perm_list == %(\"#{cmd.stdout}\").undump.split.drop(1) 80 | Chef::Log.debug 'rabbitmq_user_has_expected_permissions?: matching permissions already found' 81 | return true 82 | end 83 | Chef::Log.debug 'rabbitmq_user_has_expected_permissions?: permissions found but do not match' 84 | false 85 | end 86 | end 87 | 88 | action :add do 89 | raise( 90 | Chef::Exceptions::ValidationFailed, 91 | 'password is a required property' 92 | ) unless property_is_set?(:password) 93 | 94 | # To escape single quotes in a shell, you have to close the surrounding single quotes, add 95 | # in an escaped single quote, and then re-open the original single quotes. 96 | # Since this string is interpolated once by ruby, and then a second time by the shell, we need 97 | # to escape the escape character ('\') twice. This is why the following is such a mess 98 | # of leaning toothpicks: 99 | new_password = new_resource.password.gsub("'", "'\\\\''") 100 | cmd = "rabbitmqctl -q add_user #{new_resource.user} '#{new_password}'" 101 | execute "rabbitmqctl -q add_user #{new_resource.user}" do 102 | sensitive true if Gem::Version.new(Chef::VERSION.to_s) >= Gem::Version.new('11.14.2') 103 | command cmd 104 | environment shell_environment 105 | Chef::Log.info "Adding RabbitMQ user '#{new_resource.user}'." 106 | not_if { user_exists?(new_resource.user) } 107 | end 108 | end 109 | 110 | action :delete do 111 | cmd = "rabbitmqctl -q delete_user #{new_resource.user}" 112 | execute cmd do 113 | environment shell_environment 114 | Chef::Log.info "Deleting RabbitMQ user '#{new_resource.user}'." 115 | only_if { user_exists?(new_resource.user) } 116 | end 117 | end 118 | 119 | action :set_permissions do 120 | raise("rabbitmq_user action :set_permissions fails with nonexistent '#{new_resource.user}' user.") unless user_exists?(new_resource.user) 121 | 122 | perm_list = new_resource.permissions.split 123 | # filter out vhosts for which the user already has the permissions we expect 124 | filtered = new_resource.vhost.reject { |vhost| user_has_expected_permissions?(new_resource.user, vhost, perm_list) } 125 | filtered.each do |vhost| 126 | cmd = "rabbitmqctl -q set_permissions -p #{vhost} #{new_resource.user} \"#{perm_list.join('" "')}\"" 127 | execute cmd do 128 | environment shell_environment 129 | Chef::Log.info "Setting RabbitMQ user permissions for '#{new_resource.user}' on vhost #{vhost}." 130 | end 131 | end 132 | end 133 | 134 | action :clear_permissions do 135 | raise("rabbitmq_user action :clear_permissions fails with nonexistent '#{new_resource.user}' user.") unless user_exists?(new_resource.user) 136 | 137 | # filter out vhosts for which the user already has the permissions we expect 138 | filtered = new_resource.vhost.reject { |vhost| user_has_expected_permissions?(new_resource.user, vhost) } 139 | filtered.each do |vhost| 140 | cmd = "rabbitmqctl -q clear_permissions -p #{vhost} #{new_resource.user}" 141 | execute cmd do 142 | environment shell_environment 143 | Chef::Log.info "Clearing RabbitMQ user permissions for '#{new_resource.user}' from vhost #{vhost}." 144 | end 145 | end 146 | end 147 | 148 | action :set_tags do 149 | raise("rabbitmq_user action :set_tags fails with nonexistent '#{new_resource.user}' user.") unless user_exists?(new_resource.user) 150 | 151 | cmd = "rabbitmqctl -q set_user_tags #{new_resource.user} #{new_resource.tag}" 152 | execute cmd do 153 | environment shell_environment 154 | Chef::Log.info "Setting RabbitMQ user '#{new_resource.user}' tags '#{new_resource.tag}'" 155 | not_if { user_has_tag?(new_resource.user, new_resource.tag) } 156 | end 157 | end 158 | 159 | action :clear_tags do 160 | raise("rabbitmq_user action :clear_tags fails with nonexistent '#{new_resource.user}' user.") unless user_exists?(new_resource.user) 161 | 162 | cmd = "rabbitmqctl -q set_user_tags #{new_resource.user}" 163 | execute cmd do 164 | environment shell_environment 165 | Chef::Log.info "Clearing RabbitMQ user '#{new_resource.user}' tags." 166 | not_if { user_has_tag?(new_resource.user, '"\[\]"') } 167 | end 168 | end 169 | 170 | action :change_password do 171 | raise( 172 | Chef::Exceptions::ValidationFailed, 173 | 'password is a required property' 174 | ) unless property_is_set?(:password) 175 | 176 | new_password = new_resource.password.gsub("'", "'\\\\''") 177 | cmd = "rabbitmqctl -q change_password #{new_resource.user} '#{new_password}'" 178 | execute "rabbitmqctl -q change_password #{new_resource.user}" do 179 | sensitive true if Gem::Version.new(Chef::VERSION.to_s) >= Gem::Version.new('11.14.2') 180 | command cmd 181 | environment shell_environment 182 | Chef::Log.info "Changing password for RabbitMQ user '#{new_resource.user}'." 183 | only_if { user_exists?(new_resource.user) } 184 | end 185 | end 186 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: <%= ENV['KI_DRIVER'] || 'vagrant' %> 3 | 4 | verifier: 5 | name: inspec 6 | 7 | provisioner: 8 | name: chef_zero 9 | install_strategy: <%= ENV['KI_INSTALL_STRATEGY'] || 'once' %> 10 | chef_license: accept-no-persist 11 | 12 | transport: 13 | name: "ssh" 14 | 15 | platforms: 16 | - name: centos-stream-8 17 | - name: ubuntu-20.04 18 | - name: debian-10 19 | - name: fedora-34 20 | - name: opensuse-leap-15 21 | 22 | # 23 | # Suites 24 | # 25 | 26 | suites: 27 | - name: default-deb 28 | run_list: 29 | - recipe[erlang::default] 30 | - recipe[rabbitmq::plugins] 31 | - recipe[rabbitmq::management_ui] 32 | - recipe[rabbitmq::vhosts] 33 | - recipe[rabbitmq::users] 34 | - recipe[rabbitmq::policies] 35 | attributes: 36 | erlang: 37 | install_method: "esl" 38 | esl: 39 | version: "1:24.3.3-1" 40 | rabbitmq: 41 | version: "3.8.28" 42 | virtualhosts: 43 | - vhost1 44 | - vhost2 45 | enabled_users: 46 | - name: user1 47 | password: user1-pwd 48 | tag: management 49 | rights: 50 | - vhost: vhost1 51 | read: ".*" 52 | write: ".*" 53 | conf: ".*" 54 | - name: user2 55 | password: user2-pwd 56 | tag: management 57 | rights: 58 | - vhost: vhost2 59 | read: ".*" 60 | write: ".*" 61 | conf: ".*" 62 | policies: 63 | mirroring: 64 | pattern: "^mirrored\\." 65 | params: 66 | ha-mode: exactly 67 | ha-params: 2 68 | priority: 1 69 | verifier: 70 | inspec_tests: 71 | - test/integration/default 72 | includes: ["ubuntu-20.04", "debian-10"] 73 | 74 | - name: management-plugin-deb 75 | run_list: 76 | - recipe[erlang::default] 77 | - recipe[rabbitmq::management_ui] 78 | attributes: 79 | erlang: 80 | install_method: "esl" 81 | esl: 82 | version: "1:24.3.3-1" 83 | rabbitmq: 84 | version: "3.8.28" 85 | verifier: 86 | inspec_tests: 87 | - test/integration/management_plugin 88 | includes: ["ubuntu-20.04"] 89 | 90 | - name: system-limits-deb 91 | run_list: 92 | - recipe[erlang::default] 93 | - recipe[rabbitmq::systemd_limits] 94 | - recipe[rabbitmq::plugins] 95 | attributes: 96 | erlang: 97 | install_method: "esl" 98 | esl: 99 | version: "1:24.3.3-1" 100 | rabbitmq: 101 | version: "3.8.28" 102 | systemd: 103 | limits: 104 | NOFILE: 54000 105 | verifier: 106 | inspec_tests: 107 | - test/integration/limits 108 | includes: ["ubuntu-20.04", "debian-10"] 109 | 110 | - name: default-rpm 111 | run_list: 112 | - recipe[erlang::default] 113 | - recipe[rabbitmq::plugins] 114 | attributes: 115 | erlang: 116 | install_method: "esl" 117 | esl: 118 | version: "24.3.3-1" 119 | rabbitmq: 120 | version: "3.8.28" 121 | verifier: 122 | inspec_tests: 123 | - test/integration/default 124 | includes: ["centos-stream-8"] 125 | 126 | - name: default-modern-rpm 127 | run_list: 128 | - recipe[rabbitmq::erlang_package] 129 | - recipe[rabbitmq::plugins] 130 | attributes: 131 | rabbitmq: 132 | erlang: 133 | enabled: true 134 | version: "24.3.3" 135 | version: "3.8.28" 136 | verifier: 137 | inspec_tests: 138 | - test/integration/default 139 | includes: ["centos-stream-8", "fedora-34"] 140 | 141 | 142 | - name: system-limits-rpm 143 | run_list: 144 | - recipe[erlang::default] 145 | - recipe[rabbitmq::systemd_limits] 146 | - recipe[rabbitmq::plugins] 147 | attributes: 148 | erlang: 149 | install_method: "esl" 150 | esl: 151 | version: "24.3.3-1" 152 | rabbitmq: 153 | version: "3.8.28" 154 | systemd: 155 | limits: 156 | NOFILE: 54000 157 | verifier: 158 | inspec_tests: 159 | - test/integration/limits 160 | includes: ["centos-stream-8"] 161 | 162 | - name: lwrps 163 | run_list: 164 | - recipe[erlang::default] 165 | - recipe[rabbitmq_test::lwrps] 166 | attributes: 167 | erlang: 168 | install_method: "esl" 169 | esl: 170 | version: "1:24.3.3-1" 171 | rabbitmq: 172 | version: "3.8.28" 173 | verifier: 174 | inspec_tests: 175 | - test/integration/default 176 | - test/integration/lwrps 177 | includes: ["ubuntu-20.04"] 178 | 179 | - name: cluster-deb 180 | run_list: 181 | - recipe[erlang::default] 182 | - recipe[rabbitmq_test::cluster] 183 | attributes: 184 | erlang: 185 | install_method: "esl" 186 | esl: 187 | version: "1:24.3.3-1" 188 | rabbitmq: 189 | version: "3.8.28" 190 | verifier: 191 | inspec_tests: 192 | - test/integration/default 193 | - test/integration/cluster 194 | includes: ["ubuntu-20.04", "debian-10"] 195 | 196 | - name: cluster-rpm 197 | run_list: 198 | - recipe[erlang::default] 199 | - recipe[rabbitmq_test::cluster] 200 | attributes: 201 | erlang: 202 | install_method: "esl" 203 | esl: 204 | version: "24.3.3-1" 205 | rabbitmq: 206 | version: "3.8.28" 207 | verifier: 208 | inspec_tests: 209 | - test/integration/default 210 | - test/integration/cluster 211 | includes: ["centos-stream-8"] 212 | 213 | - name: default-force-yes 214 | run_list: 215 | - recipe[erlang::default] 216 | - recipe[rabbitmq::default] 217 | attributes: 218 | erlang: 219 | install_method: "esl" 220 | esl: 221 | version: "1:24.3.3-1" 222 | rabbitmq: 223 | version: "3.8.28" 224 | attributes: 225 | apt: 226 | confd: 227 | assume_yes: true 228 | force-yes: true 229 | erlang: 230 | install_method: "esl" 231 | esl: 232 | version: "1:24.3.3-1" 233 | rabbitmq: 234 | version: "3.8.28" 235 | verifier: 236 | inspec_tests: 237 | - test/integration/default 238 | includes: ["debian-10"] 239 | 240 | - name: default-force-yes-false 241 | run_list: 242 | - recipe[erlang::default] 243 | - recipe[rabbitmq::default] 244 | attributes: 245 | apt: 246 | confd: 247 | assume_yes: false 248 | force-yes: false 249 | erlang: 250 | install_method: "esl" 251 | esl: 252 | version: "1:24.3.3-1" 253 | rabbitmq: 254 | version: "3.8.28" 255 | verifier: 256 | inspec_tests: 257 | - test/integration/default 258 | includes: ["debian-10"] 259 | 260 | # 261 | # Team RabbitMQ Erlang packages 262 | # 263 | 264 | # Latest Erlang package, Debian 265 | - name: rabbitmq-erlang-latest-deb 266 | run_list: 267 | - recipe[rabbitmq::erlang_package] 268 | - recipe[rabbitmq::default] 269 | attributes: 270 | # relies on node.rabbitmq.erlang.version default 271 | # which is nil/"install latest" 272 | rabbitmq: 273 | erlang: 274 | enabled: true 275 | version: "3.8.28" 276 | verifier: 277 | inspec_tests: 278 | - test/erlang_package/latest_deb 279 | includes: ["debian-10", "ubuntu-20.04"] 280 | 281 | # Erlang package, Debian, version pinning 282 | - name: rabbitmq-erlang-pinned-deb 283 | run_list: 284 | - recipe[rabbitmq::erlang_package] 285 | - recipe[rabbitmq::default] 286 | attributes: 287 | rabbitmq: 288 | erlang: 289 | enabled: true 290 | version: "1:22.3.4.10.10-1" 291 | version: "3.8.28" 292 | verifier: 293 | inspec_tests: 294 | - test/erlang_package/pinned_deb 295 | includes: ["ubuntu-20.04"] 296 | 297 | # Latest Erlang package, RPM 298 | - name: rabbitmq-erlang-latest-rpm-el8 299 | run_list: 300 | - recipe[rabbitmq::erlang_package] 301 | - recipe[rabbitmq::default] 302 | attributes: 303 | # relies on node.rabbitmq.erlang.version default 304 | # which is nil/"install latest" 305 | rabbitmq: 306 | erlang: 307 | enabled: true 308 | version: "3.8.28" 309 | verifier: 310 | inspec_tests: 311 | - test/erlang_package/latest_rpm 312 | includes: ["fedora-34", "centos-stream-8"] 313 | 314 | # Erlang package, RPM, version pinning 315 | - name: rabbitmq-erlang-pinned-rpm-el8 316 | run_list: 317 | - recipe[rabbitmq::erlang_package] 318 | - recipe[rabbitmq::default] 319 | attributes: 320 | rabbitmq: 321 | erlang: 322 | enabled: true 323 | version: "23.3.4.11" 324 | yum: 325 | baseurl: https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/8/noarch 326 | repo_gpgcheck: true 327 | version: "3.8.28" 328 | verifier: 329 | inspec_tests: 330 | - test/erlang_package/pinned_rpm 331 | includes: ["fedora-34", "centos-stream-8"] 332 | 333 | # Latest Erlang package, RPM, openSUSE leap 15 repo 334 | - name: rabbitmq-erlang-latest-rpm-suse 335 | run_list: 336 | - recipe[rabbitmq::erlang_package] 337 | - recipe[rabbitmq::default] 338 | attributes: 339 | rabbitmq: 340 | erlang: 341 | enabled: true 342 | zypper: 343 | baseurl: https://download.opensuse.org/repositories/network:/messaging:/amqp/openSUSE_Leap_15.1 344 | version: "3.8.28" 345 | verifier: 346 | inspec_tests: 347 | - test/erlang_package/latest_rpm 348 | includes: ["opensuse-leap-15"] 349 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the RabbitMQ Chef Cookbook 2 | 3 | Thank you for using Chef, RabbitMQ, this cookbook 4 | and for taking the time to contribute to the project! 5 | 6 | ## Quick-contribute 7 | 8 | * Visit the Github page for the project. 9 | * Fork the repository 10 | * Create a feature branch for your change. 11 | * Create a Pull Request for your change. 12 | * Provide some context and reasoning behind the change. 13 | 14 | We regularly review contributions and will get back to you if we have 15 | any suggestions or concerns. 16 | 17 | 18 | ## How to Report Issues (and When Not To) 19 | 20 | The RabbitMQ team uses GitHub issues for _specific actionable items_ that 21 | engineers can work on. This assumes the following: 22 | 23 | * GitHub issues are not used for questions, investigations, root cause 24 | analysis, discussions of potential issues, etc (as defined by this team) 25 | * Enough information is provided by the reporter for maintainers to work with 26 | 27 | The team receives many questions through various venues every single 28 | day. Frequently, these questions do not include the necessary details 29 | the team needs to begin useful work. GitHub issues can very quickly 30 | turn into a something impossible to navigate and make sense 31 | of. Because of this, questions, investigations, root cause analysis, 32 | and discussions of potential features are all considered to be 33 | [mailing list][rmq-users] material. If you are unsure where to begin, 34 | the [RabbitMQ users mailing list][rmq-users] is the right place. 35 | 36 | 37 | ## Information Required to Reproduce 38 | 39 | Getting all the details necessary to reproduce an issue, make a 40 | conclusion or even form a hypothesis about what's happening can take a 41 | fair amount of time. Please help others help you by providing a way to 42 | reproduce the behavior you're observing, or at least sharing as much 43 | relevant information as possible on the [RabbitMQ users mailing 44 | list][rmq-users]. 45 | 46 | Please provide versions of the software used: 47 | 48 | * Chef version 49 | * Cookbook version 50 | * Node attributes (as many as possible, make sure to edit out **sensitive information**) 51 | * RabbitMQ server version(s) you target 52 | * Erlang version used 53 | * Operating system version and distribution 54 | * What RabbitMQ plugins are used, in particular 3rd party ones 55 | 56 | The following information greatly helps in investigating and reproducing issues: 57 | 58 | * A Vagrant and `chef-zero`-based example that demonstrates the problem 59 | * Chef client debug logs 60 | * RabbitMQ server logs 61 | * Full exception stack traces (a single line message is not enough!) 62 | 63 | Again, please make sure to edit out all **sensitive information**. 64 | 65 | 66 | ## The Apache License and the CLA/CCLA 67 | 68 | Licensing is very important to open source projects, it helps ensure 69 | the software continues to be available under the terms that the author 70 | desired. Chef uses the Apache 2.0 license to strike a balance between 71 | open contribution and allowing you to use the software however you 72 | would like to. 73 | 74 | The license tells you what rights you have that are provided by the 75 | copyright holder. It is important that the contributor fully 76 | understands what rights they are licensing and agrees to them. 77 | Sometimes the copyright holder isn't the contributor, most often when 78 | the contributor is doing work for a company. 79 | 80 | To make a good faith effort to ensure these criteria are met, Chef 81 | Software Inc requires a Contributor License Agreement (CLA) or a Corporate 82 | Contributor License Agreement (CCLA) for all contributions. This is 83 | without exception due to some matters not being related to copyright 84 | and to avoid having to continually check with our lawyers about small 85 | patches. 86 | 87 | It only takes a few minutes to complete a CLA, and you retain the 88 | copyright to your contribution. 89 | 90 | ## Using git 91 | 92 | You can get a quick copy of the repository for this cookbook by 93 | running ```https://github.com/jjasghar/rabbitmq```. 94 | 95 | For collaboration purposes, it is best if you create a Github account 96 | and fork the repository to your own account. Once you do this you will 97 | be able to push your changes to your Github repository for others to 98 | see and use. 99 | 100 | If you have another repository in your GitHub account named the same 101 | as the cookbook, we suggest you suffix the repository with -cookbook. 102 | 103 | ### Branches and Commits 104 | 105 | Create a _topic branch_ and a pull request on Github. It is a best 106 | practice to have your commit message have a _summary line_ followed by 107 | an empty line and then a brief description of the commit. This also 108 | helps other contributors understand the purpose of changes to the 109 | code. 110 | 111 | If your branch has multiple commits, please quash them into a 112 | single commit. If the PR is addressing an issue in the Github issue 113 | tracker, please reference it in the summary line. 114 | 115 | [#42] - platform_family and style 116 | 117 | * use platform_family for platform checking 118 | * update notifies syntax to "resource_type[resource_name]" instead of 119 | resources() lookup 120 | * #40 - delete config files dropped off by packages in conf.d 121 | * dropped debian 4 support because all other platforms have the same 122 | values, and it is older than "old stable" debian release 123 | 124 | Remember that not all users use Chef in the same way or on the same 125 | operating systems as you, so it is helpful to be clear about your use 126 | case and change so they can understand it even when it doesn't apply 127 | to them. 128 | 129 | ## Functional and Unit Tests 130 | 131 | This cookbook is set up to run tests under 132 | [Kitchen-ci's test-kitchen](https://github.com/test-kitchen/test-kitchen). 133 | It uses [inspec](https://inspec.io) to perform integration tests after the node 134 | has been converged. 135 | 136 | Test kitchen should run completely without exception using the default 137 | [baseboxes provided by Chef](https://github.com/chef/bento). 138 | Because Test Kitchen creates VirtualBox machines and runs through 139 | every configuration in the Kitchenfile, it may take some time for 140 | these tests to complete. 141 | 142 | If your changes are only for a specific recipe, run only its 143 | configuration with Test Kitchen. If you are adding a new recipe, or 144 | other functionality such as a LWRP or definition, please add 145 | appropriate tests and ensure they run with Test Kitchen. 146 | 147 | If any don't pass, investigate them before submitting your patch. 148 | 149 | Any new feature should have unit tests included with the patch with 150 | good code coverage to help protect it from future changes. Similarly, 151 | patches that fix a bug or regression should have a _regression test_. 152 | Simply put, this is a test that would fail without your patch but 153 | passes with it. The goal is to ensure this bug doesn't regress in the 154 | future. Consider a regular expression that doesn't match a certain 155 | pattern that it should, so you provide a patch and a test to ensure 156 | that the part of the code that uses this regular expression works as 157 | expected. Later another contributor may modify this regular expression 158 | in a way that breaks your use cases. The test you wrote will fail, 159 | signalling to them to research your ticket and use case and accounting 160 | for it. 161 | 162 | If you need help writing tests, please ask on the Chef Developer's 163 | mailing list or the OpenStack Mailing List, or the #openstack-chef 164 | #chef-hacking IRC channels. 165 | 166 | ## Code Review 167 | 168 | Chef regularly reviews code contributions and provides suggestions 169 | for improvement in the code itself or the implementation. 170 | 171 | Depending on the project, these tickets are then merged within a week 172 | or two, depending on the current release cycle. 173 | 174 | ## Release Cycle 175 | 176 | The versioning for Chef Cookbook projects is X.Y.Z. 177 | 178 | * X is a major release, which may not be fully compatible with prior 179 | major releases 180 | * Y is a minor release, which adds both new features and bug fixes 181 | * Z is a patch release, which adds just bug fixes 182 | 183 | Releases of Chef's cookbooks are usually announced on the Chef user 184 | mailing list. Releases of several cookbooks may be batched together 185 | and announced on the [Chef Blog](https://www.chef.io/blog). 186 | 187 | ## Working with the community 188 | 189 | These resources will help you learn more about Chef and connect to 190 | other members of the Chef community: 191 | 192 | * [openstack cookbook group](https://groups.google.com/forum/#!forum/opscode-chef-openstack) 193 | * [chef](http://lists.opscode.com/sympa/info/chef) and 194 | [chef-dev](http://lists.opscode.com/sympa/info/chef-dev) mailing 195 | lists 196 | * #openstack-chef, #chef, #chef-hacking IRC channels on irc.freenode.net 197 | * Chef, Inc [product page](https://www.chef.io/chef) 198 | 199 | ## Cookbook Contribution Do's and Don't's 200 | 201 | Please do include tests for your contribution. If you need help, ask 202 | on the [openstack cookbook group](https://groups.google.com/forum/#!forum/opscode-chef-openstack) 203 | or the [chef-dev mailing list](http://lists.opscode.com/sympa/info/chef-dev) 204 | or the [#chef-hacking IRC channel](https://community.chef.io/chat/chef-hacking). 205 | 206 | Not all platforms that a cookbook supports may be supported by Test 207 | Kitchen. Please provide evidence of testing your contribution if it 208 | isn't trivial so we don't have to duplicate effort in testing. Chef 209 | 10.14+ "doc" formatted output is sufficient. 210 | 211 | Please do indicate new platform (families) or platform versions in the 212 | commit message, and update the relevant ticket. 213 | 214 | If a contribution adds new platforms or platform versions, indicate 215 | such in the body of the commit message(s). 216 | 217 | git commit -m 'Updated pool resource to correctly delete.' 218 | 219 | Please do ensure that your changes do not break or modify behavior for 220 | other platforms supported by the cookbook. For example if your changes 221 | are for Debian, make sure that they do not break on CentOS. 222 | 223 | Please do not modify the version number in the metadata.rb, Chef 224 | Software, Inc will select the appropriate version based on the release 225 | cycle information above. 226 | 227 | Please do not update the CHANGELOG.md for a new version. Not all 228 | changes to a cookbook may be merged and released in the same versions. 229 | A maintainer will update the CHANGELOG.md when releasing a new version of 230 | the cookbook. 231 | 232 | [rmq-users]: https://groups.google.com/forum/#!forum/rabbitmq-users 233 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | https://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /.kitchen.dokken.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: dokken 3 | privileged: true # because Docker and SystemD/Upstart 4 | chef_version: <%= ENV['CHEF_VERSION'] || 'current' %> 5 | volumes: 6 | - /sys/fs/cgroup:/sys/fs/cgroup 7 | chef_license: accept-no-persist 8 | 9 | transport: 10 | name: dokken 11 | 12 | provisioner: 13 | name: dokken 14 | multiple_converge: 2 15 | # this is an awful productivity killer, 16 | # see rabbitmq/chef-cookbook#555 17 | enforce_idempotency: false 18 | # chef_log_level: debug 19 | 20 | verifier: 21 | name: inspec 22 | root_path: '/opt/verifier' 23 | sudo: false 24 | 25 | platforms: 26 | - name: opensuse-leap-15 27 | driver: 28 | image: dokken/opensuse-leap-15 29 | platform: suse 30 | pid_one_command: /usr/lib/systemd/systemd 31 | hostname: localhost 32 | intermediate_instructions: 33 | - RUN zypper -n install sudo lsof which openssl net-tools 34 | 35 | - name: centos-stream-8 36 | driver: 37 | image: dokken/centos-stream-8 38 | platform: rhel 39 | pid_one_command: /usr/lib/systemd/systemd 40 | intermediate_instructions: 41 | - RUN yum -y install sudo lsof which systemd-sysv initscripts openssl net-tools 42 | 43 | - name: centos-stream-9 44 | driver: 45 | image: dokken/centos-stream-9 46 | platform: rhel 47 | pid_one_command: /usr/lib/systemd/systemd 48 | intermediate_instructions: 49 | - RUN yum -y install sudo lsof which systemd-sysv initscripts openssl net-tools libxcrypt-compat 50 | 51 | - name: fedora-34 52 | driver: 53 | image: dokken/fedora-34 54 | pid_one_command: /usr/lib/systemd/systemd 55 | intermediate_instructions: 56 | - RUN dnf -y install sudo 57 | 58 | - name: amazonlinux-2 59 | driver: 60 | image: dokken/amazonlinux-2 61 | pid_one_command: /usr/lib/systemd/systemd 62 | intermediate_instructions: 63 | - RUN yum -y install sudo lsof which systemd-sysv initscripts openssl net-tools 64 | 65 | - name: amazonlinux-2022 66 | driver: 67 | image: dokken/amazonlinux-2022 68 | pid_one_command: /usr/lib/systemd/systemd 69 | intermediate_instructions: 70 | - RUN yum -y install sudo lsof which systemd-sysv initscripts openssl net-tools 71 | 72 | - name: ubuntu-21.04 73 | driver: 74 | image: dokken/ubuntu-21.04 75 | pid_one_command: /bin/systemd 76 | intermediate_instructions: 77 | - ENV DEBIAN_FRONTEND noninteractive 78 | - RUN /usr/bin/apt-get update -y 79 | - RUN /usr/bin/apt-get upgrade -y 80 | - RUN /usr/bin/apt-get install -y ca-certificates sudo apt-transport-https lsb-release procps net-tools 81 | 82 | - name: ubuntu-20.04 83 | driver: 84 | image: dokken/ubuntu-20.04 85 | pid_one_command: /bin/systemd 86 | intermediate_instructions: 87 | - ENV DEBIAN_FRONTEND noninteractive 88 | - RUN /usr/bin/apt-get update -y 89 | - RUN /usr/bin/apt-get upgrade -y 90 | - RUN /usr/bin/apt-get install -y ca-certificates sudo apt-transport-https lsb-release procps net-tools 91 | 92 | - name: debian-10 93 | driver: 94 | image: dokken/debian-10 95 | pid_one_command: /bin/systemd 96 | intermediate_instructions: 97 | - ENV DEBIAN_FRONTEND noninteractive 98 | - RUN /usr/bin/apt-get update -y 99 | - RUN /usr/bin/apt-get upgrade -y 100 | - RUN /usr/bin/apt-get install -y ca-certificates sudo apt-transport-https lsb-release procps net-tools 101 | 102 | - name: opensuse-leap 103 | driver: 104 | image: dokken/opensuse-leap 105 | pid_one_command: /bin/systemd 106 | intermediate_instructions: 107 | - RUN zypper --non-interactive install sudo 108 | 109 | # 110 | # Suites 111 | # 112 | 113 | suites: 114 | - name: default-deb 115 | run_list: 116 | - recipe[erlang::default] 117 | - recipe[rabbitmq::plugins] 118 | - recipe[rabbitmq::management_ui] 119 | - recipe[rabbitmq::vhosts] 120 | - recipe[rabbitmq::users] 121 | - recipe[rabbitmq::policies] 122 | attributes: 123 | erlang: 124 | install_method: "esl" 125 | esl: 126 | version: "1:24.3.3-1" 127 | rabbitmq: 128 | version: "3.8.28" 129 | virtualhosts: 130 | - vhost1 131 | - vhost2 132 | enabled_users: 133 | - name: user1 134 | password: user1-pwd 135 | tag: management 136 | rights: 137 | - vhost: vhost1 138 | read: ".*" 139 | write: ".*" 140 | conf: ".*" 141 | - name: user2 142 | password: user2-pwd 143 | tag: management 144 | rights: 145 | - vhost: vhost2 146 | read: ".*" 147 | write: ".*" 148 | conf: ".*" 149 | policies: 150 | mirroring: 151 | pattern: "^mirrored\\." 152 | params: 153 | ha-mode: exactly 154 | ha-params: 2 155 | priority: 1 156 | verifier: 157 | inspec_tests: 158 | - test/integration/default 159 | includes: ["ubuntu-20.04", "debian-10"] 160 | 161 | - name: management-plugin-deb 162 | run_list: 163 | - recipe[erlang::default] 164 | - recipe[rabbitmq::management_ui] 165 | attributes: 166 | erlang: 167 | install_method: "esl" 168 | esl: 169 | version: "1:24.3.3-1" 170 | rabbitmq: 171 | version: "3.8.28" 172 | verifier: 173 | inspec_tests: 174 | - test/integration/management_plugin 175 | includes: ["ubuntu-20.04"] 176 | 177 | - name: system-limits-deb 178 | run_list: 179 | - recipe[erlang::default] 180 | - recipe[rabbitmq::systemd_limits] 181 | - recipe[rabbitmq::plugins] 182 | attributes: 183 | erlang: 184 | install_method: "esl" 185 | esl: 186 | version: "1:24.3.3-1" 187 | rabbitmq: 188 | version: "3.8.28" 189 | systemd: 190 | limits: 191 | NOFILE: 54000 192 | verifier: 193 | inspec_tests: 194 | - test/integration/limits 195 | includes: ["ubuntu-20.04", "debian-10"] 196 | 197 | - name: default-rpm 198 | run_list: 199 | - recipe[erlang::default] 200 | - recipe[rabbitmq::plugins] 201 | attributes: 202 | erlang: 203 | install_method: "esl" 204 | esl: 205 | version: "24.1.7-1" 206 | rabbitmq: 207 | version: "3.8.28" 208 | verifier: 209 | inspec_tests: 210 | - test/integration/default 211 | includes: ["centos-stream-8"] 212 | 213 | - name: default-modern-rpm 214 | run_list: 215 | - recipe[rabbitmq::erlang_package] 216 | - recipe[rabbitmq::plugins] 217 | attributes: 218 | rabbitmq: 219 | erlang: 220 | enabled: true 221 | version: "3.8.28" 222 | verifier: 223 | inspec_tests: 224 | - test/integration/default 225 | includes: ["centos-stream-9", "centos-stream-8", "fedora-34", "amazonlinux-2022"] 226 | 227 | - name: system-limits-rpm 228 | run_list: 229 | - recipe[erlang::default] 230 | - recipe[rabbitmq::systemd_limits] 231 | - recipe[rabbitmq::plugins] 232 | attributes: 233 | erlang: 234 | install_method: "esl" 235 | esl: 236 | version: "24.1.7-1" 237 | rabbitmq: 238 | version: "3.8.28" 239 | systemd: 240 | limits: 241 | NOFILE: 54000 242 | verifier: 243 | inspec_tests: 244 | - test/integration/limits 245 | includes: ["centos-stream-8"] 246 | 247 | - name: lwrps 248 | run_list: 249 | - recipe[erlang::default] 250 | - recipe[rabbitmq_test::lwrps] 251 | attributes: 252 | erlang: 253 | install_method: "esl" 254 | esl: 255 | version: "1:24.3.3-1" 256 | rabbitmq: 257 | version: "3.8.28" 258 | verifier: 259 | inspec_tests: 260 | - test/integration/default 261 | - test/integration/lwrps 262 | includes: ["ubuntu-20.04"] 263 | 264 | - name: cluster-deb 265 | run_list: 266 | - recipe[erlang::default] 267 | - recipe[rabbitmq_test::cluster] 268 | attributes: 269 | erlang: 270 | install_method: "esl" 271 | esl: 272 | version: "1:24.3.3-1" 273 | rabbitmq: 274 | version: "3.8.28" 275 | verifier: 276 | inspec_tests: 277 | - test/integration/default 278 | - test/integration/cluster 279 | includes: ["ubuntu-20.04", "debian-10"] 280 | 281 | - name: cluster-rpm 282 | run_list: 283 | - recipe[erlang::default] 284 | - recipe[rabbitmq_test::cluster] 285 | attributes: 286 | erlang: 287 | install_method: "esl" 288 | esl: 289 | version: "24.1.7-1" 290 | rabbitmq: 291 | version: "3.8.28" 292 | verifier: 293 | inspec_tests: 294 | - test/integration/default 295 | - test/integration/cluster 296 | includes: ["centos-stream-8"] 297 | 298 | - name: default-force-yes 299 | run_list: 300 | - recipe[erlang::default] 301 | - recipe[rabbitmq::default] 302 | attributes: 303 | erlang: 304 | install_method: "esl" 305 | esl: 306 | version: "1:24.3.3-1" 307 | rabbitmq: 308 | version: "3.8.28" 309 | attributes: 310 | apt: 311 | confd: 312 | assume_yes: true 313 | force-yes: true 314 | erlang: 315 | install_method: "esl" 316 | esl: 317 | version: "1:24.3.3-1" 318 | rabbitmq: 319 | version: "3.8.28" 320 | verifier: 321 | inspec_tests: 322 | - test/integration/default 323 | includes: ["debian-10"] 324 | 325 | - name: default-force-yes-false 326 | run_list: 327 | - recipe[erlang::default] 328 | - recipe[rabbitmq::default] 329 | attributes: 330 | apt: 331 | confd: 332 | assume_yes: false 333 | force-yes: false 334 | erlang: 335 | install_method: "esl" 336 | esl: 337 | version: "1:24.3.3-1" 338 | rabbitmq: 339 | version: "3.8.28" 340 | verifier: 341 | inspec_tests: 342 | - test/integration/default 343 | includes: ["debian-10"] 344 | 345 | # 346 | # Team RabbitMQ Erlang packages 347 | # 348 | 349 | # Latest Erlang package, Debian 350 | - name: rabbitmq-erlang-latest-deb 351 | run_list: 352 | - recipe[rabbitmq::erlang_package] 353 | - recipe[rabbitmq::default] 354 | attributes: 355 | # relies on node.rabbitmq.erlang.version default 356 | # which is nil/"install latest" 357 | rabbitmq: 358 | erlang: 359 | enabled: true 360 | version: "3.8.28" 361 | verifier: 362 | inspec_tests: 363 | - test/erlang_package/latest_deb 364 | includes: ["debian-10", "ubuntu-20.04"] 365 | 366 | # Erlang package, Debian, version pinning 367 | - name: rabbitmq-erlang-pinned-deb 368 | run_list: 369 | - recipe[rabbitmq::erlang_package] 370 | - recipe[rabbitmq::default] 371 | attributes: 372 | rabbitmq: 373 | erlang: 374 | enabled: true 375 | version: "1:24.3.3-1" 376 | version: "3.8.28" 377 | verifier: 378 | inspec_tests: 379 | - test/erlang_package/pinned_deb 380 | includes: ["debian-10", "ubuntu-20.04"] 381 | 382 | 383 | # Latest Erlang package, RPM 384 | - name: rabbitmq-erlang-latest-rpm 385 | run_list: 386 | - recipe[rabbitmq::erlang_package] 387 | - recipe[rabbitmq::default] 388 | attributes: 389 | # relies on node.rabbitmq.erlang.version default 390 | # which is nil/"install latest" 391 | rabbitmq: 392 | erlang: 393 | version: "24.3.3" 394 | enabled: true 395 | version: "3.8.28" 396 | verifier: 397 | inspec_tests: 398 | - test/erlang_package/latest_rpm 399 | includes: ["fedora-34", "centos-stream-8", "amazonlinux-2022"] 400 | 401 | # Latest Erlang package, RPM, openSUSE leap 15 repo 402 | - name: rabbitmq-erlang-latest-suse 403 | run_list: 404 | - recipe[rabbitmq::erlang_package] 405 | - recipe[rabbitmq::default] 406 | attributes: 407 | rabbitmq: 408 | erlang: 409 | enabled: true 410 | zypper: 411 | baseurl: https://download.opensuse.org/repositories/network:/messaging:/amqp/openSUSE_Leap_15.1/ 412 | version: "3.8.28" 413 | verifier: 414 | inspec_tests: 415 | - test/erlang_package/latest_rpm 416 | includes: ["opensuse-leap-15"] 417 | -------------------------------------------------------------------------------- /resources/cluster.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Resource:: cluster 5 | # 6 | # Author: Sunggun Yu 7 | # Copyright (C) 2015 Sunggun Yu 8 | # Copyright 2019-2021, VMware, Inc or its affiliates. 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | unified_mode true if respond_to?(:unified_mode) 24 | 25 | default_action :join 26 | 27 | property :cluster_nodes, String, name_property: true # first node name to join 28 | property :cluster_name, String # cluster name 29 | 30 | action_class do 31 | include RabbitMQ::CoreHelpers 32 | 33 | # Get ShellOut 34 | def get_shellout(cmd) 35 | Mixlib::ShellOut.new(cmd, :env => shell_environment) 36 | end 37 | 38 | # Execute rabbitmqctl command with args 39 | def run_rabbitmqctl(*args) 40 | cmd = "rabbitmqctl #{args.join(' ')}" 41 | Chef::Log.debug("[rabbitmq_cluster] Executing #{cmd}") 42 | cmd = get_shellout(cmd) 43 | cmd.run_command 44 | begin 45 | cmd.error! 46 | Chef::Log.debug("[rabbitmq_cluster] #{cmd.stdout}") 47 | rescue 48 | raise("[rabbitmq_cluster] #{cmd.stderr}") 49 | end 50 | end 51 | 52 | # Get cluster status result 53 | def cluster_status 54 | # Default formatting changed to "table" in 3.8, need to explicity specify 55 | # "erlang" to parse output properly. 56 | installed_version = Gem::Version.new(installed_rabbitmq_version) 57 | version_requiring_formatter = Gem::Version.new('3.8.0') 58 | cmd = +'rabbitmqctl -q cluster_status' 59 | cmd << ' --formatter erlang' if installed_version >= version_requiring_formatter 60 | # execute > rabbitmqctl cluster_status" 61 | # This removes an optional "... Done" linee that older version used to output 62 | Chef::Log.debug("[rabbitmq_cluster] Executing #{cmd}") 63 | cmd = get_shellout(cmd) 64 | cmd.run_command 65 | cmd.error! 66 | result = cmd.stdout.squeeze(' ').gsub(/\n */, '').gsub('...done.', '') 67 | Chef::Log.debug("[rabbitmq_cluster] #{cmd} : #{result}") 68 | result 69 | end 70 | 71 | # Match regex pattern from result of rabbitmqctl cluster_status 72 | def match_pattern_cluster_status(cluster_status, pattern) 73 | if cluster_status.nil? || cluster_status.to_s.empty? 74 | raise('[rabbitmq_cluster] cluster_status should not be empty') 75 | end 76 | match = cluster_status.match(pattern) 77 | match && match[2] 78 | end 79 | 80 | # Get currently joined cluster name from result string of "rabbitmqctl cluster_status" 81 | def current_cluster_name(cluster_status) 82 | pattern = '({cluster_name,<<")(.*?)(">>})' 83 | result = match_pattern_cluster_status(cluster_status, pattern) 84 | Chef::Log.debug("[rabbitmq_cluster] current_cluster_name : #{result}") 85 | result 86 | end 87 | 88 | # Get running nodes 89 | def running_nodes(cluster_status) 90 | pattern = '({running_nodes,\[\'*)(.*?)(\'*\]})' 91 | match = match_pattern_cluster_status(cluster_status, pattern) 92 | result = match && match.delete("'") 93 | Chef::Log.debug("[rabbitmq_cluster] running_nodes : #{result}") 94 | result.nil? ? [] : result 95 | end 96 | 97 | # Get disc nodes 98 | def disc_nodes(cluster_status) 99 | pattern = '({disc,\[\'*)(.*?)(\'*\]})' 100 | match = match_pattern_cluster_status(cluster_status, pattern) 101 | result = match && match.delete("'").split(',') 102 | Chef::Log.debug("[rabbitmq_cluster] disc_nodes : #{result}") 103 | result.nil? ? [] : result 104 | end 105 | 106 | # Get ram nodes 107 | def ram_nodes(cluster_status) 108 | pattern = '({ram,\[\'*)(.*?)(\'*\]})' 109 | match = match_pattern_cluster_status(cluster_status, pattern) 110 | result = match && match.delete("'").split(',') 111 | Chef::Log.debug("[rabbitmq_cluster] ram_nodes : #{result}") 112 | result.nil? ? [] : result 113 | end 114 | 115 | # Get node name 116 | def node_name 117 | # execute > rabbitmqctl eval 'node().' 118 | cmd = 'rabbitmqctl eval "node()." | head -1' 119 | Chef::Log.debug("[rabbitmq_cluster] Executing #{cmd}") 120 | cmd = get_shellout(cmd) 121 | cmd.run_command 122 | cmd.error! 123 | result = cmd.stdout.chomp.delete("'") 124 | Chef::Log.debug("[rabbitmq_cluster] node name : #{result}") 125 | result 126 | end 127 | 128 | # Get cluster_node_type of current node 129 | def current_cluster_node_type(node_name, cluster_status) 130 | var_cluster_node_type = '' 131 | if disc_nodes(cluster_status).include?(node_name) 132 | var_cluster_node_type = 'disc' 133 | elsif ram_nodes(cluster_status).include?(node_name) 134 | var_cluster_node_type = 'ram' 135 | end 136 | Chef::Log.debug("[rabbitmq_cluster] current cluster node type : #{var_cluster_node_type}") 137 | var_cluster_node_type 138 | end 139 | 140 | # Parse hash string of cluster_nodes to JSON object 141 | def parse_cluster_nodes_string(cluster_nodes) 142 | JSON.parse(cluster_nodes.gsub('=>', ':')) 143 | end 144 | 145 | # Checking node is joined in cluster 146 | def joined_cluster?(node_name, cluster_status) 147 | (running_nodes(cluster_status) || '').include?(node_name) 148 | end 149 | 150 | # Custom exception for join errors 151 | class JoinError < StandardError 152 | end 153 | 154 | # Join cluster. 155 | def join_cluster(cluster_name, type) 156 | cmd = "rabbitmqctl join_cluster #{type == 'ram' ? '--ram' : ''} #{cluster_name}".squeeze(' ') 157 | Chef::Log.debug("[rabbitmq_cluster] Executing #{cmd}") 158 | cmd = get_shellout(cmd) 159 | cmd.run_command 160 | begin 161 | cmd.error! 162 | Chef::Log.info("[rabbitmq_cluster] #{cmd.stdout}") 163 | rescue 164 | err = cmd.stderr 165 | Chef::Log.warn("[rabbitmq_cluster] #{err}") 166 | if err.include?('{ok,already_member}') 167 | Chef::Log.info('[rabbitmq_cluster] Node is already a member of the cluster, error will be ignored.') 168 | elsif err.include?('cannot_cluster_node_with_itself') 169 | Chef::Log.info('[rabbitmq_cluster] Cannot cluster node itself, error will be ignored.') 170 | else 171 | # Don't fatal here, raise JoinError so that Rabbit can be restarted for the next run 172 | raise JoinError, err 173 | end 174 | end 175 | end 176 | 177 | # Change cluster node type 178 | def change_cluster_node_type(cluster_node_type) 179 | cmd = "rabbitmqctl change_cluster_node_type #{cluster_node_type}" 180 | Chef::Log.debug("[rabbitmq_cluster] Executing #{cmd}") 181 | cmd = get_shellout(cmd) 182 | cmd.run_command 183 | begin 184 | cmd.error! 185 | Chef::Log.debug("[rabbitmq_cluster] #{cmd.stdout}") 186 | rescue 187 | err = cmd.stderr 188 | Chef::Log.warn("[rabbitmq_cluster] #{err}") 189 | if err.include?('{not_clustered,"Non-clustered nodes can only be disc nodes."}') 190 | Chef::Log.info('[rabbitmq_cluster] Node is not clustered yet, error will be ignored.') 191 | else 192 | raise("[rabbitmq_cluster] #{err}") 193 | end 194 | end 195 | end 196 | end 197 | 198 | ######################################################################################################################## 199 | # Actions 200 | # :join 201 | # :change_cluster_node_type 202 | ######################################################################################################################## 203 | 204 | # Action for joining cluster 205 | action :join do 206 | Chef::Log.info('[rabbitmq_cluster] Action join ... ') 207 | 208 | raise('rabbitmq_cluster with action :join requires a non-nil/empty cluster_nodes.') if new_resource.cluster_nodes.nil? || new_resource.cluster_nodes.empty? 209 | 210 | var_cluster_status = cluster_status 211 | var_node_name = node_name 212 | var_node_name_to_join = parse_cluster_nodes_string(new_resource.cluster_nodes).first['name'] 213 | var_node_type = parse_cluster_nodes_string(new_resource.cluster_nodes).first['type'] 214 | var_cluster_name = new_resource.cluster_name 215 | 216 | if var_node_name == var_node_name_to_join 217 | Chef::Log.warn('[rabbitmq_cluster] Trying to join cluster node itself. Joining cluster will be skipped.') 218 | elsif joined_cluster?(var_node_name, var_cluster_status) && current_cluster_name(var_cluster_status) == var_cluster_name 219 | Chef::Log.warn("[rabbitmq_cluster] Node is already member of your desired cluster #{current_cluster_name(var_cluster_status)}. Joining cluster will be skipped.") 220 | else 221 | if joined_cluster?(var_node_name, var_cluster_status) && current_cluster_name(var_cluster_status) != var_cluster_name 222 | unless var_cluster_name.nil? 223 | Chef::Log.warn("[rabbitmq_cluster] Node is already member of #{current_cluster_name(var_cluster_status)}. Rejoining the desired cluster.") 224 | end 225 | end 226 | run_rabbitmqctl('stop_app') 227 | 228 | # Catch JoinError so that we can leave Rabbit started, if possible 229 | begin 230 | join_cluster(var_node_name_to_join, var_node_type) 231 | rescue JoinError => exc 232 | raise("[rabbitmq_cluster] #{exc.message}") 233 | ensure 234 | run_rabbitmqctl('start_app') 235 | end 236 | 237 | Chef::Log.info("[rabbitmq_cluster] Node #{var_node_name} joined in #{var_node_name_to_join} with type #{var_node_type}") 238 | Chef::Log.info(cluster_status) 239 | end 240 | end 241 | 242 | # Action for set cluster name 243 | action :set_cluster_name do 244 | raise('rabbitmq_cluster with action :join requires a non-nil/empty cluster_nodes.') if new_resource.cluster_nodes.nil? || new_resource.cluster_nodes.empty? 245 | var_cluster_status = cluster_status 246 | var_cluster_name = new_resource.cluster_name 247 | if current_cluster_name(var_cluster_status).nil? 248 | Chef::Log.warn('[rabbitmq_cluster] Currently not a cluster. Set cluster name will be skipped.') 249 | else 250 | unless current_cluster_name(var_cluster_status) == var_cluster_name 251 | unless var_cluster_name.empty? 252 | run_rabbitmqctl("set_cluster_name #{var_cluster_name}") 253 | Chef::Log.info("[rabbitmq_cluster] Cluster name has been set : #{current_cluster_name(cluster_status)}") 254 | end 255 | end 256 | end 257 | end 258 | 259 | # Action for changing cluster node type 260 | action :change_cluster_node_type do 261 | Chef::Log.info('[rabbitmq_cluster] Action change_cluster_node_type ... ') 262 | 263 | raise('rabbitmq_cluster with action :join requires a non-nil/empty cluster_nodes.') if new_resource.cluster_nodes.nil? || new_resource.cluster_nodes.empty? 264 | 265 | var_cluster_status = cluster_status 266 | var_node_name = node_name 267 | var_current_cluster_node_type = current_cluster_node_type(var_node_name, var_cluster_status) 268 | var_cluster_node_type = parse_cluster_nodes_string(new_resource.cluster_nodes).compact.select { |node| node['name'] == var_node_name }.first['type'] 269 | 270 | if var_current_cluster_node_type == var_cluster_node_type 271 | Chef::Log.warn('[rabbitmq_cluster] Skip changing cluster node type : trying to change to same cluster node type') 272 | node_type_changeable = false 273 | else 274 | if var_cluster_node_type == 'ram' # rubocop:disable all 275 | if var_current_cluster_node_type == 'disc' && disc_nodes(var_cluster_status).length < 2 276 | Chef::Log.warn('[rabbitmq_cluster] At least one disc node is required for rabbitmq cluster. Changing cluster node type will be ignored.') 277 | node_type_changeable = false 278 | else 279 | node_type_changeable = true 280 | end 281 | elsif var_cluster_node_type == 'disc' 282 | node_type_changeable = true 283 | else 284 | Chef::Log.warn("[rabbitmq_cluster] Unexpected cluster_note_type #{var_cluster_node_type}. Changing cluster node type will be ignored.") 285 | node_type_changeable = false 286 | end 287 | end 288 | 289 | # Change cluster node type 290 | if node_type_changeable 291 | run_rabbitmqctl('stop_app') 292 | change_cluster_node_type(var_cluster_node_type) 293 | run_rabbitmqctl('start_app') 294 | Chef::Log.info("[rabbitmq_cluster] The cluster node type of #{var_node_name} has been changed into #{var_cluster_node_type}") 295 | Chef::Log.info(cluster_status) 296 | end 297 | end 298 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Version to install 3 | default['rabbitmq']['version'] = '3.8.28' 4 | 5 | # When true, distribution-provided package will be used. 6 | # This may be useful e.g. on old distributions. 7 | default['rabbitmq']['use_distro_version'] = false 8 | # Allow the distro version to be optionally pinned 9 | default['rabbitmq']['pin_distro_version'] = false 10 | 11 | # provide options to override download urls and package names 12 | default['rabbitmq']['deb_package'] = nil 13 | default['rabbitmq']['deb_package_url'] = nil 14 | 15 | default['rabbitmq']['rpm_package'] = nil 16 | default['rabbitmq']['rpm_package_url'] = nil 17 | 18 | # Set to true when using recipe[rabbitmq::erlang_package] 19 | default['rabbitmq']['erlang']['enabled'] = false 20 | 21 | # On older distributions use ESL packages unless node['rabbitmq']['erlang']['enabled'] 22 | # suggests that the intent is to use recipe[rabbitmq::erlang_package] 23 | # 24 | if !node['rabbitmq']['use_distro_version'] && !node['rabbitmq']['erlang']['enabled'] && 25 | (platform_family?('debian') && node['platform_version'].to_i < 8 || 26 | platform_family?('rhel') && node['platform_version'].to_i < 7) 27 | default['erlang']['install_method'] = 'esl' 28 | end 29 | 30 | default['rabbitmq']['esl-erlang_package'] = 'esl-erlang-compat-R16B03-1.noarch.rpm?raw=true' 31 | default['rabbitmq']['esl-erlang_package_url'] = 'https://github.com/jasonmcintosh/esl-erlang-compat/blob/master/rpmbuild/RPMS/noarch/' 32 | 33 | # socat is not guaranteed to be available on CentOS 6 34 | default['rabbitmq']['socat_package'] = 'socat-1.7.2.3-1.el6.x86_64.rpm' 35 | default['rabbitmq']['socat_package_url'] = 'https://kojipkgs.fedoraproject.org//packages/socat/1.7.2.3/1.el6/x86_64/' 36 | 37 | # being nil, the rabbitmq defaults will be used 38 | default['rabbitmq']['nodename'] = nil 39 | default['rabbitmq']['address'] = nil 40 | default['rabbitmq']['port'] = nil 41 | default['rabbitmq']['config'] = nil 42 | default['rabbitmq']['logdir'] = nil 43 | default['rabbitmq']['server_additional_erl_args'] = nil 44 | default['rabbitmq']['ctl_erl_args'] = nil 45 | 46 | default['rabbitmq']['user'] = 'rabbitmq' 47 | default['rabbitmq']['group'] = 'rabbitmq' 48 | default['rabbitmq']['homedir'] = '/var/lib/rabbitmq' 49 | 50 | default['rabbitmq']['mnesiadir'] = "#{node['rabbitmq']['homedir']}/mnesia" 51 | default['rabbitmq']['service_name'] = 'rabbitmq-server' 52 | 53 | default['rabbitmq']['manage_service'] = true 54 | # service management operation retries. These defaults 55 | # as the same as Chef's. 56 | default['rabbitmq']['retry'] = 0 57 | default['rabbitmq']['retry_delay'] = 2 58 | 59 | # See https://www.rabbitmq.com/configure.html and specifically 60 | # https://www.rabbitmq.com/configure.html#config-file-formats 61 | # Note that the cookbook currently uses classic config format (rabbitmq.config) 62 | # and the docs have moved to recommend rabbitmq.conf + advanced.config where needed. 63 | default['rabbitmq']['config_root'] = '/etc/rabbitmq' 64 | default['rabbitmq']['config'] = "#{node['rabbitmq']['config_root']}/rabbitmq" 65 | default['rabbitmq']['erlang_cookie_path'] = '/var/lib/rabbitmq/.erlang.cookie' 66 | default['rabbitmq']['erlang_cookie'] = 'AnyAlphaNumericStringWillDo' 67 | # override this if you wish to provide `rabbitmq.config.erb` in your own wrapper cookbook 68 | default['rabbitmq']['config_template_cookbook'] = 'rabbitmq' 69 | # override this if you wish to provide `rabbitmq-env.config.erb` in your own wrapper cookbook 70 | default['rabbitmq']['config-env_template_cookbook'] = 'rabbitmq' 71 | 72 | # rabbitmq.config defaults 73 | default['rabbitmq']['default_user'] = 'guest' 74 | default['rabbitmq']['default_pass'] = 'guest' 75 | 76 | # loopback_users 77 | # List of users which are only permitted to connect to the broker via a loopback interface (i.e. localhost). 78 | # If you wish to allow the default guest user to connect remotely, you need to change this to []. 79 | default['rabbitmq']['loopback_users'] = nil 80 | 81 | # Erlang kernel application options 82 | # See https://www.erlang.org/doc/man/kernel_app.html 83 | default['rabbitmq']['kernel']['inet_dist_listen_min'] = nil 84 | default['rabbitmq']['kernel']['inet_dist_listen_max'] = nil 85 | 86 | # Tell Erlang what IP to bind to 87 | default['rabbitmq']['kernel']['inet_dist_use_interface'] = nil 88 | 89 | # clustering 90 | default['rabbitmq']['clustering']['enable'] = false 91 | default['rabbitmq']['clustering']['cluster_partition_handling'] = 'ignore' 92 | 93 | default['rabbitmq']['clustering']['use_auto_clustering'] = false 94 | default['rabbitmq']['clustering']['cluster_name'] = nil 95 | default['rabbitmq']['clustering']['cluster_nodes'] = [] 96 | 97 | ## Chef-driven clustering. 98 | ## 99 | ## Note that there are no leader/master or follower nodes in RabbitMQ, 100 | ## all nodes are equal peers: https://www.rabbitmq.com/clustering.html#peer-equality 101 | default['rabbitmq']['clustering']['node_type'] = 'master' 102 | default['rabbitmq']['clustering']['master_node_name'] = 'rabbit@rabbit1' 103 | default['rabbitmq']['clustering']['cluster_node_type'] = 'disc' 104 | 105 | # log levels 106 | default['rabbitmq']['log_levels'] = { 'connection' => 'info' } 107 | 108 | # Logrotate 109 | default['rabbitmq']['logrotate']['enable'] = true 110 | default['rabbitmq']['logrotate']['path'] = '/var/log/rabbitmq/*.log' 111 | default['rabbitmq']['logrotate']['rotate'] = 20 112 | default['rabbitmq']['logrotate']['frequency'] = 'weekly' 113 | default['rabbitmq']['logrotate']['options'] = %w(missingok notifempty compress delaycompress) 114 | default['rabbitmq']['logrotate']['sharedscripts'] = true 115 | default['rabbitmq']['logrotate']['postrotate'] = '/usr/sbin/rabbitmqctl rotate_logs > /dev/null' 116 | 117 | # resource usage 118 | default['rabbitmq']['disk_free_limit_relative'] = nil 119 | default['rabbitmq']['disk_free_limit'] = nil 120 | default['rabbitmq']['vm_memory_high_watermark'] = nil 121 | default['rabbitmq']['channel_max'] = nil 122 | default['rabbitmq']['max_file_descriptors'] = 1024 123 | default['rabbitmq']['open_file_limit'] = nil 124 | 125 | # job control 126 | default['rabbitmq']['job_control'] = 'initd' 127 | 128 | # authentication and authorization backends 129 | # For example, to enable LDAP: 130 | # default['rabbitmq']['auth_backends'] = 'rabbit_auth_backend_internal, rabbit_auth_backend_ldap' 131 | default['rabbitmq']['auth_backends'] = 'rabbit_auth_backend_internal' 132 | default['rabbitmq']['ldap']['enabled'] = false 133 | default['rabbitmq']['ldap']['conf'] = {} 134 | 135 | # TLS 136 | default['rabbitmq']['ssl'] = false 137 | default['rabbitmq']['ssl_port'] = 5671 138 | default['rabbitmq']['ssl_listen_interface'] = nil 139 | default['rabbitmq']['ssl_cacert'] = '/path/to/cacert.pem' 140 | default['rabbitmq']['ssl_cert'] = '/path/to/cert.pem' 141 | default['rabbitmq']['ssl_key'] = '/path/to/key.pem' 142 | default['rabbitmq']['ssl_verify'] = 'verify_none' 143 | default['rabbitmq']['ssl_depth'] = 1 144 | default['rabbitmq']['ssl_fail_if_no_peer_cert'] = false 145 | # Specify SSL versions 146 | # Example: 147 | # ['tlsv1.2', 'tlsv1.1'] 148 | default['rabbitmq']['ssl_versions'] = nil 149 | # Specify SSL ciphers 150 | # Examples: 151 | # ['{ecdhe_ecdsa,aes_128_cbc,sha256}', '{ecdhe_ecdsa,aes_256_cbc,sha}'] 152 | # or in OpenSSL format: 153 | # ['"ECDHE-ECDSA-AES128-SHA256"', '"ECDHE-ECDSA-AES256-SHA"'] 154 | default['rabbitmq']['ssl_ciphers'] = nil 155 | default['rabbitmq']['ssl_secure_renegotiate'] = true 156 | default['rabbitmq']['ssl_honor_cipher_order'] = true 157 | default['rabbitmq']['ssl_honor_ecc_order'] = true 158 | 159 | default['rabbitmq']['web_console_ssl'] = false 160 | default['rabbitmq']['web_console_ssl_port'] = 15_671 161 | 162 | # If configured to true, allows downstream cookbooks to supply definitions on start 163 | default['rabbitmq']['management']['load_definitions'] = false 164 | default['rabbitmq']['management']['definitions_file'] = '/etc/rabbitmq/load_definitions.json' 165 | 166 | # Change non SSL web console listen port 167 | default['rabbitmq']['web_console_port'] = 15672 168 | 169 | # Add an ability to set web console listen ip. 170 | default['rabbitmq']['web_console_interface'] = nil 171 | 172 | # TCP listener options, see 173 | # https://www.rabbitmq.com/networking.html for details. 174 | default['rabbitmq']['tcp_listen'] = true 175 | 176 | default['rabbitmq']['port'] = 5672 177 | default['rabbitmq']['tcp_listen_interface'] = nil 178 | 179 | default['rabbitmq']['tcp_listen_packet'] = 'raw' 180 | default['rabbitmq']['tcp_listen_reuseaddr'] = true 181 | default['rabbitmq']['tcp_listen_backlog'] = 128 182 | default['rabbitmq']['tcp_listen_nodelay'] = true 183 | default['rabbitmq']['tcp_listen_exit_on_close'] = false 184 | default['rabbitmq']['tcp_listen_keepalive'] = false 185 | default['rabbitmq']['tcp_listen_linger'] = true 186 | default['rabbitmq']['tcp_listen_linger_timeout'] = 0 187 | default['rabbitmq']['tcp_listen_buffer'] = nil 188 | default['rabbitmq']['tcp_listen_sndbuf'] = nil 189 | default['rabbitmq']['tcp_listen_recbuf'] = nil 190 | 191 | # virtualhosts 192 | default['rabbitmq']['virtualhosts'] = [] 193 | default['rabbitmq']['disabled_virtualhosts'] = [] 194 | 195 | # users 196 | default['rabbitmq']['enabled_users'] = 197 | [{ :name => 'guest', :password => 'guest', :rights => 198 | [{ :vhost => nil, :conf => '.*', :write => '.*', :read => '.*' }] 199 | }] 200 | default['rabbitmq']['disabled_users'] = [] 201 | 202 | # plugins 203 | default['rabbitmq']['enabled_plugins'] = [] 204 | default['rabbitmq']['disabled_plugins'] = [] 205 | default['rabbitmq']['community_plugins'] = {} 206 | 207 | # systemd unit files directory 208 | default['rabbitmq']['systemd_unit_root'] = '/etc/systemd/system/rabbitmq-server.service.d' 209 | 210 | default['rabbitmq']['systemd']['limits']['NOFILE'] = 500_000 211 | 212 | # platform specific settings 213 | case node['platform_family'] 214 | when 'smartos' 215 | default['rabbitmq']['service_name'] = 'rabbitmq' 216 | default['rabbitmq']['config_root'] = '/opt/local/etc/rabbitmq' 217 | default['rabbitmq']['config'] = "#{node['rabbitmq']['config_root']}/rabbitmq" 218 | default['rabbitmq']['erlang_cookie_path'] = '/var/db/rabbitmq/.erlang.cookie' 219 | when 'debian' 220 | default['apt']['confd']['assume_yes'] = false 221 | default['apt']['confd']['force-yes'] = false 222 | end 223 | 224 | # heartbeat 225 | default['rabbitmq']['heartbeat'] = 60 226 | 227 | # per default all policies and disabled policies are empty but need to be 228 | # defined 229 | default['rabbitmq']['policies'] = {} 230 | default['rabbitmq']['disabled_policies'] = [] 231 | 232 | # Example HA policies 233 | # default['rabbitmq']['policies']['ha-all']['pattern'] = '^(?!amq\.).*' 234 | # default['rabbitmq']['policies']['ha-all']['params'] = { 'ha-mode' => 'all' } 235 | # default['rabbitmq']['policies']['ha-all']['priority'] = 0 236 | # 237 | # default['rabbitmq']['policies']['ha-two']['pattern'] = '^two.' 238 | # default['rabbitmq']['policies']['ha-two']['params'] = { 'ha-mode' => 'exactly', 'ha-params' => 2 } 239 | # default['rabbitmq']['policies']['ha-two']['priority'] = 1 240 | 241 | # conf 242 | default['rabbitmq']['conf'] = {} 243 | default['rabbitmq']['additional_rabbit_configs'] = {} 244 | 245 | # 246 | # Erlang packages 247 | # 248 | 249 | default['rabbitmq']['erlang']['version'] = nil 250 | # HiPE's been deprecated since Erlang/OTP 22 and was removed completely in Erlang/OTP 24. 251 | # DO NOT USE. 252 | default['rabbitmq']['erlang']['hipe'] = false 253 | default['rabbitmq']['erlang']['retry_delay'] = 10 254 | 255 | # apt 256 | 257 | deb_distro = value_for_platform( 258 | 'debian' => { 259 | 'default' => 'debian' 260 | }, 261 | 'ubuntu' => { 262 | 'default' => 'ubuntu' 263 | } 264 | ) 265 | default['rabbitmq']['erlang']['apt']['uri'] = "https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/deb/#{deb_distro}" 266 | unless node['lsb'].nil? 267 | default['rabbitmq']['erlang']['apt']['lsb_codename'] = node['lsb']['codename'] 268 | end 269 | default['rabbitmq']['erlang']['apt']['components'] = ['main'] 270 | default['rabbitmq']['erlang']['apt']['key'] = 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/gpg.E495BB49CC4BBE5B.key' 271 | 272 | default['rabbitmq']['erlang']['apt']['install_options'] = %w(--fix-missing) 273 | 274 | # yum 275 | default['rabbitmq']['erlang']['yum']['baseurl'] = value_for_platform( 276 | %w(centos redhat scientific oracle) => { 277 | '< 8.0' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/7/$basearch', 278 | 'default' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/8/$basearch' 279 | }, 280 | 'fedora' => { 281 | 'default' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/8/$basearch' 282 | }, 283 | 'amazon' => { 284 | # Amazon Linux 2022 uses el/8 as it is based on Fedora 34+ 285 | '>= 2022' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/8/$basearch', 286 | # Amazon Linux 2 uses el/7 as it is based on CentOS 7 287 | '< 2022' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/7/$basearch', 288 | 'default' => 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/rpm/el/8/$basearch' 289 | } 290 | ) 291 | default['rabbitmq']['erlang']['yum']['gpgkey'] = 'https://dl.cloudsmith.io/public/rabbitmq/rabbitmq-erlang/gpg.E495BB49CC4BBE5B.key' 292 | default['rabbitmq']['erlang']['yum']['gpgcheck'] = true 293 | default['rabbitmq']['erlang']['yum']['repo_gpgcheck'] = false 294 | default['rabbitmq']['erlang']['yum']['enabled'] = true 295 | 296 | # zypper 297 | 298 | default['rabbitmq']['erlang']['zypper']['baseurl'] = 'https://download.opensuse.org/repositories/network:/messaging:/amqp/openSUSE_Leap_15.1/' 299 | default['rabbitmq']['erlang']['zypper']['enabled'] = true 300 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Cookbook Name:: rabbitmq 4 | # Recipe:: default 5 | # 6 | # Copyright 2009, Benjamin Black 7 | # Copyright 2009-2013, Chef Software, Inc. 8 | # Copyright 2012, Kevin Nuckolls 9 | # Copyright 2016-2021, VMware, Inc or its affiliates. 10 | # 11 | # Licensed under the Apache License, Version 2.0 (the "License"); 12 | # you may not use this file except in compliance with the License. 13 | # You may obtain a copy of the License at 14 | # 15 | # https://www.apache.org/licenses/LICENSE-2.0 16 | # 17 | # Unless required by applicable law or agreed to in writing, software 18 | # distributed under the License is distributed on an "AS IS" BASIS, 19 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | # See the License for the specific language governing permissions and 21 | # limitations under the License. 22 | 23 | class Chef::Resource 24 | include RabbitMQ::CoreHelpers # rubocop:enable all 25 | end 26 | 27 | class Chef::Recipe 28 | include RabbitMQ::CoreHelpers # rubocop:enable all 29 | end 30 | 31 | unless node['rabbitmq']['erlang']['enabled'] 32 | include_recipe 'erlang' 33 | end 34 | 35 | version = node['rabbitmq']['version'] 36 | 37 | default_package_url = "https://github.com/rabbitmq/rabbitmq-server/releases/download/v#{version}/" 38 | 39 | default_deb_package_name = "rabbitmq-server_#{version}-1_all.deb" 40 | 41 | default_rpm_package_name = value_for_platform( 42 | %w(centos redhat scientific oracle) => { 43 | '< 8.0' => "rabbitmq-server-#{version}-1.el7.noarch.rpm", 44 | 'default' => "rabbitmq-server-#{version}-1.el8.noarch.rpm" 45 | }, 46 | 'fedora' => { 47 | 'default' => "rabbitmq-server-#{version}-1.el8.noarch.rpm" 48 | }, 49 | 'amazon' => { 50 | 'default' => "rabbitmq-server-#{version}-1.el8.noarch.rpm" 51 | }, 52 | 'suse' => { 53 | 'default' => "rabbitmq-server-#{version}-1.suse.noarch.rpm" 54 | } 55 | ) 56 | 57 | deb_package_name = node['rabbitmq']['deb_package'] || default_deb_package_name 58 | deb_package_url = node['rabbitmq']['deb_package_url'] || default_package_url 59 | rpm_package_name = node['rabbitmq']['rpm_package'] || default_rpm_package_name 60 | rpm_package_url = node['rabbitmq']['rpm_package_url'] || default_package_url 61 | 62 | # see rabbitmq/chef-cookbook#351 63 | directory node['rabbitmq']['config_root'] do 64 | owner 'root' 65 | group 'root' 66 | mode '755' 67 | recursive true 68 | action :create 69 | end 70 | 71 | ## Install the package 72 | if platform_family?('debian') 73 | template '/etc/apt/apt.conf.d/90forceyes' do 74 | source '90forceyes.erb' 75 | owner 'root' 76 | group 'root' 77 | mode '0644' 78 | end 79 | 80 | # logrotate is a package dependency of rabbitmq-server 81 | package 'logrotate' 82 | 83 | # socat is a package dependency of rabbitmq-server 84 | package 'socat' 85 | 86 | # => Prevent Debian systems from automatically starting RabbitMQ after dpkg install 87 | dpkg_autostart node['rabbitmq']['service_name'] do 88 | allow false 89 | end 90 | 91 | if node['platform_version'].to_i < 9 && !use_distro_version? 92 | Chef::Log.warn 'This Debian release is too old to use the recent .deb RabbitMQ packages. Falling back to distro package!' 93 | node.override['rabbitmq']['use_distro_version'] = true 94 | end 95 | 96 | if use_distro_version? 97 | package 'rabbitmq-server' do 98 | action :install 99 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 100 | notifies :reload, 'ohai[reload_packages]', :immediately 101 | end 102 | else 103 | # we need to download the package 104 | remote_file "#{Chef::Config[:file_cache_path]}/#{deb_package_name}" do 105 | source "#{deb_package_url}#{deb_package_name}" 106 | action :create_if_missing 107 | end 108 | dpkg_package 'rabbitmq-server' do 109 | source ::File.join(Chef::Config[:file_cache_path], deb_package_name) 110 | action :upgrade 111 | notifies :reload, 'ohai[reload_packages]', :immediately 112 | end 113 | end 114 | 115 | if service_control_upstart? && manage_rabbitmq_service? 116 | # We start with stock init.d, remove it if we're not using init.d, otherwise leave it alone 117 | service node['rabbitmq']['service_name'] do 118 | action [:stop] 119 | only_if { ::File.exist?('/etc/init.d/rabbitmq-server') } 120 | end 121 | 122 | execute 'remove rabbitmq init.d command' do 123 | command 'update-rc.d -f rabbitmq-server remove' 124 | end 125 | 126 | file '/etc/init.d/rabbitmq-server' do 127 | action :delete 128 | end 129 | 130 | include_recipe 'logrotate' 131 | 132 | logrotate_app 'rabbitmq-server' do 133 | path node['rabbitmq']['logrotate']['path'] 134 | enable node['rabbitmq']['logrotate']['enable'] 135 | rotate node['rabbitmq']['logrotate']['rotate'] 136 | frequency node['rabbitmq']['logrotate']['frequency'] 137 | options node['rabbitmq']['logrotate']['options'] 138 | sharedscripts node['rabbitmq']['logrotate']['sharedscripts'] 139 | postrotate node['rabbitmq']['logrotate']['postrotate'] 140 | end 141 | 142 | template "/etc/init/#{node['rabbitmq']['service_name']}.conf" do 143 | source 'rabbitmq.upstart.conf.erb' 144 | owner 'root' 145 | group 'root' 146 | mode '644' 147 | variables(max_file_descriptors: node['rabbitmq']['max_file_descriptors']) 148 | end 149 | end 150 | end 151 | 152 | if platform_family?('fedora') 153 | package 'logrotate' 154 | package 'socat' 155 | 156 | # This is needed since Erlang Solutions' packages provide "esl-erlang"; this package just requires "esl-erlang" and provides "erlang". 157 | if node['erlang']['install_method'] == 'esl' 158 | Chef::Log.info('Downloading a shim package for esl-erlang') 159 | remote_file "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" do 160 | source "#{node['rabbitmq']['esl-erlang_package_url']}#{node['rabbitmq']['esl-erlang_package']}" 161 | end 162 | rpm_package "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" 163 | end 164 | 165 | if use_distro_version? 166 | package 'rabbitmq-server' do 167 | action :install 168 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 169 | notifies :reload, 'ohai[reload_packages]', :immediately 170 | end 171 | else 172 | remote_file "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 173 | source "#{rpm_package_url}#{rpm_package_name}" 174 | action :create_if_missing 175 | end 176 | rpm_package "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 177 | notifies :reload, 'ohai[reload_packages]', :immediately 178 | end 179 | end 180 | end 181 | 182 | if platform_family?('rhel') 183 | package 'logrotate' 184 | if node['platform_version'].to_i >= 7 185 | package 'socat' 186 | else 187 | Chef::Log.info('Downloading socat installation on CentOS 6') 188 | remote_file "#{Chef::Config[:file_cache_path]}/#{node['rabbitmq']['socat_package']}" do 189 | source "#{node['rabbitmq']['socat_package_url']}#{node['rabbitmq']['socat_package']}" 190 | action :create_if_missing 191 | end 192 | yum_package "#{Chef::Config[:file_cache_path]}/#{node['rabbitmq']['socat_package']}" 193 | end 194 | 195 | # This is needed since Erlang Solutions' packages provide "esl-erlang"; this package 196 | # just requires "esl-erlang" and provides "erlang". 197 | if node['erlang']['install_method'] == 'esl' 198 | Chef::Log.info('Downloading a shim package for esl-erlang') 199 | remote_file "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" do 200 | source "#{node['rabbitmq']['esl-erlang_package_url']}#{node['rabbitmq']['esl-erlang_package']}" 201 | end 202 | rpm_package "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" 203 | end 204 | 205 | if use_distro_version? 206 | package 'rabbitmq-server' do 207 | action :install 208 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 209 | notifies :reload, 'ohai[reload_packages]', :immediately 210 | end 211 | else 212 | remote_file "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 213 | source "#{rpm_package_url}#{rpm_package_name}" 214 | action :create_if_missing 215 | end 216 | rpm_package "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 217 | notifies :reload, 'ohai[reload_packages]', :immediately 218 | end 219 | end 220 | end 221 | 222 | if platform_family?('amazon') 223 | package 'logrotate' 224 | package 'socat' 225 | 226 | # This is needed since Erlang Solutions' packages provide "esl-erlang"; this package 227 | # just requires "esl-erlang" and provides "erlang". 228 | if node['erlang']['install_method'] == 'esl' 229 | Chef::Log.info('Downloading a shim package for esl-erlang') 230 | remote_file "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" do 231 | source "#{node['rabbitmq']['esl-erlang_package_url']}#{node['rabbitmq']['esl-erlang_package']}" 232 | end 233 | rpm_package "#{Chef::Config[:file_cache_path]}/esl-erlang-compat.rpm" 234 | end 235 | 236 | if use_distro_version? 237 | package 'rabbitmq-server' do 238 | action :install 239 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 240 | 241 | notifies :reload, 'ohai[reload_packages]', :immediately 242 | end 243 | else 244 | remote_file "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 245 | source "#{rpm_package_url}#{rpm_package_name}" 246 | action :create_if_missing 247 | end 248 | # Amazon Linux 2022 is based on Fedora 34+ 249 | rpm_package "#{Chef::Config[:file_cache_path]}/#{rpm_package_name}" do 250 | notifies :reload, 'ohai[reload_packages]', :immediately 251 | end 252 | end 253 | end 254 | 255 | if platform_family?('suse') 256 | package 'logrotate' 257 | package 'socat' 258 | 259 | # rabbitmq-server-plugins needs to be first so they both get installed 260 | # from the right repository. Otherwise, zypper will stop and ask for a 261 | # vendor change. 262 | package 'rabbitmq-server-plugins' do 263 | action :install 264 | version node['rabbitmq']['version'] 265 | end 266 | package 'rabbitmq-server' do 267 | action :install 268 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 269 | notifies :reload, 'ohai[reload_packages]', :immediately 270 | end 271 | end 272 | 273 | if platform_family?('smartos') 274 | package 'rabbitmq' do 275 | action :install 276 | version node['rabbitmq']['version'] if node['rabbitmq']['pin_distro_version'] 277 | end 278 | 279 | service 'epmd' do 280 | action :start 281 | end 282 | end 283 | 284 | # 285 | # Users and directories 286 | # 287 | 288 | if platform_family?('amazon') 289 | user 'rabbitmq' do 290 | username node['rabbitmq']['user'] 291 | shell '/sbin/nologin' 292 | home '/var/lib/rabbitmq' 293 | action :create 294 | end 295 | 296 | group 'rabbitmq' do 297 | group_name node['rabbitmq']['group'] 298 | members [node['rabbitmq']['user']] 299 | action :manage 300 | end 301 | end 302 | 303 | if node['rabbitmq']['logdir'] 304 | directory node['rabbitmq']['logdir'] do 305 | owner 'rabbitmq' 306 | group 'rabbitmq' 307 | mode '775' 308 | recursive true 309 | end 310 | end 311 | 312 | directory node['rabbitmq']['mnesiadir'] do 313 | owner 'rabbitmq' 314 | group 'rabbitmq' 315 | mode '775' 316 | recursive true 317 | end 318 | 319 | template "#{node['rabbitmq']['config_root']}/rabbitmq-env.conf" do 320 | source 'rabbitmq-env.conf.erb' 321 | cookbook node['rabbitmq']['config-env_template_cookbook'] 322 | owner 'root' 323 | group 'root' 324 | mode '644' 325 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 326 | variables( 327 | :config_path => rabbitmq_config_file_path 328 | ) 329 | end 330 | 331 | template rabbitmq_config_file_path do 332 | sensitive true if Gem::Version.new(Chef::VERSION.to_s) >= Gem::Version.new('11.14.2') 333 | source 'rabbitmq.config.erb' 334 | cookbook node['rabbitmq']['config_template_cookbook'] 335 | owner 'root' 336 | group 'root' 337 | mode '644' 338 | variables( 339 | :kernel => format_kernel_parameters, 340 | :ssl_versions => (format_ssl_versions if node['rabbitmq']['ssl_versions']), 341 | :ssl_ciphers => (format_ssl_ciphers if node['rabbitmq']['ssl_ciphers']) 342 | ) 343 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 344 | end 345 | 346 | template "/etc/default/#{node['rabbitmq']['service_name']}" do 347 | source 'default.rabbitmq-server.erb' 348 | owner 'root' 349 | group 'root' 350 | mode '644' 351 | notifies :restart, "service[#{node['rabbitmq']['service_name']}]" 352 | end 353 | 354 | existing_erlang_key = if File.exist?(node['rabbitmq']['erlang_cookie_path']) && File.readable?((node['rabbitmq']['erlang_cookie_path'])) 355 | File.read(node['rabbitmq']['erlang_cookie_path']).strip 356 | else 357 | '' 358 | end 359 | 360 | if node['rabbitmq']['clustering']['enable'] && (node['rabbitmq']['erlang_cookie'] != existing_erlang_key) 361 | log "stopping #{node['rabbitmq']['service_name']} because shared cluster secret (the Erlang cookie) has changed" 362 | service node['rabbitmq']['service_name'] do 363 | action :stop 364 | end 365 | 366 | template node['rabbitmq']['erlang_cookie_path'] do 367 | source 'doterlang.cookie.erb' 368 | owner 'rabbitmq' 369 | group 'rabbitmq' 370 | mode '400' 371 | sensitive true 372 | notifies :start, "service[#{node['rabbitmq']['service_name']}]", :immediately 373 | notifies :run, 'execute[reset-node]', :immediately 374 | end 375 | 376 | # Need to reset for clustering # 377 | execute 'reset-node' do 378 | command 'rabbitmqctl stop_app && rabbitmqctl reset && rabbitmqctl start_app' 379 | action :nothing 380 | retries 12 381 | retry_delay 5 382 | end 383 | end 384 | 385 | if manage_rabbitmq_service? 386 | service node['rabbitmq']['service_name'] do 387 | retries node['rabbitmq']['retry'] 388 | retry_delay node['rabbitmq']['retry_delay'] 389 | action [:enable, :start] 390 | supports :status => true, :restart => true 391 | 392 | provider Chef::Provider::Service::Upstart if service_control_upstart? 393 | provider Chef::Provider::Service::Init if service_control_init? 394 | provider Chef::Provider::Service::Systemd if service_control_systemd? 395 | end 396 | else 397 | service node['rabbitmq']['service_name'] do 398 | action :nothing 399 | end 400 | end 401 | 402 | # after installing rabbitmq-server, reload the 'packages' automatic attributes 403 | # from ohai. The version is used when deciding what release series-specific 404 | # features can bee used. 405 | ohai 'reload_packages' do 406 | action :nothing 407 | plugin 'packages' 408 | end 409 | -------------------------------------------------------------------------------- /spec/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'spec_helper' 3 | 4 | describe 'rabbitmq::default' do 5 | let(:runner) do 6 | ChefSpec::ServerRunner.new(REDHAT_OPTS) do |node, _| 7 | node.override['rabbitmq']['version'] = '3.8.28' 8 | end 9 | end 10 | let(:node) { runner.node } 11 | 12 | let(:chef_run) do 13 | runner.converge(described_recipe) 14 | end 15 | 16 | let(:file_cache_path) { Chef::Config[:file_cache_path] } 17 | 18 | include_context 'rabbitmq-stubs' 19 | 20 | it 'creates a node database directory' do 21 | expect(chef_run).to create_directory('/var/lib/rabbitmq/mnesia') 22 | end 23 | 24 | describe 'rabbitmq-env.conf' do 25 | let(:file) { chef_run.template('/etc/rabbitmq/rabbitmq-env.conf') } 26 | 27 | it 'creates a template rabbitmq-env.conf with attributes' do 28 | expect(chef_run).to create_template(file.name).with( 29 | :user => 'root', 30 | :group => 'root', 31 | :source => 'rabbitmq-env.conf.erb', 32 | :mode => '644') 33 | end 34 | 35 | it 'has no erl args by default' do 36 | [/^SERVER_ADDITIONAL_ERL_ARGS=/, 37 | /^CTL_ERL_ARGS=/].each do |line| 38 | expect(chef_run).not_to render_file(file.name).with_content(line) 39 | end 40 | end 41 | 42 | it 'has erl args overridden' do 43 | node.override['rabbitmq']['server_additional_erl_args'] = 'test123' 44 | node.override['rabbitmq']['ctl_erl_args'] = 'test123' 45 | [/^SERVER_ADDITIONAL_ERL_ARGS='test123'/, 46 | /^CTL_ERL_ARGS='test123'/].each do |line| 47 | expect(chef_run).to render_file(file.name).with_content(line) 48 | end 49 | end 50 | 51 | it 'has no additional_env_settings default' do 52 | expect(chef_run).not_to render_file(file.name).with_content(/^# Additional ENV settings/) 53 | end 54 | 55 | it 'has additional_env_settings' do 56 | node.override['rabbitmq']['additional_env_settings'] = [ 57 | 'USE_LONGNAME=true', 58 | 'WHATS_ON_THE_TELLY=penguin'] 59 | [/^WHATS_ON_THE_TELLY=penguin/, 60 | /^# Additional ENV settings/, 61 | /^USE_LONGNAME=true/].each do |line| 62 | expect(chef_run).to render_file(file.name).with_content(line) 63 | end 64 | end 65 | end 66 | 67 | it 'should create the config root directory' do 68 | expect(chef_run).to create_directory('/etc/rabbitmq') 69 | .with( 70 | :user => 'root', 71 | :group => 'root', 72 | :mode => '755' 73 | ) 74 | end 75 | 76 | it 'should create the node data directory' do 77 | expect(chef_run).to create_directory('/var/lib/rabbitmq/mnesia') 78 | .with( 79 | :user => 'rabbitmq', 80 | :group => 'rabbitmq', 81 | :mode => '775' 82 | ) 83 | end 84 | 85 | it 'does not enable a rabbitmq service when manage_service is false' do 86 | node.override['rabbitmq']['manage_service'] = false 87 | expect(chef_run).not_to enable_service('rabbitmq-server') 88 | end 89 | 90 | it 'does not start a rabbitmq service when manage_service is false' do 91 | node.override['rabbitmq']['manage_service'] = false 92 | expect(chef_run).not_to start_service('rabbitmq-server') 93 | end 94 | 95 | it 'enables a rabbitmq service when manage_service is true' do 96 | node.override['rabbitmq']['manage_service'] = true 97 | expect(chef_run).to enable_service('rabbitmq-server') 98 | end 99 | 100 | it 'starts a rabbitmq service when manage_service is true' do 101 | node.override['rabbitmq']['manage_service'] = true 102 | expect(chef_run).to start_service('rabbitmq-server') 103 | end 104 | 105 | it 'should have the use_distro_version set to false' do 106 | expect(chef_run.node['rabbitmq']['use_distro_version']).to eq(false) 107 | end 108 | 109 | describe 'when Erlang is provisioned from ESL' do 110 | let(:runner) do 111 | ChefSpec::ServerRunner.new(REDHAT_OPTS) do |node, _| 112 | node.override['rabbitmq']['version'] = '3.8.28' 113 | node.override['rabbitmq']['erlang']['enabled'] = false 114 | end 115 | end 116 | 117 | let(:chef_run) do 118 | runner.converge(described_recipe, 'rabbitmq::esl_erlang_package') 119 | end 120 | 121 | it 'should install the ESL Erlang package' do 122 | expect(chef_run).to install_package('esl-erlang') 123 | end 124 | end 125 | 126 | it 'should create the rabbitmq /etc/default file' do 127 | expect(chef_run).to create_template("/etc/default/#{chef_run.node['rabbitmq']['service_name']}").with( 128 | :user => 'root', 129 | :group => 'root', 130 | :source => 'default.rabbitmq-server.erb', 131 | :mode => '644' 132 | ) 133 | end 134 | 135 | it 'creates a template rabbitmq.config with attributes' do 136 | expect(chef_run).to create_template('/etc/rabbitmq/rabbitmq.config').with( 137 | :user => 'root', 138 | :group => 'root', 139 | :source => 'rabbitmq.config.erb', 140 | :mode => '644') 141 | 142 | if Gem::Version.new(Chef::VERSION.to_s) >= Gem::Version.new('11.14.2') 143 | expect(chef_run).to create_template('/etc/rabbitmq/rabbitmq.config').with(:sensitive => true) 144 | else 145 | expect(chef_run).to create_template('/etc/rabbitmq/rabbitmq.config').with(:sensitive => false) 146 | end 147 | end 148 | 149 | it 'should set additional rabbitmq config' do 150 | node.override['rabbitmq']['additional_rabbit_configs'] = { 'foo' => 'bar' } 151 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('foo, bar') 152 | end 153 | 154 | describe 'TLS configuration' do 155 | it 'has no ssl ciphers specified by default' do 156 | expect(chef_run).not_to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 157 | /{ciphers,[{.*}]}/) 158 | end 159 | 160 | it 'enables secure renegotiation by default' do 161 | node.override['rabbitmq']['ssl'] = true 162 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 163 | '{secure_renegotiate, true}') 164 | end 165 | 166 | it 'uses server cipher suite preference by default' do 167 | node.override['rabbitmq']['ssl'] = true 168 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 169 | '{honor_cipher_order, true}') 170 | end 171 | 172 | it 'uses server ECC curve preference by default' do 173 | node.override['rabbitmq']['ssl'] = true 174 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 175 | '{honor_ecc_order, true}') 176 | end 177 | 178 | it 'allows ssl ciphers' do 179 | node.override['rabbitmq']['ssl'] = true 180 | node.override['rabbitmq']['ssl_ciphers'] = ['{ecdhe_ecdsa,aes_128_cbc,sha256}', '{ecdhe_ecdsa,aes_256_cbc,sha}'] 181 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 182 | '{ciphers,[{ecdhe_ecdsa,aes_128_cbc,sha256},{ecdhe_ecdsa,aes_256_cbc,sha}]}') 183 | end 184 | 185 | it 'allows web console ssl ciphers' do 186 | node.override['rabbitmq']['web_console_ssl'] = true 187 | node.override['rabbitmq']['ssl_ciphers'] = ['"ECDHE-ECDSA-AES256-SHA384"', '"ECDH-ECDSA-AES256-SHA384"'] 188 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 189 | '{ciphers,["ECDHE-ECDSA-AES256-SHA384","ECDH-ECDSA-AES256-SHA384"]}') 190 | end 191 | 192 | it 'does not enable TLS listeners by default' do 193 | node.override['rabbitmq']['ssl'] = true 194 | expect(chef_run).not_to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 195 | /{ssl_listeners, [5671]},/) 196 | end 197 | 198 | it 'enables TLS listener, if set' do 199 | node.override['rabbitmq']['ssl'] = true 200 | node.override['rabbitmq']['ssl_listen_interface'] = '0.0.0.0' 201 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 202 | /{ssl_listeners, \[{"0.0.0.0", 5671}\]},/) 203 | end 204 | 205 | it 'overrides TLS listener port, if set' do 206 | node.override['rabbitmq']['ssl'] = true 207 | node.override['rabbitmq']['ssl_port'] = 5670 208 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content( 209 | /{ssl_listeners, \[5670\]},/) 210 | end 211 | end 212 | 213 | describe 'TCP listener options' do 214 | it 'allows interface to be overridden' do 215 | node.override['rabbitmq']['tcp_listen_interface'] = '192.168.1.10' 216 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{"192.168.1.10", 5672}') 217 | end 218 | 219 | it 'allows AMQP port to be overridden' do 220 | node.override['rabbitmq']['port'] = 5674 221 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('[5674]') 222 | end 223 | 224 | it 'enables socket lingering by default' do 225 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{linger, {true,0}}') 226 | end 227 | 228 | it 'supports disabling lingering' do 229 | node.override['rabbitmq']['tcp_listen_linger'] = false 230 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{linger, {false,0}}') 231 | end 232 | 233 | it 'supports setting lingering timeout' do 234 | node.override['rabbitmq']['tcp_listen_linger_timeout'] = 5 235 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{linger, {true,5}}') 236 | end 237 | 238 | it 'supports explicit setting of TCP socket buffer' do 239 | node.override['rabbitmq']['tcp_listen_buffer'] = 16384 240 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{buffer, 16384}') 241 | end 242 | 243 | it 'supports explicit setting of TCP socket send buffer' do 244 | node.override['rabbitmq']['tcp_listen_sndbuf'] = 8192 245 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{sndbuf, 8192}') 246 | end 247 | 248 | it 'supports explicit setting of TCP socket receive buffer' do 249 | node.override['rabbitmq']['tcp_listen_recbuf'] = 8192 250 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{recbuf, 8192}') 251 | end 252 | end 253 | 254 | describe 'credit flow' do 255 | it 'can configure defaults' do 256 | node.override['rabbitmq']['credit_flow_defaults']['initial'] = 500 257 | node.override['rabbitmq']['credit_flow_defaults']['more_credit_after'] = 250 258 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('{credit_flow_default_credit, {500, 250}}') 259 | end 260 | end 261 | 262 | describe 'suse' do 263 | let(:runner) do 264 | ChefSpec::ServerRunner.new(SUSE_OPTS) do |node, _| 265 | node.override['rabbitmq']['version'] = '3.8.28' 266 | end 267 | end 268 | let(:node) { runner.node } 269 | let(:chef_run) do 270 | runner.converge(described_recipe) 271 | end 272 | 273 | it 'should install the socat package' do 274 | expect(chef_run).to install_package('socat') 275 | end 276 | 277 | it 'should install the logrotate package' do 278 | expect(chef_run).to install_package('logrotate') 279 | end 280 | 281 | it 'should install the rabbitmq package' do 282 | expect(chef_run).to install_package('rabbitmq-server') 283 | end 284 | 285 | it 'should install the rabbitmq plugin package' do 286 | expect(chef_run).to install_package('rabbitmq-server-plugins') 287 | end 288 | end 289 | 290 | describe 'ubuntu' do 291 | let(:runner) do 292 | ChefSpec::ServerRunner.new(UBUNTU_OPTS) do |node, _| 293 | node.override['rabbitmq']['version'] = '3.8.28' 294 | end 295 | end 296 | let(:node) { runner.node } 297 | let(:chef_run) do 298 | node.override['rabbitmq']['version'] = '3.8.28' 299 | runner.converge(described_recipe) 300 | end 301 | 302 | it 'creates a template for 90forceyes' do 303 | expect(chef_run).to create_template('/etc/apt/apt.conf.d/90forceyes') 304 | end 305 | 306 | include_context 'rabbitmq-stubs' 307 | 308 | it 'should install the logrotate package' do 309 | expect(chef_run).to install_package('logrotate') 310 | end 311 | 312 | it 'should install the socat package' do 313 | expect(chef_run).to install_package('socat') 314 | end 315 | 316 | it 'creates a rabbitmq-server deb in the cache path' do 317 | expect(chef_run).to create_remote_file_if_missing('/tmp/rabbitmq-server_3.8.28-1_all.deb') 318 | end 319 | 320 | it 'installs the rabbitmq-server deb_package with the default action' do 321 | expect(chef_run).to upgrade_dpkg_package('rabbitmq-server') 322 | end 323 | 324 | it 'creates a template rabbitmq-server with attributes' do 325 | expect(chef_run).to create_template('/etc/default/rabbitmq-server').with( 326 | :user => 'root', 327 | :group => 'root', 328 | :source => 'default.rabbitmq-server.erb', 329 | :mode => '644') 330 | end 331 | 332 | describe 'uses distro version' do 333 | before do 334 | node.override['rabbitmq']['use_distro_version'] = true 335 | end 336 | 337 | it 'should install rabbitmq-server package' do 338 | expect(chef_run).to install_package('rabbitmq-server') 339 | end 340 | 341 | it 'should install the logrotate package' do 342 | expect(chef_run).to install_package('logrotate') 343 | end 344 | end 345 | end 346 | 347 | describe 'redhat' do 348 | let(:runner) do 349 | ChefSpec::ServerRunner.new(REDHAT_OPTS) do |node, _| 350 | node.override['rabbitmq']['version'] = '3.8.28' 351 | end 352 | end 353 | let(:node) { runner.node } 354 | let(:chef_run) do 355 | runner.converge(described_recipe) 356 | end 357 | 358 | let(:rpm_file) { 'rabbitmq-server-3.8.28-1.el8.noarch.rpm' } 359 | 360 | it 'creates a rabbitmq-server rpm in the cache path' do 361 | expect(chef_run).to create_remote_file_if_missing("/tmp/#{rpm_file}") 362 | end 363 | 364 | it 'installs the rabbitmq-server rpm_package with the default action' do 365 | expect(chef_run).to install_rpm_package("/tmp/#{rpm_file}") 366 | end 367 | 368 | describe 'uses distro version' do 369 | before do 370 | node.override['rabbitmq']['use_distro_version'] = true 371 | end 372 | 373 | it 'should install rabbitmq-server package' do 374 | expect(chef_run).to install_package('rabbitmq-server') 375 | end 376 | end 377 | 378 | it 'loopback_users will not show in config file unless attribute is specified' do 379 | expect(chef_run).not_to render_file('/etc/rabbitmq/rabbitmq.config').with_content('loopback_users') 380 | end 381 | 382 | it 'loopback_users is empty when attribute is empty array' do 383 | node.override['rabbitmq']['loopback_users'] = [] 384 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('loopback_users, []') 385 | end 386 | 387 | it 'loopback_users can list single user' do 388 | node.override['rabbitmq']['loopback_users'] = ['one'] 389 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('loopback_users, [<<"one">>]') 390 | end 391 | 392 | it 'loopback_users can list multiple users' do 393 | node.override['rabbitmq']['loopback_users'] = %w(one two) 394 | expect(chef_run).to render_file('/etc/rabbitmq/rabbitmq.config').with_content('loopback_users, [<<"one">>,<<"two">>]') 395 | end 396 | 397 | it 'should install the logrotate package' do 398 | expect(chef_run).to install_package('logrotate') 399 | end 400 | 401 | it 'should install the socat package' do 402 | expect(chef_run).to install_package('socat') 403 | end 404 | end 405 | end 406 | --------------------------------------------------------------------------------