dcell-s3-registry 0.0.1

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.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Joe Hosteny
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ dcell-s3-registry
2
+ =================
3
+
4
+ This provides an [AWS S3](http://aws.amazon.com/s3/) registry for
5
+ [DCell](https://github.com/celluloid/dcell).
6
+
7
+ The S3 registry adapter allows DCell to use S3 as a registry instead of Redis, Zookeeper, etc.
8
+
9
+ ## Prerequisites
10
+
11
+ Please follow the [instructions for DCell](https://github.com/celluloid/dcell).
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'dcell-s3-adapter'
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install dcell-s3-adapter
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require 'dcell'
31
+ require 'dcell/registries/s3_adapter'
32
+
33
+ DCell.start(registry: { adapter: 's3', bucket: 'bucket-name' })
34
+ ```
35
+
36
+ Please see the DCell documentation for further details.
37
+
38
+ There is an executable example in `examples/dcell-s3-registry.rb`.
39
+
40
+ $ ruby examples/dcell-s3-registry.rb -n master -p 7777 -b your-unique-bucket
41
+ $ ruby examples/dcell-s3-registry.rb -n node_1 -p 7778 -b your-unique-bucket
42
+
43
+ ## Copyright
44
+
45
+ Copyright (c) 2013 Joe Hosteny. Distributed under the MIT License.
46
+ See LICENSE.txt for further details.
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc 'Run all specs'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dcell/s3_registry/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'dcell-s3-registry'
8
+ spec.version = DCell::S3Registry::VERSION
9
+ spec.authors = ['Joe Hosteny']
10
+ spec.email = ['jhosteny@gmail.com']
11
+ spec.description = %q{AWS S3 registry for DCell}
12
+ spec.summary = %q{An AWS S3 registry for DCell.}
13
+ spec.homepage = 'https://github.com/jhosteny/dcell-s3-registry'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
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_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'aws-sdk'
25
+
26
+ spec.add_runtime_dependency 'dcell'
27
+ end
@@ -0,0 +1,62 @@
1
+ require 'dcell'
2
+ require 'dcell/registries/s3_adapter'
3
+ require 'optparse'
4
+
5
+ # The DCell node_id
6
+ name = nil
7
+
8
+ # The local port for the 0MQ communication.
9
+ port = nil
10
+
11
+ # The S3 bucket
12
+ bucket = nil
13
+
14
+ OptionParser.new.tap { |options|
15
+ options.on('-n NAME', 'Node name') do |value|
16
+ name = value
17
+ end
18
+ options.on('-p PORT', 'Node port') do |value|
19
+ port = value.to_i
20
+ end
21
+ options.on('-b BUCKET', 'Bucket name') do |value|
22
+ bucket = value
23
+ end
24
+ }.parse(ARGV)
25
+
26
+ unless bucket and (name or port)
27
+ puts "Missing options. See -h for available options."
28
+ exit 1
29
+ end
30
+
31
+ registry = { :adapter => 's3', :env => 'test', :bucket => bucket }
32
+
33
+ class TimeServer
34
+ include Celluloid
35
+
36
+ def run
37
+ "[#{DCell.me.id}] #{Time.now}"
38
+ end
39
+ end
40
+
41
+ class StatusServer
42
+ include Celluloid
43
+
44
+ def run
45
+ "[#{DCell.me.id}] STATUS OK"
46
+ end
47
+ end
48
+
49
+ DCell.start(:id => name, :addr => "tcp://127.0.0.1:#{port}", :registry => registry)
50
+
51
+ if name == 'master'
52
+ TimeServer.supervise_as :service
53
+ else
54
+ StatusServer.supervise_as :service
55
+ end
56
+
57
+ loop do
58
+ puts DCell::Node.all.inspect
59
+ puts DCell::Node.all.shuffle.first[:service].run
60
+
61
+ sleep 1
62
+ end
@@ -0,0 +1,109 @@
1
+ require 'aws-sdk'
2
+
3
+ module DCell
4
+ module Registry
5
+ class S3Adapter
6
+ def initialize(options)
7
+ # Convert all options to symbols :/
8
+ options = options.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
9
+
10
+ @env = options[:env] || 'production'
11
+ bucket = options[:bucket] || "dcell_#{Celluloid.uuid}_#{@env}"
12
+
13
+ access_key_id = options[:access_key_id] || ENV['AWS_ACCESS_KEY_ID']
14
+ secret_access_key = options[:secret_access_key] || ENV['AWS_SECRET_ACCESS_KEY']
15
+ s3_opts = { :access_key_id => access_key_id, :secret_access_key => secret_access_key }
16
+ s3_opts.merge!({ :region => options[:region] }) if options[:region]
17
+ @s3 = AWS::S3.new(s3_opts)
18
+
19
+ @bucket = @s3.buckets[bucket]
20
+ @bucket = @s3.buckets.create(bucket) unless @bucket.exists?
21
+
22
+ @node_registry = NodeRegistry.new(@bucket)
23
+ @global_registry = GlobalRegistry.new(@bucket)
24
+ end
25
+
26
+ def clear_nodes
27
+ @node_registry.clear
28
+ end
29
+
30
+ def clear_globals
31
+ @global_registry.clear
32
+ end
33
+
34
+ def delete_store
35
+ @bucket.delete!
36
+ rescue AWS::S3::Errors::NoSuchBucket
37
+ Logger.info "Bucket #{@bucket.name} doesn't exist"
38
+ end
39
+
40
+ class NodeRegistry
41
+ def initialize(bucket)
42
+ @bucket = bucket
43
+ end
44
+
45
+ def get(node_id)
46
+ @bucket.objects["nodes/#{node_id}"].read
47
+ rescue AWS::S3::Errors::NoSuchKey
48
+ Logger.error "No such node #{node_id}"
49
+ nil
50
+ end
51
+
52
+ def set(node_id, addr)
53
+ @bucket.objects["nodes/#{node_id}"].write(addr)
54
+ end
55
+
56
+ def nodes
57
+ @bucket.objects.with_prefix('nodes/').inject([]) do |arr, elt|
58
+ elt.key =~ /^nodes\/(.+)$/
59
+ arr << $1
60
+ end
61
+ end
62
+
63
+ def clear
64
+ @bucket.objects.with_prefix('nodes/').map(&:delete)
65
+ end
66
+ end
67
+
68
+ def get_node(node_id); @node_registry.get(node_id) end
69
+ def set_node(node_id, addr); @node_registry.set(node_id, addr) end
70
+ def nodes; @node_registry.nodes end
71
+
72
+ class GlobalRegistry
73
+ def initialize(bucket)
74
+ @bucket = bucket
75
+ end
76
+
77
+ def get(key)
78
+ string = @bucket.objects["globals/#{key}"].read
79
+ Marshal.load string if string
80
+ rescue AWS::S3::Errors::NoSuchKey
81
+ Logger.error "No such global key #{key}"
82
+ nil
83
+ end
84
+
85
+ # Set a global value
86
+ def set(key, value)
87
+ string = Marshal.dump value
88
+ @bucket.objects["globals/#{key}"].write(string)
89
+ end
90
+
91
+ # The keys to all globals in the system
92
+ def global_keys
93
+ @bucket.objects.with_prefix('globals/').inject([]) do |arr, elt|
94
+ elt.key =~ /^globals\/(.+)$/
95
+ arr << $1
96
+ end
97
+ end
98
+
99
+ def clear
100
+ @bucket.objects.with_prefix('globals/').map(&:delete)
101
+ end
102
+ end
103
+
104
+ def get_global(key); @global_registry.get(key) end
105
+ def set_global(key, value); @global_registry.set(key, value) end
106
+ def global_keys; @global_registry.global_keys end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,5 @@
1
+ module DCell
2
+ class S3Registry
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'dcell/registries/s3_adapter'
3
+
4
+ describe DCell::Registry::S3Adapter do
5
+ subject { described_class.new(env: 'test') }
6
+
7
+ after do
8
+ subject.delete_store
9
+ end
10
+
11
+ context "node registry" do
12
+ before :each do
13
+ subject.clear_nodes
14
+ end
15
+
16
+ it "stores node addresses" do
17
+ address = "tcp://localhost:7777"
18
+
19
+ subject.set_node("foobar", address)
20
+ subject.get_node("foobar").should == address
21
+ end
22
+
23
+ it "stores the IDs of all nodes" do
24
+ subject.set_node("foobar", "tcp://localhost:7777")
25
+ subject.nodes.should include "foobar"
26
+ end
27
+ end
28
+
29
+ context "global registry" do
30
+ before :each do
31
+ subject.clear_globals
32
+ end
33
+
34
+ it "stores values" do
35
+ subject.set_global("foobar", [1,2,3])
36
+ subject.get_global("foobar").should == [1,2,3]
37
+ end
38
+
39
+ it "stores the keys of all globals" do
40
+ subject.set_global("foobar", true)
41
+ subject.global_keys.should include "foobar"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ require 'dcell'
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dcell-s3-registry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joe Hosteny
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
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: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
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: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: aws-sdk
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: dcell
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
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
+ description: AWS S3 registry for DCell
95
+ email:
96
+ - jhosteny@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - dcell-s3-registry.gemspec
107
+ - examples/dcell-s3-registry.rb
108
+ - lib/dcell/registries/s3_adapter.rb
109
+ - lib/dcell/s3_registry/version.rb
110
+ - spec/dcell/registries/s3_adapter_spec.rb
111
+ - spec/spec_helper.rb
112
+ homepage: https://github.com/jhosteny/dcell-s3-registry
113
+ licenses:
114
+ - MIT
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 1.8.24
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: An AWS S3 registry for DCell.
137
+ test_files:
138
+ - spec/dcell/registries/s3_adapter_spec.rb
139
+ - spec/spec_helper.rb
140
+ has_rdoc: