rabbitmq-cluster 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rabbitmq-cluster.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Reevoo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Rabbitmq::Cluster
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rabbitmq-cluster'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rabbitmq-cluster
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/rabbitmq-cluster/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,15 @@
1
+ require 'rabbitmq/cluster'
2
+
3
+ server = RabbitMQ::Cluster::Server.new(
4
+ RabbitMQManager.new 'http://guest:guest@localhost:15672',
5
+ RabbitMQ::Cluster::Etcd.new(
6
+ Etcd::Client.connect(uris: [ENV['ETCD_HOST']])
7
+ )
8
+ )
9
+
10
+ server.start
11
+
12
+ while true do
13
+ server.synchronize
14
+ sleep 0.5
15
+ end
@@ -0,0 +1,9 @@
1
+ require "rabbitmq/cluster/version"
2
+ require "rabbitmq/cluster/etcd"
3
+ require "rabbitmq/cluster/server"
4
+
5
+ module RabbitMQ
6
+ module Cluster
7
+ # Your code goes here...
8
+ end
9
+ end
@@ -0,0 +1,38 @@
1
+ require 'etcd'
2
+
3
+ module RabbitMQ::Cluster
4
+ class Etcd
5
+ attr_accessor :client
6
+ private :client
7
+
8
+ def initialize(client)
9
+ self.client = client
10
+ end
11
+
12
+ def aquire_lock
13
+ sleep 1 until lock = client.update('/rabbitmq/lock', true, false)
14
+ yield if lock
15
+ raise unless client.update('/rabbitmq/lock', false, true)
16
+ end
17
+
18
+ def nodes
19
+ (client.get('/rabbitmq/nodes') || {}).values
20
+ end
21
+
22
+ def register(node_name)
23
+ key = "/rabbitmq/nodes/#{node_name}"
24
+ client.set(key, node_name) unless client.exists?(key)
25
+ end
26
+
27
+ def erlang_cookie
28
+ client.get('/rabbitmq/erlang_cookie')
29
+ end
30
+
31
+ def erlang_cookie=(erlang_cookie)
32
+ client.set(
33
+ '/rabbitmq/erlang_cookie',
34
+ erlang_cookie
35
+ )
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,117 @@
1
+ require 'rabbitmq_manager'
2
+ require 'json'
3
+
4
+ class RabbitMQManager
5
+ def aliveness_test(vhost)
6
+ @conn.get(url :'aliveness-test', vhost).body
7
+ end
8
+ end
9
+
10
+ module RabbitMQ::Cluster
11
+ class Server
12
+ attr_accessor :client, :etcd
13
+ private :client, :etcd
14
+
15
+ def initialize(client, etcd)
16
+ self.client = client
17
+ self.etcd = etcd
18
+ end
19
+
20
+ def start
21
+ etcd.aquire_lock do
22
+ setup_erlang_cookie
23
+ start_rabbitmq_server
24
+ save_erlang_cookie
25
+ join_cluster
26
+ end
27
+ end
28
+
29
+ def synchronize
30
+ return if etcd.nodes.size == running_nodes.size
31
+
32
+ etcd.aquire_lock do
33
+ stopped_nodes.each do |node|
34
+ `rabbitmqctl forget_cluster_node #{node['name']}`
35
+ etcd.delete("/rabbitmq/nodes/#{node['name']}")
36
+ end
37
+ end
38
+ end
39
+
40
+ def name
41
+ @_name ||= client.overview["cluster_name"]
42
+ end
43
+
44
+ def up?
45
+ test_aliveness?
46
+ rescue Faraday::ConnectionFailed
47
+ false
48
+ end
49
+
50
+ private
51
+
52
+ def running_nodes
53
+ client.nodes.select { |n| n["running"] }
54
+ end
55
+
56
+ def stopped_nodes
57
+ client.nodes.select { |n| !n["running"] }
58
+ end
59
+
60
+ def test_aliveness?
61
+ unless client.vhosts.any? {|vh| vh['name'] == 'aliveness-test' }
62
+ client.vhost_create('aliveness-test')
63
+ end
64
+
65
+ unless client.user_permissions('guest').any? {|up| up['vhost'] == 'aliveness-test' }
66
+ client.user_set_permissions('guest', 'aliveness-test', '.*', '.*', '.*')
67
+ end
68
+
69
+ JSON.parse(client.aliveness_test('aliveness-test'))['status'] == 'ok'
70
+ end
71
+
72
+ def join_cluster
73
+ if !clustered? && nodes_to_join.any?
74
+ `rabbitmqctl stop_app`
75
+ system("rabbitmqctl join_cluster #{nodes_to_join.first}")
76
+ `rabbitmqctl start_app`
77
+ end
78
+ etcd.register(name)
79
+ end
80
+
81
+ def clustered?
82
+ client.nodes.size > 1
83
+ end
84
+
85
+ def nodes_to_join
86
+ etcd.nodes - [name]
87
+ end
88
+
89
+ def start_rabbitmq_server
90
+ system("/usr/sbin/rabbitmq-server &")
91
+ waits = 1
92
+ until up?
93
+ sleep waits
94
+ waits *= 2
95
+ end
96
+ end
97
+
98
+ def erlang_cookie
99
+ IO.read('/var/lib/rabbitmq/.erlang.cookie')
100
+ end
101
+
102
+ def setup_erlang_cookie
103
+ if etcd.erlang_cookie
104
+ File.open('/var/lib/rabbitmq/.erlang.cookie', 'w') { |file| file.write etcd.erlang_cookie }
105
+ `chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie`
106
+ `chmod 400 /var/lib/rabbitmq/.erlang.cookie`
107
+ end
108
+ end
109
+
110
+ def save_erlang_cookie
111
+ unless etcd.erlang_cookie
112
+ etcd.erlang_cookie = erlang_cookie
113
+ end
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,5 @@
1
+ module RabbitMQ
2
+ module Cluster
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rabbitmq/cluster/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rabbitmq-cluster"
8
+ spec.version = RabbitMQ::Cluster::VERSION
9
+ spec.authors = ["Ed Robinson"]
10
+ spec.email = ["ed.robinson@reevoo.com"]
11
+ spec.summary = %q{ Manages rabbitmq-server within a CoreOS cluster }
12
+ spec.description = %q{ etcd based cluster discovery for rabbitmq }
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'rabbitmq_manager'
22
+ spec.add_dependency 'etcd-rb'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.5"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "pry"
28
+ end
@@ -0,0 +1,2 @@
1
+ require 'rabbitmq/cluster'
2
+
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe RabbitMQ::Cluster::Etcd do
4
+ let(:etcd_client) { double }
5
+ subject { described_class.new(etcd_client) }
6
+
7
+ describe '#nodes' do
8
+ it 'returns the list of nodes registed in etcd' do
9
+ allow(etcd_client).to receive(:get).with('/rabbitmq/nodes').and_return(
10
+ {
11
+ "/rabbitmq/nodes/rabbit@rabbit1" => "rabbit@rabbit1",
12
+ "/rabbitmq/nodes/rabbit@rabbit2" => "rabbit@rabbit2"
13
+ }
14
+ )
15
+ expect(subject.nodes).to eq ["rabbit@rabbit1", "rabbit@rabbit2"]
16
+ end
17
+
18
+ it 'returns an empty array if there are no nodes registered' do
19
+ allow(etcd_client).to receive(:get).with('/rabbitmq/nodes')
20
+ expect(subject.nodes).to eq []
21
+ end
22
+ end
23
+
24
+ describe '#register' do
25
+ let(:nodename) { 'rabbit@mynode' }
26
+
27
+ context 'the node is not yet registered' do
28
+
29
+ before do
30
+ allow(etcd_client).to receive(:exists?)
31
+ .with("/rabbitmq/nodes/#{nodename}")
32
+ end
33
+
34
+ it 'sets the key in etcd' do
35
+ expect(etcd_client).to receive(:set)
36
+ .with(
37
+ "/rabbitmq/nodes/#{nodename}",
38
+ nodename
39
+ )
40
+ subject.register(nodename)
41
+ end
42
+ end
43
+
44
+ context 'the node is allready registered' do
45
+ before do
46
+ allow(etcd_client).to receive(:exists?)
47
+ .with("/rabbitmq/nodes/#{nodename}")
48
+ .and_return true
49
+ end
50
+
51
+ it 'does nothing' do
52
+ expect(etcd_client).to_not receive(:set)
53
+ subject.register(nodename)
54
+ end
55
+ end
56
+ end
57
+
58
+ describe '#erlang_cookie' do
59
+ let(:erlang_cookie) { 'afbdgCVB23423bh324h' }
60
+ before do
61
+ allow(etcd_client).to receive(:get)
62
+ .with('/rabbitmq/erlang_cookie')
63
+ .and_return(erlang_cookie)
64
+ end
65
+
66
+ it 'has a getter' do
67
+ expect(subject.erlang_cookie).to eq erlang_cookie
68
+ end
69
+
70
+ it 'has a setter' do
71
+ expect(etcd_client).to receive(:set)
72
+ .with(
73
+ '/rabbitmq/erlang_cookie',
74
+ erlang_cookie
75
+ )
76
+ subject.erlang_cookie = erlang_cookie
77
+ end
78
+ end
79
+
80
+ describe '#aquire_lock' do
81
+ let(:thingy) { double(run: nil) }
82
+ before do
83
+ allow(etcd_client).to receive(:update).with('/rabbitmq/lock', false, true).and_return(true)
84
+ allow(etcd_client).to receive(:update).with('/rabbitmq/lock', true, false).and_return(true)
85
+ end
86
+
87
+ describe 'when we can get the lock' do
88
+ it 'runs the code' do
89
+ expect(etcd_client).to receive(:update).with('/rabbitmq/lock', true, false).and_return(true)
90
+ expect(thingy).to receive(:run)
91
+
92
+ subject.aquire_lock { thingy.run }
93
+ end
94
+
95
+ it 'gives the lock back when its done' do
96
+ expect(etcd_client).to receive(:update).with('/rabbitmq/lock', false, true).and_return(true)
97
+
98
+ subject.aquire_lock { thingy.run }
99
+ end
100
+
101
+ it 'gets angry if something odd happens' do
102
+ allow(etcd_client).to receive(:update).with('/rabbitmq/lock', false, true).and_return(false)
103
+
104
+ expect { subject.aquire_lock { thingy.run } }.to raise_error
105
+ end
106
+ end
107
+
108
+ describe "when we can't get the lock" do
109
+ it 'retries till the lock can be aquired' do
110
+ expect(etcd_client).to receive(:update)
111
+ .with('/rabbitmq/lock', true, false)
112
+ .at_least(3).times
113
+ .and_return(false, false, true)
114
+ expect(thingy).to receive(:run)
115
+
116
+ subject.aquire_lock { thingy.run }
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,268 @@
1
+ require 'spec_helper'
2
+
3
+ describe RabbitMQ::Cluster::Server do
4
+ let(:client) { double }
5
+ let(:etcd) { FakeEtcd.new }
6
+
7
+ subject { described_class.new(client, etcd) }
8
+
9
+ describe '#name' do
10
+ let(:client) do
11
+ double(
12
+ :rmq,
13
+ overview: { 'cluster_name' => 'rabbit@awesome-node' }
14
+ )
15
+ end
16
+
17
+ it 'gets the name from RabbitMQ' do
18
+ expect(subject.name).to eq 'rabbit@awesome-node'
19
+ end
20
+
21
+ it 'is cached so we can still access the name when the rabbitmq management api is down' do
22
+ subject.name
23
+ allow(client).to receive(:overview).and_raise
24
+ expect(subject.name).to eq 'rabbit@awesome-node'
25
+ end
26
+ end
27
+
28
+ describe 'up?' do
29
+ let(:client) { double(:client).as_null_object }
30
+
31
+ before do
32
+ allow(client).to receive(:aliveness_test).and_return('{ "status":"ok" }')
33
+ end
34
+
35
+ it 'returns false if we cannot connect to the management api' do
36
+ allow(client).to receive(:aliveness_test).and_raise(Faraday::ConnectionFailed, "error")
37
+ expect(subject).to_not be_up
38
+ end
39
+
40
+ context 'we can can connect to the management api' do
41
+ context 'and the test vhost is allready setup' do
42
+ before do
43
+ allow(client).to receive(:vhosts).and_return([{'name' => 'aliveness-test'}])
44
+ allow(client).to receive(:user_permissions).and_return([{'vhost' => 'aliveness-test'}])
45
+ end
46
+
47
+ it 'wont set up the vhost' do
48
+ expect(client).to_not receive(:vhost_create)
49
+ expect(client).to_not receive(:user_set_permissions)
50
+ subject.up?
51
+ end
52
+ end
53
+
54
+ context 'and the test vhost is not setup' do
55
+
56
+ before do
57
+ allow(client).to receive(:vhosts).and_return([])
58
+ allow(client).to receive(:user_permissions).and_return([])
59
+ end
60
+
61
+ it 'will set up the vhost' do
62
+ expect(client).to receive(:vhost_create).with('aliveness-test')
63
+ expect(client).to receive(:user_set_permissions).with('guest', 'aliveness-test', '.*', '.*', '.*')
64
+ subject.up?
65
+ end
66
+ end
67
+
68
+ context 'the aliveness test is working' do
69
+ specify { expect(subject).to be_up }
70
+ end
71
+
72
+ context 'the aliveness test is not working' do
73
+ before do
74
+ allow(client).to receive(:aliveness_test).and_return('{ "status":"borked" }')
75
+ end
76
+
77
+ specify { expect(subject).to_not be_up }
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'starting the server' do
83
+ let(:client) { double(:client).as_null_object }
84
+
85
+ before do
86
+ allow(subject).to receive(:system)
87
+ allow(client).to receive(:aliveness_test).and_return('{ "status":"ok" }')
88
+ allow(File).to receive(:open)
89
+ allow(IO).to receive(:read)
90
+ allow(subject).to receive(:"`")
91
+ end
92
+
93
+ it 'shells out to start rabbitmq-server' do
94
+ expect(subject).to receive(:system).with("/usr/sbin/rabbitmq-server &")
95
+ subject.start
96
+ end
97
+
98
+ context 'waiting for the server to start' do
99
+ it 'waits until the server has started' do
100
+ expect(subject).to receive(:up?).twice.and_return(false, true)
101
+ subject.start
102
+ end
103
+ end
104
+
105
+ describe 'joining the cluster' do
106
+ context 'with no nodes in etcd' do
107
+ it 'does nothing' do
108
+ expect(subject).to_not receive(:"`")
109
+ subject.start
110
+ end
111
+ end
112
+
113
+ context 'with some nodes allready in etcd' do
114
+ before do
115
+ allow(client).to receive(:nodes)
116
+ .and_return([{}])
117
+ etcd.register('rabbit@node1')
118
+ etcd.register('rabbit@node2')
119
+ end
120
+
121
+ context 'allready in a cluster' do
122
+ before do
123
+ allow(client).to receive(:nodes)
124
+ .and_return([{},{}])
125
+ end
126
+
127
+ it 'does nothing' do
128
+ expect(subject).to_not receive(:"`")
129
+ subject.start
130
+ end
131
+
132
+ it 'registers itself' do
133
+ allow(client).to receive(:overview).and_return('cluster_name' => 'rabbit@this_node')
134
+ subject.start
135
+ expect(etcd.nodes).to include('rabbit@this_node')
136
+ end
137
+ end
138
+
139
+ it 'tries to join the cluster' do
140
+ expect(subject).to receive(:system).with("rabbitmqctl join_cluster rabbit@node1")
141
+ subject.start
142
+ end
143
+
144
+ it 'stops the management app before clustering' do
145
+ expect(subject).to receive(:"`")
146
+ .with('rabbitmqctl stop_app')
147
+ expect(subject).to receive(:"`")
148
+ .with('rabbitmqctl start_app')
149
+ subject.start
150
+ end
151
+
152
+ it 'does not try to cluster with itself' do
153
+ allow(client).to receive(:overview).and_return('cluster_name' => 'rabbit@node1')
154
+ expect(subject).to receive(:system).with("rabbitmqctl join_cluster rabbit@node2")
155
+ subject.start
156
+ end
157
+
158
+ it 'registers itself' do
159
+ allow(client).to receive(:overview).and_return('cluster_name' => 'rabbit@this_node')
160
+ subject.start
161
+ expect(etcd.nodes).to include('rabbit@this_node')
162
+ end
163
+ end
164
+ end
165
+
166
+ context 'with an erlang cookie in etcd' do
167
+
168
+ before do
169
+ allow(etcd).to receive(:erlang_cookie).and_return('NummmNugnnmNuyum')
170
+ end
171
+
172
+ it 'sets up the erlang cookie' do
173
+ expect(File).to receive(:open).with('/var/lib/rabbitmq/.erlang.cookie', 'w')
174
+ subject.start
175
+ end
176
+
177
+ it 'sets up the ownership and permissions of the erlang cooke' do
178
+ expect(subject).to receive(:"`")
179
+ .with("chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie")
180
+ expect(subject).to receive(:"`")
181
+ .with("chmod 400 /var/lib/rabbitmq/.erlang.cookie")
182
+ subject.start
183
+ end
184
+ end
185
+
186
+ context 'when there was no erlang cookie in etcd' do
187
+ before do
188
+ allow(IO).to receive(:read)
189
+ .with('/var/lib/rabbitmq/.erlang.cookie')
190
+ .and_return('ErLAnGCOookie')
191
+ end
192
+
193
+ it 'saves the on disk cookie to etcd' do
194
+ subject.start
195
+ expect(etcd.erlang_cookie).to eq 'ErLAnGCOookie'
196
+ end
197
+ end
198
+ end
199
+
200
+ describe '#synchronize' do
201
+ context 'etcd has more nodes than are running' do
202
+ before do
203
+ etcd.register('rabbit@node1')
204
+ etcd.register('rabbit@node2')
205
+ allow(client).to receive(:nodes)
206
+ .and_return([
207
+ {"name" => "rabbit@node1", "running" => true},
208
+ {"name" => "rabbit@node2", "running" => false}
209
+ ])
210
+ allow(subject).to receive(:"`")
211
+ allow(etcd).to receive(:delete)
212
+ end
213
+
214
+ it 'aquires the lock before doing anything' do
215
+ expect(etcd).to receive(:aquire_lock).and_call_original
216
+ subject.synchronize
217
+ end
218
+
219
+ it 'removes the stopped node from the cluster' do
220
+ expect(subject).to receive(:"`")
221
+ .with('rabbitmqctl forget_cluster_node rabbit@node2')
222
+ subject.synchronize
223
+ end
224
+
225
+ it 'removes the stopped node from etcd' do
226
+ expect(etcd).to receive(:delete)
227
+ .with('/rabbitmq/nodes/rabbit@node2')
228
+ subject.synchronize
229
+ end
230
+ end
231
+
232
+ context 'etcd has the same nodes as are running' do
233
+ before do
234
+ etcd.register('rabbit@node1')
235
+ etcd.register('rabbit@node2')
236
+ allow(client).to receive(:nodes)
237
+ .and_return([
238
+ {"name" => "rabbit@node1", "running" => true},
239
+ {"name" => "rabbit@node2", "running" => true}
240
+ ])
241
+ end
242
+
243
+ it 'does nothing' do
244
+ expect(etcd).to_not receive(:aquire_lock)
245
+ subject.synchronize
246
+ end
247
+ end
248
+ end
249
+
250
+ end
251
+
252
+ class FakeEtcd
253
+
254
+ attr_accessor :erlang_cookie, :nodes
255
+
256
+ def initialize
257
+ self.nodes = []
258
+ end
259
+
260
+ def aquire_lock
261
+ yield
262
+ end
263
+
264
+ def register(node)
265
+ nodes << node
266
+ end
267
+
268
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbitmq-cluster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ed Robinson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-07-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rabbitmq_manager
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: etcd-rb
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bundler
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: ! ' etcd based cluster discovery for rabbitmq '
111
+ email:
112
+ - ed.robinson@reevoo.com
113
+ executables:
114
+ - rabbitmq-cluster
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - Gemfile
120
+ - LICENSE.txt
121
+ - README.md
122
+ - Rakefile
123
+ - bin/rabbitmq-cluster
124
+ - lib/rabbitmq/cluster.rb
125
+ - lib/rabbitmq/cluster/etcd.rb
126
+ - lib/rabbitmq/cluster/server.rb
127
+ - lib/rabbitmq/cluster/version.rb
128
+ - rabbitmq-cluster.gemspec
129
+ - spec/spec_helper.rb
130
+ - spec/unit/etcd_spec.rb
131
+ - spec/unit/server_spec.rb
132
+ homepage: ''
133
+ licenses:
134
+ - MIT
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ! '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ segments:
146
+ - 0
147
+ hash: -2992029979682835866
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ segments:
155
+ - 0
156
+ hash: -2992029979682835866
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 1.8.25
160
+ signing_key:
161
+ specification_version: 3
162
+ summary: Manages rabbitmq-server within a CoreOS cluster
163
+ test_files:
164
+ - spec/spec_helper.rb
165
+ - spec/unit/etcd_spec.rb
166
+ - spec/unit/server_spec.rb