right_agent 2.0.7-x86-mingw32
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/LICENSE +20 -0
- data/README.rdoc +82 -0
- data/Rakefile +113 -0
- data/lib/right_agent.rb +59 -0
- data/lib/right_agent/actor.rb +182 -0
- data/lib/right_agent/actor_registry.rb +76 -0
- data/lib/right_agent/actors/agent_manager.rb +232 -0
- data/lib/right_agent/agent.rb +1149 -0
- data/lib/right_agent/agent_config.rb +480 -0
- data/lib/right_agent/agent_identity.rb +210 -0
- data/lib/right_agent/agent_tag_manager.rb +237 -0
- data/lib/right_agent/audit_formatter.rb +107 -0
- data/lib/right_agent/clients.rb +31 -0
- data/lib/right_agent/clients/api_client.rb +383 -0
- data/lib/right_agent/clients/auth_client.rb +247 -0
- data/lib/right_agent/clients/balanced_http_client.rb +369 -0
- data/lib/right_agent/clients/base_retry_client.rb +495 -0
- data/lib/right_agent/clients/right_http_client.rb +279 -0
- data/lib/right_agent/clients/router_client.rb +493 -0
- data/lib/right_agent/command.rb +30 -0
- data/lib/right_agent/command/agent_manager_commands.rb +150 -0
- data/lib/right_agent/command/command_client.rb +136 -0
- data/lib/right_agent/command/command_constants.rb +33 -0
- data/lib/right_agent/command/command_io.rb +126 -0
- data/lib/right_agent/command/command_parser.rb +87 -0
- data/lib/right_agent/command/command_runner.rb +118 -0
- data/lib/right_agent/command/command_serializer.rb +63 -0
- data/lib/right_agent/connectivity_checker.rb +179 -0
- data/lib/right_agent/console.rb +65 -0
- data/lib/right_agent/core_payload_types.rb +44 -0
- data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
- data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
- data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
- data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
- data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
- data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
- data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
- data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
- data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
- data/lib/right_agent/core_payload_types/login_user.rb +79 -0
- data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
- data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
- data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
- data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
- data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
- data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
- data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
- data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
- data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
- data/lib/right_agent/daemonize.rb +35 -0
- data/lib/right_agent/dispatched_cache.rb +109 -0
- data/lib/right_agent/dispatcher.rb +272 -0
- data/lib/right_agent/enrollment_result.rb +221 -0
- data/lib/right_agent/exceptions.rb +87 -0
- data/lib/right_agent/history.rb +145 -0
- data/lib/right_agent/log.rb +460 -0
- data/lib/right_agent/minimal.rb +46 -0
- data/lib/right_agent/monkey_patches.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
- data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
- data/lib/right_agent/multiplexer.rb +102 -0
- data/lib/right_agent/offline_handler.rb +270 -0
- data/lib/right_agent/operation_result.rb +300 -0
- data/lib/right_agent/packets.rb +673 -0
- data/lib/right_agent/payload_formatter.rb +104 -0
- data/lib/right_agent/pending_requests.rb +128 -0
- data/lib/right_agent/pid_file.rb +159 -0
- data/lib/right_agent/platform.rb +770 -0
- data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
- data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
- data/lib/right_agent/platform/unix/platform.rb +226 -0
- data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
- data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
- data/lib/right_agent/platform/windows/platform.rb +1808 -0
- data/lib/right_agent/protocol_version_mixin.rb +69 -0
- data/lib/right_agent/retryable_request.rb +195 -0
- data/lib/right_agent/scripts/agent_controller.rb +543 -0
- data/lib/right_agent/scripts/agent_deployer.rb +400 -0
- data/lib/right_agent/scripts/common_parser.rb +160 -0
- data/lib/right_agent/scripts/log_level_manager.rb +192 -0
- data/lib/right_agent/scripts/stats_manager.rb +268 -0
- data/lib/right_agent/scripts/usage.rb +58 -0
- data/lib/right_agent/secure_identity.rb +92 -0
- data/lib/right_agent/security.rb +32 -0
- data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
- data/lib/right_agent/security/certificate.rb +102 -0
- data/lib/right_agent/security/certificate_cache.rb +89 -0
- data/lib/right_agent/security/distinguished_name.rb +56 -0
- data/lib/right_agent/security/encrypted_document.rb +83 -0
- data/lib/right_agent/security/rsa_key_pair.rb +76 -0
- data/lib/right_agent/security/signature.rb +86 -0
- data/lib/right_agent/security/static_certificate_store.rb +85 -0
- data/lib/right_agent/sender.rb +792 -0
- data/lib/right_agent/serialize.rb +29 -0
- data/lib/right_agent/serialize/message_pack.rb +107 -0
- data/lib/right_agent/serialize/secure_serializer.rb +151 -0
- data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
- data/lib/right_agent/serialize/serializable.rb +151 -0
- data/lib/right_agent/serialize/serializer.rb +159 -0
- data/lib/right_agent/subprocess.rb +38 -0
- data/lib/right_agent/tracer.rb +124 -0
- data/right_agent.gemspec +101 -0
- data/spec/actor_registry_spec.rb +80 -0
- data/spec/actor_spec.rb +162 -0
- data/spec/agent_config_spec.rb +235 -0
- data/spec/agent_identity_spec.rb +78 -0
- data/spec/agent_spec.rb +734 -0
- data/spec/agent_tag_manager_spec.rb +319 -0
- data/spec/clients/api_client_spec.rb +423 -0
- data/spec/clients/auth_client_spec.rb +272 -0
- data/spec/clients/balanced_http_client_spec.rb +576 -0
- data/spec/clients/base_retry_client_spec.rb +635 -0
- data/spec/clients/router_client_spec.rb +594 -0
- data/spec/clients/spec_helper.rb +111 -0
- data/spec/command/agent_manager_commands_spec.rb +51 -0
- data/spec/command/command_io_spec.rb +93 -0
- data/spec/command/command_parser_spec.rb +79 -0
- data/spec/command/command_runner_spec.rb +107 -0
- data/spec/command/command_serializer_spec.rb +51 -0
- data/spec/connectivity_checker_spec.rb +83 -0
- data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
- data/spec/core_payload_types/dev_repository_spec.rb +33 -0
- data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
- data/spec/core_payload_types/login_user_spec.rb +102 -0
- data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
- data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
- data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
- data/spec/core_payload_types/spec_helper.rb +23 -0
- data/spec/dispatched_cache_spec.rb +136 -0
- data/spec/dispatcher_spec.rb +324 -0
- data/spec/enrollment_result_spec.rb +53 -0
- data/spec/history_spec.rb +246 -0
- data/spec/log_spec.rb +192 -0
- data/spec/monkey_patches/eventmachine_spec.rb +62 -0
- data/spec/multiplexer_spec.rb +48 -0
- data/spec/offline_handler_spec.rb +340 -0
- data/spec/operation_result_spec.rb +208 -0
- data/spec/packets_spec.rb +461 -0
- data/spec/pending_requests_spec.rb +136 -0
- data/spec/platform/spec_helper.rb +216 -0
- data/spec/platform/unix/darwin/platform_spec.rb +181 -0
- data/spec/platform/unix/linux/platform_spec.rb +540 -0
- data/spec/platform/unix/spec_helper.rb +149 -0
- data/spec/platform/windows/mingw/platform_spec.rb +222 -0
- data/spec/platform/windows/mswin/platform_spec.rb +259 -0
- data/spec/platform/windows/spec_helper.rb +720 -0
- data/spec/retryable_request_spec.rb +306 -0
- data/spec/secure_identity_spec.rb +50 -0
- data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
- data/spec/security/certificate_cache_spec.rb +71 -0
- data/spec/security/certificate_spec.rb +49 -0
- data/spec/security/distinguished_name_spec.rb +46 -0
- data/spec/security/encrypted_document_spec.rb +55 -0
- data/spec/security/rsa_key_pair_spec.rb +55 -0
- data/spec/security/signature_spec.rb +66 -0
- data/spec/security/static_certificate_store_spec.rb +58 -0
- data/spec/sender_spec.rb +1045 -0
- data/spec/serialize/message_pack_spec.rb +131 -0
- data/spec/serialize/secure_serializer_spec.rb +132 -0
- data/spec/serialize/serializable_spec.rb +90 -0
- data/spec/serialize/serializer_spec.rb +197 -0
- data/spec/spec.opts +2 -0
- data/spec/spec.win32.opts +1 -0
- data/spec/spec_helper.rb +130 -0
- data/spec/tracer_spec.rb +114 -0
- metadata +447 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
#-- -*- mode: ruby; encoding: utf-8 -*-
|
2
|
+
# Copyright: Copyright (c) 2009-2013 RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
25
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'right_agent', 'core_payload_types'))
|
26
|
+
|
27
|
+
module RightScale
|
28
|
+
describe RightScriptInstantiation do
|
29
|
+
let(:nickname) { 'foo' }
|
30
|
+
let(:source) { "echo 'hello world'" }
|
31
|
+
let(:parameters) { { 'ADMIN_PASSWORD' => 'clandestine' } }
|
32
|
+
let(:attachments) { [] }
|
33
|
+
let(:packages) { '' }
|
34
|
+
let(:id) { 123 }
|
35
|
+
let(:ready) { true }
|
36
|
+
let(:external_inputs) { {} }
|
37
|
+
let(:input_flags) { {} }
|
38
|
+
let(:display_version) { 'HEAD' }
|
39
|
+
|
40
|
+
context 'given all fields' do
|
41
|
+
subject do
|
42
|
+
described_class.new(
|
43
|
+
nickname, source, parameters, attachments, packages, id, ready,
|
44
|
+
external_inputs, input_flags, display_version)
|
45
|
+
end
|
46
|
+
|
47
|
+
its(:title) { should == "'#{nickname}' #{display_version}" }
|
48
|
+
its(:nickname) { should == nickname }
|
49
|
+
its(:source) { should == source }
|
50
|
+
its(:parameters) { should == parameters }
|
51
|
+
its(:attachments) { should == attachments }
|
52
|
+
its(:packages) { should == packages }
|
53
|
+
its(:id) { should == id }
|
54
|
+
its(:ready) { should == ready }
|
55
|
+
its(:external_inputs) { should == external_inputs }
|
56
|
+
its(:input_flags) { should == input_flags }
|
57
|
+
its(:display_version) { should == display_version }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'given minimal fields' do
|
61
|
+
subject do
|
62
|
+
described_class.new(
|
63
|
+
nickname, source, parameters, attachments, packages, id, ready)
|
64
|
+
end
|
65
|
+
|
66
|
+
its(:title) { should == nickname }
|
67
|
+
its(:nickname) { should == nickname }
|
68
|
+
its(:source) { should == source }
|
69
|
+
its(:parameters) { should == parameters }
|
70
|
+
its(:attachments) { should == attachments }
|
71
|
+
its(:packages) { should == packages }
|
72
|
+
its(:id) { should == id }
|
73
|
+
its(:ready) { should == ready }
|
74
|
+
its(:external_inputs) { should be_nil }
|
75
|
+
its(:input_flags) { should be_nil }
|
76
|
+
its(:display_version) { should be_nil }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec', 'spec_helper'))
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
24
|
+
|
25
|
+
describe "RightScale::DispatchedCache" do
|
26
|
+
|
27
|
+
include FlexMock::ArgumentTypes
|
28
|
+
|
29
|
+
before(:each) do
|
30
|
+
flexmock(RightScale::Log).should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
|
31
|
+
flexmock(RightScale::Log).should_receive(:info).by_default
|
32
|
+
@now = Time.at(1000000)
|
33
|
+
flexmock(Time).should_receive(:now).and_return(@now).by_default
|
34
|
+
@agent_id = "rs-agent-1-1"
|
35
|
+
@cache = RightScale::DispatchedCache.new(@agent_id)
|
36
|
+
@token1 = "token1"
|
37
|
+
@token2 = "token2"
|
38
|
+
@token3 = "token3"
|
39
|
+
end
|
40
|
+
|
41
|
+
context "initialize" do
|
42
|
+
|
43
|
+
it "should initialize cache" do
|
44
|
+
@cache.instance_variable_get(:@cache).should == {}
|
45
|
+
@cache.instance_variable_get(:@lru).should == []
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should initialize agent identity" do
|
49
|
+
@cache.instance_variable_get(:@identity).should == @agent_id
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
context "store" do
|
55
|
+
|
56
|
+
it "should store request token" do
|
57
|
+
@cache.store(@token1)
|
58
|
+
@cache.instance_variable_get(:@cache)[@token1].should == @now.to_i
|
59
|
+
@cache.instance_variable_get(:@lru).should == [@token1]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should update lru list when store to existing entry" do
|
63
|
+
@cache.store(@token1)
|
64
|
+
@cache.instance_variable_get(:@cache)[@token1].should == @now.to_i
|
65
|
+
@cache.instance_variable_get(:@lru).should == [@token1]
|
66
|
+
@cache.store(@token2)
|
67
|
+
@cache.instance_variable_get(:@cache)[@token2].should == @now.to_i
|
68
|
+
@cache.instance_variable_get(:@lru).should == [@token1, @token2]
|
69
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
70
|
+
@cache.store(@token1)
|
71
|
+
@cache.instance_variable_get(:@cache)[@token1].should == @now.to_i
|
72
|
+
@cache.instance_variable_get(:@lru).should == [@token2, @token1]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should remove old cache entries when store new one" do
|
76
|
+
@cache.store(@token1)
|
77
|
+
@cache.store(@token2)
|
78
|
+
@cache.instance_variable_get(:@cache).keys.should =~ [@token1, @token2]
|
79
|
+
@cache.instance_variable_get(:@lru).should == [@token1, @token2]
|
80
|
+
flexmock(Time).should_receive(:now).and_return(@now += RightScale::DispatchedCache::MAX_AGE + 1)
|
81
|
+
@cache.store(@token3)
|
82
|
+
@cache.instance_variable_get(:@cache).keys.should == [@token3]
|
83
|
+
@cache.instance_variable_get(:@lru).should == [@token3]
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not store anything if token is nil" do
|
87
|
+
@cache.store(nil)
|
88
|
+
@cache.instance_variable_get(:@cache).should be_empty
|
89
|
+
@cache.instance_variable_get(:@lru).should be_empty
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
context "serviced_by" do
|
95
|
+
|
96
|
+
it "should return who request was serviced by and make it the most recently used" do
|
97
|
+
@cache.store(@token1)
|
98
|
+
@cache.store(@token2)
|
99
|
+
@cache.instance_variable_get(:@lru).should == [@token1, @token2]
|
100
|
+
@cache.serviced_by(@token1).should == @agent_id
|
101
|
+
@cache.instance_variable_get(:@lru).should == [@token2, @token1]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return nil if request was not previously serviced" do
|
105
|
+
@cache.serviced_by(@token1).should be_nil
|
106
|
+
@cache.store(@token1)
|
107
|
+
@cache.serviced_by(@token1).should == @agent_id
|
108
|
+
@cache.serviced_by(@token2).should be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context "stats" do
|
114
|
+
|
115
|
+
it "should return nil if cache empty" do
|
116
|
+
@cache.stats.should be_nil
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should return total and max age" do
|
120
|
+
@cache.store(@token1)
|
121
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
122
|
+
@cache.store(@token2)
|
123
|
+
@cache.stats.should == {
|
124
|
+
"local total" => 2,
|
125
|
+
"local max age" => "10 sec"
|
126
|
+
}
|
127
|
+
@cache.serviced_by(@token1)
|
128
|
+
@cache.stats.should == {
|
129
|
+
"local total" => 2,
|
130
|
+
"local max age" => "0 sec"
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end # RightScale::Dispatcher
|
@@ -0,0 +1,324 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2012 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
24
|
+
|
25
|
+
class Foo
|
26
|
+
include RightScale::Actor
|
27
|
+
expose_idempotent :bar, :index, :i_kill_you
|
28
|
+
expose_non_idempotent :bar_non
|
29
|
+
on_exception :handle_exception
|
30
|
+
|
31
|
+
def index(payload)
|
32
|
+
bar(payload)
|
33
|
+
end
|
34
|
+
|
35
|
+
def bar(payload)
|
36
|
+
['hello', payload]
|
37
|
+
end
|
38
|
+
|
39
|
+
def bar2(payload, request)
|
40
|
+
['hello', payload, request]
|
41
|
+
end
|
42
|
+
|
43
|
+
def bar_non(payload)
|
44
|
+
@i = (@i || 0) + payload
|
45
|
+
end
|
46
|
+
|
47
|
+
def i_kill_you(payload)
|
48
|
+
raise RuntimeError.new('I kill you!')
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_exception(method, deliverable, error)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Bar
|
56
|
+
include RightScale::Actor
|
57
|
+
expose :i_kill_you
|
58
|
+
on_exception do |method, deliverable, error|
|
59
|
+
@scope = self
|
60
|
+
@called_with = [method, deliverable, error]
|
61
|
+
end
|
62
|
+
|
63
|
+
def i_kill_you(payload)
|
64
|
+
raise RuntimeError.new('I kill you!')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# No specs, simply ensures multiple methods for assigning on_exception callback,
|
69
|
+
# on_exception raises exception when called with an invalid argument.
|
70
|
+
class Doomed
|
71
|
+
include RightScale::Actor
|
72
|
+
on_exception do
|
73
|
+
end
|
74
|
+
on_exception lambda {}
|
75
|
+
on_exception :doh
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "RightScale::Dispatcher" do
|
79
|
+
|
80
|
+
include FlexMock::ArgumentTypes
|
81
|
+
|
82
|
+
before(:each) do
|
83
|
+
@log = flexmock(RightScale::Log)
|
84
|
+
@log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
|
85
|
+
@log.should_receive(:info).by_default
|
86
|
+
@now = Time.at(1000000)
|
87
|
+
flexmock(Time).should_receive(:now).and_return(@now).by_default
|
88
|
+
@actor = Foo.new
|
89
|
+
@registry = RightScale::ActorRegistry.new
|
90
|
+
@registry.register(@actor, nil)
|
91
|
+
@agent_id = "rs-agent-1-1"
|
92
|
+
@agent = flexmock("Agent", :identity => @agent_id, :registry => @registry, :exception_callback => nil).by_default
|
93
|
+
@cache = RightScale::DispatchedCache.new(@agent_id)
|
94
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
95
|
+
end
|
96
|
+
|
97
|
+
context "routable?" do
|
98
|
+
|
99
|
+
it "should return false if actor is not available for routing" do
|
100
|
+
@dispatcher.routable?("foo").should be_true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should return true if actor is available for routing" do
|
104
|
+
@dispatcher.routable?("bar").should be_false
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context "dispatch" do
|
110
|
+
|
111
|
+
it "should dispatch a request" do
|
112
|
+
req = RightScale::Request.new('/foo/bar', 'you', :token => 'token')
|
113
|
+
res = @dispatcher.dispatch(req)
|
114
|
+
res.should(be_kind_of(RightScale::Result))
|
115
|
+
res.token.should == 'token'
|
116
|
+
res.results.should == ['hello', 'you']
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should dispatch a request with required arity" do
|
120
|
+
req = RightScale::Request.new('/foo/bar2', 'you', :token => 'token')
|
121
|
+
res = @dispatcher.dispatch(req)
|
122
|
+
res.should(be_kind_of(RightScale::Result))
|
123
|
+
res.token.should == 'token'
|
124
|
+
res.results.should == ['hello', 'you', req]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should dispatch a request to the default action" do
|
128
|
+
req = RightScale::Request.new('/foo', 'you', :token => 'token')
|
129
|
+
res = @dispatcher.dispatch(req)
|
130
|
+
res.should(be_kind_of(RightScale::Result))
|
131
|
+
res.token.should == req.token
|
132
|
+
res.results.should == ['hello', 'you']
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should return nil for successful push" do
|
136
|
+
req = RightScale::Push.new('/foo', 'you', :token => 'token')
|
137
|
+
res = @dispatcher.dispatch(req)
|
138
|
+
res.should be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should handle custom prefixes" do
|
142
|
+
@registry.register(Foo.new, 'umbongo')
|
143
|
+
req = RightScale::Request.new('/umbongo/bar', 'you')
|
144
|
+
res = @dispatcher.dispatch(req)
|
145
|
+
res.should(be_kind_of(RightScale::Result))
|
146
|
+
res.token.should == req.token
|
147
|
+
res.results.should == ['hello', 'you']
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should raise exception if actor is unknown" do
|
151
|
+
req = RightScale::Request.new('/bad', 'you', :token => 'token')
|
152
|
+
lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::InvalidRequestType)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should raise exception if actor method is unknown" do
|
156
|
+
req = RightScale::Request.new('/foo/bar-none', 'you', :token => 'token')
|
157
|
+
lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::InvalidRequestType)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should call the on_exception callback if something goes wrong" do
|
161
|
+
@log.should_receive(:error).once
|
162
|
+
req = RightScale::Request.new('/foo/i_kill_you', nil)
|
163
|
+
flexmock(@actor).should_receive(:handle_exception).with(:i_kill_you, req, Exception).once
|
164
|
+
res = @dispatcher.dispatch(req)
|
165
|
+
res.results.error?.should be_true
|
166
|
+
(res.results.content =~ /Could not handle \/foo\/i_kill_you request/).should be_true
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should call on_exception Procs defined in a subclass with the correct arguments" do
|
170
|
+
@log.should_receive(:error).once
|
171
|
+
actor = Bar.new
|
172
|
+
@registry.register(actor, nil)
|
173
|
+
req = RightScale::Request.new('/bar/i_kill_you', nil)
|
174
|
+
@dispatcher.dispatch(req)
|
175
|
+
called_with = actor.instance_variable_get("@called_with")
|
176
|
+
called_with[0].should == :i_kill_you
|
177
|
+
called_with[1].should == req
|
178
|
+
called_with[2].should be_kind_of(RuntimeError)
|
179
|
+
called_with[2].message.should == 'I kill you!'
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should call on_exception Procs defined in a subclass in the scope of the actor" do
|
183
|
+
@log.should_receive(:error).once
|
184
|
+
actor = Bar.new
|
185
|
+
@registry.register(actor, nil)
|
186
|
+
req = RightScale::Request.new('/bar/i_kill_you', nil)
|
187
|
+
@dispatcher.dispatch(req)
|
188
|
+
actor.instance_variable_get("@scope").should == actor
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should log error if dispatch fails" do
|
192
|
+
RightScale::Log.should_receive(:error).once
|
193
|
+
req = RightScale::Request.new('/foo/i_kill_you', nil)
|
194
|
+
@dispatcher.dispatch(req)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should reject requests whose time-to-live has expired" do
|
198
|
+
flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
|
199
|
+
@log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED.*TTL 2 sec ago/})
|
200
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
201
|
+
req = RightScale::Push.new('/foo/bar', 'you', :expires_at => @now.to_i + 8)
|
202
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
203
|
+
@dispatcher.dispatch(req).should be_nil
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should return non-delivery result if Request is rejected because its time-to-live has expired" do
|
207
|
+
flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
|
208
|
+
@log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
|
209
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
210
|
+
req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => @response_queue, :expires_at => @now.to_i + 8})
|
211
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
212
|
+
res = @dispatcher.dispatch(req)
|
213
|
+
res.results.non_delivery?.should be_true
|
214
|
+
res.results.content.should == RightScale::OperationResult::TTL_EXPIRATION
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should return error result instead of non-delivery if agent does not know about non-delivery" do
|
218
|
+
flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
|
219
|
+
@log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT EXPIRED/})
|
220
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
221
|
+
req = RightScale::Request.new('/foo/bar', 'you', {:reply_to => "rs-router-1-1", :expires_at => @now.to_i + 8},
|
222
|
+
[version_cannot_handle_non_delivery_result, RightScale::AgentConfig.protocol_version])
|
223
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
224
|
+
res = @dispatcher.dispatch(req)
|
225
|
+
res.results.error?.should be_true
|
226
|
+
res.results.content.should =~ /Could not deliver/
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should not reject requests whose time-to-live has not expired" do
|
230
|
+
flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
|
231
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
232
|
+
req = RightScale::Request.new('/foo/bar', 'you', :expires_at => @now.to_i + 11)
|
233
|
+
flexmock(Time).should_receive(:now).and_return(@now += 10)
|
234
|
+
res = @dispatcher.dispatch(req)
|
235
|
+
res.should(be_kind_of(RightScale::Result))
|
236
|
+
res.token.should == req.token
|
237
|
+
res.results.should == ['hello', 'you']
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should not check age of requests with time-to-live check disabled" do
|
241
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
242
|
+
req = RightScale::Request.new('/foo/bar', 'you', :expires_at => 0)
|
243
|
+
res = @dispatcher.dispatch(req)
|
244
|
+
res.should(be_kind_of(RightScale::Result))
|
245
|
+
res.token.should == req.token
|
246
|
+
res.results.should == ['hello', 'you']
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should reject duplicate request by raising exception" do
|
250
|
+
@log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT DUP/})
|
251
|
+
EM.run do
|
252
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
253
|
+
req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
|
254
|
+
@cache.store(req.token)
|
255
|
+
lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::DuplicateRequest)
|
256
|
+
EM.stop
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should reject duplicate request from a retry by raising exception" do
|
261
|
+
@log.should_receive(:info).once.with(on {|arg| arg =~ /REJECT RETRY DUP/})
|
262
|
+
EM.run do
|
263
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
264
|
+
req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
|
265
|
+
req.tries.concat(["try1", "try2"])
|
266
|
+
@cache.store("try2")
|
267
|
+
lambda { @dispatcher.dispatch(req) }.should raise_error(RightScale::Dispatcher::DuplicateRequest)
|
268
|
+
EM.stop
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should not reject non-duplicate requests" do
|
273
|
+
EM.run do
|
274
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
275
|
+
req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
|
276
|
+
req.tries.concat(["try1", "try2"])
|
277
|
+
@cache.store("try3")
|
278
|
+
@dispatcher.dispatch(req).should_not be_nil
|
279
|
+
EM.stop
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should not reject duplicate idempotent requests" do
|
284
|
+
EM.run do
|
285
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, @cache)
|
286
|
+
req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
|
287
|
+
@cache.store(req.token)
|
288
|
+
@dispatcher.dispatch(req).should_not be_nil
|
289
|
+
EM.stop
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should not check for duplicates if duplicate checking is disabled" do
|
294
|
+
EM.run do
|
295
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
|
296
|
+
req = RightScale::Request.new('/foo/bar_non', 1, :token => "try")
|
297
|
+
req.tries.concat(["try1", "try2"])
|
298
|
+
@dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
|
299
|
+
@dispatcher.dispatch(req).should_not be_nil
|
300
|
+
EM.stop
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should not check for duplicates if actor method is idempotent" do
|
305
|
+
EM.run do
|
306
|
+
@dispatcher = RightScale::Dispatcher.new(@agent, dispatched_cache = nil)
|
307
|
+
req = RightScale::Request.new('/foo/bar', 1, :token => "try")
|
308
|
+
req.tries.concat(["try1", "try2"])
|
309
|
+
@dispatcher.instance_variable_get(:@dispatched_cache).should be_nil
|
310
|
+
@dispatcher.dispatch(req).should_not be_nil
|
311
|
+
EM.stop
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
it "should return error result if dispatch fails" do
|
316
|
+
@log.should_receive(:error).with(/Could not handle/, Exception, :trace).once
|
317
|
+
req = RightScale::Request.new('/foo/i_kill_you', nil)
|
318
|
+
res = @dispatcher.dispatch(req)
|
319
|
+
res.results.error?.should be_true
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end # RightScale::Dispatcher
|