nofxx-nanite 0.4.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +430 -0
  3. data/Rakefile +76 -0
  4. data/TODO +24 -0
  5. data/bin/nanite-admin +65 -0
  6. data/bin/nanite-agent +79 -0
  7. data/bin/nanite-mapper +50 -0
  8. data/lib/nanite.rb +74 -0
  9. data/lib/nanite/actor.rb +71 -0
  10. data/lib/nanite/actor_registry.rb +26 -0
  11. data/lib/nanite/admin.rb +138 -0
  12. data/lib/nanite/agent.rb +258 -0
  13. data/lib/nanite/amqp.rb +54 -0
  14. data/lib/nanite/cluster.rb +236 -0
  15. data/lib/nanite/config.rb +111 -0
  16. data/lib/nanite/console.rb +39 -0
  17. data/lib/nanite/daemonize.rb +13 -0
  18. data/lib/nanite/dispatcher.rb +92 -0
  19. data/lib/nanite/identity.rb +16 -0
  20. data/lib/nanite/job.rb +104 -0
  21. data/lib/nanite/local_state.rb +34 -0
  22. data/lib/nanite/log.rb +66 -0
  23. data/lib/nanite/log/formatter.rb +39 -0
  24. data/lib/nanite/mapper.rb +310 -0
  25. data/lib/nanite/mapper_proxy.rb +67 -0
  26. data/lib/nanite/packets.rb +365 -0
  27. data/lib/nanite/pid_file.rb +52 -0
  28. data/lib/nanite/reaper.rb +38 -0
  29. data/lib/nanite/security/cached_certificate_store_proxy.rb +24 -0
  30. data/lib/nanite/security/certificate.rb +55 -0
  31. data/lib/nanite/security/certificate_cache.rb +66 -0
  32. data/lib/nanite/security/distinguished_name.rb +34 -0
  33. data/lib/nanite/security/encrypted_document.rb +46 -0
  34. data/lib/nanite/security/rsa_key_pair.rb +53 -0
  35. data/lib/nanite/security/secure_serializer.rb +68 -0
  36. data/lib/nanite/security/signature.rb +46 -0
  37. data/lib/nanite/security/static_certificate_store.rb +35 -0
  38. data/lib/nanite/security_provider.rb +47 -0
  39. data/lib/nanite/serializer.rb +52 -0
  40. data/lib/nanite/state.rb +164 -0
  41. data/lib/nanite/streaming.rb +125 -0
  42. data/lib/nanite/util.rb +58 -0
  43. data/spec/actor_registry_spec.rb +60 -0
  44. data/spec/actor_spec.rb +77 -0
  45. data/spec/agent_spec.rb +240 -0
  46. data/spec/cached_certificate_store_proxy_spec.rb +34 -0
  47. data/spec/certificate_cache_spec.rb +49 -0
  48. data/spec/certificate_spec.rb +27 -0
  49. data/spec/cluster_spec.rb +485 -0
  50. data/spec/dispatcher_spec.rb +136 -0
  51. data/spec/distinguished_name_spec.rb +24 -0
  52. data/spec/encrypted_document_spec.rb +21 -0
  53. data/spec/job_spec.rb +251 -0
  54. data/spec/local_state_spec.rb +112 -0
  55. data/spec/packet_spec.rb +220 -0
  56. data/spec/rsa_key_pair_spec.rb +33 -0
  57. data/spec/secure_serializer_spec.rb +41 -0
  58. data/spec/serializer_spec.rb +107 -0
  59. data/spec/signature_spec.rb +30 -0
  60. data/spec/spec_helper.rb +33 -0
  61. data/spec/static_certificate_store_spec.rb +30 -0
  62. data/spec/util_spec.rb +63 -0
  63. metadata +131 -0
@@ -0,0 +1,60 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::ActorRegistry do
4
+
5
+ class ::WebDocumentImporter
6
+ include Nanite::Actor
7
+ expose :import, :cancel
8
+
9
+ def import
10
+ 1
11
+ end
12
+ def cancel
13
+ 0
14
+ end
15
+ end
16
+
17
+ module ::Actors
18
+ class ComedyActor
19
+ include Nanite::Actor
20
+ expose :fun_tricks
21
+ def fun_tricks
22
+ :rabbit_in_the_hat
23
+ end
24
+ end
25
+ end
26
+
27
+ before(:each) do
28
+ Nanite::Log.stub!(:info)
29
+ @registry = Nanite::ActorRegistry.new
30
+ end
31
+
32
+ it "should know about all services" do
33
+ @registry.register(WebDocumentImporter.new, nil)
34
+ @registry.register(Actors::ComedyActor.new, nil)
35
+ @registry.services.sort.should == ["/actors/comedy_actor/fun_tricks", "/web_document_importer/cancel", "/web_document_importer/import"]
36
+ end
37
+
38
+ it "should not register anything except Nanite::Actor" do
39
+ lambda { @registry.register(String.new, nil) }.should raise_error(ArgumentError)
40
+ end
41
+
42
+ it "should register an actor" do
43
+ importer = WebDocumentImporter.new
44
+ @registry.register(importer, nil)
45
+ @registry.actors['web_document_importer'].should == importer
46
+ end
47
+
48
+ it "should log info message that actor was registered" do
49
+ importer = WebDocumentImporter.new
50
+ Nanite::Log.should_receive(:info).with("[actor] #{importer.class.to_s}")
51
+ @registry.register(importer, nil)
52
+ end
53
+
54
+ it "should handle actors registered with a custom prefix" do
55
+ importer = WebDocumentImporter.new
56
+ @registry.register(importer, 'monkey')
57
+ @registry.actor_for('monkey').should == importer
58
+ end
59
+
60
+ end # Nanite::ActorRegistry
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::Actor do
4
+ class ::WebDocumentImporter
5
+ include Nanite::Actor
6
+ expose :import, :cancel
7
+
8
+ def import
9
+ 1
10
+ end
11
+ def cancel
12
+ 0
13
+ end
14
+ def continue
15
+ 1
16
+ end
17
+ end
18
+
19
+ module ::Actors
20
+ class ComedyActor
21
+ include Nanite::Actor
22
+ expose :fun_tricks
23
+ def fun_tricks
24
+ :rabbit_in_the_hat
25
+ end
26
+ end
27
+ end
28
+
29
+ class ::Actors::InvalidActor
30
+ include Nanite::Actor
31
+ expose :non_existing
32
+ end
33
+
34
+ describe ".expose" do
35
+ before :each do
36
+ @exposed = WebDocumentImporter.instance_variable_get(:@exposed).dup
37
+ end
38
+
39
+ after :each do
40
+ WebDocumentImporter.instance_variable_set(:@exposed, @exposed)
41
+ end
42
+
43
+
44
+ it "should single expose method only once" do
45
+ 3.times { WebDocumentImporter.expose(:continue) }
46
+ WebDocumentImporter.provides_for("webfiles").should == ["/webfiles/import", "/webfiles/cancel", "/webfiles/continue"]
47
+ end
48
+ end
49
+
50
+ describe ".default_prefix" do
51
+ it "is calculated as default prefix as const path of class name" do
52
+ Actors::ComedyActor.default_prefix.should == "actors/comedy_actor"
53
+ WebDocumentImporter.default_prefix.should == "web_document_importer"
54
+ end
55
+ end
56
+
57
+ describe ".provides_for(prefix)" do
58
+ before :each do
59
+ @provides = Actors::ComedyActor.provides_for("money")
60
+ end
61
+
62
+ it "returns an array" do
63
+ @provides.should be_kind_of(Array)
64
+ end
65
+
66
+ it "maps exposed service methods to prefix" do
67
+ @provides.should == ["/money/fun_tricks"]
68
+ wdi_provides = WebDocumentImporter.provides_for("webfiles")
69
+ wdi_provides.should include("/webfiles/import")
70
+ wdi_provides.should include("/webfiles/cancel")
71
+ end
72
+
73
+ it "should not include methods not existing in the actor class" do
74
+ Actors::InvalidActor.provides_for("money").should_not include("/money/non_existing")
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,240 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Agent:" do
4
+
5
+ describe "Default Option" do
6
+
7
+ before(:all) do
8
+ EM.stub!(:add_periodic_timer)
9
+ AMQP.stub!(:connect)
10
+ @amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}), :fanout => mock("fanout", :publish => nil))
11
+ MQ.stub!(:new).and_return(@amq)
12
+ @agent = Nanite::Agent.start
13
+ end
14
+
15
+ it "for daemonize is false" do
16
+ @agent.options.should include(:daemonize)
17
+ @agent.options[:daemonize].should == false
18
+ end
19
+
20
+ it "for format is marshal" do
21
+ @agent.options.should include(:format)
22
+ @agent.options[:format].should == :marshal
23
+ end
24
+
25
+ it "for console is false" do
26
+ @agent.options.should include(:console)
27
+ @agent.options[:console].should == false
28
+ end
29
+
30
+ it "for user is nanite" do
31
+ @agent.options.should include(:user)
32
+ @agent.options[:user].should == "nanite"
33
+ end
34
+
35
+ it "for pass(word) is testing" do
36
+ @agent.options.should include(:pass)
37
+ @agent.options[:pass].should == "testing"
38
+ end
39
+
40
+ it "for secure is false" do
41
+ @agent.options.should include(:secure)
42
+ @agent.options[:secure].should == false
43
+ end
44
+
45
+ it "for host is 0.0.0.0" do
46
+ @agent.options.should include(:host)
47
+ @agent.options[:host].should == "0.0.0.0"
48
+ end
49
+
50
+ it "for log_level is info" do
51
+ @agent.options.should include(:log_level)
52
+ @agent.options[:log_level].should == :info
53
+ end
54
+
55
+ it "for vhost is /nanite" do
56
+ @agent.options.should include(:vhost)
57
+ @agent.options[:vhost].should == "/nanite"
58
+ end
59
+
60
+ it "for ping_time is 15" do
61
+ @agent.options.should include(:ping_time)
62
+ @agent.options[:ping_time].should == 15
63
+ end
64
+
65
+ it "for default_services is []" do
66
+ @agent.options.should include(:default_services)
67
+ @agent.options[:default_services].should == []
68
+ end
69
+
70
+ it "for root is #{File.expand_path(File.join(File.dirname(__FILE__), '..'))}" do
71
+ @agent.options.should include(:root)
72
+ @agent.options[:root].should == File.expand_path(File.join(File.dirname(__FILE__), '..'))
73
+ end
74
+
75
+ it "for file_root is #{File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))}" do
76
+ @agent.options.should include(:file_root)
77
+ @agent.options[:file_root].should == File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))
78
+ end
79
+
80
+ end
81
+
82
+ describe "Options from config.yml" do
83
+
84
+ before(:all) do
85
+ @agent = Nanite::Agent.start
86
+ end
87
+
88
+ end
89
+
90
+ describe "Passed in Options" do
91
+
92
+ before(:each) do
93
+ EM.stub!(:add_periodic_timer)
94
+ AMQP.stub!(:connect)
95
+ @amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}), :fanout => mock("fanout", :publish => nil))
96
+ MQ.stub!(:new).and_return(@amq)
97
+ end
98
+
99
+ # TODO figure out how to stub call to daemonize
100
+ # it "for daemonize should override default (false)" do
101
+ # agent = Nanite::Agent.start(:daemonize => true)
102
+ # agent.options.should include(:daemonize)
103
+ # agent.options[:daemonize].should == true
104
+ # end
105
+
106
+ it "for format should override default (marshal)" do
107
+ agent = Nanite::Agent.start(:format => :json)
108
+ agent.options.should include(:format)
109
+ agent.options[:format].should == :json
110
+ end
111
+
112
+ # TODO figure out how to avoid console output
113
+ # it "for console should override default (false)" do
114
+ # agent = Nanite::Agent.start(:console => true)
115
+ # agent.options.should include(:console)
116
+ # agent.options[:console].should == true
117
+ # end
118
+
119
+ it "for user should override default (nanite)" do
120
+ agent = Nanite::Agent.start(:user => "me")
121
+ agent.options.should include(:user)
122
+ agent.options[:user].should == "me"
123
+ end
124
+
125
+ it "for pass(word) should override default (testing)" do
126
+ agent = Nanite::Agent.start(:pass => "secret")
127
+ agent.options.should include(:pass)
128
+ agent.options[:pass].should == "secret"
129
+ end
130
+
131
+ it "for secure should override default (false)" do
132
+ agent = Nanite::Agent.start(:secure => true)
133
+ agent.options.should include(:secure)
134
+ agent.options[:secure].should == true
135
+ end
136
+
137
+ it "for host should override default (0.0.0.0)" do
138
+ agent = Nanite::Agent.start(:host => "127.0.0.1")
139
+ agent.options.should include(:host)
140
+ agent.options[:host].should == "127.0.0.1"
141
+ end
142
+
143
+ it "for log_level should override default (info)" do
144
+ agent = Nanite::Agent.start(:log_level => :debug)
145
+ agent.options.should include(:log_level)
146
+ agent.options[:log_level].should == :debug
147
+ end
148
+
149
+ it "for vhost should override default (/nanite)" do
150
+ agent = Nanite::Agent.start(:vhost => "/virtual_host")
151
+ agent.options.should include(:vhost)
152
+ agent.options[:vhost].should == "/virtual_host"
153
+ end
154
+
155
+ it "for ping_time should override default (15)" do
156
+ agent = Nanite::Agent.start(:ping_time => 5)
157
+ agent.options.should include(:ping_time)
158
+ agent.options[:ping_time].should == 5
159
+ end
160
+
161
+ it "for default_services should override default ([])" do
162
+ agent = Nanite::Agent.start(:default_services => [:test])
163
+ agent.options.should include(:default_services)
164
+ agent.options[:default_services].should == [:test]
165
+ end
166
+
167
+ it "for root should override default (#{File.expand_path(File.join(File.dirname(__FILE__), '..'))})" do
168
+ agent = Nanite::Agent.start(:root => File.expand_path(File.dirname(__FILE__)))
169
+ agent.options.should include(:root)
170
+ agent.options[:root].should == File.expand_path(File.dirname(__FILE__))
171
+ end
172
+
173
+ it "for file_root should override default (#{File.expand_path(File.join(File.dirname(__FILE__), '..', 'files'))})" do
174
+ agent = Nanite::Agent.start(:file_root => File.expand_path(File.dirname(__FILE__)))
175
+ agent.options.should include(:file_root)
176
+ agent.options[:file_root].should == File.expand_path(File.dirname(__FILE__))
177
+ end
178
+
179
+ it "for a single tag should result in the agent's tags being set" do
180
+ agent = Nanite::Agent.start(:tag => "sample_tag")
181
+ agent.tags.should include("sample_tag")
182
+ end
183
+
184
+ it "for multiple tags should result in the agent's tags being set" do
185
+ agent = Nanite::Agent.start(:tag => ["sample_tag_1", "sample_tag_2"])
186
+ agent.tags.should include("sample_tag_1")
187
+ agent.tags.should include("sample_tag_2")
188
+ end
189
+
190
+ it "for threadpool_size" do
191
+ agent = Nanite::Agent.start(:threadpool_size => 5)
192
+ agent.dispatcher.evmclass.threadpool_size.should == 5
193
+ end
194
+
195
+ end
196
+
197
+ describe "Security" do
198
+
199
+ before(:each) do
200
+ EM.stub!(:add_periodic_timer)
201
+ AMQP.stub!(:connect)
202
+ @amq = mock("AMQueue", :queue => mock("queue", :subscribe => {}, :publish => {}), :fanout => mock("fanout", :publish => nil))
203
+ MQ.stub!(:new).and_return(@amq)
204
+ serializer = Nanite::Serializer.new
205
+ @request = Nanite::Request.new('/foo/bar', '')
206
+ @push = Nanite::Push.new('/foo/bar', '')
207
+ @agent = Nanite::Agent.start
208
+ end
209
+
210
+ it 'should correctly deny requests' do
211
+ security = mock("Security")
212
+ @agent.register_security(security)
213
+
214
+ security.should_receive(:authorize).twice.and_return(false)
215
+ @agent.dispatcher.should_not_receive(:dispatch)
216
+ @agent.__send__(:receive, @request)
217
+ @agent.__send__(:receive, @push)
218
+ end
219
+
220
+ it 'should correctly authorize requests' do
221
+ security = mock("Security")
222
+ @agent.register_security(security)
223
+
224
+ security.should_receive(:authorize).twice.and_return(true)
225
+ @agent.dispatcher.stub!(:dispatch)
226
+ @agent.dispatcher.should_receive(:dispatch).twice
227
+ @agent.__send__(:receive, @request)
228
+ @agent.__send__(:receive, @push)
229
+ end
230
+
231
+ it 'should be ignored when not specified' do
232
+ @agent.dispatcher.stub!(:dispatch)
233
+ @agent.dispatcher.should_receive(:dispatch).twice
234
+ @agent.__send__(:receive, @request)
235
+ @agent.__send__(:receive, @push)
236
+ end
237
+
238
+ end
239
+
240
+ end
@@ -0,0 +1,34 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::CachedCertificateStoreProxy do
4
+
5
+ include SpecHelpers
6
+
7
+ before(:all) do
8
+ @signer, key = issue_cert
9
+ @recipient, key = issue_cert
10
+ @store = mock("Store")
11
+ @proxy = Nanite::CachedCertificateStoreProxy.new(@store)
12
+ end
13
+
14
+ it 'should not raise and return nil for non existent certificates' do
15
+ res = nil
16
+ @store.should_receive(:get_recipients).with(nil).and_return(nil)
17
+ lambda { res = @proxy.get_recipients(nil) }.should_not raise_error
18
+ res.should == nil
19
+ @store.should_receive(:get_signer).with(nil).and_return(nil)
20
+ lambda { res = @proxy.get_signer(nil) }.should_not raise_error
21
+ res.should == nil
22
+ end
23
+
24
+ it 'should return recipient certificates' do
25
+ @store.should_receive(:get_recipients).with('anything').and_return(@recipient)
26
+ @proxy.get_recipients('anything').should == @recipient
27
+ end
28
+
29
+ it 'should return signer certificates' do
30
+ @store.should_receive(:get_signer).with('anything').and_return(@signer)
31
+ @proxy.get_signer('anything').should == @signer
32
+ end
33
+
34
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::CertificateCache do
4
+
5
+ before(:each) do
6
+ @cache = Nanite::CertificateCache.new(2)
7
+ end
8
+
9
+ it 'should allow storing and retrieving objects' do
10
+ @cache['some_id'].should be_nil
11
+ @cache['some_id'] = 'some_value'
12
+ @cache['some_id'].should == 'some_value'
13
+ end
14
+
15
+ it 'should not store more than required' do
16
+ @cache[1] = 'oldest'
17
+ @cache[2] = 'older'
18
+ @cache[1].should == 'oldest'
19
+ @cache[2].should == 'older'
20
+
21
+ @cache[3] = 'new'
22
+ @cache[3].should == 'new'
23
+
24
+ @cache[1].should be_nil
25
+ @cache[2].should == 'older'
26
+ end
27
+
28
+ it 'should use LRU to remove entries' do
29
+ @cache[1] = 'oldest'
30
+ @cache[2] = 'older'
31
+ @cache[1].should == 'oldest'
32
+ @cache[2].should == 'older'
33
+
34
+ @cache[1] = 'new'
35
+ @cache[3] = 'newer'
36
+ @cache[1].should == 'new'
37
+ @cache[3].should == 'newer'
38
+
39
+ @cache[2].should be_nil
40
+ end
41
+
42
+ it 'should store items returned by block' do
43
+ @cache[1].should be_nil
44
+ item = @cache.get(1) { 'item' }
45
+ item.should == 'item'
46
+ @cache[1].should == 'item'
47
+ end
48
+
49
+ end