rightscale-nanite 0.4.1 → 0.4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/lib/nanite.rb +71 -0
  2. data/lib/nanite/actor.rb +60 -0
  3. data/lib/nanite/actor_registry.rb +24 -0
  4. data/lib/nanite/admin.rb +153 -0
  5. data/lib/nanite/agent.rb +250 -0
  6. data/lib/nanite/amqp.rb +47 -0
  7. data/lib/nanite/cluster.rb +203 -0
  8. data/lib/nanite/config.rb +102 -0
  9. data/lib/nanite/console.rb +39 -0
  10. data/lib/nanite/daemonize.rb +13 -0
  11. data/lib/nanite/dispatcher.rb +90 -0
  12. data/lib/nanite/identity.rb +16 -0
  13. data/lib/nanite/job.rb +104 -0
  14. data/lib/nanite/local_state.rb +34 -0
  15. data/lib/nanite/log.rb +64 -0
  16. data/lib/nanite/log/formatter.rb +39 -0
  17. data/lib/nanite/mapper.rb +277 -0
  18. data/lib/nanite/mapper_proxy.rb +56 -0
  19. data/lib/nanite/packets.rb +231 -0
  20. data/lib/nanite/pid_file.rb +52 -0
  21. data/lib/nanite/reaper.rb +38 -0
  22. data/lib/nanite/security/cached_certificate_store_proxy.rb +24 -0
  23. data/lib/nanite/security/certificate.rb +55 -0
  24. data/lib/nanite/security/certificate_cache.rb +66 -0
  25. data/lib/nanite/security/distinguished_name.rb +34 -0
  26. data/lib/nanite/security/encrypted_document.rb +46 -0
  27. data/lib/nanite/security/rsa_key_pair.rb +53 -0
  28. data/lib/nanite/security/secure_serializer.rb +67 -0
  29. data/lib/nanite/security/signature.rb +40 -0
  30. data/lib/nanite/security/static_certificate_store.rb +35 -0
  31. data/lib/nanite/security_provider.rb +47 -0
  32. data/lib/nanite/serializer.rb +52 -0
  33. data/lib/nanite/state.rb +164 -0
  34. data/lib/nanite/streaming.rb +125 -0
  35. data/lib/nanite/util.rb +51 -0
  36. data/spec/actor_registry_spec.rb +62 -0
  37. data/spec/actor_spec.rb +59 -0
  38. data/spec/agent_spec.rb +235 -0
  39. data/spec/cached_certificate_store_proxy_spec.rb +34 -0
  40. data/spec/certificate_cache_spec.rb +49 -0
  41. data/spec/certificate_spec.rb +27 -0
  42. data/spec/cluster_spec.rb +300 -0
  43. data/spec/dispatcher_spec.rb +136 -0
  44. data/spec/distinguished_name_spec.rb +24 -0
  45. data/spec/encrypted_document_spec.rb +21 -0
  46. data/spec/job_spec.rb +219 -0
  47. data/spec/local_state_spec.rb +112 -0
  48. data/spec/packet_spec.rb +218 -0
  49. data/spec/rsa_key_pair_spec.rb +33 -0
  50. data/spec/secure_serializer_spec.rb +41 -0
  51. data/spec/serializer_spec.rb +107 -0
  52. data/spec/signature_spec.rb +30 -0
  53. data/spec/spec_helper.rb +23 -0
  54. data/spec/static_certificate_store_spec.rb +30 -0
  55. data/spec/util_spec.rb +63 -0
  56. metadata +62 -1
@@ -0,0 +1,218 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "Packet: Base class" do
4
+ before(:all) do
5
+ class TestPacket < Nanite::Packet
6
+ @@cls_attr = "ignore"
7
+ def initialize(attr1)
8
+ @attr1 = attr1
9
+ end
10
+ end
11
+ end
12
+
13
+ it "should be an abstract class" do
14
+ lambda { Nanite::Packet.new }.should raise_error(NotImplementedError, "Nanite::Packet is an abstract class.")
15
+ end
16
+
17
+ it "should know how to dump itself to JSON" do
18
+ packet = TestPacket.new(1)
19
+ packet.should respond_to(:to_json)
20
+ end
21
+
22
+ it "should dump the class name in 'json_class' JSON key" do
23
+ packet = TestPacket.new(42)
24
+ packet.to_json().should =~ /\"json_class\":\"TestPacket\"/
25
+ end
26
+
27
+ it "should dump instance variables in 'data' JSON key" do
28
+ packet = TestPacket.new(188)
29
+ packet.to_json().should =~ /\"data\":\{\"attr1\":188\}/
30
+ end
31
+
32
+ it "should not dump class variables" do
33
+ packet = TestPacket.new(382)
34
+ packet.to_json().should_not =~ /cls_attr/
35
+ end
36
+
37
+ it "should store instance variables in 'data' JSON key as JSON object" do
38
+ packet = TestPacket.new(382)
39
+ packet.to_json().should =~ /\"data\":\{[\w:"]+\}/
40
+ end
41
+
42
+ it "should remove '@' from instance variables" do
43
+ packet = TestPacket.new(2)
44
+ packet.to_json().should_not =~ /@attr1/
45
+ packet.to_json().should =~ /attr1/
46
+ end
47
+ end
48
+
49
+
50
+ describe "Packet: FileStart" do
51
+ it "should dump/load as JSON objects" do
52
+ packet = Nanite::FileStart.new('foo.txt', 'somewhere/foo.txt', '0xdeadbeef')
53
+ packet2 = JSON.parse(packet.to_json)
54
+ packet.filename.should == packet2.filename
55
+ packet.dest.should == packet2.dest
56
+ packet.token.should == packet2.token
57
+ end
58
+
59
+ it "should dump/load as Marshalled ruby objects" do
60
+ packet = Nanite::FileStart.new('foo.txt', 'somewhere/foo.txt', '0xdeadbeef')
61
+ packet2 = Marshal.load(Marshal.dump(packet))
62
+ packet.filename.should == packet2.filename
63
+ packet.dest.should == packet2.dest
64
+ packet.token.should == packet2.token
65
+ end
66
+ end
67
+
68
+
69
+ describe "Packet: FileEnd" do
70
+ it "should dump/load as JSON objects" do
71
+ packet = Nanite::FileEnd.new('0xdeadbeef', 'metadata')
72
+ packet2 = JSON.parse(packet.to_json)
73
+ packet.meta.should == packet2.meta
74
+ packet.token.should == packet2.token
75
+ end
76
+
77
+ it "should dump/load as Marshalled ruby objects" do
78
+ packet = Nanite::FileEnd.new('0xdeadbeef', 'metadata')
79
+ packet2 = Marshal.load(Marshal.dump(packet))
80
+ packet.meta.should == packet2.meta
81
+ packet.token.should == packet2.token
82
+ end
83
+ end
84
+
85
+
86
+ describe "Packet: FileChunk" do
87
+ it "should dump/load as JSON objects" do
88
+ packet = Nanite::FileChunk.new('chunk','0xdeadbeef')
89
+ packet2 = JSON.parse(packet.to_json)
90
+ packet.chunk.should == packet2.chunk
91
+ packet.token.should == packet2.token
92
+ end
93
+
94
+ it "should dump/load as Marshalled ruby objects" do
95
+ packet = Nanite::FileChunk.new('chunk','0xdeadbeef')
96
+ packet2 = Marshal.load(Marshal.dump(packet))
97
+ packet.chunk.should == packet2.chunk
98
+ packet.token.should == packet2.token
99
+ end
100
+ end
101
+
102
+
103
+ describe "Packet: Request" do
104
+ it "should dump/load as JSON objects" do
105
+ packet = Nanite::Request.new('/some/foo', 'payload', :from => 'from', :token => '0xdeadbeef', :reply_to => 'reply_to')
106
+ packet2 = JSON.parse(packet.to_json)
107
+ packet.type.should == packet2.type
108
+ packet.payload.should == packet2.payload
109
+ packet.from.should == packet2.from
110
+ packet.token.should == packet2.token
111
+ packet.reply_to.should == packet2.reply_to
112
+ end
113
+
114
+ it "should dump/load as Marshalled ruby objects" do
115
+ packet = Nanite::Request.new('/some/foo', 'payload', :from => 'from', :token => '0xdeadbeef', :reply_to => 'reply_to')
116
+ packet2 = Marshal.load(Marshal.dump(packet))
117
+ packet.type.should == packet2.type
118
+ packet.payload.should == packet2.payload
119
+ packet.from.should == packet2.from
120
+ packet.token.should == packet2.token
121
+ packet.reply_to.should == packet2.reply_to
122
+ end
123
+ end
124
+
125
+
126
+ describe "Packet: Result" do
127
+ it "should dump/load as JSON objects" do
128
+ packet = Nanite::Result.new('0xdeadbeef', 'to', 'results', 'from')
129
+ packet2 = JSON.parse(packet.to_json)
130
+ packet.token.should == packet2.token
131
+ packet.to.should == packet2.to
132
+ packet.results.should == packet2.results
133
+ packet.from.should == packet2.from
134
+ end
135
+
136
+ it "should dump/load as Marshalled ruby objects" do
137
+ packet = Nanite::Result.new('0xdeadbeef', 'to', 'results', 'from')
138
+ packet2 = Marshal.load(Marshal.dump(packet))
139
+ packet.token.should == packet2.token
140
+ packet.to.should == packet2.to
141
+ packet.results.should == packet2.results
142
+ packet.from.should == packet2.from
143
+ end
144
+ end
145
+
146
+
147
+ describe "Packet: IntermediateMessage" do
148
+ it "should dump/load as JSON objects" do
149
+ packet = Nanite::IntermediateMessage.new('0xdeadbeef', 'to', 'from', 'messagekey', 'message')
150
+ packet2 = JSON.parse(packet.to_json)
151
+ packet.token.should == packet2.token
152
+ packet.to.should == packet2.to
153
+ packet.from.should == packet2.from
154
+ packet.messagekey.should == packet2.messagekey
155
+ packet.message.should == packet2.message
156
+ end
157
+
158
+ it "should dump/load as Marshalled ruby objects" do
159
+ packet = Nanite::IntermediateMessage.new('0xdeadbeef', 'to', 'from', 'messagekey', 'message')
160
+ packet2 = Marshal.load(Marshal.dump(packet))
161
+ packet.token.should == packet2.token
162
+ packet.to.should == packet2.to
163
+ packet.from.should == packet2.from
164
+ packet.messagekey.should == packet2.messagekey
165
+ packet.message.should == packet2.message
166
+ end
167
+ end
168
+
169
+
170
+ describe "Packet: Register" do
171
+ it "should dump/load as JSON objects" do
172
+ packet = Nanite::Register.new('0xdeadbeef', ['/foo/bar', '/nik/qux'], 0.8, ['foo'])
173
+ packet2 = JSON.parse(packet.to_json)
174
+ packet.identity.should == packet2.identity
175
+ packet.services.should == packet2.services
176
+ packet.status.should == packet2.status
177
+ end
178
+
179
+ it "should dump/load as Marshalled ruby objects" do
180
+ packet = Nanite::Register.new('0xdeadbeef', ['/foo/bar', '/nik/qux'], 0.8, ['foo'])
181
+ packet2 = Marshal.load(Marshal.dump(packet))
182
+ packet.identity.should == packet2.identity
183
+ packet.services.should == packet2.services
184
+ packet.status.should == packet2.status
185
+ end
186
+ end
187
+
188
+
189
+ describe "Packet: UnRegister" do
190
+ it "should dump/load as JSON objects" do
191
+ packet = Nanite::UnRegister.new('0xdeadbeef')
192
+ packet2 = JSON.parse(packet.to_json)
193
+ packet.identity.should == packet2.identity
194
+ end
195
+
196
+ it "should dump/load as Marshalled ruby objects" do
197
+ packet = Nanite::UnRegister.new('0xdeadbeef')
198
+ packet2 = Marshal.load(Marshal.dump(packet))
199
+ packet.identity.should == packet2.identity
200
+ end
201
+ end
202
+
203
+
204
+ describe "Packet: Ping" do
205
+ it "should dump/load as JSON objects" do
206
+ packet = Nanite::Ping.new('0xdeadbeef', 0.8)
207
+ packet2 = JSON.parse(packet.to_json)
208
+ packet.identity.should == packet2.identity
209
+ packet.status.should == packet2.status
210
+ end
211
+
212
+ it "should dump/load as Marshalled ruby objects" do
213
+ packet = Nanite::Ping.new('0xdeadbeef', 0.8)
214
+ packet2 = Marshal.load(Marshal.dump(packet))
215
+ packet.identity.should == packet2.identity
216
+ packet.status.should == packet2.status
217
+ end
218
+ end
@@ -0,0 +1,33 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::RsaKeyPair do
4
+
5
+ before(:all) do
6
+ @pair = Nanite::RsaKeyPair.new
7
+ end
8
+
9
+ it 'should create a private and a public keys' do
10
+ @pair.has_private?.should be_true
11
+ end
12
+
13
+ it 'should strip out private key in to_public' do
14
+ @pair.to_public.has_private?.should be_false
15
+ end
16
+
17
+ it 'should save' do
18
+ filename = File.join(File.dirname(__FILE__), "key.pem")
19
+ @pair.save(filename)
20
+ File.size(filename).should be > 0
21
+ File.delete(filename)
22
+ end
23
+
24
+ it 'should load' do
25
+ filename = File.join(File.dirname(__FILE__), "key.pem")
26
+ @pair.save(filename)
27
+ key = Nanite::RsaKeyPair.load(filename)
28
+ File.delete(filename)
29
+ key.should_not be_nil
30
+ key.data.should == @pair.data
31
+ end
32
+
33
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ module Nanite
4
+
5
+ # Add the ability to compare pings for test purposes
6
+ class Ping
7
+ def ==(other)
8
+ @status == other.status && @identity == other.identity
9
+ end
10
+ end
11
+
12
+ end
13
+
14
+ describe Nanite::SecureSerializer do
15
+
16
+ include SpecHelpers
17
+
18
+ before(:all) do
19
+ @certificate, @key = issue_cert
20
+ @store = Nanite::StaticCertificateStore.new(@certificate, @certificate)
21
+ @identity = "id"
22
+ @data = Nanite::Ping.new("Test", 0.5)
23
+ end
24
+
25
+ it 'should raise when not initialized' do
26
+ lambda { Nanite::SecureSerializer.dump(@data) }.should raise_error
27
+ end
28
+
29
+ it 'should deserialize signed data' do
30
+ Nanite::SecureSerializer.init(@identity, @certificate, @key, @store, false)
31
+ data = Nanite::SecureSerializer.dump(@data)
32
+ Nanite::SecureSerializer.load(data).should == @data
33
+ end
34
+
35
+ it 'should deserialize encrypted data' do
36
+ Nanite::SecureSerializer.init(@identity, @certificate, @key, @store, true)
37
+ data = Nanite::SecureSerializer.dump(@data)
38
+ Nanite::SecureSerializer.load(data).should == @data
39
+ end
40
+
41
+ end
@@ -0,0 +1,107 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::Serializer do
4
+
5
+ describe "Format" do
6
+
7
+ it "supports JSON format" do
8
+ [ :json, "json" ].each do |format|
9
+ serializer = Nanite::Serializer.new(format)
10
+ serializer.instance_eval { @serializers.first }.should == JSON
11
+ end
12
+ end
13
+
14
+ it "supports Marshal format" do
15
+ [ :marshal, "marshal" ].each do |format|
16
+ serializer = Nanite::Serializer.new(format)
17
+ serializer.instance_eval { @serializers.first }.should == Marshal
18
+ end
19
+ end
20
+
21
+ it "supports YAML format" do
22
+ [ :yaml, "yaml" ].each do |format|
23
+ serializer = Nanite::Serializer.new(format)
24
+ serializer.instance_eval { @serializers.first }.should == YAML
25
+ end
26
+ end
27
+
28
+ it "should default to Marshal format if not specified" do
29
+ serializer = Nanite::Serializer.new
30
+ serializer.instance_eval { @serializers.first }.should == Marshal
31
+ serializer = Nanite::Serializer.new(nil)
32
+ serializer.instance_eval { @serializers.first }.should == Marshal
33
+ end
34
+
35
+ end # Format
36
+
37
+ describe "Serialization of Packet" do
38
+
39
+ it "should cascade through available serializers" do
40
+ serializer = Nanite::Serializer.new
41
+ serializer.should_receive(:cascade_serializers).with(:dump, "hello")
42
+ serializer.dump("hello")
43
+ end
44
+
45
+ it "should try all three supported formats (JSON, Marshal, YAML)" do
46
+ JSON.should_receive(:dump).with("hello").and_raise(StandardError)
47
+ Marshal.should_receive(:dump).with("hello").and_raise(StandardError)
48
+ YAML.should_receive(:dump).with("hello").and_raise(StandardError)
49
+
50
+ lambda { Nanite::Serializer.new.dump("hello") }.should raise_error(Nanite::Serializer::SerializationError)
51
+ end
52
+
53
+ it "should raise SerializationError if packet could not be serialized" do
54
+ JSON.should_receive(:dump).with("hello").and_raise(StandardError)
55
+ Marshal.should_receive(:dump).with("hello").and_raise(StandardError)
56
+ YAML.should_receive(:dump).with("hello").and_raise(StandardError)
57
+
58
+ serializer = Nanite::Serializer.new
59
+ lambda { serializer.dump("hello") }.should raise_error(Nanite::Serializer::SerializationError)
60
+ end
61
+
62
+ it "should return serialized packet" do
63
+ serialized_packet = mock("Packet")
64
+ Marshal.should_receive(:dump).with("hello").and_return(serialized_packet)
65
+
66
+ serializer = Nanite::Serializer.new(:marshal)
67
+ serializer.dump("hello").should == serialized_packet
68
+ end
69
+
70
+ end # Serialization of Packet
71
+
72
+ describe "De-Serialization of Packet" do
73
+
74
+ it "should cascade through available serializers" do
75
+ serializer = Nanite::Serializer.new
76
+ serializer.should_receive(:cascade_serializers).with(:load, "olleh")
77
+ serializer.load("olleh")
78
+ end
79
+
80
+ it "should try all three supported formats (JSON, Marshal, YAML)" do
81
+ JSON.should_receive(:load).with("olleh").and_raise(StandardError)
82
+ Marshal.should_receive(:load).with("olleh").and_raise(StandardError)
83
+ YAML.should_receive(:load).with("olleh").and_raise(StandardError)
84
+
85
+ lambda { Nanite::Serializer.new.load("olleh") }.should raise_error(Nanite::Serializer::SerializationError)
86
+ end
87
+
88
+ it "should raise SerializationError if packet could not be de-serialized" do
89
+ JSON.should_receive(:load).with("olleh").and_raise(StandardError)
90
+ Marshal.should_receive(:load).with("olleh").and_raise(StandardError)
91
+ YAML.should_receive(:load).with("olleh").and_raise(StandardError)
92
+
93
+ serializer = Nanite::Serializer.new
94
+ lambda { serializer.load("olleh") }.should raise_error(Nanite::Serializer::SerializationError)
95
+ end
96
+
97
+ it "should return de-serialized packet" do
98
+ deserialized_packet = mock("Packet")
99
+ Marshal.should_receive(:load).with("olleh").and_return(deserialized_packet)
100
+
101
+ serializer = Nanite::Serializer.new(:marshal)
102
+ serializer.load("olleh").should == deserialized_packet
103
+ end
104
+
105
+ end # De-Serialization of Packet
106
+
107
+ end # Nanite::Serializer
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Nanite::Signature do
4
+
5
+ include SpecHelpers
6
+
7
+ before(:all) do
8
+ @test_data = "Test Data"
9
+ @cert, @key = issue_cert
10
+ @sig = Nanite::Signature.new(@test_data, @cert, @key)
11
+ end
12
+
13
+ it 'should create signed data' do
14
+ @sig.to_s.should_not be_empty
15
+ end
16
+
17
+ it 'should verify the signature' do
18
+ cert2, key2 = issue_cert
19
+
20
+ @sig.should be_a_match(@cert)
21
+ @sig.should_not be_a_match(cert2)
22
+ end
23
+
24
+ it 'should load from serialized signature' do
25
+ sig2 = Nanite::Signature.from_data(@sig.data)
26
+ sig2.should_not be_nil
27
+ sig2.should be_a_match(@cert)
28
+ end
29
+
30
+ end
@@ -0,0 +1,23 @@
1
+ $TESTING=true
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'rubygems'
5
+ require 'spec'
6
+ require 'nanite'
7
+
8
+ module SpecHelpers
9
+
10
+ # Create test certificate
11
+ def issue_cert
12
+ test_dn = { 'C' => 'US',
13
+ 'ST' => 'California',
14
+ 'L' => 'Santa Barbara',
15
+ 'O' => 'Nanite',
16
+ 'OU' => 'Certification Services',
17
+ 'CN' => 'Nanite test' }
18
+ dn = Nanite::DistinguishedName.new(test_dn)
19
+ key = Nanite::RsaKeyPair.new
20
+ [ Nanite::Certificate.new(key, dn, dn), key ]
21
+ end
22
+
23
+ end