mcollective-client 2.6.1 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/mcollective.rb +2 -1
- data/lib/mcollective/client.rb +32 -6
- data/lib/mcollective/config.rb +4 -0
- data/lib/mcollective/exceptions.rb +2 -1
- data/lib/mcollective/message.rb +15 -2
- data/lib/mcollective/monkey_patches.rb +1 -1
- data/lib/mcollective/optionparser.rb +4 -0
- data/lib/mcollective/pluginpackager.rb +9 -0
- data/lib/mcollective/pluginpackager/agent_definition.rb +3 -3
- data/lib/mcollective/pluginpackager/standard_definition.rb +1 -1
- data/lib/mcollective/rpc/actionrunner.rb +21 -5
- data/lib/mcollective/rpc/client.rb +16 -16
- data/lib/mcollective/vendor/require_vendored.rb +0 -1
- data/spec/unit/client_spec.rb +81 -55
- data/spec/unit/message_spec.rb +30 -0
- data/spec/unit/optionparser_spec.rb +6 -0
- data/spec/unit/pluginpackager/agent_definition_spec.rb +21 -2
- data/spec/unit/pluginpackager/standard_definition_spec.rb +5 -1
- data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +11 -2
- data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +22 -5
- data/spec/unit/plugins/mcollective/data/collective_data_spec.rb +33 -0
- data/spec/unit/plugins/mcollective/packagers/modulepackage_packager_spec.rb +5 -0
- data/spec/unit/rpc/actionrunner_spec.rb +36 -7
- data/spec/unit/rpc/client_spec.rb +165 -31
- data/spec/unit/runner_spec.rb +18 -0
- metadata +228 -234
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5c24db8c899fd482feae76bea713511b792381c2
|
4
|
+
data.tar.gz: f5d522ecc91fa9f26758a1c6cd0cb42cb729d191
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f0d0d69945a17275b37071b4f81d77782f17fa7a011d4142c51ccff5419945fd03d91102533dbe9edc311b5bec8b81f28b5385e33c44c9ddf39908d0f56e822e
|
7
|
+
data.tar.gz: 6493eb3a377883e6d9c788cef263fd2bfdb4ae3b6c029f00b333f4518fd41f5125d2c2677287beb83e52de5c784143f90d80de2c0552a6427f1824083e63643e
|
data/lib/mcollective.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'json'
|
2
3
|
require 'stomp'
|
3
4
|
require 'timeout'
|
4
5
|
require 'digest/md5'
|
@@ -59,7 +60,7 @@ module MCollective
|
|
59
60
|
|
60
61
|
MCollective::Vendor.load_vendored
|
61
62
|
|
62
|
-
VERSION="
|
63
|
+
VERSION="2.7.0"
|
63
64
|
|
64
65
|
def self.version
|
65
66
|
VERSION
|
data/lib/mcollective/client.rb
CHANGED
@@ -1,21 +1,44 @@
|
|
1
1
|
module MCollective
|
2
2
|
# Helpers for writing clients that can talk to agents, do discovery and so forth
|
3
3
|
class Client
|
4
|
-
attr_accessor :options, :stats, :discoverer
|
4
|
+
attr_accessor :options, :stats, :discoverer, :connection_timeout
|
5
5
|
|
6
|
-
def initialize(
|
6
|
+
def initialize(options)
|
7
7
|
@config = Config.instance
|
8
|
-
@
|
8
|
+
@options = nil
|
9
|
+
|
10
|
+
if options.is_a?(String)
|
11
|
+
# String is the path to a config file
|
12
|
+
@config.loadconfig(options) unless @config.configured
|
13
|
+
elsif options.is_a?(Hash)
|
14
|
+
@config.loadconfig(options[:config]) unless @config.configured
|
15
|
+
@options = options
|
16
|
+
@connection_timeout = options[:connection_timeout]
|
17
|
+
else
|
18
|
+
raise "Invalid parameter passed to Client constructor. Valid types are Hash or String"
|
19
|
+
end
|
20
|
+
|
21
|
+
@connection_timeout ||= @config.connection_timeout
|
9
22
|
|
10
23
|
@connection = PluginManager["connector_plugin"]
|
11
24
|
@security = PluginManager["security_plugin"]
|
12
25
|
|
13
26
|
@security.initiated_by = :client
|
14
|
-
@options = nil
|
15
27
|
@subscriptions = {}
|
16
28
|
|
17
29
|
@discoverer = Discovery.new(self)
|
18
|
-
|
30
|
+
|
31
|
+
# Time box the connection if a timeout has been specified
|
32
|
+
# connection_timeout defaults to nil which means it will try forever if
|
33
|
+
# not specified
|
34
|
+
begin
|
35
|
+
Timeout::timeout(@connection_timeout, ClientTimeoutError) do
|
36
|
+
@connection.connect
|
37
|
+
end
|
38
|
+
rescue ClientTimeoutError => e
|
39
|
+
Log.error("Timeout occured while trying to connect to middleware")
|
40
|
+
raise e
|
41
|
+
end
|
19
42
|
end
|
20
43
|
|
21
44
|
@@request_sequence = 0
|
@@ -101,9 +124,12 @@ module MCollective
|
|
101
124
|
reply.expected_msgid = requestid
|
102
125
|
|
103
126
|
reply.decode!
|
127
|
+
|
104
128
|
unless reply.requestid == requestid
|
105
129
|
raise(MsgDoesNotMatchRequestID, "Message reqid #{reply.requestid} does not match our reqid #{requestid}")
|
106
130
|
end
|
131
|
+
|
132
|
+
Log.debug("Received reply to #{reply.requestid} from #{reply.payload[:senderid]}")
|
107
133
|
rescue SecurityValidationFailed => e
|
108
134
|
Log.warn("Ignoring a message that did not pass security validations")
|
109
135
|
retry
|
@@ -122,7 +148,7 @@ module MCollective
|
|
122
148
|
# of the discovery being cancelled soon as it reached the
|
123
149
|
# requested limit of hosts
|
124
150
|
def discover(filter, timeout, limit=0)
|
125
|
-
|
151
|
+
@discoverer.discover(filter.merge({'collective' => collective}), timeout, limit)
|
126
152
|
end
|
127
153
|
|
128
154
|
# Send a request, performs the passed block for each response
|
data/lib/mcollective/config.rb
CHANGED
@@ -17,6 +17,7 @@ module MCollective
|
|
17
17
|
attr_reader :default_discovery_method, :default_discovery_options
|
18
18
|
attr_reader :publish_timeout, :threaded, :soft_shutdown, :activate_agents
|
19
19
|
attr_reader :registration_splay, :discovery_timeout, :soft_shutdown_timeout
|
20
|
+
attr_reader :connection_timeout
|
20
21
|
|
21
22
|
def initialize
|
22
23
|
@configured = false
|
@@ -94,6 +95,8 @@ module MCollective
|
|
94
95
|
@discovery_timeout = Integer(val)
|
95
96
|
when "publish_timeout"
|
96
97
|
@publish_timeout = Integer(val)
|
98
|
+
when "connection_timeout"
|
99
|
+
@connection_timeout = Integer(val)
|
97
100
|
when "rpcaudit"
|
98
101
|
@rpcaudit = Util.str_to_bool(val)
|
99
102
|
when "rpcauditprovider"
|
@@ -205,6 +208,7 @@ module MCollective
|
|
205
208
|
@soft_shutdown = false
|
206
209
|
@soft_shutdown_timeout = nil
|
207
210
|
@activate_agents = true
|
211
|
+
@connection_timeout = nil
|
208
212
|
end
|
209
213
|
|
210
214
|
def read_plugin_config_dir(dir)
|
@@ -2,8 +2,9 @@ module MCollective
|
|
2
2
|
# Exceptions for the RPC system
|
3
3
|
class DDLValidationError<RuntimeError;end
|
4
4
|
class ValidatorError<RuntimeError; end
|
5
|
+
class ClientTimeoutError<RuntimeError; end
|
5
6
|
class MsgDoesNotMatchRequestID < RuntimeError; end
|
6
|
-
class MsgTTLExpired<RuntimeError;end
|
7
|
+
class MsgTTLExpired<RuntimeError;end
|
7
8
|
class NotTargettedAtUs<RuntimeError;end
|
8
9
|
class RPCError<StandardError;end
|
9
10
|
class SecurityValidationFailed<RuntimeError;end
|
data/lib/mcollective/message.rb
CHANGED
@@ -175,7 +175,21 @@ module MCollective
|
|
175
175
|
def decode!
|
176
176
|
raise "Cannot decode message type #{type}" unless [:request, :reply].include?(type)
|
177
177
|
|
178
|
-
|
178
|
+
begin
|
179
|
+
@payload = PluginManager["security_plugin"].decodemsg(self)
|
180
|
+
rescue Exception => e
|
181
|
+
if type == :request
|
182
|
+
# If we're a server receiving a request, reraise
|
183
|
+
raise(e)
|
184
|
+
else
|
185
|
+
# We're in the client, log and carry on as best we can
|
186
|
+
|
187
|
+
# Note: mc_sender is unverified. The verified identity is in the
|
188
|
+
# payload we just failed to decode
|
189
|
+
Log.warn("Failed to decode a message from '#{headers["mc_sender"]}': #{e}")
|
190
|
+
return
|
191
|
+
end
|
192
|
+
end
|
179
193
|
|
180
194
|
if type == :request
|
181
195
|
raise 'callerid in request is not valid, surpressing reply to potentially forged request' unless PluginManager["security_plugin"].valid_callerid?(payload[:callerid])
|
@@ -203,7 +217,6 @@ module MCollective
|
|
203
217
|
raise(MsgTTLExpired, "message #{requestid} from #{cid} created at #{msgtime} is #{msg_age} seconds old, TTL is #{ttl}. Rejecting message.")
|
204
218
|
end
|
205
219
|
end
|
206
|
-
|
207
220
|
raise(NotTargettedAtUs, "Received message is not targetted to us") unless PluginManager["security_plugin"].validate_filter?(payload[:filter])
|
208
221
|
|
209
222
|
@validated = true
|
@@ -181,6 +181,10 @@ module MCollective
|
|
181
181
|
@parser.on("--sort", "Sort the output of an RPC call before processing.") do |v|
|
182
182
|
@options[:sort] = true
|
183
183
|
end
|
184
|
+
|
185
|
+
@parser.on("--connection-timeout TIMEOUT", Integer, "Set the timeout for establishing a connection to the middleware") do |v|
|
186
|
+
@options[:connection_timeout] = Integer(v)
|
187
|
+
end
|
184
188
|
end
|
185
189
|
|
186
190
|
private
|
@@ -85,5 +85,14 @@ module MCollective
|
|
85
85
|
end
|
86
86
|
end.reject{ |dependency| dependency == nil }
|
87
87
|
end
|
88
|
+
|
89
|
+
# Return the path to a plugin's core directories
|
90
|
+
def self.get_plugin_path(target)
|
91
|
+
if (File.exists?(File.join(target, "lib", "mcollective")))
|
92
|
+
return File.join(target, "lib", "mcollective")
|
93
|
+
end
|
94
|
+
|
95
|
+
return target
|
96
|
+
end
|
88
97
|
end
|
89
98
|
end
|
@@ -7,7 +7,7 @@ module MCollective
|
|
7
7
|
|
8
8
|
def initialize(configuration, mcdependency, plugintype)
|
9
9
|
@plugintype = plugintype
|
10
|
-
@path = configuration[:target]
|
10
|
+
@path = PluginPackager.get_plugin_path(configuration[:target])
|
11
11
|
@packagedata = {}
|
12
12
|
@revision = configuration[:revision] || 1
|
13
13
|
@preinstall = configuration[:preinstall]
|
@@ -42,9 +42,9 @@ module MCollective
|
|
42
42
|
|
43
43
|
agentdir = File.join(@path, "agent")
|
44
44
|
|
45
|
-
if PluginPackager.check_dir_present
|
45
|
+
if (PluginPackager.check_dir_present(agentdir))
|
46
46
|
ddls = Dir.glob(File.join(agentdir, "*.ddl"))
|
47
|
-
agent[:files] = (Dir.glob(File.join(agentdir, "
|
47
|
+
agent[:files] = (Dir.glob(File.join(agentdir, "**", "**")) - ddls)
|
48
48
|
else
|
49
49
|
return nil
|
50
50
|
end
|
@@ -6,7 +6,7 @@ module MCollective
|
|
6
6
|
|
7
7
|
def initialize(configuration, mcdependency, plugintype)
|
8
8
|
@plugintype = plugintype
|
9
|
-
@path = configuration[:target]
|
9
|
+
@path = PluginPackager.get_plugin_path(configuration[:target])
|
10
10
|
@packagedata = {}
|
11
11
|
@revision = configuration[:revision] || 1
|
12
12
|
@preinstall = configuration[:preinstall]
|
@@ -127,15 +127,31 @@ module MCollective
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def path_to_command(command)
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
if Util.absolute_path?(command)
|
131
|
+
return command
|
132
|
+
end
|
133
133
|
|
134
|
-
|
134
|
+
Config.instance.libdir.each do |libdir|
|
135
|
+
command_file_old = File.join(libdir, "agent", agent, command)
|
136
|
+
command_file_new = File.join(libdir, "mcollective", "agent", agent, command)
|
137
|
+
command_file_old_exists = File.exists?(command_file_old)
|
138
|
+
command_file_new_exists = File.exists?(command_file_new)
|
139
|
+
|
140
|
+
if command_file_new_exists && command_file_old_exists
|
141
|
+
Log.debug("Found 'implemented_by' scripts found in two locations #{command_file_old} and #{command_file_new}")
|
142
|
+
Log.debug("Running script: #{command_file_new}")
|
143
|
+
return command_file_new
|
144
|
+
elsif command_file_old_exists
|
145
|
+
Log.debug("Running script: #{command_file_old}")
|
146
|
+
return command_file_old
|
147
|
+
elsif command_file_new_exists
|
148
|
+
Log.debug("Running script: #{command_file_new}")
|
149
|
+
return command_file_new
|
135
150
|
end
|
136
151
|
end
|
137
152
|
|
138
|
-
|
153
|
+
Log.warn("No script found for: #{command}")
|
154
|
+
command
|
139
155
|
end
|
140
156
|
end
|
141
157
|
end
|
@@ -25,11 +25,11 @@ module MCollective
|
|
25
25
|
initial_options = Marshal.load(@@initial_options)
|
26
26
|
|
27
27
|
else
|
28
|
-
oparser = MCollective::Optionparser.new({ :verbose => false,
|
29
|
-
:progress_bar => true,
|
30
|
-
:mcollective_limit_targets => false,
|
31
|
-
:batch_size => nil,
|
32
|
-
:batch_sleep_time => 1 },
|
28
|
+
oparser = MCollective::Optionparser.new({ :verbose => false,
|
29
|
+
:progress_bar => true,
|
30
|
+
:mcollective_limit_targets => false,
|
31
|
+
:batch_size => nil,
|
32
|
+
:batch_sleep_time => 1 },
|
33
33
|
"filter")
|
34
34
|
|
35
35
|
initial_options = oparser.parse do |parser, opts|
|
@@ -46,8 +46,7 @@ module MCollective
|
|
46
46
|
@initial_options = initial_options
|
47
47
|
|
48
48
|
@config = initial_options[:config]
|
49
|
-
@client = MCollective::Client.new(@
|
50
|
-
@client.options = initial_options
|
49
|
+
@client = MCollective::Client.new(@initial_options)
|
51
50
|
|
52
51
|
@stats = Stats.new
|
53
52
|
@agent = agent
|
@@ -247,7 +246,7 @@ module MCollective
|
|
247
246
|
# TODO(ploubser): The logic here seems poor. It implies that it is valid to
|
248
247
|
# pass arguments where batch_mode is set to false and batch_mode > 0.
|
249
248
|
# If this is the case we completely ignore the supplied value of batch_mode
|
250
|
-
# and do our own thing.
|
249
|
+
# and do our own thing.
|
251
250
|
|
252
251
|
# if a global batch size is set just use that else set it
|
253
252
|
# in the case that it was passed as an argument
|
@@ -542,10 +541,11 @@ module MCollective
|
|
542
541
|
# and if we're configured to use the first found hosts as the
|
543
542
|
# limit method then pass in the limit thus minimizing the amount
|
544
543
|
# of work we do in the discover phase and speeding it up significantly
|
544
|
+
filter = @filter.merge({'collective' => @collective})
|
545
545
|
if @limit_method == :first and @limit_targets.is_a?(Fixnum)
|
546
|
-
@discovered_agents = @client.discover(
|
546
|
+
@discovered_agents = @client.discover(filter, discovery_timeout, @limit_targets)
|
547
547
|
else
|
548
|
-
@discovered_agents = @client.discover(
|
548
|
+
@discovered_agents = @client.discover(filter, discovery_timeout)
|
549
549
|
end
|
550
550
|
|
551
551
|
@stderr.puts(@discovered_agents.size) if verbose
|
@@ -625,7 +625,7 @@ module MCollective
|
|
625
625
|
unless Config.instance.direct_addressing
|
626
626
|
raise "Can only set batch size if direct addressing is supported"
|
627
627
|
end
|
628
|
-
|
628
|
+
|
629
629
|
validate_batch_size(limit)
|
630
630
|
|
631
631
|
@batch_size = limit
|
@@ -813,10 +813,10 @@ module MCollective
|
|
813
813
|
processed_nodes = 0
|
814
814
|
|
815
815
|
discovered.in_groups_of(batch_size) do |hosts|
|
816
|
-
message = Message.new(req, nil, {:agent => @agent,
|
817
|
-
:type => :direct_request,
|
818
|
-
:collective => @collective,
|
819
|
-
:filter => opts[:filter],
|
816
|
+
message = Message.new(req, nil, {:agent => @agent,
|
817
|
+
:type => :direct_request,
|
818
|
+
:collective => @collective,
|
819
|
+
:filter => opts[:filter],
|
820
820
|
:options => opts})
|
821
821
|
|
822
822
|
# first time round we let the Message object create a request id
|
@@ -1007,7 +1007,7 @@ module MCollective
|
|
1007
1007
|
end
|
1008
1008
|
|
1009
1009
|
private
|
1010
|
-
|
1010
|
+
|
1011
1011
|
def determine_batch_mode(batch_size)
|
1012
1012
|
if (batch_size != 0 && batch_size != "0")
|
1013
1013
|
return true
|
data/spec/unit/client_spec.rb
CHANGED
@@ -4,7 +4,13 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
module MCollective
|
6
6
|
describe Client do
|
7
|
-
|
7
|
+
let(:client) do
|
8
|
+
c = Client.new("/nonexisting")
|
9
|
+
c.options = Util.default_options
|
10
|
+
c
|
11
|
+
end
|
12
|
+
|
13
|
+
before :each do
|
8
14
|
@security = mock
|
9
15
|
@security.stubs(:initiated_by=)
|
10
16
|
@connector = mock
|
@@ -20,9 +26,19 @@ module MCollective
|
|
20
26
|
Config.instance.instance_variable_set("@configured", true)
|
21
27
|
PluginManager.expects("[]").with("connector_plugin").returns(@connector)
|
22
28
|
PluginManager.expects("[]").with("security_plugin").returns(@security)
|
29
|
+
Timeout.stubs(:timeout).with(nil, MCollective::ClientTimeoutError)
|
30
|
+
end
|
23
31
|
|
24
|
-
|
25
|
-
|
32
|
+
describe "#initialize" do
|
33
|
+
it "should set a timeout if a timeout has been specified" do
|
34
|
+
Timeout.expects(:timeout).with(1, MCollective::ClientTimeoutError)
|
35
|
+
Client.new({:config => "/nonexisting", :connection_timeout => 1})
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should try forever if no timeout has been set" do
|
39
|
+
Timeout.expects(:timeout).with(nil, MCollective::ClientTimeoutError)
|
40
|
+
Client.new({:config => "/nonexisting"})
|
41
|
+
end
|
26
42
|
end
|
27
43
|
|
28
44
|
describe "#sendreq" do
|
@@ -31,10 +47,10 @@ module MCollective
|
|
31
47
|
request.stubs(:agent)
|
32
48
|
request.stubs(:ttl)
|
33
49
|
request.stubs(:collective)
|
34
|
-
|
50
|
+
client.expects(:createreq).with(request, "rspec", {}).returns(request)
|
35
51
|
request.expects(:publish)
|
36
52
|
request.expects(:requestid).returns("13fegbcw").twice
|
37
|
-
result =
|
53
|
+
result = client.sendreq(request, "rspec")
|
38
54
|
result.should == "13fegbcw"
|
39
55
|
end
|
40
56
|
end
|
@@ -43,36 +59,36 @@ module MCollective
|
|
43
59
|
it "should create a request" do
|
44
60
|
message = Message.new("rspec", nil, {:agent => "rspec", :type => :request, :collective => "mcollective", :filter => Util.empty_filter, :options => Util.default_options})
|
45
61
|
message.stubs(:encode!)
|
46
|
-
|
62
|
+
client.stubs(:subscribe)
|
47
63
|
message.stubs(:reply_to)
|
48
|
-
result =
|
64
|
+
result = client.createreq(message, "rspec")
|
49
65
|
result.should == message
|
50
66
|
end
|
51
67
|
|
52
68
|
it "should create a new request if the message if not of type Message" do
|
53
69
|
message = mock
|
54
70
|
message.stubs(:encode!)
|
55
|
-
|
71
|
+
client.stubs(:subscribe)
|
56
72
|
message.stubs(:reply_to)
|
57
73
|
Message.expects(:new).returns(message)
|
58
|
-
result =
|
74
|
+
result = client.createreq("message", "rspec")
|
59
75
|
result.should == message
|
60
76
|
end
|
61
77
|
|
62
78
|
it "should subscripe to the reply queue unless has been specified" do
|
63
79
|
message = Message.new("rspec", nil, {:agent => "rspec", :type => :request, :collective => "mcollective", :filter => Util.empty_filter, :options => Util.default_options})
|
64
80
|
message.stubs(:encode!)
|
65
|
-
|
81
|
+
client.expects(:subscribe).with("rspec", :reply)
|
66
82
|
message.stubs(:reply_to).returns(nil)
|
67
|
-
|
83
|
+
client.createreq(message, "rspec")
|
68
84
|
end
|
69
85
|
|
70
86
|
it "should not subscribe to the reply queue if one has been specified" do
|
71
87
|
message = Message.new("rspec", nil, {:agent => "rspec", :type => :request, :collective => "mcollective", :filter => Util.empty_filter, :options => Util.default_options})
|
72
88
|
message.stubs(:encode!)
|
73
|
-
|
89
|
+
client.expects(:subscribe).never
|
74
90
|
message.stubs(:reply_to).returns(:reply)
|
75
|
-
|
91
|
+
client.createreq(message, "rspec")
|
76
92
|
end
|
77
93
|
end
|
78
94
|
|
@@ -81,75 +97,85 @@ module MCollective
|
|
81
97
|
subscription = mock
|
82
98
|
Util.stubs(:make_subscriptions).returns(subscription)
|
83
99
|
Util.expects(:subscribe).with(subscription)
|
84
|
-
|
85
|
-
|
100
|
+
client.subscribe("rspec", :queue)
|
101
|
+
client.instance_variable_get(:@subscriptions).should == {"rspec" => 1}
|
86
102
|
end
|
87
103
|
|
88
104
|
it "should not subscribe to a destination if it already has" do
|
89
|
-
|
105
|
+
client.instance_variable_get(:@subscriptions)["rspec"] = 1
|
90
106
|
Util.expects(:make_subscription).never
|
91
|
-
|
107
|
+
client.subscribe("rspec", :queue)
|
92
108
|
end
|
93
109
|
end
|
94
110
|
|
95
111
|
describe "#unsubscribe" do
|
96
112
|
it "should unsubscribe if a subscription has been made" do
|
97
113
|
subscription = mock
|
98
|
-
|
114
|
+
client.instance_variable_get(:@subscriptions)["rspec"] = 1
|
99
115
|
Util.expects(:make_subscriptions).returns(subscription)
|
100
116
|
Util.expects(:unsubscribe).with(subscription)
|
101
|
-
|
117
|
+
client.unsubscribe("rspec", :queue)
|
102
118
|
end
|
103
119
|
|
104
120
|
it "should no unsubscribe if a subscription hasn't been made" do
|
105
121
|
Util.expects(:make_subscription).never
|
106
|
-
|
122
|
+
client.unsubscribe("rspec", :queue)
|
107
123
|
end
|
108
124
|
end
|
109
125
|
|
110
126
|
describe "receive" do
|
111
127
|
let(:message) do
|
112
|
-
m = mock
|
128
|
+
m = mock('message')
|
113
129
|
m.stubs(:type=)
|
114
130
|
m.stubs(:expected_msgid=)
|
115
131
|
m.stubs(:decode!)
|
116
132
|
m.stubs(:requestid).returns("erfs123")
|
133
|
+
m.stubs(:payload).returns({:senderid => 'test-sender'})
|
117
134
|
m
|
118
135
|
end
|
119
136
|
|
120
137
|
let(:badmessage) do
|
121
|
-
m = mock
|
138
|
+
m = mock('badmessage')
|
122
139
|
m.stubs(:type=)
|
123
140
|
m.stubs(:expected_msgid=)
|
124
141
|
m.stubs(:decode!)
|
125
142
|
m.stubs(:requestid).returns("badmessage")
|
143
|
+
m.stubs(:payload).returns({})
|
126
144
|
m
|
127
145
|
end
|
128
146
|
|
129
147
|
it "should receive a message" do
|
130
148
|
@connector.stubs(:receive).returns(message)
|
131
|
-
result =
|
149
|
+
result = client.receive("erfs123")
|
132
150
|
result.should == message
|
133
151
|
end
|
134
152
|
|
135
|
-
it
|
153
|
+
it 'should log who the message was from' do
|
154
|
+
@connector.stubs(:receive).returns(message)
|
155
|
+
Log.expects(:debug).with("Received reply to erfs123 from test-sender")
|
156
|
+
|
157
|
+
client.receive("erfs123")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should log and retry if the message reqid does not match the expected msgid" do
|
161
|
+
Log.stubs(:debug)
|
136
162
|
Log.expects(:debug).with("Ignoring a message for some other client : Message reqid badmessage does not match our reqid erfs123")
|
137
163
|
@connector.stubs(:receive).returns(badmessage, message)
|
138
|
-
|
164
|
+
client.receive("erfs123")
|
139
165
|
end
|
140
166
|
|
141
167
|
it "should log and retry if a SecurityValidationFailed expection is raised" do
|
142
168
|
Log.expects(:warn).with("Ignoring a message that did not pass security validations")
|
143
169
|
badmessage.stubs(:decode!).raises(SecurityValidationFailed)
|
144
170
|
@connector.stubs(:receive).returns(badmessage, message)
|
145
|
-
|
171
|
+
client.receive("erfs123")
|
146
172
|
end
|
147
173
|
end
|
148
174
|
|
149
175
|
describe "#discover" do
|
150
176
|
it "should delegate to the discovery plugins" do
|
151
|
-
@discoverer.expects(:discover).with({}, 1, 0).returns([])
|
152
|
-
|
177
|
+
@discoverer.expects(:discover).with({'collective' => 'mcollective'}, 1, 0).returns([])
|
178
|
+
client.discover({}, 1).should == []
|
153
179
|
end
|
154
180
|
end
|
155
181
|
|
@@ -171,23 +197,23 @@ module MCollective
|
|
171
197
|
end
|
172
198
|
|
173
199
|
before :each do
|
174
|
-
|
200
|
+
client.expects(:unsubscribe)
|
175
201
|
@discoverer.expects(:discovery_timeout).with(message.options[:timeout], message.options[:filter]).returns(0)
|
176
|
-
|
177
|
-
|
202
|
+
client.stubs(:createreq).returns(request)
|
203
|
+
client.expects(:update_stat)
|
178
204
|
end
|
179
205
|
|
180
206
|
it "should thread the publisher and receiver if configured" do
|
181
|
-
|
182
|
-
|
207
|
+
client.instance_variable_get(:@options)[:threaded] = true
|
208
|
+
client.expects(:threaded_req).with(request, nil, 0, 1)
|
183
209
|
message.options[:threaded] = true
|
184
|
-
|
210
|
+
client.req(message)
|
185
211
|
end
|
186
212
|
|
187
213
|
it "should not thread the publisher and receiver if configured" do
|
188
|
-
|
189
|
-
|
190
|
-
|
214
|
+
client.instance_variable_set(:@threaded, false)
|
215
|
+
client.expects(:unthreaded_req).with(request, nil, 0, 1)
|
216
|
+
client.req(message)
|
191
217
|
end
|
192
218
|
end
|
193
219
|
|
@@ -195,9 +221,9 @@ module MCollective
|
|
195
221
|
it "should start a publisher and then start a receiver" do
|
196
222
|
request = mock
|
197
223
|
request.stubs(:requestid).returns("erfs123")
|
198
|
-
|
199
|
-
|
200
|
-
|
224
|
+
client.expects(:start_publisher).with(request, 5)
|
225
|
+
client.expects(:start_receiver).with("erfs123", 2, 10)
|
226
|
+
client.unthreaded_req(request, 5, 10, 2)
|
201
227
|
end
|
202
228
|
end
|
203
229
|
|
@@ -209,10 +235,10 @@ module MCollective
|
|
209
235
|
r_thread = mock
|
210
236
|
Thread.expects(:new).yields.returns(p_thread)
|
211
237
|
Thread.expects(:new).yields.returns(r_thread)
|
212
|
-
|
213
|
-
|
238
|
+
client.expects(:start_publisher).with(request, 5)
|
239
|
+
client.expects(:start_receiver).with("erfs123", 2, 15).returns(2)
|
214
240
|
p_thread.expects(:join)
|
215
|
-
result =
|
241
|
+
result = client.threaded_req(request, 5, 10, 2)
|
216
242
|
result.should == 2
|
217
243
|
end
|
218
244
|
end
|
@@ -230,13 +256,13 @@ module MCollective
|
|
230
256
|
it "should publish the message" do
|
231
257
|
Timeout.stubs(:timeout).with(2).yields
|
232
258
|
message.expects(:publish)
|
233
|
-
|
259
|
+
client.start_publisher(message, 2)
|
234
260
|
end
|
235
261
|
|
236
262
|
it "should log a warning on a timeout" do
|
237
|
-
Timeout.stubs(:timeout).raises(Timeout::Error)
|
263
|
+
Timeout.stubs(:timeout).with(2).raises(Timeout::Error)
|
238
264
|
Log.expects(:warn).with("Could not publish all messages. Publishing timed out.")
|
239
|
-
|
265
|
+
client.start_publisher(message,2)
|
240
266
|
end
|
241
267
|
end
|
242
268
|
|
@@ -245,9 +271,9 @@ module MCollective
|
|
245
271
|
results = []
|
246
272
|
Timeout.stubs(:timeout).yields
|
247
273
|
message = mock
|
248
|
-
|
274
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
249
275
|
message.stubs(:payload).returns("msg1", "msg2", "msg3")
|
250
|
-
|
276
|
+
client.start_receiver("erfs123", 3, 5) do |msg|
|
251
277
|
results << msg
|
252
278
|
end
|
253
279
|
results.should == ["msg1", "msg2", "msg3"]
|
@@ -257,10 +283,10 @@ module MCollective
|
|
257
283
|
results = []
|
258
284
|
Timeout.stubs(:timeout).yields
|
259
285
|
message = mock
|
260
|
-
|
286
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
261
287
|
message.stubs(:payload).returns("msg1", "msg2", "timeout")
|
262
288
|
Log.expects(:warn).with("Could not receive all responses. Expected : 3. Received : 2")
|
263
|
-
responded =
|
289
|
+
responded = client.start_receiver("erfs123", 3, 5) do |msg|
|
264
290
|
if msg == "timeout"
|
265
291
|
raise Timeout::Error
|
266
292
|
end
|
@@ -274,10 +300,10 @@ module MCollective
|
|
274
300
|
results = []
|
275
301
|
Timeout.stubs(:timeout).yields
|
276
302
|
message = mock
|
277
|
-
|
303
|
+
client.stubs(:receive).with("erfs123").returns(message)
|
278
304
|
message.stubs(:payload).returns("msg1", "msg2", "timeout")
|
279
305
|
Log.expects(:warn).never
|
280
|
-
responded =
|
306
|
+
responded = client.start_receiver("erfs123", 2, 5) do |msg|
|
281
307
|
if msg == "timeout"
|
282
308
|
raise Timeout::Error
|
283
309
|
end
|
@@ -291,7 +317,7 @@ module MCollective
|
|
291
317
|
describe "#update_stat" do
|
292
318
|
let(:before) do
|
293
319
|
{ :starttime => Time.now.to_f,
|
294
|
-
:discoverytime => 0,
|
320
|
+
:discoverytime => 0,
|
295
321
|
:blocktime => 0,
|
296
322
|
:totaltime => 0 }
|
297
323
|
end
|
@@ -308,14 +334,14 @@ module MCollective
|
|
308
334
|
|
309
335
|
it "should update stats and return the stats hash" do
|
310
336
|
Time.stubs(:now).returns(10, 20)
|
311
|
-
|
337
|
+
client.update_stat(before, 5, "erfs123").should == after
|
312
338
|
end
|
313
339
|
end
|
314
340
|
|
315
341
|
describe "#discovered_req" do
|
316
342
|
it "should raise a deprecation exception" do
|
317
343
|
expect{
|
318
|
-
|
344
|
+
client.discovered_req(nil, nil)
|
319
345
|
}.to raise_error("Client#discovered_req has been removed, please port your agent and client to the SimpleRPC framework")
|
320
346
|
end
|
321
347
|
end
|