pylon 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/NOTICE +8 -0
- data/Rakefile +53 -0
- data/Vagrantfile +18 -0
- data/cookbooks/pylon/README.rdoc +8 -0
- data/cookbooks/pylon/metadata.rb +7 -0
- data/cookbooks/pylon/recipes/default.rb +43 -0
- data/lib/pylon.rb +1 -1
- data/lib/pylon/config.rb +3 -3
- data/lib/pylon/elector.rb +82 -27
- data/lib/pylon/node.rb +56 -8
- data/pylon.gemspec +116 -0
- data/test/helper.rb +19 -0
- data/test/test_pylon.rb +7 -0
- metadata +122 -32
data/Gemfile
ADDED
data/NOTICE
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler"
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
require "rake"
|
14
|
+
require "jeweler"
|
15
|
+
require "rake/testtask"
|
16
|
+
require "bundler/gem_tasks"
|
17
|
+
require_relative "lib/pylon"
|
18
|
+
|
19
|
+
Jeweler::Tasks.new do |gem|
|
20
|
+
gem.name = "pylon"
|
21
|
+
gem.homepage = "http://github.com/fujin/pylon"
|
22
|
+
gem.license = "APLv2"
|
23
|
+
gem.summary = %Q{standalone leader election with zeromq for ruby}
|
24
|
+
gem.description = %Q{leader election with zeromq for ruby using widely available leader election algorithms, similar to gen_leader erlang project in essence}
|
25
|
+
gem.email = "aj@junglist.gen.nz"
|
26
|
+
gem.authors = ["AJ Christensen"]
|
27
|
+
gem.version = Pylon::VERSION
|
28
|
+
{ "ffi-rzmq" => "~> 0.8.2",
|
29
|
+
"mixlib-log" => ">= 0",
|
30
|
+
"mixlib-cli" => ">= 0",
|
31
|
+
"mixlib-config" => ">= 0",
|
32
|
+
"uuidtools" => "~> 2.1.2",
|
33
|
+
"json" => ">= 0"
|
34
|
+
}.each { |dep,ver| gem.add_runtime_dependency dep, ver }
|
35
|
+
{ "minitest" => "~> 2.6.0",
|
36
|
+
"bundler" => "~> 1.0.0",
|
37
|
+
"jeweler" => "~> 1.6.4",
|
38
|
+
"rcov" => ">= 0",
|
39
|
+
"vagrant" => ">= 0",
|
40
|
+
"virtualbox" => ">= 0"
|
41
|
+
}.each { |dep,ver| gem.add_development_dependency dep, ver }
|
42
|
+
end
|
43
|
+
|
44
|
+
Jeweler::RubygemsDotOrgTasks.new
|
45
|
+
|
46
|
+
Rake::TestTask.new(:test) do |test|
|
47
|
+
test.libs << 'lib' << 'test'
|
48
|
+
test.pattern = 'test/**/test_*.rb'
|
49
|
+
test.verbose = true
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|
data/Vagrantfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
def pylon_vm(config=nil, name=:pylon, count=0)
|
2
|
+
return unless config
|
3
|
+
config.vm.define(name) do |config|
|
4
|
+
config.vm.box = 'natty64_cloudscaling_4.1'
|
5
|
+
config.vm.box_url = "http://d1lfnqkkmlbdsd.cloudfront.net/vagrant/natty64_cloudscaling_4.1.box"
|
6
|
+
config.vm.network "33.33.33.#{10 + count}"
|
7
|
+
config.vm.provision :chef_solo do |chef|
|
8
|
+
chef.cookbooks_path = "cookbooks"
|
9
|
+
chef.add_recipe "pylon"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Vagrant::Config.run do |config|
|
15
|
+
10.times do |i|
|
16
|
+
pylon_vm(config, "pylon#{i}".to_sym, i)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
maintainer "AJ Christensen"
|
2
|
+
maintainer_email "aj@junglist.gen.nz"
|
3
|
+
license "Apache 2.0"
|
4
|
+
description "Installs/Configures pylon"
|
5
|
+
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__),"..", "..", "lib", "/pylon.rb"))
|
7
|
+
version Pylon::VERSION
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Cookbook Name:: pylon
|
3
|
+
# Recipe:: default
|
4
|
+
#
|
5
|
+
# Copyright 2011, AJ Christensen
|
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
|
+
# http://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
|
+
execute "apt-get update"
|
21
|
+
%w{zeromq build-essential tmux}.each do |pkg|
|
22
|
+
package pkg
|
23
|
+
end
|
24
|
+
|
25
|
+
execute "rsync -avu --progress --delete /vagrant/ /srv/pylon/" do
|
26
|
+
notifies :delete, "directory[/srv/pylon/vendor/bundle]"
|
27
|
+
notifies :run, "execute[bundle]"
|
28
|
+
end
|
29
|
+
|
30
|
+
directory "/srv/pylon/vendor/bundle" do
|
31
|
+
action :nothing
|
32
|
+
recursive true
|
33
|
+
end
|
34
|
+
|
35
|
+
execute "bundle" do
|
36
|
+
command "bundle install --deployment"
|
37
|
+
cwd "/srv/pylon"
|
38
|
+
user "vagrant"
|
39
|
+
group "vagrant"
|
40
|
+
action :nothing
|
41
|
+
end
|
42
|
+
|
43
|
+
|
data/lib/pylon.rb
CHANGED
data/lib/pylon/config.rb
CHANGED
data/lib/pylon/elector.rb
CHANGED
@@ -37,7 +37,7 @@ class Pylon
|
|
37
37
|
Pylon::Log.info "elector[#{cluster_name}] initialized, starting pub/sub sockets on #{multicast_endpoint} and tcp listener socket on #{node.unicast_endpoint}"
|
38
38
|
|
39
39
|
Thread.abort_on_exception = true
|
40
|
-
|
40
|
+
|
41
41
|
scheduler = Thread.new do
|
42
42
|
@unicast_announcer_thread = node.unicast_announcer
|
43
43
|
@multicast_announcer_thread = node.multicast_announcer
|
@@ -88,12 +88,65 @@ class Pylon
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def add_node node
|
91
|
-
|
91
|
+
nodes << node unless nodes.include? node
|
92
|
+
# fire up a new failure detector
|
93
|
+
failure_detectors.each do |thread|
|
94
|
+
thread.join
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def ping_node node
|
99
|
+
begin
|
100
|
+
Pylon::Config[:fd_retries].times do |attempt|
|
101
|
+
begin
|
102
|
+
Timeout::timeout(Pylon::Config[:fd_timeout]) do
|
103
|
+
pong, timestamp = node.send "ping", :attempt => attempt
|
104
|
+
if (timestamp - Time.now.to_i) >= 600
|
105
|
+
Log.warn "failure_detector: received bad timestamp from #{node}, sending 'exit' message"
|
106
|
+
node.send "exit", {"message" => "bad timestamp received after #{Pylon::Config[:fd_retries]}"}
|
107
|
+
nodes.delete node
|
108
|
+
else
|
109
|
+
Log.debug "failure_detector: received good pong with timestamp: #{timestamp}"
|
110
|
+
Thread.pass
|
111
|
+
end
|
112
|
+
end
|
113
|
+
rescue Timeout::Error
|
114
|
+
Log.warn "failure_detector: #{node} timed out, removing"
|
115
|
+
nodes.delete node
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def assert_leadership
|
122
|
+
nodes.each do |node|
|
123
|
+
Thread.new do
|
124
|
+
status = node.send "status"
|
125
|
+
Log.info "assert_leadership: status of #{node}: #{status}"
|
126
|
+
sync_time = node.send "sync_time"
|
127
|
+
Log.info "assert_leadership: sync_time: #{sync_time}"
|
128
|
+
end
|
129
|
+
end.each do |thread|
|
130
|
+
thread.join
|
131
|
+
end if master
|
132
|
+
end
|
133
|
+
|
134
|
+
def failure_detectors
|
135
|
+
nodes.reject{|n| n == node}.map do |node|
|
136
|
+
Thread.new do
|
137
|
+
Log.info "failure_detector: starting failure detection against #{node}"
|
138
|
+
loop do
|
139
|
+
assert_leadership
|
140
|
+
ping_node node
|
141
|
+
allocate_master
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
92
145
|
end
|
93
146
|
|
94
147
|
def multicast_listener
|
95
148
|
Thread.new do
|
96
|
-
Log.debug "multicast_listener: zeromq sub socket starting up on #{
|
149
|
+
Log.debug "multicast_listener: zeromq sub socket starting up on #{multicast_endpoint}"
|
97
150
|
sub_socket = context.socket ZMQ::SUB
|
98
151
|
sub_socket.setsockopt ZMQ::IDENTITY, "node"
|
99
152
|
sub_socket.setsockopt ZMQ::SUBSCRIBE, ""
|
@@ -109,14 +162,14 @@ class Pylon
|
|
109
162
|
end
|
110
163
|
|
111
164
|
def allocate_master
|
112
|
-
nodes.sort
|
113
|
-
Log.debug "node: #{node}"
|
165
|
+
nodes.sort!.each do |node|
|
166
|
+
Log.debug "allocate_master: node: #{node}"
|
114
167
|
end
|
115
|
-
if node.uuid == nodes.
|
168
|
+
if node.uuid == nodes.last.uuid
|
116
169
|
@master = true
|
117
|
-
Log.info "allocate_master: master allocated"
|
170
|
+
Log.info "allocate_master: master allocated; sending new_leader"
|
118
171
|
nodes.each do |node|
|
119
|
-
|
172
|
+
node.send "new_leader", node
|
120
173
|
end
|
121
174
|
else
|
122
175
|
Log.info "allocate_master: someone else is the master, getting ready for work"
|
@@ -126,33 +179,34 @@ class Pylon
|
|
126
179
|
|
127
180
|
def handle_announce recv_string
|
128
181
|
Log.info "handle_announce: got string #{recv_string}"
|
129
|
-
|
130
|
-
Log.info "handle_anounce: got announce from #{
|
182
|
+
new_node = JSON.parse(recv_string)
|
183
|
+
Log.info "handle_anounce: got announce from #{new_node}"
|
131
184
|
if master
|
132
|
-
Log.info "handle_announce: I am the master: updating #{
|
133
|
-
|
185
|
+
Log.info "handle_announce: I am the master: updating #{new_node} of leadership status"
|
186
|
+
if node.weight > new_node.weight
|
187
|
+
Log.info "handle_announce: I'm bigger than you: sending new_leader to #{new_node}"
|
188
|
+
new_node.send "new_leader", node
|
189
|
+
else
|
190
|
+
Log.info "handle_announce: new leader, sending change_leader to all nodes"
|
191
|
+
nodes.each do |n|
|
192
|
+
n.send "change_leader", new_node
|
193
|
+
end
|
194
|
+
end
|
134
195
|
elsif nodes.length < Pylon::Config[:minimum_master_nodes]
|
135
196
|
if nodes.include? node
|
136
197
|
Log.info "handle_announce: skipping node #{node}, already known"
|
137
198
|
Log.debug "handle_announce: nodes: #{nodes}"
|
138
199
|
else
|
139
|
-
Log.info "handle_announce:
|
140
|
-
connect_node
|
200
|
+
Log.info "handle_announce: connecting to #{node} on endpoint: #{node.unicast_endpoint}"
|
201
|
+
connect_node node
|
141
202
|
end
|
142
|
-
else
|
143
|
-
allocate_master
|
144
203
|
end
|
145
204
|
end
|
146
205
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
sub_socket.setsockopt ZMQ::SUBSCRIBE, uuid
|
152
|
-
sub_socket.connect endpoint
|
153
|
-
uuid = sub_socket.recv_string
|
154
|
-
Log.debug "connect_node: got uuid on sub socket, parsing node"
|
155
|
-
new_node = JSON.parse(sub_socket.recv_string) if sub_socket.more_parts?
|
206
|
+
|
207
|
+
def connect_node node
|
208
|
+
Log.debug "connect_node: request socket connecting to #{node}"
|
209
|
+
new_node = node.send "status"
|
156
210
|
Log.debug "connect_node: node: #{new_node}"
|
157
211
|
if nodes.include? new_node
|
158
212
|
Log.info "connect_node: skipping node #{new_node}, already in local list, sleeping for 60 secs"
|
@@ -163,5 +217,6 @@ class Pylon
|
|
163
217
|
add_node new_node
|
164
218
|
end
|
165
219
|
end
|
166
|
-
|
167
|
-
end
|
220
|
+
|
221
|
+
end # Elector
|
222
|
+
end # Pylon
|
data/lib/pylon/node.rb
CHANGED
@@ -78,18 +78,64 @@ class Pylon
|
|
78
78
|
UUIDTools::UUID.timestamp_create
|
79
79
|
end
|
80
80
|
|
81
|
+
# Expects a two element tuple containing a string command and a
|
82
|
+
# hash of params:
|
83
|
+
# ["command", :params => {}]
|
84
|
+
def handle_command string
|
85
|
+
command, params = JSON.parse(string)
|
86
|
+
case command
|
87
|
+
when "sync_time"
|
88
|
+
Log.info "handle_command: sync time received, running ntpdate"
|
89
|
+
["sync_time", %x{ntpdate -u pool.ntp.org}]
|
90
|
+
when "add"
|
91
|
+
Log.info "handle_command: add message received, params: #{params.inspect}"
|
92
|
+
when "new_leader"
|
93
|
+
Log.info "handle_command: new_leader message received"
|
94
|
+
new_leader = params
|
95
|
+
new_leader.send "add", self
|
96
|
+
self
|
97
|
+
when "status"
|
98
|
+
Log.info "handle_command: status message received, sending node back"
|
99
|
+
self
|
100
|
+
when "ping"
|
101
|
+
timestamp = Time.now.to_i
|
102
|
+
Log.info "handle_command: ping requested, sending pong with timestamp: #{timestamp}"
|
103
|
+
["pong", timestamp]
|
104
|
+
when "exit"
|
105
|
+
error = "handle_command: exit command received"
|
106
|
+
error << " with message: #{params["message"]}" if params.has_key? "message"
|
107
|
+
Pylon::Application.fatal! error, 1
|
108
|
+
else
|
109
|
+
Pylon::Application.fatal! "handle_command: unrecognized command '#{command.inspect}' (params: #{params.inspect}), exiting!", -99
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def send(command = "status", params = {})
|
114
|
+
Thread.new do
|
115
|
+
req_socket = context.socket ZMQ::REQ
|
116
|
+
req_socket.setsockopt ZMQ::LINGER, 0
|
117
|
+
req_socket.connect unicast_endpoint
|
118
|
+
if req_socket.send_string "command", ZMQ::SNDMORE
|
119
|
+
Log.debug "connect_node: sent command protocol initiator"
|
120
|
+
if req_socket.send_string([command, params].to_json)
|
121
|
+
response = JSON.parse(req_socket.recv_string)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
response
|
125
|
+
end.value
|
126
|
+
end
|
127
|
+
|
81
128
|
def unicast_announcer
|
82
129
|
Thread.new do
|
83
130
|
Log.debug "unicast_announcer: zeromq pub socket announcer starting up on #{unicast_endpoint}"
|
84
|
-
|
85
|
-
|
86
|
-
pub_socket.bind unicast_endpoint
|
131
|
+
rep_socket = context.socket ZMQ::REP
|
132
|
+
rep_socket.bind unicast_endpoint
|
87
133
|
loop do
|
134
|
+
if rep_socket.recv_string == "command"
|
135
|
+
rep_socket.send_string handle_command(rep_socket.recv_string).to_json if rep_socket.more_parts?
|
136
|
+
end
|
88
137
|
sleep_after_announce = Pylon::Config[:sleep_after_announce]
|
89
|
-
|
90
|
-
pub_socket.send_string uuid.to_s, ZMQ::SNDMORE
|
91
|
-
pub_socket.send_string self.to_json
|
92
|
-
#Thread.pass
|
138
|
+
Thread.pass
|
93
139
|
sleep sleep_after_announce
|
94
140
|
end
|
95
141
|
|
@@ -109,7 +155,7 @@ class Pylon
|
|
109
155
|
Log.debug "#{self}: announcing then sleeping #{sleep_after_announce} secs"
|
110
156
|
pub_socket.send_string uuid.to_s, ZMQ::SNDMORE
|
111
157
|
pub_socket.send_string self.to_json
|
112
|
-
|
158
|
+
Thread.pass
|
113
159
|
sleep sleep_after_announce
|
114
160
|
end
|
115
161
|
end
|
@@ -143,5 +189,7 @@ class Pylon
|
|
143
189
|
Log.debug "#{node}: created from json succesfully"
|
144
190
|
node
|
145
191
|
end
|
192
|
+
|
146
193
|
end
|
147
194
|
end
|
195
|
+
|
data/pylon.gemspec
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{pylon}
|
8
|
+
s.version = "0.2.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["AJ Christensen"]
|
12
|
+
s.date = %q{2011-09-19}
|
13
|
+
s.default_executable = %q{pylon}
|
14
|
+
s.description = %q{leader election with zeromq for ruby using widely available leader election algorithms, similar to gen_leader erlang project in essence}
|
15
|
+
s.email = %q{aj@junglist.gen.nz}
|
16
|
+
s.executables = ["pylon"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.org"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
"Gemfile",
|
23
|
+
"LICENSE",
|
24
|
+
"NOTICE",
|
25
|
+
"README.org",
|
26
|
+
"Rakefile",
|
27
|
+
"Vagrantfile",
|
28
|
+
"bin/pylon",
|
29
|
+
"cookbooks/pylon/README.rdoc",
|
30
|
+
"cookbooks/pylon/metadata.rb",
|
31
|
+
"cookbooks/pylon/recipes/default.rb",
|
32
|
+
"lib/pylon.rb",
|
33
|
+
"lib/pylon/application.rb",
|
34
|
+
"lib/pylon/config.rb",
|
35
|
+
"lib/pylon/daemon.rb",
|
36
|
+
"lib/pylon/elector.rb",
|
37
|
+
"lib/pylon/log.rb",
|
38
|
+
"lib/pylon/node.rb",
|
39
|
+
"lib/pylon/version.rb",
|
40
|
+
"pylon.gemspec",
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_pylon.rb"
|
43
|
+
]
|
44
|
+
s.homepage = %q{http://github.com/fujin/pylon}
|
45
|
+
s.licenses = ["APLv2"]
|
46
|
+
s.require_paths = ["lib"]
|
47
|
+
s.rubygems_version = %q{1.6.2}
|
48
|
+
s.summary = %q{standalone leader election with zeromq for ruby}
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<pylon>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<minitest>, [">= 0"])
|
56
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
57
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
58
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<vagrant>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<virtualbox>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
|
62
|
+
s.add_runtime_dependency(%q<mixlib-log>, [">= 0"])
|
63
|
+
s.add_runtime_dependency(%q<mixlib-cli>, [">= 0"])
|
64
|
+
s.add_runtime_dependency(%q<mixlib-config>, [">= 0"])
|
65
|
+
s.add_runtime_dependency(%q<uuidtools>, ["~> 2.1.2"])
|
66
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
67
|
+
s.add_development_dependency(%q<minitest>, ["~> 2.6.0"])
|
68
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
69
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
70
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
71
|
+
s.add_development_dependency(%q<vagrant>, [">= 0"])
|
72
|
+
s.add_development_dependency(%q<virtualbox>, [">= 0"])
|
73
|
+
else
|
74
|
+
s.add_dependency(%q<pylon>, [">= 0"])
|
75
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
76
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
77
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
78
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
79
|
+
s.add_dependency(%q<vagrant>, [">= 0"])
|
80
|
+
s.add_dependency(%q<virtualbox>, [">= 0"])
|
81
|
+
s.add_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
|
82
|
+
s.add_dependency(%q<mixlib-log>, [">= 0"])
|
83
|
+
s.add_dependency(%q<mixlib-cli>, [">= 0"])
|
84
|
+
s.add_dependency(%q<mixlib-config>, [">= 0"])
|
85
|
+
s.add_dependency(%q<uuidtools>, ["~> 2.1.2"])
|
86
|
+
s.add_dependency(%q<json>, [">= 0"])
|
87
|
+
s.add_dependency(%q<minitest>, ["~> 2.6.0"])
|
88
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
89
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
90
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
91
|
+
s.add_dependency(%q<vagrant>, [">= 0"])
|
92
|
+
s.add_dependency(%q<virtualbox>, [">= 0"])
|
93
|
+
end
|
94
|
+
else
|
95
|
+
s.add_dependency(%q<pylon>, [">= 0"])
|
96
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
97
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
98
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
99
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
100
|
+
s.add_dependency(%q<vagrant>, [">= 0"])
|
101
|
+
s.add_dependency(%q<virtualbox>, [">= 0"])
|
102
|
+
s.add_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
|
103
|
+
s.add_dependency(%q<mixlib-log>, [">= 0"])
|
104
|
+
s.add_dependency(%q<mixlib-cli>, [">= 0"])
|
105
|
+
s.add_dependency(%q<mixlib-config>, [">= 0"])
|
106
|
+
s.add_dependency(%q<uuidtools>, ["~> 2.1.2"])
|
107
|
+
s.add_dependency(%q<json>, [">= 0"])
|
108
|
+
s.add_dependency(%q<minitest>, ["~> 2.6.0"])
|
109
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
110
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
111
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
112
|
+
s.add_dependency(%q<vagrant>, [">= 0"])
|
113
|
+
s.add_dependency(%q<virtualbox>, [">= 0"])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'minitest/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
require 'pylon'
|
15
|
+
|
16
|
+
class MiniTest::Unit::TestCase
|
17
|
+
end
|
18
|
+
|
19
|
+
MiniTest::Unit.autorun
|
data/test/test_pylon.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pylon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,89 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-19 00:00:00.000000000 +12:00
|
13
13
|
default_executable: pylon
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: pylon
|
17
|
+
requirement: &2162102520 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2162102520
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: minitest
|
28
|
+
requirement: &2162101520 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2162101520
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
requirement: &2162099020 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.0.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2162099020
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: jeweler
|
50
|
+
requirement: &2162097740 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.6.4
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *2162097740
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rcov
|
61
|
+
requirement: &2162096500 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *2162096500
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: vagrant
|
72
|
+
requirement: &2162095180 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *2162095180
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: virtualbox
|
83
|
+
requirement: &2162093740 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *2162093740
|
15
92
|
- !ruby/object:Gem::Dependency
|
16
93
|
name: ffi-rzmq
|
17
|
-
requirement: &
|
94
|
+
requirement: &2162092260 !ruby/object:Gem::Requirement
|
18
95
|
none: false
|
19
96
|
requirements:
|
20
97
|
- - ~>
|
@@ -22,10 +99,10 @@ dependencies:
|
|
22
99
|
version: 0.8.2
|
23
100
|
type: :runtime
|
24
101
|
prerelease: false
|
25
|
-
version_requirements: *
|
102
|
+
version_requirements: *2162092260
|
26
103
|
- !ruby/object:Gem::Dependency
|
27
104
|
name: mixlib-log
|
28
|
-
requirement: &
|
105
|
+
requirement: &2162054420 !ruby/object:Gem::Requirement
|
29
106
|
none: false
|
30
107
|
requirements:
|
31
108
|
- - ! '>='
|
@@ -33,10 +110,10 @@ dependencies:
|
|
33
110
|
version: '0'
|
34
111
|
type: :runtime
|
35
112
|
prerelease: false
|
36
|
-
version_requirements: *
|
113
|
+
version_requirements: *2162054420
|
37
114
|
- !ruby/object:Gem::Dependency
|
38
115
|
name: mixlib-cli
|
39
|
-
requirement: &
|
116
|
+
requirement: &2162053640 !ruby/object:Gem::Requirement
|
40
117
|
none: false
|
41
118
|
requirements:
|
42
119
|
- - ! '>='
|
@@ -44,10 +121,10 @@ dependencies:
|
|
44
121
|
version: '0'
|
45
122
|
type: :runtime
|
46
123
|
prerelease: false
|
47
|
-
version_requirements: *
|
124
|
+
version_requirements: *2162053640
|
48
125
|
- !ruby/object:Gem::Dependency
|
49
126
|
name: mixlib-config
|
50
|
-
requirement: &
|
127
|
+
requirement: &2162052900 !ruby/object:Gem::Requirement
|
51
128
|
none: false
|
52
129
|
requirements:
|
53
130
|
- - ! '>='
|
@@ -55,10 +132,10 @@ dependencies:
|
|
55
132
|
version: '0'
|
56
133
|
type: :runtime
|
57
134
|
prerelease: false
|
58
|
-
version_requirements: *
|
135
|
+
version_requirements: *2162052900
|
59
136
|
- !ruby/object:Gem::Dependency
|
60
137
|
name: uuidtools
|
61
|
-
requirement: &
|
138
|
+
requirement: &2162052220 !ruby/object:Gem::Requirement
|
62
139
|
none: false
|
63
140
|
requirements:
|
64
141
|
- - ~>
|
@@ -66,10 +143,10 @@ dependencies:
|
|
66
143
|
version: 2.1.2
|
67
144
|
type: :runtime
|
68
145
|
prerelease: false
|
69
|
-
version_requirements: *
|
146
|
+
version_requirements: *2162052220
|
70
147
|
- !ruby/object:Gem::Dependency
|
71
148
|
name: json
|
72
|
-
requirement: &
|
149
|
+
requirement: &2162051620 !ruby/object:Gem::Requirement
|
73
150
|
none: false
|
74
151
|
requirements:
|
75
152
|
- - ! '>='
|
@@ -77,21 +154,21 @@ dependencies:
|
|
77
154
|
version: '0'
|
78
155
|
type: :runtime
|
79
156
|
prerelease: false
|
80
|
-
version_requirements: *
|
157
|
+
version_requirements: *2162051620
|
81
158
|
- !ruby/object:Gem::Dependency
|
82
159
|
name: minitest
|
83
|
-
requirement: &
|
160
|
+
requirement: &2162051020 !ruby/object:Gem::Requirement
|
84
161
|
none: false
|
85
162
|
requirements:
|
86
|
-
- -
|
163
|
+
- - ~>
|
87
164
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
165
|
+
version: 2.6.0
|
89
166
|
type: :development
|
90
167
|
prerelease: false
|
91
|
-
version_requirements: *
|
168
|
+
version_requirements: *2162051020
|
92
169
|
- !ruby/object:Gem::Dependency
|
93
170
|
name: bundler
|
94
|
-
requirement: &
|
171
|
+
requirement: &2162050280 !ruby/object:Gem::Requirement
|
95
172
|
none: false
|
96
173
|
requirements:
|
97
174
|
- - ~>
|
@@ -99,10 +176,10 @@ dependencies:
|
|
99
176
|
version: 1.0.0
|
100
177
|
type: :development
|
101
178
|
prerelease: false
|
102
|
-
version_requirements: *
|
179
|
+
version_requirements: *2162050280
|
103
180
|
- !ruby/object:Gem::Dependency
|
104
181
|
name: jeweler
|
105
|
-
requirement: &
|
182
|
+
requirement: &2162049140 !ruby/object:Gem::Requirement
|
106
183
|
none: false
|
107
184
|
requirements:
|
108
185
|
- - ~>
|
@@ -110,10 +187,10 @@ dependencies:
|
|
110
187
|
version: 1.6.4
|
111
188
|
type: :development
|
112
189
|
prerelease: false
|
113
|
-
version_requirements: *
|
190
|
+
version_requirements: *2162049140
|
114
191
|
- !ruby/object:Gem::Dependency
|
115
192
|
name: rcov
|
116
|
-
requirement: &
|
193
|
+
requirement: &2162047900 !ruby/object:Gem::Requirement
|
117
194
|
none: false
|
118
195
|
requirements:
|
119
196
|
- - ! '>='
|
@@ -121,10 +198,10 @@ dependencies:
|
|
121
198
|
version: '0'
|
122
199
|
type: :development
|
123
200
|
prerelease: false
|
124
|
-
version_requirements: *
|
201
|
+
version_requirements: *2162047900
|
125
202
|
- !ruby/object:Gem::Dependency
|
126
203
|
name: vagrant
|
127
|
-
requirement: &
|
204
|
+
requirement: &2162005180 !ruby/object:Gem::Requirement
|
128
205
|
none: false
|
129
206
|
requirements:
|
130
207
|
- - ! '>='
|
@@ -132,10 +209,10 @@ dependencies:
|
|
132
209
|
version: '0'
|
133
210
|
type: :development
|
134
211
|
prerelease: false
|
135
|
-
version_requirements: *
|
212
|
+
version_requirements: *2162005180
|
136
213
|
- !ruby/object:Gem::Dependency
|
137
214
|
name: virtualbox
|
138
|
-
requirement: &
|
215
|
+
requirement: &2162004500 !ruby/object:Gem::Requirement
|
139
216
|
none: false
|
140
217
|
requirements:
|
141
218
|
- - ! '>='
|
@@ -143,7 +220,7 @@ dependencies:
|
|
143
220
|
version: '0'
|
144
221
|
type: :development
|
145
222
|
prerelease: false
|
146
|
-
version_requirements: *
|
223
|
+
version_requirements: *2162004500
|
147
224
|
description: leader election with zeromq for ruby using widely available leader election
|
148
225
|
algorithms, similar to gen_leader erlang project in essence
|
149
226
|
email: aj@junglist.gen.nz
|
@@ -154,6 +231,17 @@ extra_rdoc_files:
|
|
154
231
|
- LICENSE
|
155
232
|
- README.org
|
156
233
|
files:
|
234
|
+
- Gemfile
|
235
|
+
- LICENSE
|
236
|
+
- NOTICE
|
237
|
+
- README.org
|
238
|
+
- Rakefile
|
239
|
+
- Vagrantfile
|
240
|
+
- bin/pylon
|
241
|
+
- cookbooks/pylon/README.rdoc
|
242
|
+
- cookbooks/pylon/metadata.rb
|
243
|
+
- cookbooks/pylon/recipes/default.rb
|
244
|
+
- lib/pylon.rb
|
157
245
|
- lib/pylon/application.rb
|
158
246
|
- lib/pylon/config.rb
|
159
247
|
- lib/pylon/daemon.rb
|
@@ -161,10 +249,9 @@ files:
|
|
161
249
|
- lib/pylon/log.rb
|
162
250
|
- lib/pylon/node.rb
|
163
251
|
- lib/pylon/version.rb
|
164
|
-
-
|
165
|
-
-
|
166
|
-
-
|
167
|
-
- README.org
|
252
|
+
- pylon.gemspec
|
253
|
+
- test/helper.rb
|
254
|
+
- test/test_pylon.rb
|
168
255
|
has_rdoc: true
|
169
256
|
homepage: http://github.com/fujin/pylon
|
170
257
|
licenses:
|
@@ -179,6 +266,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
266
|
- - ! '>='
|
180
267
|
- !ruby/object:Gem::Version
|
181
268
|
version: '0'
|
269
|
+
segments:
|
270
|
+
- 0
|
271
|
+
hash: 352816243979508191
|
182
272
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
273
|
none: false
|
184
274
|
requirements:
|