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 ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pylon.gemspec
4
+ gemspec
data/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ Pylon Notice
2
+ ===========
3
+
4
+ Developed by AJ Christensen (http://junglist.gen.nz)
5
+
6
+ * Copyright 2011, AJ Christensen <aj@junglist.gen.nz>
7
+
8
+
@@ -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
+
@@ -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,8 @@
1
+ = DESCRIPTION:
2
+
3
+ = REQUIREMENTS:
4
+
5
+ = ATTRIBUTES:
6
+
7
+ = USAGE:
8
+
@@ -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
+
@@ -15,5 +15,5 @@
15
15
  # limitations under the License.
16
16
 
17
17
  class Pylon
18
- VERSION = "0.2.2"
18
+ VERSION = "0.2.3"
19
19
  end
@@ -53,9 +53,9 @@ class Pylon
53
53
  sleep_after_announce 5
54
54
 
55
55
  # TODO: not implemented
56
- ping_interval 1
57
- ping_timeout 30
58
- ping_retries 3
56
+ fd_interval 30
57
+ fd_timeout 30
58
+ fd_retries 3
59
59
 
60
60
  end
61
61
  end
@@ -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
- @nodes << node unless @nodes.include? node
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 #{@multicast_endpoint}"
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.each do |node|
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.sort.last.uuid
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
- connect_node node.uuid.to_s, node.unicast_endpoint
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
- node = JSON.parse(recv_string)
130
- Log.info "handle_anounce: got announce from #{node}"
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 #{node} of leadership status"
133
- connect_node(node.uuid.to_s, node.unicast_endpoint)
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: subscribing for #{node} on endpoint: #{node.unicast_endpoint}"
140
- connect_node(node.uuid.to_s, node.unicast_endpoint)
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
- def connect_node uuid, endpoint
148
- Log.debug "connect_node: subscribe socket connecting to #{endpoint}"
149
- sub_socket = context.socket ZMQ::SUB
150
- sub_socket.setsockopt ZMQ::IDENTITY, uuid
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
- end
167
- end
220
+
221
+ end # Elector
222
+ end # Pylon
@@ -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
- pub_socket = context.socket ZMQ::PUB
85
- pub_socket.setsockopt ZMQ::IDENTITY, "node"
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
- Log.debug "#{self}: unicast announcing then sleeping #{sleep_after_announce} secs"
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
- #Thread.pass
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
+
@@ -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
+
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestPylon < MiniTest::Unit::TestCase
4
+ def test_something_for_real
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
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.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-18 00:00:00.000000000 +12:00
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: &2170156880 !ruby/object:Gem::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: *2170156880
102
+ version_requirements: *2162092260
26
103
  - !ruby/object:Gem::Dependency
27
104
  name: mixlib-log
28
- requirement: &2170156400 !ruby/object:Gem::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: *2170156400
113
+ version_requirements: *2162054420
37
114
  - !ruby/object:Gem::Dependency
38
115
  name: mixlib-cli
39
- requirement: &2170155920 !ruby/object:Gem::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: *2170155920
124
+ version_requirements: *2162053640
48
125
  - !ruby/object:Gem::Dependency
49
126
  name: mixlib-config
50
- requirement: &2170155440 !ruby/object:Gem::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: *2170155440
135
+ version_requirements: *2162052900
59
136
  - !ruby/object:Gem::Dependency
60
137
  name: uuidtools
61
- requirement: &2170154960 !ruby/object:Gem::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: *2170154960
146
+ version_requirements: *2162052220
70
147
  - !ruby/object:Gem::Dependency
71
148
  name: json
72
- requirement: &2170154480 !ruby/object:Gem::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: *2170154480
157
+ version_requirements: *2162051620
81
158
  - !ruby/object:Gem::Dependency
82
159
  name: minitest
83
- requirement: &2170154000 !ruby/object:Gem::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: '0'
165
+ version: 2.6.0
89
166
  type: :development
90
167
  prerelease: false
91
- version_requirements: *2170154000
168
+ version_requirements: *2162051020
92
169
  - !ruby/object:Gem::Dependency
93
170
  name: bundler
94
- requirement: &2170153520 !ruby/object:Gem::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: *2170153520
179
+ version_requirements: *2162050280
103
180
  - !ruby/object:Gem::Dependency
104
181
  name: jeweler
105
- requirement: &2170153040 !ruby/object:Gem::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: *2170153040
190
+ version_requirements: *2162049140
114
191
  - !ruby/object:Gem::Dependency
115
192
  name: rcov
116
- requirement: &2170152560 !ruby/object:Gem::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: *2170152560
201
+ version_requirements: *2162047900
125
202
  - !ruby/object:Gem::Dependency
126
203
  name: vagrant
127
- requirement: &2170180220 !ruby/object:Gem::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: *2170180220
212
+ version_requirements: *2162005180
136
213
  - !ruby/object:Gem::Dependency
137
214
  name: virtualbox
138
- requirement: &2170179740 !ruby/object:Gem::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: *2170179740
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
- - lib/pylon.rb
165
- - bin/pylon
166
- - LICENSE
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: