diff --git a/lib/puppet/type/rabbitmq_policy.rb b/lib/puppet/type/rabbitmq_policy.rb index 65275a7..a118525 100644 --- a/lib/puppet/type/rabbitmq_policy.rb +++ b/lib/puppet/type/rabbitmq_policy.rb @@ -1,163 +1,172 @@ Puppet::Type.newtype(:rabbitmq_policy) do desc <<-DESC Type for managing rabbitmq policies @example Create a rabbitmq_policy rabbitmq_policy { 'ha-all@myvhost': pattern => '.*', priority => 0, applyto => 'all', definition => { 'ha-mode' => 'all', 'ha-sync-mode' => 'automatic', }, } DESC ensurable do defaultto(:present) newvalue(:present) do provider.create end newvalue(:absent) do provider.destroy end end autorequire(:service) { 'rabbitmq-server' } validate do raise('pattern parameter is required.') if self[:ensure] == :present && self[:pattern].nil? raise('definition parameter is required.') if self[:ensure] == :present && self[:definition].nil? end newparam(:name, namevar: true) do desc 'combination of policy@vhost to create policy for' newvalues(%r{^\S+@\S+$}) end newproperty(:pattern) do desc 'policy pattern' validate do |value| resource.validate_pattern(value) end end newproperty(:applyto) do desc 'policy apply to' newvalue(:all) newvalue(:exchanges) newvalue(:queues) defaultto :all end newproperty(:definition) do desc 'policy definition' validate do |value| resource.validate_definition(value) end munge do |value| resource.munge_definition(value) end end newproperty(:priority) do desc 'policy priority' newvalues(%r{^\d+$}) defaultto 0 end autorequire(:rabbitmq_vhost) do [self[:name].split('@')[1]] end def validate_pattern(value) Regexp.new(value) rescue RegexpError raise ArgumentError, "Invalid regexp #{value}" end def validate_definition(definition) unless [Hash].include?(definition.class) raise ArgumentError, 'Invalid definition' end definition.each do |k, v| if k == 'ha-params' && definition['ha-mode'] == 'nodes' unless [Array].include?(v.class) raise ArgumentError, "Invalid definition, value #{v} for key #{k} is not an array" end else unless [String].include?(v.class) raise ArgumentError, "Invalid definition, value #{v} is not a string" end end end if definition['ha-mode'] == 'exactly' ha_params = definition['ha-params'] unless ha_params.to_i.to_s == ha_params raise ArgumentError, "Invalid ha-params '#{ha_params}' for ha-mode 'exactly'" end end if definition.key? 'expires' expires_val = definition['expires'] unless expires_val.to_i.to_s == expires_val raise ArgumentError, "Invalid expires value '#{expires_val}'" end end if definition.key? 'message-ttl' message_ttl_val = definition['message-ttl'] unless message_ttl_val.to_i.to_s == message_ttl_val raise ArgumentError, "Invalid message-ttl value '#{message_ttl_val}'" end end if definition.key? 'max-length' max_length_val = definition['max-length'] unless max_length_val.to_i.to_s == max_length_val raise ArgumentError, "Invalid max-length value '#{max_length_val}'" end end if definition.key? 'max-length-bytes' max_length_bytes_val = definition['max-length-bytes'] unless max_length_bytes_val.to_i.to_s == max_length_bytes_val raise ArgumentError, "Invalid max-length-bytes value '#{max_length_bytes_val}'" end end if definition.key? 'shards-per-node' shards_per_node_val = definition['shards-per-node'] unless shards_per_node_val.to_i.to_s == shards_per_node_val raise ArgumentError, "Invalid shards-per-node value '#{shards_per_node_val}'" end end - if definition.key? 'ha-sync-batch-size' # rubocop:disable Style/GuardClause + if definition.key? 'ha-sync-batch-size' ha_sync_batch_size_val = definition['ha-sync-batch-size'] unless ha_sync_batch_size_val.to_i.to_s == ha_sync_batch_size_val raise ArgumentError, "Invalid ha-sync-batch-size value '#{ha_sync_batch_size_val}'" end end + if definition.key? 'delivery-limit' # rubocop:disable Style/GuardClause + delivery_limit_val = definition['delivery-limit'] + unless delivery_limit_val.to_i.to_s == delivery_limit_val + raise ArgumentError, "Invalid delivery-limit value '#{delivery_limit_val}'" + end + end end def munge_definition(definition) if definition['ha-mode'] == 'exactly' definition['ha-params'] = definition['ha-params'].to_i end if definition.key? 'expires' definition['expires'] = definition['expires'].to_i end if definition.key? 'message-ttl' definition['message-ttl'] = definition['message-ttl'].to_i end if definition.key? 'max-length' definition['max-length'] = definition['max-length'].to_i end if definition.key? 'max-length-bytes' definition['max-length-bytes'] = definition['max-length-bytes'].to_i end if definition.key? 'shards-per-node' definition['shards-per-node'] = definition['shards-per-node'].to_i end if definition.key? 'ha-sync-batch-size' definition['ha-sync-batch-size'] = definition['ha-sync-batch-size'].to_i end + if definition.key? 'delivery-limit' + definition['delivery-limit'] = definition['delivery-limit'].to_i + end definition end end diff --git a/spec/unit/puppet/type/rabbitmq_policy_spec.rb b/spec/unit/puppet/type/rabbitmq_policy_spec.rb index fca3c61..ae11863 100644 --- a/spec/unit/puppet/type/rabbitmq_policy_spec.rb +++ b/spec/unit/puppet/type/rabbitmq_policy_spec.rb @@ -1,202 +1,215 @@ require 'spec_helper' describe Puppet::Type.type(:rabbitmq_policy) do let(:policy) do Puppet::Type.type(:rabbitmq_policy).new( name: 'ha-all@/', pattern: '.*', definition: { 'ha-mode' => 'all' } ) end it 'accepts a valid name' do policy[:name] = 'ha-all@/' expect(policy[:name]).to eq('ha-all@/') end it 'requires a name' do expect do Puppet::Type.type(:rabbitmq_policy).new({}) end.to raise_error(Puppet::Error, 'Title or name must be provided') end it 'fails when name does not have a @' do expect do policy[:name] = 'ha-all' end.to raise_error(Puppet::Error, %r{Valid values match}) end it 'accepts a valid regex for pattern' do policy[:pattern] = '.*?' expect(policy[:pattern]).to eq('.*?') end it 'accepts an empty string for pattern' do policy[:pattern] = '' expect(policy[:pattern]).to eq('') end it 'does not accept invalid regex for pattern' do expect do policy[:pattern] = '*' end.to raise_error(Puppet::Error, %r{Invalid regexp}) end it 'accepts valid value for applyto' do [:all, :exchanges, :queues].each do |v| policy[:applyto] = v expect(policy[:applyto]).to eq(v) end end it 'does not accept invalid value for applyto' do expect do policy[:applyto] = 'me' end.to raise_error(Puppet::Error, %r{Invalid value}) end it 'accepts a valid hash for definition' do definition = { 'ha-mode' => 'all', 'ha-sync-mode' => 'automatic' } policy[:definition] = definition expect(policy[:definition]).to eq(definition) end it 'does not accept a string for definition' do expect do policy[:definition] = 'ha-mode' end.to raise_error(Puppet::Error, %r{Invalid definition}) end it 'does not accept invalid hash for definition' do expect do policy[:definition] = { 'ha-mode' => %w[a b] } end.to raise_error(Puppet::Error, %r{Invalid definition}) end it 'accepts valid value for priority' do [0, 10, '0', '10'].each do |v| policy[:priority] = v expect(policy[:priority]).to eq(v) end end it 'does not accept invalid value for priority' do ['-1', -1, '1.0', 1.0, 'abc', ''].each do |v| expect do policy[:priority] = v end.to raise_error(Puppet::Error, %r{Invalid value}) end end it 'accepts and convert ha-params for ha-mode exactly' do definition = { 'ha-mode' => 'exactly', 'ha-params' => '2' } policy[:definition] = definition expect(policy[:definition]['ha-params']).to eq(2) end it 'does not accept non-numeric ha-params for ha-mode exactly' do definition = { 'ha-mode' => 'exactly', 'ha-params' => 'nonnumeric' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid ha-params.*nonnumeric.*exactly}) end it 'accepts and convert the expires value' do definition = { 'expires' => '1800000' } policy[:definition] = definition expect(policy[:definition]['expires']).to eq(1_800_000) end it 'does not accept non-numeric expires value' do definition = { 'expires' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid expires value.*future}) end it 'accepts and convert the message-ttl value' do definition = { 'message-ttl' => '1800000' } policy[:definition] = definition expect(policy[:definition]['message-ttl']).to eq(1_800_000) end it 'does not accept non-numeric message-ttl value' do definition = { 'message-ttl' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid message-ttl value.*future}) end it 'accepts and convert the max-length value' do definition = { 'max-length' => '1800000' } policy[:definition] = definition expect(policy[:definition]['max-length']).to eq(1_800_000) end it 'does not accept non-numeric max-length value' do definition = { 'max-length' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid max-length value.*future}) end it 'accepts and convert the max-length-bytes value' do definition = { 'max-length-bytes' => '1800000' } policy[:definition] = definition expect(policy[:definition]['max-length-bytes']).to eq(1_800_000) end it 'does not accept non-numeric max-length-bytes value' do definition = { 'max-length-bytes' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid max-length-bytes value.*future}) end it 'accepts and convert the shards-per-node value' do definition = { 'shards-per-node' => '1800000' } policy[:definition] = definition expect(policy[:definition]['shards-per-node']).to eq(1_800_000) end it 'does not accept non-numeric shards-per-node value' do definition = { 'shards-per-node' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid shards-per-node value.*future}) end it 'accepts and convert the ha-sync-batch-size value' do definition = { 'ha-sync-batch-size' => '1800000' } policy[:definition] = definition expect(policy[:definition]['ha-sync-batch-size']).to eq(1_800_000) end it 'does not accept non-numeric ha-sync-batch-size value' do definition = { 'ha-sync-batch-size' => 'future' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid ha-sync-batch-size value.*future}) end + it 'accepts and converts the delivery-limit value' do + definition = { 'delivery-limit' => '3' } + policy[:definition] = definition + expect(policy[:definition]['delivery-limit']).to eq(3) + end + + it 'does not accept non-numeric delivery-limit value' do + definition = { 'delivery-limit' => 'future' } + expect do + policy[:definition] = definition + end.to raise_error(Puppet::Error, %r{Invalid delivery-limit value.*future}) + end + context 'accepts list value in ha-params when ha-mode = nodes' do before do policy[:definition] = definition end let(:definition) { { 'ha-mode' => 'nodes', 'ha-params' => ['rabbit@rabbit-01', 'rabbit@rabbit-02'] } } it { expect(policy[:definition]['ha-mode']).to eq('nodes') } it { expect(policy[:definition]['ha-params']).to be_a(Array) } it { expect(policy[:definition]['ha-params'][0]).to eq('rabbit@rabbit-01') } it { expect(policy[:definition]['ha-params'][1]).to eq('rabbit@rabbit-02') } end it 'does not accept non-list value in ha-params when ha-mode = nodes' do definition = { 'ha-mode' => 'nodes', 'ha-params' => 'this-will-fail' } expect do policy[:definition] = definition end.to raise_error(Puppet::Error, %r{Invalid definition, value this-will-fail for key ha-params is not an array}) end end