mcollective-client 2.6.1 → 2.7.0
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.
- 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
|