rightscale-nanite 0.4.1.2 → 0.4.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +4 -3
- data/bin/nanite-agent +5 -0
- data/lib/nanite/actor.rb +12 -1
- data/lib/nanite/agent.rb +12 -7
- data/lib/nanite/amqp.rb +10 -3
- data/lib/nanite/cluster.rb +18 -14
- data/lib/nanite/config.rb +11 -2
- data/lib/nanite/dispatcher.rb +3 -2
- data/lib/nanite/local_state.rb +2 -2
- data/lib/nanite/log.rb +19 -18
- data/lib/nanite/mapper.rb +30 -10
- data/lib/nanite/mapper_proxy.rb +11 -1
- data/lib/nanite/packets.rb +8 -13
- data/lib/nanite/security/encrypted_document.rb +1 -1
- data/lib/nanite/security/secure_serializer.rb +1 -0
- data/lib/nanite/security/signature.rb +7 -1
- data/lib/nanite/state.rb +1 -1
- data/lib/nanite/util.rb +23 -16
- data/lib/nanite.rb +5 -2
- data/spec/actor_registry_spec.rb +16 -18
- data/spec/actor_spec.rb +38 -20
- data/spec/agent_spec.rb +6 -1
- data/spec/cluster_spec.rb +23 -9
- data/spec/log_spec.rb +49 -0
- data/spec/mapper_proxy_spec.rb +72 -0
- data/spec/mapper_spec.rb +70 -0
- data/spec/nanite_spec.rb +36 -0
- data/spec/packet_spec.rb +8 -6
- data/spec/spec_helper.rb +1 -4
- metadata +5 -1
data/Rakefile
CHANGED
@@ -8,9 +8,9 @@ rescue LoadError
|
|
8
8
|
require 'rake/rdoctask'
|
9
9
|
end
|
10
10
|
require 'rake/clean'
|
11
|
+
require 'lib/nanite'
|
11
12
|
|
12
13
|
GEM = "nanite"
|
13
|
-
VER = "0.4.1"
|
14
14
|
AUTHOR = "Ezra Zygmuntowicz"
|
15
15
|
EMAIL = "ezra@engineyard.com"
|
16
16
|
HOMEPAGE = "http://github.com/ezmobius/nanite"
|
@@ -19,8 +19,9 @@ SUMMARY = "self assembling fabric of ruby daemons"
|
|
19
19
|
Dir.glob('tasks/*.rake').each { |r| Rake.application.add_import r }
|
20
20
|
|
21
21
|
spec = Gem::Specification.new do |s|
|
22
|
+
|
22
23
|
s.name = GEM
|
23
|
-
s.version = ::
|
24
|
+
s.version = Nanite::VERSION
|
24
25
|
s.platform = Gem::Platform::RUBY
|
25
26
|
s.has_rdoc = true
|
26
27
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE", 'TODO']
|
@@ -46,7 +47,7 @@ end
|
|
46
47
|
task :default => :spec
|
47
48
|
|
48
49
|
task :install => [:package] do
|
49
|
-
sh %{sudo gem install pkg/#{GEM}-#{
|
50
|
+
sh %{sudo gem install pkg/#{GEM}-#{Nanite::VERSION}}
|
50
51
|
end
|
51
52
|
|
52
53
|
desc "Run unit specs"
|
data/bin/nanite-agent
CHANGED
@@ -37,6 +37,11 @@ opts = OptionParser.new do |opts|
|
|
37
37
|
opts.on("--single-threaded", "Run all operations in one thread") do
|
38
38
|
options[:single_threaded] = true
|
39
39
|
end
|
40
|
+
|
41
|
+
opts.on("--threadpool COUNT", Integer, "Number of threads to run all operations in") do |tps|
|
42
|
+
options[:threadpool_size] = tps
|
43
|
+
end
|
44
|
+
|
40
45
|
end
|
41
46
|
|
42
47
|
opts.parse!
|
data/lib/nanite/actor.rb
CHANGED
@@ -35,7 +35,14 @@ module Nanite
|
|
35
35
|
|
36
36
|
def provides_for(prefix)
|
37
37
|
return [] unless @exposed
|
38
|
-
@exposed.
|
38
|
+
@exposed.select do |meth|
|
39
|
+
if instance_methods.include?(meth.to_s) or instance_methods.include?(meth.to_sym)
|
40
|
+
true
|
41
|
+
else
|
42
|
+
Nanite::Log.warn("Exposing non-existing method #{meth} in actor #{name}")
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end.map {|meth| "/#{prefix}/#{meth}".squeeze('/')}
|
39
46
|
end
|
40
47
|
|
41
48
|
def on_exception(proc = nil, &blk)
|
@@ -54,6 +61,10 @@ module Nanite
|
|
54
61
|
def request(*args, &blk)
|
55
62
|
MapperProxy.instance.request(*args, &blk)
|
56
63
|
end
|
64
|
+
|
65
|
+
def push(*args)
|
66
|
+
MapperProxy.instance.push(*args)
|
67
|
+
end
|
57
68
|
end # InstanceMethods
|
58
69
|
|
59
70
|
end # Actor
|
data/lib/nanite/agent.rb
CHANGED
@@ -8,8 +8,11 @@ module Nanite
|
|
8
8
|
attr_reader :identity, :options, :serializer, :dispatcher, :registry, :amq, :tags
|
9
9
|
attr_accessor :status_proc
|
10
10
|
|
11
|
-
DEFAULT_OPTIONS = COMMON_DEFAULT_OPTIONS.merge({
|
12
|
-
:
|
11
|
+
DEFAULT_OPTIONS = COMMON_DEFAULT_OPTIONS.merge({
|
12
|
+
:user => 'nanite',
|
13
|
+
:ping_time => 15,
|
14
|
+
:default_services => []
|
15
|
+
}) unless defined?(DEFAULT_OPTIONS)
|
13
16
|
|
14
17
|
# Initializes a new agent and establishes AMQP connection.
|
15
18
|
# This must be used inside EM.run block or if EventMachine reactor
|
@@ -54,6 +57,8 @@ module Nanite
|
|
54
57
|
#
|
55
58
|
# single_threaded: Run all operations in one thread
|
56
59
|
#
|
60
|
+
# threadpool_size: Number of threads to run operations in
|
61
|
+
#
|
57
62
|
# Connection options:
|
58
63
|
#
|
59
64
|
# vhost : AMQP broker vhost that should be used
|
@@ -94,7 +99,7 @@ module Nanite
|
|
94
99
|
Log.init(@identity, log_path)
|
95
100
|
Log.level = @options[:log_level] if @options[:log_level]
|
96
101
|
@serializer = Serializer.new(@options[:format])
|
97
|
-
@status_proc = lambda { parse_uptime(`uptime`) rescue 'no status' }
|
102
|
+
@status_proc = lambda { parse_uptime(`uptime 2> /dev/null`) rescue 'no status' }
|
98
103
|
pid_file = PidFile.new(@identity, @options)
|
99
104
|
pid_file.check
|
100
105
|
if @options[:daemonize]
|
@@ -169,7 +174,7 @@ module Nanite
|
|
169
174
|
Nanite::Log.debug("RECV #{packet.to_s}")
|
170
175
|
case packet
|
171
176
|
when Advertise
|
172
|
-
Nanite::Log.info("RECV #{packet.to_s}") unless Nanite::Log.level ==
|
177
|
+
Nanite::Log.info("RECV #{packet.to_s}") unless Nanite::Log.level == :debug
|
173
178
|
advertise_services
|
174
179
|
when Request, Push
|
175
180
|
if @security && !@security.authorize(packet)
|
@@ -179,14 +184,14 @@ module Nanite
|
|
179
184
|
amq.queue(packet.reply_to, :no_declare => options[:secure]).publish(serializer.dump(r))
|
180
185
|
end
|
181
186
|
else
|
182
|
-
Nanite::Log.info("RECV #{packet.to_s([:from, :tags])}") unless Nanite::Log.level ==
|
187
|
+
Nanite::Log.info("RECV #{packet.to_s([:from, :tags])}") unless Nanite::Log.level == :debug
|
183
188
|
dispatcher.dispatch(packet)
|
184
189
|
end
|
185
190
|
when Result
|
186
|
-
Nanite::Log.info("RECV #{packet.to_s([])}") unless Nanite::Log.level ==
|
191
|
+
Nanite::Log.info("RECV #{packet.to_s([])}") unless Nanite::Log.level == :debug
|
187
192
|
@mapper_proxy.handle_result(packet)
|
188
193
|
when IntermediateMessage
|
189
|
-
Nanite::Log.info("RECV #{packet.to_s([])}") unless Nanite::Log.level ==
|
194
|
+
Nanite::Log.info("RECV #{packet.to_s([])}") unless Nanite::Log.level == :debug
|
190
195
|
@mapper_proxy.handle_intermediate_result(packet)
|
191
196
|
end
|
192
197
|
end
|
data/lib/nanite/amqp.rb
CHANGED
@@ -39,9 +39,16 @@ end
|
|
39
39
|
module Nanite
|
40
40
|
module AMQPHelper
|
41
41
|
def start_amqp(options)
|
42
|
-
connection = AMQP.connect(
|
43
|
-
:
|
42
|
+
connection = AMQP.connect({
|
43
|
+
:user => options[:user],
|
44
|
+
:pass => options[:pass],
|
45
|
+
:vhost => options[:vhost],
|
46
|
+
:host => options[:host],
|
47
|
+
:port => (options[:port] || ::AMQP::PORT).to_i,
|
48
|
+
:insist => options[:insist] || false,
|
49
|
+
:retry => options[:retry] || 5
|
50
|
+
})
|
44
51
|
MQ.new(connection)
|
45
52
|
end
|
46
53
|
end
|
47
|
-
end
|
54
|
+
end
|
data/lib/nanite/cluster.rb
CHANGED
@@ -87,22 +87,26 @@ module Nanite
|
|
87
87
|
# forward request coming from agent
|
88
88
|
def handle_request(request)
|
89
89
|
if @security.authorize_request(request)
|
90
|
-
Nanite::Log.info("RECV #{request.to_s([:from, :target, :tags])}") unless Nanite::Log.level ==
|
90
|
+
Nanite::Log.info("RECV #{request.to_s([:from, :target, :tags])}") unless Nanite::Log.level == :debug
|
91
91
|
Nanite::Log.debug("RECV #{request.to_s}")
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
case request
|
93
|
+
when Push
|
94
|
+
mapper.send_push(request)
|
95
|
+
else
|
96
|
+
intm_handler = lambda do |result, job|
|
97
|
+
result = IntermediateMessage.new(request.token, job.request.from, mapper.identity, nil, result)
|
98
|
+
forward_response(result, request.persistent)
|
99
|
+
end
|
97
100
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
101
|
+
result = Result.new(request.token, request.from, nil, mapper.identity)
|
102
|
+
ok = mapper.send_request(request, :intermediate_handler => intm_handler) do |res|
|
103
|
+
result.results = res
|
104
|
+
forward_response(result, request.persistent)
|
105
|
+
end
|
106
|
+
|
107
|
+
if ok == false
|
108
|
+
forward_response(result, request.persistent)
|
109
|
+
end
|
106
110
|
end
|
107
111
|
else
|
108
112
|
Nanite::Log.warn("RECV NOT AUTHORIZED #{request.to_s}")
|
data/lib/nanite/config.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module Nanite
|
2
2
|
|
3
|
-
COMMON_DEFAULT_OPTIONS = {
|
4
|
-
:
|
3
|
+
COMMON_DEFAULT_OPTIONS = {
|
4
|
+
:pass => 'testing',
|
5
|
+
:vhost => '/nanite',
|
6
|
+
:secure => false,
|
7
|
+
:host => '0.0.0.0',
|
8
|
+
:log_level => :info,
|
9
|
+
:format => :marshal,
|
10
|
+
:daemonize => false,
|
11
|
+
:console => false,
|
12
|
+
:root => Dir.pwd
|
13
|
+
}
|
5
14
|
|
6
15
|
module CommonConfig
|
7
16
|
def setup_mapper_options(opts, options)
|
data/lib/nanite/dispatcher.rb
CHANGED
@@ -10,6 +10,7 @@ module Nanite
|
|
10
10
|
@identity = identity
|
11
11
|
@options = options
|
12
12
|
@evmclass = EM
|
13
|
+
@evmclass.threadpool_size = (@options[:threadpool_size] || 20).to_i
|
13
14
|
end
|
14
15
|
|
15
16
|
def dispatch(deliverable)
|
@@ -37,7 +38,7 @@ module Nanite
|
|
37
38
|
r # For unit tests
|
38
39
|
end
|
39
40
|
|
40
|
-
if @options[:single_threaded]
|
41
|
+
if @options[:single_threaded] || @options[:thread_poolsize] == 1
|
41
42
|
@evmclass.next_tick { callback.call(operation.call) }
|
42
43
|
else
|
43
44
|
@evmclass.defer(operation, callback)
|
@@ -88,4 +89,4 @@ module Nanite
|
|
88
89
|
error
|
89
90
|
end
|
90
91
|
end
|
91
|
-
end
|
92
|
+
end
|
data/lib/nanite/local_state.rb
CHANGED
@@ -18,10 +18,10 @@ module Nanite
|
|
18
18
|
tags = tags.dup.flatten
|
19
19
|
nanites = select { |name, state| state[:services].include?(service) }
|
20
20
|
unless tags.empty?
|
21
|
-
nanites.select { |a| !(
|
21
|
+
nanites.select { |a, b| !(b[:tags] & tags).empty? }
|
22
22
|
else
|
23
23
|
nanites
|
24
|
-
end
|
24
|
+
end.to_a
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
data/lib/nanite/log.rb
CHANGED
@@ -6,6 +6,13 @@ module Nanite
|
|
6
6
|
class Log
|
7
7
|
|
8
8
|
@logger = nil
|
9
|
+
|
10
|
+
# Map log levels symbols to values
|
11
|
+
LEVELS = { :debug => Logger::DEBUG,
|
12
|
+
:info => Logger::INFO,
|
13
|
+
:warn => Logger::WARN,
|
14
|
+
:error => Logger::ERROR,
|
15
|
+
:fatal => Logger::FATAL }
|
9
16
|
|
10
17
|
class << self
|
11
18
|
attr_accessor :logger, :level, :file #:nodoc
|
@@ -21,31 +28,25 @@ module Nanite
|
|
21
28
|
end
|
22
29
|
@logger = Logger.new(file)
|
23
30
|
@logger.formatter = Nanite::Log::Formatter.new
|
24
|
-
level =
|
31
|
+
Log.level = :info
|
25
32
|
end
|
26
33
|
|
27
34
|
# Sets the level for the Logger by symbol or by command line argument.
|
28
35
|
# Throws an ArgumentError if you feed it a bogus log level (that is not
|
29
|
-
# one of :debug, :info, :warn, :error, :fatal or the corresponding strings)
|
36
|
+
# one of :debug, :info, :warn, :error, :fatal or the corresponding strings or a valid Logger level)
|
30
37
|
def level=(loglevel)
|
31
38
|
init() unless @logger
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@logger.level = Logger::INFO
|
40
|
-
when :warn
|
41
|
-
@logger.level = Logger::WARN
|
42
|
-
when :error
|
43
|
-
@logger.level = Logger::ERROR
|
44
|
-
when :fatal
|
45
|
-
@logger.level = Logger::FATAL
|
46
|
-
else
|
47
|
-
raise ArgumentError, "Log level must be one of :debug, :info, :warn, :error, or :fatal"
|
39
|
+
lvl = case loglevel
|
40
|
+
when String then loglevel.intern
|
41
|
+
when Integer then LEVELS.invert[loglevel]
|
42
|
+
else loglevel
|
43
|
+
end
|
44
|
+
unless LEVELS.include?(lvl)
|
45
|
+
raise(ArgumentError, 'Log level must be one of :debug, :info, :warn, :error, or :fatal')
|
48
46
|
end
|
47
|
+
@logger.info("[setup] setting log level to #{lvl.to_s.upcase}")
|
48
|
+
@level = lvl
|
49
|
+
@logger.level = LEVELS[lvl]
|
49
50
|
end
|
50
51
|
|
51
52
|
# Passes any other method calls on directly to the underlying Logger object created with init. If
|
data/lib/nanite/mapper.rb
CHANGED
@@ -23,9 +23,15 @@ module Nanite
|
|
23
23
|
|
24
24
|
attr_reader :cluster, :identity, :job_warden, :options, :serializer, :amq
|
25
25
|
|
26
|
-
DEFAULT_OPTIONS = COMMON_DEFAULT_OPTIONS.merge({
|
27
|
-
:
|
28
|
-
:
|
26
|
+
DEFAULT_OPTIONS = COMMON_DEFAULT_OPTIONS.merge({
|
27
|
+
:user => 'mapper',
|
28
|
+
:identity => Identity.generate,
|
29
|
+
:agent_timeout => 15,
|
30
|
+
:offline_redelivery_frequency => 10,
|
31
|
+
:persistent => false,
|
32
|
+
:offline_failsafe => false,
|
33
|
+
:callbacks => {}
|
34
|
+
}) unless defined?(DEFAULT_OPTIONS)
|
29
35
|
|
30
36
|
# Initializes a new mapper and establishes
|
31
37
|
# AMQP connection. This must be used inside EM.run block or if EventMachine reactor
|
@@ -66,9 +72,15 @@ module Nanite
|
|
66
72
|
#
|
67
73
|
# persistent : true instructs the AMQP broker to save messages to persistent storage so that they aren't lost when the
|
68
74
|
# broker is restarted. Default is false. Can be overriden on a per-message basis using the request and push methods.
|
69
|
-
#
|
75
|
+
#
|
70
76
|
# secure : use Security features of rabbitmq to restrict nanites to themselves
|
71
77
|
#
|
78
|
+
# prefetch : Sets prefetch (only supported in RabbitMQ >= 1.6)
|
79
|
+
# callbacks : A set of callbacks to have code executed on specific events, supported events are :register,
|
80
|
+
# :unregister and :timeout. Parameter must be a hash with the corresponding events as keys and
|
81
|
+
# a block as value. The block will get the corresponding nanite's identity and a copy of the
|
82
|
+
# mapper
|
83
|
+
#
|
72
84
|
# Connection options:
|
73
85
|
#
|
74
86
|
# vhost : AMQP broker vhost that should be used
|
@@ -106,7 +118,7 @@ module Nanite
|
|
106
118
|
@options[:file_root] ||= File.join(@options[:root], 'files')
|
107
119
|
@options.freeze
|
108
120
|
end
|
109
|
-
|
121
|
+
|
110
122
|
def run
|
111
123
|
setup_logging
|
112
124
|
@serializer = Serializer.new(@options[:format])
|
@@ -187,7 +199,7 @@ module Nanite
|
|
187
199
|
false
|
188
200
|
end
|
189
201
|
end
|
190
|
-
|
202
|
+
|
191
203
|
# Make a nanite request which does not expect a response.
|
192
204
|
#
|
193
205
|
# ==== Parameters
|
@@ -210,6 +222,10 @@ module Nanite
|
|
210
222
|
# @api :public:
|
211
223
|
def push(type, payload = '', opts = {})
|
212
224
|
push = build_deliverable(Push, type, payload, opts)
|
225
|
+
send_push(push, opts)
|
226
|
+
end
|
227
|
+
|
228
|
+
def send_push(push, opts = {})
|
213
229
|
targets = cluster.targets_for(push)
|
214
230
|
if !targets.empty?
|
215
231
|
cluster.route(push, targets)
|
@@ -221,7 +237,7 @@ module Nanite
|
|
221
237
|
false
|
222
238
|
end
|
223
239
|
end
|
224
|
-
|
240
|
+
|
225
241
|
private
|
226
242
|
|
227
243
|
def build_deliverable(deliverable_type, type, payload, opts)
|
@@ -233,6 +249,10 @@ module Nanite
|
|
233
249
|
end
|
234
250
|
|
235
251
|
def setup_queues
|
252
|
+
if amq.respond_to?(:prefetch) && @options.has_key?(:prefetch)
|
253
|
+
amq.prefetch(@options[:prefetch])
|
254
|
+
end
|
255
|
+
|
236
256
|
setup_offline_queue
|
237
257
|
setup_message_queue
|
238
258
|
end
|
@@ -264,14 +284,14 @@ module Nanite
|
|
264
284
|
begin
|
265
285
|
msg = serializer.load(msg)
|
266
286
|
Nanite::Log.debug("RECV #{msg.to_s}")
|
267
|
-
Nanite::Log.info("RECV #{msg.to_s([:from])}") unless Nanite::Log.level ==
|
287
|
+
Nanite::Log.info("RECV #{msg.to_s([:from])}") unless Nanite::Log.level == :debug
|
268
288
|
job_warden.process(msg)
|
269
289
|
rescue Exception => e
|
270
290
|
Nanite::Log.error("RECV [result] #{e.message}")
|
271
291
|
end
|
272
292
|
end
|
273
293
|
end
|
274
|
-
|
294
|
+
|
275
295
|
def setup_logging
|
276
296
|
log_path = false
|
277
297
|
if @options[:daemonize]
|
@@ -280,7 +300,7 @@ module Nanite
|
|
280
300
|
Nanite::Log.init(@identity, log_path)
|
281
301
|
Nanite::Log.level = @options[:log_level] if @options[:log_level]
|
282
302
|
end
|
283
|
-
|
303
|
+
|
284
304
|
def setup_cluster
|
285
305
|
@cluster = Cluster.new(@amq, @options[:agent_timeout], @options[:identity], @serializer, self, @options[:redis], @options[:callbacks])
|
286
306
|
end
|
data/lib/nanite/mapper_proxy.rb
CHANGED
@@ -16,7 +16,7 @@ module Nanite
|
|
16
16
|
|
17
17
|
# Accessor for actor
|
18
18
|
def self.instance
|
19
|
-
@@instance
|
19
|
+
@@instance if defined?(@@instance)
|
20
20
|
end
|
21
21
|
|
22
22
|
def initialize(id, opts)
|
@@ -40,6 +40,16 @@ module Nanite
|
|
40
40
|
Nanite::Log.info("SEND #{request.to_s([:tags, :target])}")
|
41
41
|
amqp.fanout('request', :no_declare => options[:secure]).publish(serializer.dump(request))
|
42
42
|
end
|
43
|
+
|
44
|
+
def push(type, payload = '', opts = {})
|
45
|
+
raise "Mapper proxy not initialized" unless identity && options
|
46
|
+
push = Push.new(type, payload, opts)
|
47
|
+
push.from = identity
|
48
|
+
push.token = Identity.generate
|
49
|
+
push.persistent = opts.key?(:persistent) ? opts[:persistent] : options[:persistent]
|
50
|
+
Nanite::Log.info("SEND #{push.to_s([:tags, :target])}")
|
51
|
+
amqp.fanout('request', :no_declare => options[:secure]).publish(serializer.dump(push))
|
52
|
+
end
|
43
53
|
|
44
54
|
# Handle intermediary result
|
45
55
|
def handle_intermediate_result(res)
|
data/lib/nanite/packets.rb
CHANGED
@@ -12,7 +12,7 @@ module Nanite
|
|
12
12
|
def to_json(*a)
|
13
13
|
js = {
|
14
14
|
'json_class' => self.class.name,
|
15
|
-
'data' => instance_variables.inject({}) {|m,ivar| m[ivar.sub(/@/,'')] = instance_variable_get(ivar); m }
|
15
|
+
'data' => instance_variables.inject({}) {|m,ivar| m[ivar.to_s.sub(/@/,'')] = instance_variable_get(ivar); m }
|
16
16
|
}.to_json(*a)
|
17
17
|
js = js.chop + ",\"size\":#{js.size}}"
|
18
18
|
js
|
@@ -37,11 +37,6 @@ module Nanite
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
# Wrap given string to given maximum number of characters per line
|
41
|
-
def wrap(txt, col=120)
|
42
|
-
txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n").chomp
|
43
|
-
end
|
44
|
-
|
45
40
|
end
|
46
41
|
|
47
42
|
# packet that means start of a file transfer
|
@@ -63,7 +58,7 @@ module Nanite
|
|
63
58
|
end
|
64
59
|
|
65
60
|
def to_s
|
66
|
-
|
61
|
+
"#{super} <#{token}> #{filename} to #{dest}"
|
67
62
|
end
|
68
63
|
end
|
69
64
|
|
@@ -85,7 +80,7 @@ module Nanite
|
|
85
80
|
end
|
86
81
|
|
87
82
|
def to_s
|
88
|
-
|
83
|
+
"#{super} <#{token}> meta #{meta}"
|
89
84
|
end
|
90
85
|
end
|
91
86
|
|
@@ -158,7 +153,7 @@ module Nanite
|
|
158
153
|
log_msg += ", reply_to #{id_to_s(reply_to)}" if reply_to && (filter.nil? || filter.include?(:reply_to))
|
159
154
|
log_msg += ", tags #{tags.inspect}" if tags && !tags.empty? && (filter.nil? || filter.include?(:tags))
|
160
155
|
log_msg += ", payload #{payload.inspect}" if filter.nil? || filter.include?(:payload)
|
161
|
-
|
156
|
+
log_msg
|
162
157
|
end
|
163
158
|
|
164
159
|
end
|
@@ -207,7 +202,7 @@ module Nanite
|
|
207
202
|
log_msg += ", target #{id_to_s(target)}" if target && (filter.nil? || filter.include?(:target))
|
208
203
|
log_msg += ", tags #{tags.inspect}" if tags && !tags.empty? && (filter.nil? || filter.include?(:tags))
|
209
204
|
log_msg += ", payload #{payload.inspect}" if filter.nil? || filter.include?(:payload)
|
210
|
-
|
205
|
+
log_msg
|
211
206
|
end
|
212
207
|
end
|
213
208
|
|
@@ -239,7 +234,7 @@ module Nanite
|
|
239
234
|
log_msg += " from #{id_to_s(from)}" if filter.nil? || filter.include?(:from)
|
240
235
|
log_msg += " to #{id_to_s(to)}" if filter.nil? || filter.include?(:to)
|
241
236
|
log_msg += " results: #{results.inspect}" if filter.nil? || filter.include?(:results)
|
242
|
-
|
237
|
+
log_msg
|
243
238
|
end
|
244
239
|
end
|
245
240
|
|
@@ -269,7 +264,7 @@ module Nanite
|
|
269
264
|
end
|
270
265
|
|
271
266
|
def to_s
|
272
|
-
|
267
|
+
"#{super} <#{token}> from #{id_to_s(from)}, key #{messagekey}"
|
273
268
|
end
|
274
269
|
end
|
275
270
|
|
@@ -300,7 +295,7 @@ module Nanite
|
|
300
295
|
log_msg = "#{super} #{id_to_s(identity)}"
|
301
296
|
log_msg += ", services: #{services.join(', ')}" if services && !services.empty?
|
302
297
|
log_msg += ", tags: #{tags.join(', ')}" if tags && !tags.empty?
|
303
|
-
|
298
|
+
log_msg
|
304
299
|
end
|
305
300
|
end
|
306
301
|
|
@@ -25,7 +25,7 @@ module Nanite
|
|
25
25
|
# Initialize from encrypted data.
|
26
26
|
def self.from_data(encrypted_data)
|
27
27
|
doc = EncryptedDocument.allocate
|
28
|
-
doc.instance_variable_set(:@pkcs7,
|
28
|
+
doc.instance_variable_set(:@pkcs7, Nanite::PKCS7.new(encrypted_data))
|
29
29
|
doc
|
30
30
|
end
|
31
31
|
|
@@ -51,6 +51,7 @@ module Nanite
|
|
51
51
|
data = JSON.load(json)
|
52
52
|
sig = Signature.from_data(data['signature'])
|
53
53
|
certs = @store.get_signer(data['id'])
|
54
|
+
raise "Could not find a cert for signer #{data['id']}" unless certs
|
54
55
|
certs = [ certs ] unless certs.respond_to?(:each)
|
55
56
|
jsn = data['data'] if certs.any? { |c| sig.match?(c) }
|
56
57
|
if jsn && @encrypt && data['encrypted']
|
@@ -1,3 +1,9 @@
|
|
1
|
+
if defined?(OpenSSL::PKCS7::PKCS7)
|
2
|
+
Nanite::PKCS7 = OpenSSL::PKCS7::PKCS7
|
3
|
+
else
|
4
|
+
Nanite::PKCS7 = OpenSSL::PKCS7
|
5
|
+
end
|
6
|
+
|
1
7
|
module Nanite
|
2
8
|
|
3
9
|
# Signature that can be validated against certificates
|
@@ -20,7 +26,7 @@ module Nanite
|
|
20
26
|
# Load signature previously serialized via 'data'
|
21
27
|
def self.from_data(data)
|
22
28
|
sig = Signature.allocate
|
23
|
-
sig.instance_variable_set(:@p7,
|
29
|
+
sig.instance_variable_set(:@p7, Nanite::PKCS7.new(data))
|
24
30
|
sig.instance_variable_set(:@store, OpenSSL::X509::Store.new)
|
25
31
|
sig
|
26
32
|
end
|
data/lib/nanite/state.rb
CHANGED
data/lib/nanite/util.rb
CHANGED
@@ -30,22 +30,29 @@ class String
|
|
30
30
|
end
|
31
31
|
|
32
32
|
class Object
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
unless defined? instance_exec # 1.9 and 1.8.7
|
34
|
+
module InstanceExecHelper; end
|
35
|
+
include InstanceExecHelper
|
36
|
+
|
37
|
+
# Evaluate the block with the given arguments within the context of
|
38
|
+
# this object, so self is set to the method receiver.
|
39
|
+
#
|
40
|
+
# From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
|
41
|
+
def instance_exec(*args, &block)
|
42
|
+
begin
|
43
|
+
old_critical, Thread.critical = Thread.critical, true
|
44
|
+
n = 0
|
45
|
+
n += 1 while respond_to?(method_name = "__instance_exec#{n}")
|
46
|
+
InstanceExecMethods.module_eval { define_method(method_name, &block) }
|
47
|
+
ensure
|
48
|
+
Thread.critical = old_critical
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
send(method_name, *args)
|
53
|
+
ensure
|
54
|
+
InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
|
55
|
+
end
|
48
56
|
end
|
49
|
-
ret
|
50
57
|
end
|
51
58
|
end
|
data/lib/nanite.rb
CHANGED
@@ -39,7 +39,7 @@ require 'nanite/security/static_certificate_store'
|
|
39
39
|
require 'nanite/serializer'
|
40
40
|
|
41
41
|
module Nanite
|
42
|
-
VERSION = '0.4.
|
42
|
+
VERSION = '0.4.1.3' unless defined?(Nanite::VERSION)
|
43
43
|
|
44
44
|
class MapperNotRunning < StandardError; end
|
45
45
|
|
@@ -65,7 +65,10 @@ module Nanite
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def ensure_mapper
|
68
|
-
|
68
|
+
@mapper ||= MapperProxy.instance
|
69
|
+
unless @mapper
|
70
|
+
raise MapperNotRunning.new('A mapper needs to be started via Nanite.start_mapper')
|
71
|
+
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
end
|
data/spec/actor_registry_spec.rb
CHANGED
@@ -2,30 +2,28 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
2
2
|
|
3
3
|
describe Nanite::ActorRegistry do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
expose :import, :cancel
|
5
|
+
class ::WebDocumentImporter
|
6
|
+
include Nanite::Actor
|
7
|
+
expose :import, :cancel
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
9
|
+
def import
|
10
|
+
1
|
11
|
+
end
|
12
|
+
def cancel
|
13
|
+
0
|
16
14
|
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
17
|
+
module ::Actors
|
18
|
+
class ComedyActor
|
19
|
+
include Nanite::Actor
|
20
|
+
expose :fun_tricks
|
21
|
+
def fun_tricks
|
22
|
+
:rabbit_in_the_hat
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
28
|
-
|
26
|
+
|
29
27
|
before(:each) do
|
30
28
|
Nanite::Log.stub!(:info)
|
31
29
|
@registry = Nanite::ActorRegistry.new
|
data/spec/actor_spec.rb
CHANGED
@@ -1,33 +1,46 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
describe Nanite::Actor do
|
4
|
+
class ::WebDocumentImporter
|
5
|
+
include Nanite::Actor
|
6
|
+
expose :import, :cancel
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
def import
|
9
|
+
1
|
10
|
+
end
|
11
|
+
def cancel
|
12
|
+
0
|
13
|
+
end
|
14
|
+
def continue
|
15
|
+
1
|
16
|
+
end
|
15
17
|
end
|
16
|
-
end
|
17
18
|
|
18
|
-
module Actors
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
24
26
|
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
+
class ::Actors::InvalidActor
|
30
|
+
include Nanite::Actor
|
31
|
+
expose :non_existing
|
32
|
+
end
|
29
33
|
|
30
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
|
+
|
31
44
|
it "should single expose method only once" do
|
32
45
|
3.times { WebDocumentImporter.expose(:continue) }
|
33
46
|
WebDocumentImporter.provides_for("webfiles").should == ["/webfiles/import", "/webfiles/cancel", "/webfiles/continue"]
|
@@ -45,6 +58,7 @@ describe Nanite::Actor do
|
|
45
58
|
before :each do
|
46
59
|
@provides = Actors::ComedyActor.provides_for("money")
|
47
60
|
end
|
61
|
+
|
48
62
|
it "returns an array" do
|
49
63
|
@provides.should be_kind_of(Array)
|
50
64
|
end
|
@@ -55,5 +69,9 @@ describe Nanite::Actor do
|
|
55
69
|
wdi_provides.should include("/webfiles/import")
|
56
70
|
wdi_provides.should include("/webfiles/cancel")
|
57
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
|
58
76
|
end
|
59
77
|
end
|
data/spec/agent_spec.rb
CHANGED
@@ -186,7 +186,12 @@ describe "Agent:" do
|
|
186
186
|
agent.tags.should include("sample_tag_1")
|
187
187
|
agent.tags.should include("sample_tag_2")
|
188
188
|
end
|
189
|
-
|
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
|
+
|
190
195
|
end
|
191
196
|
|
192
197
|
describe "Security" do
|
data/spec/cluster_spec.rb
CHANGED
@@ -94,17 +94,23 @@ describe Nanite::Cluster do
|
|
94
94
|
end # Reaper
|
95
95
|
|
96
96
|
describe "State" do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
cluster.nanites.instance_of?(Nanite::LocalState).should == true
|
97
|
+
begin
|
98
|
+
require 'nanite/state'
|
99
|
+
rescue LoadError
|
101
100
|
end
|
101
|
+
|
102
|
+
if defined?(Redis)
|
103
|
+
it "should use a local state by default" do
|
104
|
+
cluster = Nanite::Cluster.new(@amq, 443, "the_identity", @serializer, @mapper)
|
105
|
+
cluster.nanites.instance_of?(Nanite::LocalState).should == true
|
106
|
+
end
|
102
107
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
+
it "should set up a redis state when requested" do
|
109
|
+
state = Nanite::State.new("")
|
110
|
+
Nanite::State.should_receive(:new).with("localhost:1234").and_return(state)
|
111
|
+
cluster = Nanite::Cluster.new(@amq, 443, "the_identity", @serializer, @mapper, "localhost:1234")
|
112
|
+
cluster.nanites.instance_of?(Nanite::State).should == true
|
113
|
+
end
|
108
114
|
end
|
109
115
|
end
|
110
116
|
end # Intialization
|
@@ -410,6 +416,14 @@ describe Nanite::Cluster do
|
|
410
416
|
@cluster_with_target.should_receive(:forward_response)
|
411
417
|
@cluster_with_target.__send__(:handle_request, @request_with_target)
|
412
418
|
end
|
419
|
+
|
420
|
+
describe "when getting push requests from an agent" do
|
421
|
+
it "should send the push message through the mapper" do
|
422
|
+
push = Nanite::Push.new(nil, nil)
|
423
|
+
@mapper_with_target.should_receive(:send_push).with(push)
|
424
|
+
@cluster_with_target.__send__(:handle_request, push)
|
425
|
+
end
|
426
|
+
end
|
413
427
|
end # Agent Request Handling
|
414
428
|
|
415
429
|
describe "Heartbeat" do
|
data/spec/log_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::Log do
|
4
|
+
describe "Using log without initializing it first" do
|
5
|
+
before(:each) do
|
6
|
+
Nanite::Log.instance_variable_set(:@logger, nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should use standard out for logging" do
|
10
|
+
Nanite::Log.init
|
11
|
+
STDOUT.should_receive(:write) do |arg|
|
12
|
+
arg.include?("For your consideration").should == true
|
13
|
+
end
|
14
|
+
Nanite::Log.info("For your consideration")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "Initializing the log level" do
|
19
|
+
it "should default to :info" do
|
20
|
+
Nanite::Log.init
|
21
|
+
Nanite::Log.level.should == :info
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an error if level is incorrect" do
|
25
|
+
lambda { Nanite::Log.level = "fool" }.should raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should succeed when using symbols" do
|
29
|
+
[ :debug, :info, :warn, :error, :fatal ].each do |level|
|
30
|
+
Nanite::Log.level = level
|
31
|
+
Nanite::Log.level.should == level
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
it "should succeed when using log levels" do
|
37
|
+
lvls = { Logger::DEBUG => :debug,
|
38
|
+
Logger::INFO => :info,
|
39
|
+
Logger::WARN => :warn,
|
40
|
+
Logger::ERROR => :error,
|
41
|
+
Logger::FATAL => :fatal }
|
42
|
+
lvls.keys.each do |level|
|
43
|
+
Nanite::Log.level = level
|
44
|
+
Nanite::Log.level.should == lvls[level]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::MapperProxy do
|
4
|
+
describe "when fetching the instance" do
|
5
|
+
before(:each) do
|
6
|
+
if Nanite::MapperProxy.class_variables.include?('@@instance')
|
7
|
+
Nanite::MapperProxy.__send__(:remove_class_variable, :@@instance)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return nil when the instance is undefined" do
|
12
|
+
Nanite::MapperProxy.instance.should == nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return the instance if defined" do
|
16
|
+
instance = mock
|
17
|
+
Nanite::MapperProxy.class_eval do
|
18
|
+
@@instance = "instance"
|
19
|
+
end
|
20
|
+
|
21
|
+
Nanite::MapperProxy.instance.should_not == nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when pushing a message" do
|
26
|
+
before do
|
27
|
+
AMQP.stub!(:connect)
|
28
|
+
MQ.stub!(:new)
|
29
|
+
Nanite::MapperProxy.new('mapperproxy', {})
|
30
|
+
@instance = Nanite::MapperProxy.instance
|
31
|
+
@fanout = stub(:fanout, :publish => true)
|
32
|
+
@instance.amqp.stub!(:fanout).and_return(@fanout)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should raise an error if mapper proxy is not initialized" do
|
36
|
+
lambda {
|
37
|
+
@instance.stub!(:identity).and_return nil
|
38
|
+
@instance.push('/welcome/aboard', 'iZac')
|
39
|
+
}.should raise_error("Mapper proxy not initialized")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should set correct attributes on the push message" do
|
43
|
+
@fanout.should_receive(:publish).with do |push|
|
44
|
+
push = @instance.serializer.load(push)
|
45
|
+
push.token.should_not == nil
|
46
|
+
push.persistent.should_not == true
|
47
|
+
push.from.should == 'mapperproxy'
|
48
|
+
end
|
49
|
+
|
50
|
+
@instance.push('/welcome/aboard', 'iZac')
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should mark the message as persistent when the option is specified on the parameter" do
|
54
|
+
@fanout.should_receive(:publish).with do |push|
|
55
|
+
push = @instance.serializer.load(push)
|
56
|
+
push.persistent.should == true
|
57
|
+
end
|
58
|
+
|
59
|
+
@instance.push('/welcome/aboard', 'iZac', :persistent => true)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should mark the message as persistent when the option is set globally" do
|
63
|
+
@instance.options[:persistent] = true
|
64
|
+
@fanout.should_receive(:publish).with do |push|
|
65
|
+
push = @instance.serializer.load(push)
|
66
|
+
push.persistent.should == true
|
67
|
+
end
|
68
|
+
|
69
|
+
@instance.push('/welcome/aboard', 'iZac')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/spec/mapper_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite::Mapper do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
describe "Initializing" do
|
7
|
+
before(:each) do
|
8
|
+
@mapper = Nanite::Mapper.new({})
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set the identity" do
|
12
|
+
@mapper.identity.should_not == nil
|
13
|
+
@mapper.identity.should =~ /mapper-.*/
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set the identity to a custom identity" do
|
17
|
+
@mapper = Nanite::Mapper.new({:identity => "bob"})
|
18
|
+
@mapper.identity.should == "mapper-bob"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set the file root" do
|
22
|
+
@mapper.options[:file_root].should == File.expand_path("#{File.dirname(__FILE__)}/../files")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "Starting" do
|
27
|
+
before(:each) do
|
28
|
+
@mapper = Nanite::Mapper.new({:log_level => :debug})
|
29
|
+
@mapper.stub!(:setup_queues)
|
30
|
+
@mapper.stub!(:start_amqp)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should initialize the logger" do
|
34
|
+
@mapper.stub!(:setup_cluster)
|
35
|
+
run_in_em do
|
36
|
+
@mapper.run
|
37
|
+
Nanite::Log.logger.level.should == Logger::DEBUG
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should set up the cluster" do
|
42
|
+
Nanite::Cluster.should_receive(:new).with(nil, 15, instance_of(String), instance_of(Nanite::Serializer), @mapper, nil, {})
|
43
|
+
run_in_em do
|
44
|
+
@mapper.run
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should set the prefetch value" do
|
49
|
+
amqp = mock("AMQP")
|
50
|
+
|
51
|
+
mapper = Nanite::Mapper.new(:prefetch => 11)
|
52
|
+
mapper.stub!(:setup_offline_queue)
|
53
|
+
mapper.stub!(:setup_message_queue)
|
54
|
+
mapper.stub!(:start_amqp)
|
55
|
+
mapper.stub!(:setup_cluster)
|
56
|
+
|
57
|
+
mapper.stub!(:start_amqp).and_return(amqp)
|
58
|
+
amqp.should_receive(:prefetch).with(11)
|
59
|
+
mapper.run
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should hand over callback options to the cluster" do
|
63
|
+
@mapper = Nanite::Mapper.new({:callbacks => {:register => lambda {|*args|}}})
|
64
|
+
@mapper.stub!(:setup_queues)
|
65
|
+
@mapper.stub!(:start_amqp)
|
66
|
+
Nanite::Cluster.should_receive(:new)
|
67
|
+
run_in_em {@mapper.run}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/nanite_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Nanite do
|
4
|
+
describe "when ensuring a mapper exists" do
|
5
|
+
describe "with a configured mapper proxy" do
|
6
|
+
before(:each) do
|
7
|
+
Nanite.instance_variable_set(:@mapper, nil)
|
8
|
+
Nanite::MapperProxy.stub!(:instance).and_return(mock(:mapper_proxy))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should not raise an error" do
|
12
|
+
lambda {
|
13
|
+
Nanite.ensure_mapper
|
14
|
+
}.should_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set the mapper instance variable to the mapper proxy instance" do
|
18
|
+
Nanite.ensure_mapper
|
19
|
+
Nanite.mapper.should == Nanite::MapperProxy.instance
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when the mapper wasn't started yet" do
|
24
|
+
before do
|
25
|
+
Nanite.instance_variable_set(:@mapper, nil)
|
26
|
+
Nanite::MapperProxy.stub!(:instance).and_return(nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should raise an error" do
|
30
|
+
lambda {
|
31
|
+
Nanite.ensure_mapper
|
32
|
+
}.should raise_error(Nanite::MapperNotRunning)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/packet_spec.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
+
class TestPacket < Nanite::Packet
|
4
|
+
@@cls_attr = "ignore"
|
5
|
+
def initialize(attr1)
|
6
|
+
@attr1 = attr1
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
describe "Packet: Base class" do
|
11
|
+
|
4
12
|
before(:all) do
|
5
|
-
class TestPacket < Nanite::Packet
|
6
|
-
@@cls_attr = "ignore"
|
7
|
-
def initialize(attr1)
|
8
|
-
@attr1 = attr1
|
9
|
-
end
|
10
|
-
end
|
11
13
|
end
|
12
14
|
|
13
15
|
it "should be an abstract class" do
|
data/spec/spec_helper.rb
CHANGED
@@ -7,9 +7,6 @@ require 'nanite'
|
|
7
7
|
|
8
8
|
module SpecHelpers
|
9
9
|
|
10
|
-
# Initialize logger so it writes to file instead of STDOUT
|
11
|
-
Nanite::Log.init('test', File.join(File.dirname(__FILE__)))
|
12
|
-
|
13
10
|
# Create test certificate
|
14
11
|
def issue_cert
|
15
12
|
test_dn = { 'C' => 'US',
|
@@ -30,4 +27,4 @@ module SpecHelpers
|
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
|
-
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rightscale-nanite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.1.
|
4
|
+
version: 0.4.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -86,9 +86,11 @@ files:
|
|
86
86
|
- spec/certificate_cache_spec.rb
|
87
87
|
- spec/cached_certificate_store_proxy_spec.rb
|
88
88
|
- spec/dispatcher_spec.rb
|
89
|
+
- spec/log_spec.rb
|
89
90
|
- spec/rsa_key_pair_spec.rb
|
90
91
|
- spec/cluster_spec.rb
|
91
92
|
- spec/spec_helper.rb
|
93
|
+
- spec/mapper_spec.rb
|
92
94
|
- spec/actor_registry_spec.rb
|
93
95
|
- spec/actor_spec.rb
|
94
96
|
- spec/packet_spec.rb
|
@@ -96,9 +98,11 @@ files:
|
|
96
98
|
- spec/static_certificate_store_spec.rb
|
97
99
|
- spec/job_spec.rb
|
98
100
|
- spec/signature_spec.rb
|
101
|
+
- spec/mapper_proxy_spec.rb
|
99
102
|
- spec/secure_serializer_spec.rb
|
100
103
|
- spec/serializer_spec.rb
|
101
104
|
- spec/certificate_spec.rb
|
105
|
+
- spec/nanite_spec.rb
|
102
106
|
- spec/distinguished_name_spec.rb
|
103
107
|
has_rdoc: true
|
104
108
|
homepage: http://github.com/ezmobius/nanite
|