Skip to content

Commit ebc20c2

Browse files
ironpinguinglobin
authored andcommitted
Add new resource rabbitmq_queue
1 parent 04145c1 commit ebc20c2

4 files changed

Lines changed: 293 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
require 'json'
2+
require 'puppet'
3+
Puppet::Type.type(:rabbitmq_queue).provide(:rabbitmqadmin) do
4+
5+
if Puppet::PUPPETVERSION.to_f < 3
6+
commands :rabbitmqctl => 'rabbitmqctl'
7+
commands :rabbitmqadmin => '/usr/local/bin/rabbitmqadmin'
8+
else
9+
has_command(:rabbitmqctl, 'rabbitmqctl') do
10+
environment :HOME => "/tmp"
11+
end
12+
has_command(:rabbitmqadmin, '/usr/local/bin/rabbitmqadmin') do
13+
environment :HOME => "/tmp"
14+
end
15+
end
16+
defaultfor :feature => :posix
17+
18+
def should_vhost
19+
if @should_vhost
20+
@should_vhost
21+
else
22+
@should_vhost = resource[:name].rpartition('@').last
23+
end
24+
end
25+
26+
def self.all_vhosts
27+
vhosts = []
28+
rabbitmqctl('list_vhosts', '-q').split(/\n/).collect do |vhost|
29+
vhosts.push(vhost)
30+
end
31+
vhosts
32+
end
33+
34+
def self.all_queues(vhost)
35+
rabbitmqctl('list_queues', '-q', '-p', vhost, 'name', 'durable', 'auto_delete', 'arguments').split(/\n/)
36+
end
37+
38+
def self.instances
39+
resources = []
40+
all_vhosts.each do |vhost|
41+
all_queues(vhost).collect do |line|
42+
name, durable, auto_delete, arguments = line.split()
43+
# Convert output of arguments from the rabbitmqctl command to a json string.
44+
if !arguments.nil?
45+
arguments = arguments.gsub(/^\[(.*)\]$/, "").gsub(/\{("(?:.|\\")*?"),/, '{\1:').gsub(/\},\{/, ",")
46+
if arguments == ""
47+
arguments = '{}'
48+
end
49+
else
50+
arguments = '{}'
51+
end
52+
queue = {
53+
:durable => durable,
54+
:auto_delete => auto_delete,
55+
:arguments => JSON.parse(arguments),
56+
:ensure => :present,
57+
:name => "%s@%s" % [name, vhost],
58+
}
59+
resources << new(queue) if queue[:name]
60+
end
61+
end
62+
resources
63+
end
64+
65+
def self.prefetch(resources)
66+
packages = instances
67+
resources.keys.each do |name|
68+
if provider = packages.find{ |pkg| pkg.name == name }
69+
resources[name].provider = provider
70+
end
71+
end
72+
end
73+
74+
def exists?
75+
@property_hash[:ensure] == :present
76+
end
77+
78+
def create
79+
vhost_opt = should_vhost ? "--vhost=#{should_vhost}" : ''
80+
name = resource[:name].rpartition('@').first
81+
arguments = resource[:arguments]
82+
if arguments.nil?
83+
arguments = {}
84+
end
85+
rabbitmqadmin('declare',
86+
'queue',
87+
vhost_opt,
88+
"--user=#{resource[:user]}",
89+
"--password=#{resource[:password]}",
90+
"name=#{name}",
91+
"durable=#{resource[:durable]}",
92+
"auto_delete=#{resource[:auto_delete]}",
93+
"arguments=#{arguments.to_json}"
94+
)
95+
@property_hash[:ensure] = :present
96+
end
97+
98+
def destroy
99+
vhost_opt = should_vhost ? "--vhost=#{should_vhost}" : ''
100+
name = resource[:name].rpartition('@').first
101+
rabbitmqadmin('delete', 'queue', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", "name=#{name}")
102+
@property_hash[:ensure] = :absent
103+
end
104+
105+
end

lib/puppet/type/rabbitmq_queue.rb

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
Puppet::Type.newtype(:rabbitmq_queue) do
2+
desc 'Native type for managing rabbitmq queue'
3+
4+
ensurable do
5+
defaultto(:present)
6+
newvalue(:present) do
7+
provider.create
8+
end
9+
newvalue(:absent) do
10+
provider.destroy
11+
end
12+
end
13+
14+
newparam(:name, :namevar => true) do
15+
desc 'Name of queue'
16+
newvalues(/^\S*@\S+$/)
17+
end
18+
19+
newparam(:durable) do
20+
desc 'Queue is durable'
21+
newvalues(/true|false/)
22+
defaultto('true')
23+
end
24+
25+
newparam(:auto_delete) do
26+
desc 'Queue will be auto deleted'
27+
newvalues(/true|false/)
28+
defaultto('false')
29+
end
30+
31+
newparam(:arguments) do
32+
desc 'Queue arguments example: {x-message-ttl => 60, x-expires => 10}'
33+
defaultto {}
34+
validate do |value|
35+
resource.validate_argument(value)
36+
end
37+
end
38+
39+
newparam(:user) do
40+
desc 'The user to use to connect to rabbitmq'
41+
defaultto('guest')
42+
newvalues(/^\S+$/)
43+
end
44+
45+
newparam(:password) do
46+
desc 'The password to use to connect to rabbitmq'
47+
defaultto('guest')
48+
newvalues(/\S+/)
49+
end
50+
51+
autorequire(:rabbitmq_vhost) do
52+
[self[:name].split('@')[1]]
53+
end
54+
55+
autorequire(:rabbitmq_user) do
56+
[self[:user]]
57+
end
58+
59+
autorequire(:rabbitmq_user_permissions) do
60+
["#{self[:user]}@#{self[:name].split('@')[1]}"]
61+
end
62+
63+
def validate_argument(argument)
64+
unless [Hash].include?(argument.class)
65+
raise ArgumentError, "Invalid argument"
66+
end
67+
end
68+
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require 'puppet'
2+
require 'mocha/api'
3+
RSpec.configure do |config|
4+
config.mock_with :mocha
5+
end
6+
provider_class = Puppet::Type.type(:rabbitmq_queue).provider(:rabbitmqadmin)
7+
describe provider_class do
8+
before :each do
9+
@resource = Puppet::Type::Rabbitmq_queue.new(
10+
{:name => 'test@/',
11+
:durable => :true,
12+
:auto_delete => :false,
13+
:arguments => {}
14+
}
15+
)
16+
@provider = provider_class.new(@resource)
17+
end
18+
19+
it 'should return instances' do
20+
provider_class.expects(:rabbitmqctl).with('list_vhosts', '-q').returns <<-EOT
21+
/
22+
EOT
23+
provider_class.expects(:rabbitmqctl).with('list_queues', '-q', '-p', '/', 'name', 'durable', 'auto_delete', 'arguments').returns <<-EOT
24+
test true false []
25+
test2 true false [{"x-message-ttl",342423},{"x-expires",53253232},{"x-max-length",2332},{"x-max-length-bytes",32563324242},{"x-dead-letter-exchange","amq.direct"},{"x-dead-letter-routing-key","test.routing"}]
26+
EOT
27+
instances = provider_class.instances
28+
instances.size.should == 2
29+
end
30+
31+
it 'should call rabbitmqadmin to create' do
32+
@provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=guest', '--password=guest', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}')
33+
@provider.create
34+
end
35+
36+
it 'should call rabbitmqadmin to destroy' do
37+
@provider.expects(:rabbitmqadmin).with('delete', 'queue', '--vhost=/', '--user=guest', '--password=guest', 'name=test')
38+
@provider.destroy
39+
end
40+
41+
context 'specifying credentials' do
42+
before :each do
43+
@resource = Puppet::Type::Rabbitmq_queue.new(
44+
{:name => 'test@/',
45+
:durable => 'true',
46+
:auto_delete => 'false',
47+
:arguments => {},
48+
:user => 'colin',
49+
:password => 'secret',
50+
}
51+
)
52+
@provider = provider_class.new(@resource)
53+
end
54+
55+
it 'should call rabbitmqadmin to create' do
56+
@provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=colin', '--password=secret', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}')
57+
@provider.create
58+
end
59+
end
60+
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
require 'puppet'
2+
require 'puppet/type/rabbitmq_queue'
3+
require 'json'
4+
describe Puppet::Type.type(:rabbitmq_queue) do
5+
before :each do
6+
@queue = Puppet::Type.type(:rabbitmq_queue).new(
7+
:name => 'foo@bar',
8+
:durable => :true,
9+
:arguments => {
10+
'x-message-ttl' => 45,
11+
'x-dead-letter-exchange' => 'deadexchange'
12+
}
13+
)
14+
end
15+
it 'should accept an queue name' do
16+
@queue[:name] = 'dan@pl'
17+
@queue[:name].should == 'dan@pl'
18+
end
19+
it 'should require a name' do
20+
expect {
21+
Puppet::Type.type(:rabbitmq_queue).new({})
22+
}.to raise_error(Puppet::Error, 'Title or name must be provided')
23+
end
24+
it 'should not allow whitespace in the name' do
25+
expect {
26+
@queue[:name] = 'b r'
27+
}.to raise_error(Puppet::Error, /Valid values match/)
28+
end
29+
it 'should not allow names without @' do
30+
expect {
31+
@queue[:name] = 'b_r'
32+
}.to raise_error(Puppet::Error, /Valid values match/)
33+
end
34+
35+
it 'should accept an arguments with numbers value' do
36+
@queue[:arguments] = {'x-message-ttl' => 30}
37+
@queue[:arguments].to_json.should == "{\"x-message-ttl\":30}"
38+
@queue[:arguments]['x-message-ttl'].should == 30
39+
end
40+
41+
it 'should accept an arguments with string value' do
42+
@queue[:arguments] = {'x-dead-letter-exchange' => 'catchallexchange'}
43+
@queue[:arguments].to_json.should == "{\"x-dead-letter-exchange\":\"catchallexchange\"}"
44+
end
45+
46+
it 'should accept an queue durable' do
47+
@queue[:durable] = :true
48+
@queue[:durable].should == :true
49+
end
50+
51+
it 'should accept a user' do
52+
@queue[:user] = :root
53+
@queue[:user].should == :root
54+
end
55+
56+
it 'should accept a password' do
57+
@queue[:password] = :PaSsw0rD
58+
@queue[:password].should == :PaSsw0rD
59+
end
60+
end

0 commit comments

Comments
 (0)