Skip to content

Commit

Permalink
Merge pull request #390 from mkrakowitzer/set_parameter
Browse files Browse the repository at this point in the history
Adds support for rabbitmqctl command option set_parameter
  • Loading branch information
hunner committed Sep 29, 2015
2 parents 1e2ea5c + cbc51d3 commit c420e12
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 2 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake
matrix:
fast_finish: true
include:
- rvm: 1.8.7
env: PUPPET_GEM_VERSION="~> 3.0"
- rvm: 1.9.3
env: PUPPET_GEM_VERSION="~> 3.0"
- rvm: 2.1.5
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,28 @@ rabbitmq_plugin {'rabbitmq_stomp':
}
```

### rabbitmq\_parameter

```puppet
rabbitmq_parameter { 'documentumShovel@/':
component_name => '',
value => {
'src-uri' => 'amqp://',
'src-queue' => 'my-queue',
'dest-uri' => 'amqp://remote-server',
'dest-queue' => 'another-queue',
},
}
rabbitmq_parameter { 'documentumFed@/':
component_name => 'federation-upstream',
value => {
'uri' => 'amqp://myserver',
'expires' => '360000',
},
}
```

### rabbitmq\_erlang\_cookie

This is essentially a private type used by the rabbitmq::config class
Expand Down
84 changes: 84 additions & 0 deletions lib/puppet/provider/rabbitmq_parameter/rabbitmqctl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require 'json'
require 'puppet/util/package'

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rabbitmqctl'))
Puppet::Type.type(:rabbitmq_parameter).provide(:rabbitmqctl, :parent => Puppet::Provider::Rabbitmqctl) do

defaultfor :feature => :posix

# cache parameters
def self.parameters(name, vhost)
@parameters = {} unless @parameters
unless @parameters[vhost]
@parameters[vhost] = {}
self.run_with_retries {
rabbitmqctl('list_parameters', '-q', '-p', vhost)
}.split(/\n/).each do |line|
if line =~ /^(\S+)\s+(\S+)\s+(\S+)$/
@parameters[vhost][$2] = {
:component_name => $1,
:value => JSON.parse($3),
}
else
raise Puppet::Error, "cannot parse line from list_parameter:#{line}"
end
end
end
@parameters[vhost][name]
end

def parameters(name, vhost)
self.class.parameters(vhost, name)
end

def should_parameter
@should_parameter ||= resource[:name].rpartition('@').first
end

def should_vhost
@should_vhost ||= resource[:name].rpartition('@').last
end

def create
set_parameter
end

def destroy
rabbitmqctl('clear_parameter', '-p', should_vhost, 'shovel', should_parameter)
end

def exists?
parameters(should_vhost, should_parameter)
end

def component_name
parameters(should_vhost, should_parameter)[:component_name]
end

def component_name=(component_name)
set_parameter
end

def value
parameters(should_vhost, should_parameter)[:value]
end

def value=(value)
set_parameter
end

def set_parameter
unless @set_parameter
@set_parameter = true
resource[:value] ||= value
resource[:component_name] ||= component_name
rabbitmqctl('set_parameter',
'-p', should_vhost,
resource[:component_name],
should_parameter,
resource[:value].to_json
)
end
end

end
73 changes: 73 additions & 0 deletions lib/puppet/type/rabbitmq_parameter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Puppet::Type.newtype(:rabbitmq_parameter) do

desc 'Type for managing rabbitmq parameters'

ensurable do
defaultto(:present)
newvalue(:present) do
provider.create
end
newvalue(:absent) do
provider.destroy
end
end

autorequire(:service) { 'rabbitmq-server' }

validate do
fail('component_name parameter is required.') if self[:ensure] == :present and self[:component_name].nil?
fail('value parameter is required.') if self[:ensure] == :present and self[:value].nil?
end

newparam(:name, :namevar => true) do
desc 'combination of name@vhost to set parameter for'
newvalues(/^\S+@\S+$/)
end

newproperty(:component_name) do
desc 'The component_name to use when setting parameter, eg: shovel or federation'
validate do |value|
resource.validate_component_name(value)
end
end

newproperty(:value) do
desc 'A hash of values to use with the component name you are setting'
validate do |value|
resource.validate_value(value)
end
munge do |value|
resource.munge_value(value)
end
end

autorequire(:rabbitmq_vhost) do
[self[:name].split('@')[1]]
end

def validate_component_name(value)
if value.empty?
raise ArgumentError, "component_name must be defined"
end
end

def validate_value(value)
unless [Hash].include?(value.class)
raise ArgumentError, "Invalid value"
end
value.each do |k,v|
unless [String].include?(v.class)
raise ArgumentError, "Invalid value"
end
end
end

def munge_value(value)
value.each do |k,v|
if (v =~ /\A[-+]?[0-9]+\z/)
value[k] = v.to_i
end
end
value
end
end
87 changes: 87 additions & 0 deletions spec/unit/puppet/provider/rabbitmq_parameter/rabbitmqctl_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require 'puppet'
require 'mocha'

RSpec.configure do |config|
config.mock_with :mocha
end

describe Puppet::Type.type(:rabbitmq_parameter).provider(:rabbitmqctl) do

let(:resource) do
Puppet::Type.type(:rabbitmq_parameter).new(
:name => 'documentumShovel@/',
:component_name => 'shovel',
:value => {
'src-uri' => 'amqp://',
'src-queue' => 'my-queue',
'dest-uri' => 'amqp://remote-server',
'dest-queue' => 'another-queue',
},
:provider => described_class.name
)
end

let(:provider) { resource.provider }

after(:each) do
described_class.instance_variable_set(:@parameters, nil)
end

it 'should accept @ in parameter name' do
resource = Puppet::Type.type(:rabbitmq_parameter).new(
:name => 'documentumShovel@/',
:component_name => 'shovel',
:value => {
'src-uri' => 'amqp://',
'src-queue' => 'my-queue',
'dest-uri' => 'amqp://remote-server',
'dest-queue' => 'another-queue',
},
:provider => described_class.name
)
provider = described_class.new(resource)
provider.should_parameter.should == 'documentumShovel'
provider.should_vhost.should == '/'
end

it 'should fail with invalid output from list' do
provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns 'foobar'
expect { provider.exists? }.to raise_error(Puppet::Error, /cannot parse line from list_parameter/)
end

it 'should match parameters from list' do
provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns <<-EOT
shovel documentumShovel {"src-uri":"amqp://","src-queue":"my-queue","dest-uri":"amqp://remote-server","dest-queue":"another-queue"}
EOT
provider.exists?.should == {
:component_name => 'shovel',
:value => {
'src-uri' => 'amqp://',
'src-queue' => 'my-queue',
'dest-uri' => 'amqp://remote-server',
'dest-queue' => 'another-queue',
}
}
end

it 'should not match an empty list' do
provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns ''
provider.exists?.should == nil
end

it 'should destroy parameter' do
provider.expects(:rabbitmqctl).with('clear_parameter', '-p', '/', 'shovel', 'documentumShovel')
provider.destroy
end

it 'should only call set_parameter once' do
provider.expects(:rabbitmqctl).with('set_parameter',
'-p', '/',
'shovel',
'documentumShovel',
'{"src-uri":"amqp://","src-queue":"my-queue","dest-uri":"amqp://remote-server","dest-queue":"another-queue"}'
).once
provider.create
end

end
81 changes: 81 additions & 0 deletions spec/unit/puppet/type/rabbitmq_parameter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require 'puppet'
require 'puppet/type/rabbitmq_parameter'

describe Puppet::Type.type(:rabbitmq_parameter) do

before do
@parameter = Puppet::Type.type(:rabbitmq_parameter).new(
:name => 'documentumShovel@/',
:component_name => 'shovel',
:value => {
'src-uri' => 'amqp://myremote-server',
'src-queue' => 'queue.docs.outgoing',
'dest-uri' => 'amqp://',
'dest-queue' => 'queue.docs.incoming',
})
end

it 'should accept a valid name' do
@parameter[:name] = 'documentumShovel@/'
@parameter[:name].should == 'documentumShovel@/'
end

it 'should require a name' do
expect {
Puppet::Type.type(:rabbitmq_parameter).new({})
}.to raise_error(Puppet::Error, 'Title or name must be provided')
end

it 'should fail when name does not have a @' do
expect {
@parameter[:name] = 'documentumShovel'
}.to raise_error(Puppet::Error, /Valid values match/)
end

it 'should accept a string' do
@parameter[:component_name] = 'mystring'
@parameter[:component_name].should == 'mystring'
end

it 'should not be empty' do
expect {
@parameter[:component_name] = ''
}.to raise_error(Puppet::Error, /component_name must be defined/)
end

it 'should accept a valid hash for value' do
value = {'message-ttl' => '1800000'}
@parameter[:value] = value
@parameter[:value].should == value
end

it 'should not accept invalid hash for definition' do
expect {
@parameter[:value] = ''
}.to raise_error(Puppet::Error, /Invalid value/)

expect {
@parameter[:value] = 'guest'
}.to raise_error(Puppet::Error, /Invalid value/)

expect {
@parameter[:value] = {'message-ttl' => ['999', '100']}
}.to raise_error(Puppet::Error, /Invalid value/)
end

it 'should accept string as myparameter' do
value = {'myparameter' => 'mystring'}
@parameter[:value] = value
@parameter[:value]['myparameter'].should be_a(String)
@parameter[:value]['myparameter'].should == 'mystring'
end


it 'should convert to integer when string only contains numbers' do
value = {'myparameter' => '1800000'}
@parameter[:value] = value
@parameter[:value]['myparameter'].should be_a(Fixnum)
@parameter[:value]['myparameter'].should == 1800000
end

end

0 comments on commit c420e12

Please sign in to comment.