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.
Files changed (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +82 -0
  3. data/Rakefile +113 -0
  4. data/lib/right_agent.rb +59 -0
  5. data/lib/right_agent/actor.rb +182 -0
  6. data/lib/right_agent/actor_registry.rb +76 -0
  7. data/lib/right_agent/actors/agent_manager.rb +232 -0
  8. data/lib/right_agent/agent.rb +1149 -0
  9. data/lib/right_agent/agent_config.rb +480 -0
  10. data/lib/right_agent/agent_identity.rb +210 -0
  11. data/lib/right_agent/agent_tag_manager.rb +237 -0
  12. data/lib/right_agent/audit_formatter.rb +107 -0
  13. data/lib/right_agent/clients.rb +31 -0
  14. data/lib/right_agent/clients/api_client.rb +383 -0
  15. data/lib/right_agent/clients/auth_client.rb +247 -0
  16. data/lib/right_agent/clients/balanced_http_client.rb +369 -0
  17. data/lib/right_agent/clients/base_retry_client.rb +495 -0
  18. data/lib/right_agent/clients/right_http_client.rb +279 -0
  19. data/lib/right_agent/clients/router_client.rb +493 -0
  20. data/lib/right_agent/command.rb +30 -0
  21. data/lib/right_agent/command/agent_manager_commands.rb +150 -0
  22. data/lib/right_agent/command/command_client.rb +136 -0
  23. data/lib/right_agent/command/command_constants.rb +33 -0
  24. data/lib/right_agent/command/command_io.rb +126 -0
  25. data/lib/right_agent/command/command_parser.rb +87 -0
  26. data/lib/right_agent/command/command_runner.rb +118 -0
  27. data/lib/right_agent/command/command_serializer.rb +63 -0
  28. data/lib/right_agent/connectivity_checker.rb +179 -0
  29. data/lib/right_agent/console.rb +65 -0
  30. data/lib/right_agent/core_payload_types.rb +44 -0
  31. data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
  32. data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
  33. data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
  34. data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
  35. data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
  36. data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
  37. data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
  38. data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
  39. data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
  40. data/lib/right_agent/core_payload_types/login_user.rb +79 -0
  41. data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
  42. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
  43. data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
  44. data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
  45. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
  46. data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
  47. data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
  48. data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
  49. data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
  50. data/lib/right_agent/daemonize.rb +35 -0
  51. data/lib/right_agent/dispatched_cache.rb +109 -0
  52. data/lib/right_agent/dispatcher.rb +272 -0
  53. data/lib/right_agent/enrollment_result.rb +221 -0
  54. data/lib/right_agent/exceptions.rb +87 -0
  55. data/lib/right_agent/history.rb +145 -0
  56. data/lib/right_agent/log.rb +460 -0
  57. data/lib/right_agent/minimal.rb +46 -0
  58. data/lib/right_agent/monkey_patches.rb +30 -0
  59. data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
  60. data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
  61. data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
  62. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
  63. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
  64. data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
  65. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
  66. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
  67. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
  68. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
  69. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
  70. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
  71. data/lib/right_agent/multiplexer.rb +102 -0
  72. data/lib/right_agent/offline_handler.rb +270 -0
  73. data/lib/right_agent/operation_result.rb +300 -0
  74. data/lib/right_agent/packets.rb +673 -0
  75. data/lib/right_agent/payload_formatter.rb +104 -0
  76. data/lib/right_agent/pending_requests.rb +128 -0
  77. data/lib/right_agent/pid_file.rb +159 -0
  78. data/lib/right_agent/platform.rb +770 -0
  79. data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
  80. data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
  81. data/lib/right_agent/platform/unix/platform.rb +226 -0
  82. data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
  83. data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
  84. data/lib/right_agent/platform/windows/platform.rb +1808 -0
  85. data/lib/right_agent/protocol_version_mixin.rb +69 -0
  86. data/lib/right_agent/retryable_request.rb +195 -0
  87. data/lib/right_agent/scripts/agent_controller.rb +543 -0
  88. data/lib/right_agent/scripts/agent_deployer.rb +400 -0
  89. data/lib/right_agent/scripts/common_parser.rb +160 -0
  90. data/lib/right_agent/scripts/log_level_manager.rb +192 -0
  91. data/lib/right_agent/scripts/stats_manager.rb +268 -0
  92. data/lib/right_agent/scripts/usage.rb +58 -0
  93. data/lib/right_agent/secure_identity.rb +92 -0
  94. data/lib/right_agent/security.rb +32 -0
  95. data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
  96. data/lib/right_agent/security/certificate.rb +102 -0
  97. data/lib/right_agent/security/certificate_cache.rb +89 -0
  98. data/lib/right_agent/security/distinguished_name.rb +56 -0
  99. data/lib/right_agent/security/encrypted_document.rb +83 -0
  100. data/lib/right_agent/security/rsa_key_pair.rb +76 -0
  101. data/lib/right_agent/security/signature.rb +86 -0
  102. data/lib/right_agent/security/static_certificate_store.rb +85 -0
  103. data/lib/right_agent/sender.rb +792 -0
  104. data/lib/right_agent/serialize.rb +29 -0
  105. data/lib/right_agent/serialize/message_pack.rb +107 -0
  106. data/lib/right_agent/serialize/secure_serializer.rb +151 -0
  107. data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
  108. data/lib/right_agent/serialize/serializable.rb +151 -0
  109. data/lib/right_agent/serialize/serializer.rb +159 -0
  110. data/lib/right_agent/subprocess.rb +38 -0
  111. data/lib/right_agent/tracer.rb +124 -0
  112. data/right_agent.gemspec +101 -0
  113. data/spec/actor_registry_spec.rb +80 -0
  114. data/spec/actor_spec.rb +162 -0
  115. data/spec/agent_config_spec.rb +235 -0
  116. data/spec/agent_identity_spec.rb +78 -0
  117. data/spec/agent_spec.rb +734 -0
  118. data/spec/agent_tag_manager_spec.rb +319 -0
  119. data/spec/clients/api_client_spec.rb +423 -0
  120. data/spec/clients/auth_client_spec.rb +272 -0
  121. data/spec/clients/balanced_http_client_spec.rb +576 -0
  122. data/spec/clients/base_retry_client_spec.rb +635 -0
  123. data/spec/clients/router_client_spec.rb +594 -0
  124. data/spec/clients/spec_helper.rb +111 -0
  125. data/spec/command/agent_manager_commands_spec.rb +51 -0
  126. data/spec/command/command_io_spec.rb +93 -0
  127. data/spec/command/command_parser_spec.rb +79 -0
  128. data/spec/command/command_runner_spec.rb +107 -0
  129. data/spec/command/command_serializer_spec.rb +51 -0
  130. data/spec/connectivity_checker_spec.rb +83 -0
  131. data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
  132. data/spec/core_payload_types/dev_repository_spec.rb +33 -0
  133. data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
  134. data/spec/core_payload_types/login_user_spec.rb +102 -0
  135. data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
  136. data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
  137. data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
  138. data/spec/core_payload_types/spec_helper.rb +23 -0
  139. data/spec/dispatched_cache_spec.rb +136 -0
  140. data/spec/dispatcher_spec.rb +324 -0
  141. data/spec/enrollment_result_spec.rb +53 -0
  142. data/spec/history_spec.rb +246 -0
  143. data/spec/log_spec.rb +192 -0
  144. data/spec/monkey_patches/eventmachine_spec.rb +62 -0
  145. data/spec/multiplexer_spec.rb +48 -0
  146. data/spec/offline_handler_spec.rb +340 -0
  147. data/spec/operation_result_spec.rb +208 -0
  148. data/spec/packets_spec.rb +461 -0
  149. data/spec/pending_requests_spec.rb +136 -0
  150. data/spec/platform/spec_helper.rb +216 -0
  151. data/spec/platform/unix/darwin/platform_spec.rb +181 -0
  152. data/spec/platform/unix/linux/platform_spec.rb +540 -0
  153. data/spec/platform/unix/spec_helper.rb +149 -0
  154. data/spec/platform/windows/mingw/platform_spec.rb +222 -0
  155. data/spec/platform/windows/mswin/platform_spec.rb +259 -0
  156. data/spec/platform/windows/spec_helper.rb +720 -0
  157. data/spec/retryable_request_spec.rb +306 -0
  158. data/spec/secure_identity_spec.rb +50 -0
  159. data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
  160. data/spec/security/certificate_cache_spec.rb +71 -0
  161. data/spec/security/certificate_spec.rb +49 -0
  162. data/spec/security/distinguished_name_spec.rb +46 -0
  163. data/spec/security/encrypted_document_spec.rb +55 -0
  164. data/spec/security/rsa_key_pair_spec.rb +55 -0
  165. data/spec/security/signature_spec.rb +66 -0
  166. data/spec/security/static_certificate_store_spec.rb +58 -0
  167. data/spec/sender_spec.rb +1045 -0
  168. data/spec/serialize/message_pack_spec.rb +131 -0
  169. data/spec/serialize/secure_serializer_spec.rb +132 -0
  170. data/spec/serialize/serializable_spec.rb +90 -0
  171. data/spec/serialize/serializer_spec.rb +197 -0
  172. data/spec/spec.opts +2 -0
  173. data/spec/spec.win32.opts +1 -0
  174. data/spec/spec_helper.rb +130 -0
  175. data/spec/tracer_spec.rb +114 -0
  176. metadata +447 -0
@@ -0,0 +1,734 @@
1
+ #
2
+ # 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
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
+ require 'tmpdir'
25
+
26
+ def run_in_em(stop_event_loop = true)
27
+ EM.run do
28
+ yield
29
+ EM.stop_event_loop if stop_event_loop
30
+ end
31
+ end
32
+
33
+ describe RightScale::Agent do
34
+
35
+ include FlexMock::ArgumentTypes
36
+
37
+ describe "Default Option" do
38
+
39
+ before(:all) do
40
+ @log = flexmock(RightScale::Log)
41
+ @log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
42
+ flexmock(EM).should_receive(:next_tick).and_yield
43
+ flexmock(EM).should_receive(:add_timer).and_yield
44
+ @timer = flexmock("timer")
45
+ flexmock(EM::Timer).should_receive(:new).and_return(@timer)
46
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer)
47
+ @timer.should_receive(:cancel)
48
+ @broker = flexmock("broker", :subscribe => ["b1"], :publish => ["b1"], :prefetch => true,
49
+ :all => ["b1"], :connected => ["b1"], :failed => [], :close_one => true,
50
+ :non_delivery => true).by_default
51
+ @broker.should_receive(:connection_status).and_yield(:connected)
52
+ flexmock(RightAMQP::HABrokerClient).should_receive(:new).and_return(@broker)
53
+ @history = flexmock("history")
54
+ @history.should_receive(:update).and_return(true).by_default
55
+ flexmock(RightScale::History).should_receive(:new).and_return(@history)
56
+ flexmock(RightScale::PidFile).should_receive(:new).
57
+ and_return(flexmock("pid file", :check=>true, :write=>true, :remove=>true))
58
+ @identity = "rs-instance-123-1"
59
+ @agent = RightScale::Agent.new(:identity => @identity)
60
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
61
+ @agent.run
62
+ end
63
+
64
+ after(:each) do
65
+ FileUtils.rm_rf(File.normalize_path(File.join(@agent.options[:root_dir], 'config.yml'))) if @agent
66
+ end
67
+
68
+ it "for daemonize is false" do
69
+ @agent.options.should include(:daemonize)
70
+ @agent.options[:daemonize].should == false
71
+ end
72
+
73
+ it "for console is false" do
74
+ @agent.options.should include(:console)
75
+ @agent.options[:console].should == false
76
+ end
77
+
78
+ it "for user is agent" do
79
+ @agent.options.should include(:user)
80
+ @agent.options[:user].should == "agent"
81
+ end
82
+
83
+ it "for pass(word) is testing" do
84
+ @agent.options.should include(:pass)
85
+ @agent.options[:pass].should == "testing"
86
+ end
87
+
88
+ it "for secure is true" do
89
+ @agent.options.should include(:secure)
90
+ @agent.options[:secure].should == true
91
+ end
92
+
93
+ it "for log_level is info" do
94
+ @agent.options.should include(:log_level)
95
+ @agent.options[:log_level].should == :info
96
+ end
97
+
98
+ it "for vhost is /right_net" do
99
+ @agent.options.should include(:vhost)
100
+ @agent.options[:vhost].should == "/right_net"
101
+ end
102
+
103
+ it "for root_dir is #{Dir.pwd}" do
104
+ @agent.options.should include(:root_dir)
105
+ @agent.options[:root_dir].should == Dir.pwd
106
+ end
107
+
108
+ it "for heartbeat is 0" do
109
+ @agent.options.should include(:heartbeat)
110
+ @agent.options[:heartbeat].should == 0
111
+ end
112
+
113
+ end
114
+
115
+ describe "Options from config.yml" do
116
+
117
+ before(:all) do
118
+ @agent = RightScale::Agent.new(:identity => @identity)
119
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
120
+ @agent.run
121
+ end
122
+
123
+ after(:each) do
124
+ FileUtils.rm_rf(File.normalize_path(File.join(@agent.options[:root_dir], 'config.yml'))) if @agent
125
+ end
126
+
127
+ end
128
+
129
+ describe "Passed in Options" do
130
+
131
+ before(:each) do
132
+ @log = flexmock(RightScale::Log)
133
+ @log.should_receive(:error).never.by_default
134
+ flexmock(EM).should_receive(:next_tick).and_yield
135
+ flexmock(EM).should_receive(:add_timer).and_yield
136
+ @timer = flexmock("timer")
137
+ flexmock(EM::Timer).should_receive(:new).and_return(@timer)
138
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@timer)
139
+ @timer.should_receive(:cancel)
140
+ @broker = flexmock("broker", :subscribe => ["b1"], :publish => ["b1"], :prefetch => true,
141
+ :connected => ["b1"], :failed => [], :all => ["b0", "b1"],
142
+ :non_delivery => true).by_default
143
+ @broker.should_receive(:connection_status).and_yield(:connected)
144
+ flexmock(RightAMQP::HABrokerClient).should_receive(:new).and_return(@broker)
145
+ @history = flexmock("history")
146
+ @history.should_receive(:update).and_return(true).by_default
147
+ flexmock(RightScale::History).should_receive(:new).and_return(@history)
148
+ flexmock(RightScale::PidFile).should_receive(:new).
149
+ and_return(flexmock("pid file", :check=>true, :write=>true, :remove=>true))
150
+ @identity = "rs-instance-123-1"
151
+ @agent = nil
152
+ end
153
+
154
+ after(:each) do
155
+ FileUtils.rm_rf(File.normalize_path(File.join(@agent.options[:root_dir], 'config.yml'))) if @agent
156
+ end
157
+
158
+ it "for user should override default (agent)" do
159
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
160
+ @agent.options.should include(:user)
161
+ @agent.options[:user].should == "me"
162
+ end
163
+
164
+ it "for pass(word) should override default (testing)" do
165
+ @agent = RightScale::Agent.new(:pass => "secret", :identity => @identity)
166
+ @agent.options.should include(:pass)
167
+ @agent.options[:pass].should == "secret"
168
+ end
169
+
170
+ it "for secure should override default (false)" do
171
+ @agent = RightScale::Agent.new(:secure => true, :identity => @identity)
172
+ @agent.options.should include(:secure)
173
+ @agent.options[:secure].should == true
174
+ end
175
+
176
+ it "for host should override default (localhost)" do
177
+ @agent = RightScale::Agent.new(:host => "127.0.0.1", :identity => @identity)
178
+ @agent.options.should include(:host)
179
+ @agent.options[:host].should == "127.0.0.1"
180
+ end
181
+
182
+ it "for log_dir" do
183
+ # testing path, remove it before the test to verify the directory is
184
+ # actually created
185
+ test_log_path = File.normalize_path(File.join(Dir.tmpdir, "right_net", "testing"))
186
+ FileUtils.rm_rf(test_log_path)
187
+
188
+ @agent = RightScale::Agent.new(:log_dir => File.normalize_path(File.join(Dir.tmpdir, "right_net", "testing")),
189
+ :identity => @identity)
190
+
191
+ # passing log_dir will cause log_path to be set to the same value and the
192
+ # directory wil be created
193
+ @agent.options.should include(:log_dir)
194
+ @agent.options[:log_dir].should == test_log_path
195
+
196
+ @agent.options.should include(:log_path)
197
+ @agent.options[:log_path].should == test_log_path
198
+
199
+ File.directory?(@agent.options[:log_path]).should == true
200
+ end
201
+
202
+ it "for log_level should override default (info)" do
203
+ @agent = RightScale::Agent.new(:log_level => :debug, :identity => @identity)
204
+ @agent.options.should include(:log_level)
205
+ @agent.options[:log_level].should == :debug
206
+ end
207
+
208
+ it "for vhost should override default (/right_net)" do
209
+ @agent = RightScale::Agent.new(:vhost => "/virtual_host", :identity => @identity)
210
+ @agent.options.should include(:vhost)
211
+ @agent.options[:vhost].should == "/virtual_host"
212
+ end
213
+
214
+ it "for ping_time should override default (15)" do
215
+ @agent = RightScale::Agent.new(:ping_time => 5, :identity => @identity)
216
+ @agent.options.should include(:ping_time)
217
+ @agent.options[:ping_time].should == 5
218
+ end
219
+
220
+ it "for heartbeat should override default (60)" do
221
+ @agent = RightScale::Agent.new(:heartbeat => 45, :identity => @identity)
222
+ @agent.options.should include(:heartbeat)
223
+ @agent.options[:heartbeat].should == 45
224
+ end
225
+
226
+ it "for root_dir should override default (#{File.dirname(__FILE__)})" do
227
+ root_dir = File.normalize_path(File.join(File.dirname(__FILE__), '..', '..'))
228
+ @agent = RightScale::Agent.new(:root_dir => root_dir, :identity => @identity)
229
+ @agent.options.should include(:root_dir)
230
+ @agent.options[:root_dir].should == root_dir
231
+ end
232
+
233
+ it "for a single tag should result in the agent's tags being set" do
234
+ @agent = RightScale::Agent.new(:tag => "sample_tag", :identity => @identity)
235
+ @agent.tags.should include("sample_tag")
236
+ end
237
+
238
+ it "for multiple tags should result in the agent's tags being set" do
239
+ @agent = RightScale::Agent.new(:tag => ["sample_tag_1", "sample_tag_2"], :identity => @identity)
240
+ @agent.tags.should include("sample_tag_1")
241
+ @agent.tags.should include("sample_tag_2")
242
+ end
243
+
244
+ end
245
+
246
+ describe "" do
247
+
248
+ before(:each) do
249
+ @log = flexmock(RightScale::Log)
250
+ @log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
251
+ flexmock(EM).should_receive(:next_tick).and_yield
252
+ flexmock(EM).should_receive(:add_timer).and_yield
253
+ @timer = flexmock("timer")
254
+ flexmock(EM::Timer).should_receive(:new).and_return(@timer).by_default
255
+ @timer.should_receive(:cancel).by_default
256
+ @periodic_timer = flexmock("timer")
257
+ flexmock(EM::PeriodicTimer).should_receive(:new).and_return(@periodic_timer)
258
+ @periodic_timer.should_receive(:cancel).by_default
259
+ @broker_id = "rs-broker-123-1"
260
+ @broker_id2 = "rs-broker-123-2"
261
+ @broker_ids = [@broker_id, @broker_id2]
262
+ @broker = flexmock("broker", :subscribe => @broker_ids, :publish => @broker_ids.first(1), :prefetch => true,
263
+ :all => @broker_ids, :connected => @broker_ids.first(1), :failed => @broker_ids.last(1),
264
+ :unusable => @broker_ids.last(1), :close_one => true, :non_delivery => true,
265
+ :stats => "", :status => "status", :hosts => ["123"], :ports => [1, 2], :get => true,
266
+ :alias_ => "b1", :aliases => ["b1"]).by_default
267
+ @broker.should_receive(:connection_status).and_yield(:connected).by_default
268
+ @broker.should_receive(:identity_parts).with(@broker_id).and_return(["123", 1, 0, 0])
269
+ @broker.should_receive(:identity_parts).with(@broker_id2).and_return(["123", 2, 1, 1])
270
+ flexmock(RightAMQP::HABrokerClient).should_receive(:new).and_return(@broker)
271
+ flexmock(RightScale::PidFile).should_receive(:new).
272
+ and_return(flexmock("pid file", :check=>true, :write=>true, :remove=>true))
273
+ @history = flexmock("history")
274
+ @history.should_receive(:update).and_return(true).by_default
275
+ @history.should_receive(:analyze_service).and_return({}).by_default
276
+ flexmock(RightScale::History).should_receive(:new).and_return(@history)
277
+ @header = flexmock("amqp header")
278
+ @header.should_receive(:ack).by_default
279
+ @sender = flexmock("sender", :pending_requests => [], :request_age => nil,
280
+ :message_received => true, :stats => "").by_default
281
+ @sender.should_receive(:terminate).and_return([0, 0]).by_default
282
+ flexmock(RightScale::Sender).should_receive(:new).and_return(@sender)
283
+ @dispatcher = flexmock("dispatcher", :dispatch_age => nil, :dispatch => true, :stats => "").by_default
284
+ flexmock(RightScale::Dispatcher).should_receive(:new).and_return(@dispatcher)
285
+ @identity = "rs-instance-123-1"
286
+ @agent = RightScale::Agent.new(:user => "tester", :identity => @identity)
287
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
288
+ end
289
+
290
+ after(:each) do
291
+ FileUtils.rm_rf(File.normalize_path(File.join(@agent.options[:root_dir], 'config.yml'))) if @agent
292
+ end
293
+
294
+ describe "Setting up queues" do
295
+
296
+ it "should subscribe to identity queue using identity exchange" do
297
+ run_in_em do
298
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).and_return(@broker_ids).once
299
+ @agent.run
300
+ end
301
+ end
302
+
303
+ it "should try to finish setup by connecting to failed brokers when check status" do
304
+ run_in_em do
305
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
306
+ and_return(@broker_ids.first(1)).once
307
+ @broker.should_receive(:queue_status).with([@identity], 30).once
308
+ @agent.run
309
+ @agent.instance_variable_get(:@remaining_queue_setup).should == {@identity => @broker_ids.last(1)}
310
+ @sender.should_receive(:send_push).with("/registrar/connect", {:agent_identity => @identity, :host => "123",
311
+ :port => 2, :id => 1, :priority => 1}).once
312
+ @agent.send(:check_status)
313
+ end
314
+ end
315
+
316
+ it "should try to connect to broker when requested" do
317
+ run_in_em do
318
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
319
+ and_return(@broker_ids.first(1)).once
320
+ @agent.run
321
+ @broker.should_receive(:connect).with("123", 2, 1, 1, false, Proc).once
322
+ @agent.connect("123", 2, 1, 1)
323
+ end
324
+ end
325
+
326
+ it "should setup queues and update configuration when successfully connect to broker" do
327
+ run_in_em do
328
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
329
+ and_return(@broker_ids.first(1)).once
330
+ @agent.run
331
+ @broker.should_receive(:connect).with("123", 2, 1, 1, false, Proc).and_yield(@broker_ids.last).once
332
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => @broker_ids.last(1)), Proc).
333
+ and_return(@broker_ids.last(1)).once
334
+ flexmock(@agent).should_receive(:update_configuration).with(:host => ["123"], :port => [1, 2]).and_return(true).once
335
+ @agent.connect("123", 2, 1, 1)
336
+ end
337
+ end
338
+
339
+ it "should update history with start and then run when agent is for service" do
340
+ @history.should_receive(:update).with("start").and_return(true).ordered.once
341
+ flexmock(@agent).should_receive(:setup_queues).ordered.once
342
+ @history.should_receive(:update).with("run").and_return(true).ordered.once
343
+ @agent.run
344
+ end
345
+
346
+ it "should log error if fail to connect to broker" do
347
+ run_in_em do
348
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
349
+ and_return(@broker_ids.first(1)).once
350
+ @agent.run
351
+ @broker.should_receive(:connect).with("123", 2, 1, 1, false, Proc).and_yield(@broker_ids.last).once
352
+ @broker.should_receive(:connection_status).and_yield(:failed)
353
+ @log.should_receive(:error).with(/Failed to connect to broker/).once
354
+ flexmock(@agent).should_receive(:update_configuration).never
355
+ @agent.connect("123", 2, 1, 1)
356
+ end
357
+ end
358
+
359
+ it "should disconnect from broker when requested" do
360
+ run_in_em do
361
+ @broker.should_receive(:connected).and_return(@broker_ids)
362
+ @broker.should_receive(:failed).and_return([])
363
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
364
+ and_return(@broker_ids).once
365
+ @agent.run
366
+ @broker.should_receive(:close_one).with(@broker_ids.last).once
367
+ @agent.disconnect("123", 2)
368
+ end
369
+ end
370
+
371
+ it "should remove broker from configuration if requested" do
372
+ run_in_em do
373
+ @broker.should_receive(:connected).and_return(@broker_ids)
374
+ @broker.should_receive(:failed).and_return([])
375
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
376
+ and_return(@broker_ids).once
377
+ @agent.run
378
+ @broker.should_receive(:remove).with("123", 2, Proc).and_yield(@broker_ids.last).once
379
+ @broker.should_receive(:ports).and_return([1])
380
+ flexmock(@agent).should_receive(:update_configuration).with(:host => ["123"], :port => [1]).and_return(true).once
381
+ @agent.disconnect("123", 2, remove = true)
382
+ end
383
+ end
384
+
385
+ it "should not disconnect broker if it is the last connected broker" do
386
+ run_in_em do
387
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, hsh(:brokers => nil), Proc).
388
+ and_return(@broker_ids.first(1)).once
389
+ @agent.run
390
+ @broker.should_receive(:remove).never
391
+ @broker.should_receive(:close_one).never
392
+ flexmock(@agent).should_receive(:update_configuration).never
393
+ @log.should_receive(:error).with(/Not disconnecting.*last connected broker/).once
394
+ @agent.disconnect("123", 1)
395
+ end
396
+ end
397
+
398
+ it "should declare broker connection unusable if requested to do so" do
399
+ run_in_em do
400
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).and_return(@broker_ids).once
401
+ @agent.run
402
+ @broker.should_receive(:declare_unusable).with(@broker_ids.last(1)).once
403
+ @agent.connect_failed(@broker_ids.last(1))
404
+ end
405
+ end
406
+
407
+ it "should not declare a broker connection unusable if currently connected" do
408
+ run_in_em do
409
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).and_return(@broker_ids).once
410
+ @agent.run
411
+ @broker.should_receive(:declare_unusable).with([]).once
412
+ @agent.connect_failed(@broker_ids.first(1))
413
+ end
414
+ end
415
+
416
+ end
417
+
418
+ describe "Handling messages" do
419
+
420
+ it "should use dispatcher to handle requests" do
421
+ run_in_em do
422
+ request = RightScale::Request.new("/foo/bar", "payload")
423
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
424
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
425
+ @dispatcher.should_receive(:dispatch).with(request).once
426
+ @agent.run
427
+ end
428
+ end
429
+
430
+ it "should publish result from dispatched request to request reply_to" do
431
+ run_in_em do
432
+ request = RightScale::Request.new("/foo/bar", "payload", {:reply_to => "response"})
433
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
434
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
435
+ result = flexmock("result")
436
+ @dispatcher.should_receive(:dispatch).with(request).and_return(result).once
437
+ @broker.should_receive(:publish).with(hsh(:name => "response"), result,
438
+ hsh(:persistent => true, :mandatory => true)).once
439
+ @agent.run
440
+ end
441
+ end
442
+
443
+ it "should not publish result from dispatched request if there is none" do
444
+ run_in_em do
445
+ request = RightScale::Request.new("/foo/bar", "payload")
446
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
447
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
448
+ @dispatcher.should_receive(:dispatch).with(request).and_return(nil).once
449
+ @broker.should_receive(:publish).never
450
+ @agent.run
451
+ end
452
+ end
453
+
454
+ it "should ignore dispatcher duplicate request errors" do
455
+ run_in_em do
456
+ request = RightScale::Request.new("/foo/bar", "payload")
457
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
458
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
459
+ @dispatcher.should_receive(:dispatch).and_raise(RightScale::Dispatcher::DuplicateRequest).once
460
+ @agent.run
461
+ end
462
+ end
463
+
464
+ it "should use sender to handle results" do
465
+ run_in_em do
466
+ result = RightScale::Result.new("token", "to", "results", "from")
467
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
468
+ and_return(@broker_ids).and_yield(@broker_id, result, @header).once
469
+ @sender.should_receive(:handle_response).with(result).once
470
+ @agent.run
471
+ end
472
+ end
473
+
474
+ it "should notify sender when a message is received" do
475
+ run_in_em do
476
+ result = RightScale::Result.new("token", "to", "results", "from")
477
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
478
+ and_return(@broker_ids).and_yield(@broker_id, result, @header).once
479
+ @sender.should_receive(:handle_response).with(result).once
480
+ @sender.should_receive(:message_received).once
481
+ @agent.run
482
+ end
483
+ end
484
+
485
+ it "should ignore and ack unrecognized messages" do
486
+ run_in_em do
487
+ request = RightScale::Stats.new(nil, nil)
488
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
489
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
490
+ @dispatcher.should_receive(:dispatch).never
491
+ @header.should_receive(:ack).once
492
+ @agent.run
493
+ end
494
+ end
495
+
496
+ it "should ack if request dispatch fails" do
497
+ run_in_em do
498
+ request = RightScale::Request.new("/foo/bar", "payload")
499
+ @log.should_receive(:error).with(/Failed to dispatch request/, Exception, :trace).once
500
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
501
+ and_return(@broker_ids).and_yield(@broker_id, request, @header).once
502
+ @dispatcher.should_receive(:dispatch).and_raise(Exception)
503
+ @header.should_receive(:ack).once
504
+ @agent.run
505
+ end
506
+ end
507
+
508
+ it "should ack if response delivery fails" do
509
+ run_in_em do
510
+ result = RightScale::Result.new("token", "to", "results", "from")
511
+ @log.should_receive(:error).with(/Failed to deliver response/, Exception, :trace).once
512
+ @broker.should_receive(:subscribe).with(hsh(:name => @identity), nil, Hash, Proc).
513
+ and_return(@broker_ids).and_yield(@broker_id, result, @header).once
514
+ @sender.should_receive(:handle_response).and_raise(Exception)
515
+ @header.should_receive(:ack).once
516
+ @agent.run
517
+ end
518
+ end
519
+
520
+ end
521
+
522
+ describe "Terminating" do
523
+
524
+ it "should log error for abnormal termination" do
525
+ run_in_em do
526
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
527
+ @broker.should_receive(:nil?).and_return(true)
528
+ @log.should_receive(:error).with("[stop] Terminating because just because", nil, :trace).once
529
+ @agent.terminate("just because")
530
+ end
531
+ end
532
+
533
+ it "should log error plus exception for abnormal termination" do
534
+ run_in_em do
535
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
536
+ @broker.should_receive(:nil?).and_return(true)
537
+ @log.should_receive(:error).with(/Terminating because just because/, Exception, :trace).once
538
+ @agent.terminate("just because", Exception.new("error"))
539
+ end
540
+ end
541
+
542
+ it "should sleep before an abnormal termination that is following a crash" do
543
+ run_in_em do
544
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
545
+ @broker.should_receive(:nil?).and_return(true)
546
+ @log.should_receive(:error).with(/Terminating because just because/, Exception, :trace).once
547
+ @log.should_receive(:info).with(/Delaying termination for 10 sec/).once.ordered
548
+ @log.should_receive(:info).with(/Terminating immediately/).once.ordered
549
+ now = Time.now
550
+ flexmock(Time).should_receive(:now).and_return(now)
551
+ flexmock(@agent.instance_variable_get(:@history)).should_receive(:analyze_service).
552
+ and_return({:last_crashed => true, :last_crash_time => now.to_i - 5}).once
553
+ flexmock(@agent).should_receive(:sleep).with(10).once
554
+ @agent.terminate("just because", Exception.new("error"))
555
+ end
556
+ end
557
+
558
+ it "should limit the sleep time before an abnormal termination" do
559
+ run_in_em do
560
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
561
+ @broker.should_receive(:nil?).and_return(true)
562
+ @log.should_receive(:error).with(/Terminating because just because/, Exception, :trace).once
563
+ @log.should_receive(:info).with(/Delaying termination for 60 min 0 sec/).once.ordered
564
+ @log.should_receive(:info).with(/Terminating immediately/).once.ordered
565
+ now = Time.now
566
+ flexmock(Time).should_receive(:now).and_return(now)
567
+ flexmock(@agent.instance_variable_get(:@history)).should_receive(:analyze_service).
568
+ and_return({:last_crashed => true, :last_crash_time => now.to_i - 1801}).once
569
+ flexmock(@agent).should_receive(:sleep).with(3600).once
570
+ @agent.terminate("just because", Exception.new("error"))
571
+ end
572
+ end
573
+
574
+ it "should close unusable broker connections at start of termination" do
575
+ @broker.should_receive(:unusable).and_return(["rs-broker-123-1"]).once
576
+ @broker.should_receive(:close_one).with("rs-broker-123-1", false).once
577
+ run_in_em do
578
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
579
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
580
+ @agent.run
581
+ @agent.terminate
582
+ end
583
+ end
584
+
585
+ it "should wait to terminate if there are recent unfinished requests" do
586
+ @sender.should_receive(:terminate).and_return([1, 10]).once
587
+ flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).once
588
+ run_in_em do
589
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
590
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
591
+ @agent.run
592
+ @agent.terminate
593
+ end
594
+ end
595
+
596
+ it "should log that terminating and then log the reason for waiting to terminate" do
597
+ @sender.should_receive(:terminate).and_return([1, 21]).once
598
+ flexmock(EM::Timer).should_receive(:new).with(9, Proc).and_return(@timer).once
599
+ run_in_em do
600
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
601
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
602
+ @agent.run
603
+ @log.should_receive(:info).with(/Agent rs-instance-123-1 terminating/).once
604
+ @log.should_receive(:info).with(/Termination waiting 9 seconds for/).once
605
+ @agent.terminate
606
+ end
607
+ end
608
+
609
+ it "should not log reason for waiting to terminate if no need to wait" do
610
+ @sender.should_receive(:terminate).and_return([0, nil]).twice
611
+ @broker.should_receive(:close).once
612
+ flexmock(EM::Timer).should_receive(:new).with(0, Proc).never
613
+ run_in_em do
614
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
615
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
616
+ @agent.run
617
+ @log.should_receive(:info).with(/Agent rs-instance-123-1 terminating/).once
618
+ @log.should_receive(:info).with(/Termination waiting/).never
619
+ @agent.terminate
620
+ end
621
+ end
622
+
623
+ it "should continue with termination after waiting and log that continuing" do
624
+ @sender.should_receive(:terminate).and_return([1, 10]).twice
625
+ @sender.should_receive(:dump_requests).and_return(["request"]).once
626
+ @broker.should_receive(:close).once
627
+ flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).and_yield.once
628
+ run_in_em do
629
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
630
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
631
+ @agent.run
632
+ @log.should_receive(:info).with(/Agent rs-instance-123-1 terminating/).once
633
+ @log.should_receive(:info).with(/Termination waiting/).once
634
+ @log.should_receive(:info).with(/Continuing with termination/).once
635
+ @log.should_receive(:info).with(/The following 1 request/).once
636
+ @agent.terminate
637
+ end
638
+ end
639
+
640
+ it "should execute block after all brokers have been closed" do
641
+ @sender.should_receive(:terminate).and_return([1, 10]).twice
642
+ @sender.should_receive(:dump_requests).and_return(["request"]).once
643
+ @broker.should_receive(:close).and_yield.once
644
+ flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).and_yield.once
645
+ run_in_em do
646
+ called = 0
647
+ callback = lambda { called += 1}
648
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
649
+ @agent.instance_variable_set(:@terminate_callback, callback)
650
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
651
+ @agent.run
652
+ @agent.terminate
653
+ called.should == 1
654
+ end
655
+ end
656
+
657
+ it "should stop EM if no block specified" do
658
+ @sender.should_receive(:terminate).and_return([1, 10]).twice
659
+ @sender.should_receive(:dump_requests).and_return(["request"]).once
660
+ @broker.should_receive(:close).and_yield.once
661
+ flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).and_yield.once
662
+ run_in_em(stop_event_loop = false) do
663
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
664
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
665
+ @agent.run
666
+ @agent.terminate
667
+ end
668
+ end
669
+
670
+ it "should terminate immediately if broker not initialized" do
671
+ run_in_em do
672
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
673
+ @log.should_receive(:info).with("[stop] Terminating immediately").once
674
+ @agent.terminate
675
+ end
676
+ end
677
+
678
+ it "should terminate immediately if called a second time but should still execute block" do
679
+ @sender.should_receive(:terminate).and_return([1, 10]).once
680
+ flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).once
681
+ @timer.should_receive(:cancel).once
682
+ @periodic_timer.should_receive(:cancel).once
683
+ run_in_em do
684
+ called = 0
685
+ callback = lambda { called += 1}
686
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
687
+ @agent.instance_variable_set(:@terminate_callback, callback)
688
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
689
+ @agent.run
690
+ @agent.terminate
691
+ called.should == 0
692
+ @agent.terminate
693
+ called.should == 1
694
+ end
695
+ end
696
+
697
+ it "should update history with stop and graceful exit if broker not initialized" do
698
+ run_in_em do
699
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
700
+ @log.should_receive(:error).once
701
+ @history.should_receive(:update).with("stop").and_return(true).ordered.once
702
+ @history.should_receive(:update).with("graceful exit").and_return(true).ordered.once
703
+ @agent.terminate("just because")
704
+ end
705
+ end
706
+
707
+ it "should update history with stop but not graceful exit if called a second time to terminate immediately" do
708
+ run_in_em do
709
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
710
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
711
+ @agent.run
712
+ @agent.instance_variable_set(:@terminating, true)
713
+ @history.should_receive(:update).with("stop").and_return(true).once
714
+ @history.should_receive(:update).with("graceful exit").never
715
+ @agent.terminate
716
+ end
717
+ end
718
+
719
+ it "should update history with stop and graceful exit if gracefully terminate" do
720
+ run_in_em do
721
+ @agent = RightScale::Agent.new(:user => "me", :identity => @identity)
722
+ flexmock(@agent).should_receive(:load_actors).and_return(true)
723
+ @agent.run
724
+ @history.should_receive(:update).with("stop").and_return(true).ordered.once
725
+ @history.should_receive(:update).with("graceful exit").and_return(true).ordered.once
726
+ @agent.terminate
727
+ end
728
+ end
729
+
730
+ end
731
+
732
+ end
733
+
734
+ end