pylon 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|