mcollective-client 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mcollective-client might be problematic. Click here for more details.
- data/bin/mc-call-agent +54 -0
- data/bin/mco +27 -0
- data/lib/mcollective.rb +70 -0
- data/lib/mcollective/agents.rb +160 -0
- data/lib/mcollective/application.rb +354 -0
- data/lib/mcollective/applications.rb +145 -0
- data/lib/mcollective/client.rb +292 -0
- data/lib/mcollective/config.rb +202 -0
- data/lib/mcollective/connector.rb +18 -0
- data/lib/mcollective/connector/base.rb +24 -0
- data/lib/mcollective/facts.rb +39 -0
- data/lib/mcollective/facts/base.rb +86 -0
- data/lib/mcollective/log.rb +103 -0
- data/lib/mcollective/logger.rb +5 -0
- data/lib/mcollective/logger/base.rb +73 -0
- data/lib/mcollective/logger/console_logger.rb +61 -0
- data/lib/mcollective/logger/file_logger.rb +46 -0
- data/lib/mcollective/logger/syslog_logger.rb +53 -0
- data/lib/mcollective/matcher.rb +16 -0
- data/lib/mcollective/matcher/parser.rb +93 -0
- data/lib/mcollective/matcher/scanner.rb +123 -0
- data/lib/mcollective/message.rb +201 -0
- data/lib/mcollective/monkey_patches.rb +104 -0
- data/lib/mcollective/optionparser.rb +164 -0
- data/lib/mcollective/pluginmanager.rb +180 -0
- data/lib/mcollective/pluginpackager.rb +26 -0
- data/lib/mcollective/pluginpackager/agent_definition.rb +79 -0
- data/lib/mcollective/pluginpackager/standard_definition.rb +59 -0
- data/lib/mcollective/registration.rb +16 -0
- data/lib/mcollective/registration/base.rb +75 -0
- data/lib/mcollective/rpc.rb +188 -0
- data/lib/mcollective/rpc/actionrunner.rb +142 -0
- data/lib/mcollective/rpc/agent.rb +441 -0
- data/lib/mcollective/rpc/audit.rb +38 -0
- data/lib/mcollective/rpc/client.rb +793 -0
- data/lib/mcollective/rpc/ddl.rb +258 -0
- data/lib/mcollective/rpc/helpers.rb +339 -0
- data/lib/mcollective/rpc/progress.rb +63 -0
- data/lib/mcollective/rpc/reply.rb +61 -0
- data/lib/mcollective/rpc/request.rb +51 -0
- data/lib/mcollective/rpc/result.rb +41 -0
- data/lib/mcollective/rpc/stats.rb +185 -0
- data/lib/mcollective/runnerstats.rb +90 -0
- data/lib/mcollective/security.rb +26 -0
- data/lib/mcollective/security/base.rb +237 -0
- data/lib/mcollective/shell.rb +87 -0
- data/lib/mcollective/ssl.rb +246 -0
- data/lib/mcollective/unix_daemon.rb +37 -0
- data/lib/mcollective/util.rb +274 -0
- data/lib/mcollective/vendor.rb +41 -0
- data/lib/mcollective/vendor/require_vendored.rb +2 -0
- data/lib/mcollective/windows_daemon.rb +25 -0
- data/spec/Rakefile +16 -0
- data/spec/fixtures/application/test.rb +7 -0
- data/spec/fixtures/test-cert.pem +15 -0
- data/spec/fixtures/test-private.pem +15 -0
- data/spec/fixtures/test-public.pem +6 -0
- data/spec/monkey_patches/instance_variable_defined.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/unit/agents_spec.rb +280 -0
- data/spec/unit/application_spec.rb +636 -0
- data/spec/unit/applications_spec.rb +155 -0
- data/spec/unit/array.rb +30 -0
- data/spec/unit/config_spec.rb +148 -0
- data/spec/unit/facts/base_spec.rb +118 -0
- data/spec/unit/facts_spec.rb +39 -0
- data/spec/unit/log_spec.rb +71 -0
- data/spec/unit/logger/base_spec.rb +110 -0
- data/spec/unit/logger/syslog_logger_spec.rb +86 -0
- data/spec/unit/matcher/parser_spec.rb +106 -0
- data/spec/unit/matcher/scanner_spec.rb +71 -0
- data/spec/unit/message_spec.rb +401 -0
- data/spec/unit/optionparser_spec.rb +113 -0
- data/spec/unit/pluginmanager_spec.rb +173 -0
- data/spec/unit/pluginpackager/agent_definition_spec.rb +130 -0
- data/spec/unit/pluginpackager/standard_definition_spec.rb +75 -0
- data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +533 -0
- data/spec/unit/plugins/mcollective/connector/stomp/eventlogger_spec.rb +34 -0
- data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +417 -0
- data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +229 -0
- data/spec/unit/plugins/mcollective/security/psk_spec.rb +156 -0
- data/spec/unit/registration/base_spec.rb +77 -0
- data/spec/unit/rpc/actionrunner_spec.rb +213 -0
- data/spec/unit/rpc/agent_spec.rb +155 -0
- data/spec/unit/rpc/client_spec.rb +523 -0
- data/spec/unit/rpc/ddl_spec.rb +388 -0
- data/spec/unit/rpc/helpers_spec.rb +55 -0
- data/spec/unit/rpc/reply_spec.rb +143 -0
- data/spec/unit/rpc/request_spec.rb +115 -0
- data/spec/unit/rpc/result_spec.rb +66 -0
- data/spec/unit/rpc/stats_spec.rb +288 -0
- data/spec/unit/runnerstats_spec.rb +40 -0
- data/spec/unit/security/base_spec.rb +279 -0
- data/spec/unit/shell_spec.rb +144 -0
- data/spec/unit/ssl_spec.rb +244 -0
- data/spec/unit/symbol.rb +11 -0
- data/spec/unit/unix_daemon.rb +41 -0
- data/spec/unit/util_spec.rb +342 -0
- data/spec/unit/vendor_spec.rb +34 -0
- data/spec/unit/windows_daemon.rb +43 -0
- data/spec/windows_spec.opts +1 -0
- metadata +242 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module MCollective
|
6
|
+
module RPC
|
7
|
+
describe ActionRunner do
|
8
|
+
before(:each) do
|
9
|
+
@req = mock
|
10
|
+
@req.stubs(:agent).returns("spectester")
|
11
|
+
@req.stubs(:action).returns("tester")
|
12
|
+
|
13
|
+
command = "/bin/echo 1"
|
14
|
+
|
15
|
+
@runner = ActionRunner.new(command, @req, :json)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#initialize" do
|
19
|
+
it "should set command" do
|
20
|
+
@runner.command.should == "/bin/echo 1"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set agent" do
|
24
|
+
@runner.agent.should == "spectester"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should set action" do
|
28
|
+
@runner.action.should == "tester"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should set format" do
|
32
|
+
@runner.format.should == :json
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should set request" do
|
36
|
+
@runner.request.should == @req
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should set stdout" do
|
40
|
+
@runner.stdout.should == ""
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should set stderr" do
|
44
|
+
@runner.stderr.should == ""
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should set the command via path_to_command" do
|
48
|
+
ActionRunner.any_instance.expects(:path_to_command).with("rspec").once
|
49
|
+
ActionRunner.new("rspec", @req, :json)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#shell" do
|
54
|
+
it "should create a shell instance with correct settings" do
|
55
|
+
s = @runner.shell("test", "infile", "outfile")
|
56
|
+
|
57
|
+
s.command.should == "test infile outfile"
|
58
|
+
s.cwd.should == Dir.tmpdir
|
59
|
+
s.stdout.should == ""
|
60
|
+
s.stderr.should == ""
|
61
|
+
s.environment["MCOLLECTIVE_REQUEST_FILE"].should == "infile"
|
62
|
+
s.environment["MCOLLECTIVE_REPLY_FILE"].should == "outfile"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#load_results" do
|
67
|
+
it "should call the correct format loader" do
|
68
|
+
req = mock
|
69
|
+
req.expects(:agent).returns("spectester")
|
70
|
+
req.expects(:action).returns("tester")
|
71
|
+
|
72
|
+
runner = ActionRunner.new("/bin/echo 1", req, :foo)
|
73
|
+
runner.expects("load_foo_results").returns({:foo => :bar})
|
74
|
+
runner.load_results("/dev/null").should == {:foo => :bar}
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should set all keys to Symbol" do
|
78
|
+
data = {"foo" => "bar", "bar" => "baz"}
|
79
|
+
Tempfile.open("mcollective_test", Dir.tmpdir) do |f|
|
80
|
+
f.puts data.to_json
|
81
|
+
f.close
|
82
|
+
|
83
|
+
results = @runner.load_results(f.path)
|
84
|
+
results.should == {:foo => "bar", :bar => "baz"}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#load_json_results" do
|
90
|
+
it "should load data from a file" do
|
91
|
+
Tempfile.open("mcollective_test", Dir.tmpdir) do |f|
|
92
|
+
f.puts '{"foo":"bar","bar":"baz"}'
|
93
|
+
f.close
|
94
|
+
|
95
|
+
@runner.load_json_results(f.path).should == {"foo" => "bar", "bar" => "baz"}
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return empty data on JSON parse error" do
|
101
|
+
@runner.load_json_results("/dev/null").should == {}
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return empty data for missing files" do
|
105
|
+
@runner.load_json_results("/nonexisting").should == {}
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should load complex data correctly" do
|
109
|
+
data = {"foo" => "bar", "bar" => {"one" => "two"}}
|
110
|
+
Tempfile.open("mcollective_test", Dir.tmpdir) do |f|
|
111
|
+
f.puts data.to_json
|
112
|
+
f.close
|
113
|
+
|
114
|
+
@runner.load_json_results(f.path).should == data
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#saverequest" do
|
121
|
+
it "should call the correct format serializer" do
|
122
|
+
req = mock
|
123
|
+
req.expects(:agent).returns("spectester")
|
124
|
+
req.expects(:action).returns("tester")
|
125
|
+
|
126
|
+
runner = ActionRunner.new("/bin/echo 1", req, :foo)
|
127
|
+
|
128
|
+
runner.expects("save_foo_request").with(req).returns('{"foo":"bar"}')
|
129
|
+
|
130
|
+
runner.saverequest(req)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should save to a temp file" do
|
134
|
+
@req.expects(:to_json).returns({:foo => "bar"}.to_json)
|
135
|
+
fname = @runner.saverequest(@req).path
|
136
|
+
|
137
|
+
JSON.load(File.read(fname)).should == {"foo" => "bar"}
|
138
|
+
File.dirname(fname).should == Dir.tmpdir
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "#save_json_request" do
|
143
|
+
it "should return correct json data" do
|
144
|
+
@req.expects(:to_json).returns({:foo => "bar"}.to_json)
|
145
|
+
@runner.save_json_request(@req).should == '{"foo":"bar"}'
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#canrun?" do
|
150
|
+
it "should correctly report executables" do
|
151
|
+
if Util.windows?
|
152
|
+
@runner.canrun?(File.join(ENV['SystemRoot'], "explorer.exe")).should == true
|
153
|
+
else
|
154
|
+
@runner.canrun?("/bin/true").should == true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should detect missing files" do
|
159
|
+
@runner.canrun?("/nonexisting").should == false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "#to_s" do
|
164
|
+
it "should return correct data" do
|
165
|
+
@runner.to_s.should == "spectester#tester command: /bin/echo 1"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#tempfile" do
|
170
|
+
it "should return a TempFile" do
|
171
|
+
@runner.tempfile("foo").class.should == Tempfile
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should contain the prefix in its name" do
|
175
|
+
@runner.tempfile("foo").path.should match(/foo/)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "#path_to_command" do
|
180
|
+
it "should return the command if it starts with separator" do
|
181
|
+
command = "#{File::SEPARATOR}rspec"
|
182
|
+
|
183
|
+
runner = ActionRunner.new(command , @req, :json)
|
184
|
+
runner.path_to_command(command).should == command
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should find the first match in the libdir" do
|
188
|
+
Config.any_instance.expects(:libdir).returns(["#{File::SEPARATOR}libdir1", "#{File::SEPARATOR}libdir2"])
|
189
|
+
|
190
|
+
action_in_first_dir = File.join(File::SEPARATOR, "libdir1", "agent", "spectester", "action.sh")
|
191
|
+
action_in_last_dir = File.join(File::SEPARATOR, "libdir2", "agent", "spectester", "action.sh")
|
192
|
+
|
193
|
+
File.expects("exist?").with(action_in_first_dir).returns(true)
|
194
|
+
File.expects("exist?").with(action_in_last_dir).never
|
195
|
+
|
196
|
+
ActionRunner.new("action.sh", @req, :json).command.should == action_in_first_dir
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should find the match even in the last libdir" do
|
200
|
+
Config.any_instance.expects(:libdir).returns(["#{File::SEPARATOR}libdir1", "#{File::SEPARATOR}libdir2"])
|
201
|
+
|
202
|
+
action_in_first_dir = File.join(File::SEPARATOR, "libdir1", "agent", "spectester", "action.sh")
|
203
|
+
action_in_last_dir = File.join(File::SEPARATOR, "libdir2", "agent", "spectester", "action.sh")
|
204
|
+
|
205
|
+
File.expects("exist?").with(action_in_first_dir).returns(false)
|
206
|
+
File.expects("exist?").with(action_in_last_dir).returns(true)
|
207
|
+
|
208
|
+
ActionRunner.new("action.sh", @req, :json).command.should == action_in_last_dir
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module MCollective
|
6
|
+
module RPC
|
7
|
+
describe Agent do
|
8
|
+
before do
|
9
|
+
@agent = Agent.new
|
10
|
+
@agent.reply = {}
|
11
|
+
@agent.request = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#run" do
|
15
|
+
before do
|
16
|
+
@status = mock
|
17
|
+
@status.stubs(:exitstatus).returns(0)
|
18
|
+
@shell = mock
|
19
|
+
@shell.stubs(:runcommand)
|
20
|
+
@shell.stubs(:status).returns(@status)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should accept stderr and stdout and force them to be strings" do
|
24
|
+
Shell.expects(:new).with("rspec", {:stderr => "", :stdout => ""}).returns(@shell)
|
25
|
+
@agent.send(:run, "rspec", {:stderr => :err, :stdout => :out})
|
26
|
+
@agent.reply[:err].should == ""
|
27
|
+
@agent.reply[:out].should == ""
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should accept existing variables for stdout and stderr and fail if they dont support <<" do
|
31
|
+
@agent.reply[:err] = "err"
|
32
|
+
@agent.reply[:out] = "out"
|
33
|
+
|
34
|
+
Shell.expects(:new).with("rspec", {:stderr => "err", :stdout => "out"}).returns(@shell)
|
35
|
+
@agent.send(:run, "rspec", {:stderr => @agent.reply[:err], :stdout => @agent.reply[:out]})
|
36
|
+
@agent.reply[:err].should == "err"
|
37
|
+
@agent.reply[:out].should == "out"
|
38
|
+
|
39
|
+
@agent.reply.expects("fail!").with("stderr should support << while calling run(rspec)").raises("stderr fail")
|
40
|
+
expect { @agent.send(:run, "rspec", {:stderr => nil, :stdout => ""}) }.to raise_error("stderr fail")
|
41
|
+
|
42
|
+
@agent.reply.expects("fail!").with("stdout should support << while calling run(rspec)").raises("stdout fail")
|
43
|
+
expect { @agent.send(:run, "rspec", {:stderr => "", :stdout => nil}) }.to raise_error("stdout fail")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set stdin, cwd and environment if supplied" do
|
47
|
+
Shell.expects(:new).with("rspec", {:stdin => "stdin", :cwd => "cwd", :environment => "env"}).returns(@shell)
|
48
|
+
@agent.send(:run, "rspec", {:stdin => "stdin", :cwd => "cwd", :environment => "env"})
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should ignore unknown options" do
|
52
|
+
Shell.expects(:new).with("rspec", {}).returns(@shell)
|
53
|
+
@agent.send(:run, "rspec", {:rspec => "rspec"})
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should chomp strings if configured to do so" do
|
57
|
+
Shell.expects(:new).with("rspec", {:stderr => 'err', :stdout => 'out'}).returns(@shell)
|
58
|
+
|
59
|
+
@agent.reply[:err] = "err"
|
60
|
+
@agent.reply[:out] = "out"
|
61
|
+
|
62
|
+
@agent.reply[:err].expects("chomp!")
|
63
|
+
@agent.reply[:out].expects("chomp!")
|
64
|
+
|
65
|
+
@agent.send(:run, "rspec", {:chomp => true, :stdout => @agent.reply[:out], :stderr => @agent.reply[:err]})
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return the exitstatus" do
|
69
|
+
Shell.expects(:new).with("rspec", {}).returns(@shell)
|
70
|
+
@agent.send(:run, "rspec", {}).should == 0
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should handle nil from the shell handler" do
|
74
|
+
@shell.expects(:status).returns(nil)
|
75
|
+
Shell.expects(:new).with("rspec", {}).returns(@shell)
|
76
|
+
@agent.send(:run, "rspec", {}).should == -1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#validate" do
|
81
|
+
it "should detect missing data" do
|
82
|
+
@agent.request = {}
|
83
|
+
expect { @agent.send(:validate, :foo, String) }.to raise_error(MissingRPCData, "please supply a foo argument")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should support regular expressions" do
|
87
|
+
@agent.request = {:foo => "this is a test, 123"}
|
88
|
+
|
89
|
+
expect { @agent.send(:validate, :foo, /foo/) }.to raise_error(InvalidRPCData, /foo should match/)
|
90
|
+
@agent.send(:validate, :foo, /is a test, \d\d\d$/)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should support type checking" do
|
94
|
+
@agent.request = {:str => "foo"}
|
95
|
+
|
96
|
+
expect { @agent.send(:validate, :str, Numeric) }.to raise_error(InvalidRPCData, /str should be a Numeric/)
|
97
|
+
@agent.send(:validate, :str, String)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should correctly validate ipv4 addresses" do
|
101
|
+
@agent.request = {:goodip4 => "1.1.1.1",
|
102
|
+
:badip4 => "300.300.300.300"}
|
103
|
+
|
104
|
+
expect { @agent.send(:validate, :badip4, :ipv4address) }.to raise_error(InvalidRPCData, /badip4 should be an ipv4 address/)
|
105
|
+
@agent.send(:validate, :goodip4, :ipv4address)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should correctly validate ipv6 addresses" do
|
109
|
+
@agent.request = {:goodip6 => "2a00:1450:8006::93",
|
110
|
+
:badip6 => "300.300.300.300"}
|
111
|
+
|
112
|
+
expect { @agent.send(:validate, :badip6, :ipv6address) }.to raise_error(InvalidRPCData, /badip6 should be an ipv6 address/)
|
113
|
+
@agent.send(:validate, :goodip6, :ipv6address)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should correctly validate boolean data" do
|
117
|
+
@agent.request = {:true => true, :false => false, :string => "foo", :number => 1}
|
118
|
+
|
119
|
+
@agent.send(:validate, :true, :boolean)
|
120
|
+
@agent.send(:validate, :false, :boolean)
|
121
|
+
expect { @agent.send(:validate, :string, :boolean) }.to raise_error(InvalidRPCData)
|
122
|
+
expect { @agent.send(:validate, :number, :boolean) }.to raise_error(InvalidRPCData)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should correctly validate list data" do
|
126
|
+
@agent.request = {:str => "foo"}
|
127
|
+
expect { @agent.send(:validate, :str, ["bar", "baz"]) }.to raise_error(InvalidRPCData, /str should be one of bar, baz/)
|
128
|
+
|
129
|
+
@agent.request = {:str => "foo"}
|
130
|
+
expect { @agent.send(:validate, :str, ["bar", "baz", "foo"]) }
|
131
|
+
@agent.send(:validate, :str, ["bar", "baz", "foo"])
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should correctly identify characters that are not shell safe" do
|
135
|
+
@agent.request = {:backtick => 'foo`bar',
|
136
|
+
:semicolon => 'foo;bar',
|
137
|
+
:dollar => 'foo$(bar)',
|
138
|
+
:pipe => 'foo|bar',
|
139
|
+
:redirto => 'foo>bar',
|
140
|
+
:inputfrom => 'foo<bar',
|
141
|
+
:good => 'foo bar baz'}
|
142
|
+
|
143
|
+
expect { @agent.send(:validate, :backtick, :shellsafe) }.to raise_error(InvalidRPCData, /backtick should not have ` in it/)
|
144
|
+
expect { @agent.send(:validate, :semicolon, :shellsafe) }.to raise_error(InvalidRPCData, /semicolon should not have ; in it/)
|
145
|
+
expect { @agent.send(:validate, :dollar, :shellsafe) }.to raise_error(InvalidRPCData, /dollar should not have \$ in it/)
|
146
|
+
expect { @agent.send(:validate, :pipe, :shellsafe) }.to raise_error(InvalidRPCData, /pipe should not have \| in it/)
|
147
|
+
expect { @agent.send(:validate, :redirto, :shellsafe) }.to raise_error(InvalidRPCData, /redirto should not have > in it/)
|
148
|
+
expect { @agent.send(:validate, :inputfrom, :shellsafe) }.to raise_error(InvalidRPCData, /inputfrom should not have \< in it/)
|
149
|
+
|
150
|
+
@agent.send(:validate, :good, :shellsafe)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,523 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module MCollective
|
6
|
+
module RPC
|
7
|
+
describe Client do
|
8
|
+
describe "#limit_method" do
|
9
|
+
before do
|
10
|
+
client = stub
|
11
|
+
|
12
|
+
client.stubs("options=")
|
13
|
+
client.stubs(:collective).returns("mcollective")
|
14
|
+
|
15
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
16
|
+
MCollective::Client.expects(:new).returns(client)
|
17
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
18
|
+
|
19
|
+
@client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should force strings to symbols" do
|
23
|
+
@client.limit_method = "first"
|
24
|
+
@client.limit_method.should == :first
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should only allow valid methods" do
|
28
|
+
@client.limit_method = :first
|
29
|
+
@client.limit_method.should == :first
|
30
|
+
@client.limit_method = :random
|
31
|
+
@client.limit_method.should == :random
|
32
|
+
|
33
|
+
expect { @client.limit_method = :fail }.to raise_error(/Unknown/)
|
34
|
+
expect { @client.limit_method = "fail" }.to raise_error(/Unknown/)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#method_missing" do
|
39
|
+
before do
|
40
|
+
client = stub
|
41
|
+
client.stubs("options=")
|
42
|
+
client.stubs(:collective).returns("mcollective")
|
43
|
+
MCollective::Client.stubs(:new).returns(client)
|
44
|
+
|
45
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should reset the stats" do
|
49
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
50
|
+
client.stubs(:call_agent)
|
51
|
+
|
52
|
+
Stats.any_instance.expects(:reset).once
|
53
|
+
client.foo
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should validate the request against the ddl" do
|
57
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
58
|
+
|
59
|
+
client.stubs(:call_agent)
|
60
|
+
|
61
|
+
ddl = mock
|
62
|
+
ddl.expects(:validate_request).with("rspec", {:arg => :val}).raises("validation failed")
|
63
|
+
client.instance_variable_set("@ddl", ddl)
|
64
|
+
|
65
|
+
expect { client.rspec(:arg => :val) }.to raise_error("validation failed")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should support limited targets" do
|
69
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
70
|
+
client.limit_targets = 10
|
71
|
+
|
72
|
+
client.expects(:pick_nodes_from_discovered).with(10).returns(["one", "two"])
|
73
|
+
client.expects(:custom_request).with("foo", {}, ["one", "two"], {"identity" => /^(one|two)$/}).once
|
74
|
+
|
75
|
+
client.foo
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "batch mode" do
|
79
|
+
before do
|
80
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
81
|
+
@client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should support global batch_size" do
|
85
|
+
@client.batch_size = 10
|
86
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 10, 1)
|
87
|
+
@client.rspec
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should support custom batch_size" do
|
91
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 10, 1)
|
92
|
+
@client.rspec :batch_size => 10
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should allow supplied batch_size override global one" do
|
96
|
+
@client.batch_size = 10
|
97
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 20, 1)
|
98
|
+
@client.rspec :batch_size => 20
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should support global batch_sleep_time" do
|
102
|
+
@client.batch_size = 10
|
103
|
+
@client.batch_sleep_time = 20
|
104
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 10, 20)
|
105
|
+
@client.rspec
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should support custom batch_sleep_time" do
|
109
|
+
@client.batch_size = 10
|
110
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 10, 20)
|
111
|
+
@client.rspec :batch_sleep_time => 20
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should allow supplied batch_sleep_time override global one" do
|
115
|
+
@client.batch_size = 10
|
116
|
+
@client.batch_sleep_time = 10
|
117
|
+
@client.expects(:call_agent_batched).with("rspec", {}, @client.options, 10, 20)
|
118
|
+
@client.rspec :batch_sleep_time => 20
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should support normal calls" do
|
123
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
124
|
+
|
125
|
+
client.expects(:call_agent).with("foo", {}, client.options, :auto).once
|
126
|
+
|
127
|
+
client.foo
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#limit_targets=" do
|
132
|
+
before do
|
133
|
+
client = stub
|
134
|
+
|
135
|
+
client.stubs("options=")
|
136
|
+
client.stubs(:collective).returns("mcollective")
|
137
|
+
|
138
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
139
|
+
MCollective::Client.expects(:new).returns(client)
|
140
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
141
|
+
|
142
|
+
@client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should support percentages" do
|
146
|
+
@client.limit_targets = "10%"
|
147
|
+
@client.limit_targets.should == "10%"
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should support integers" do
|
151
|
+
@client.limit_targets = 10
|
152
|
+
@client.limit_targets.should == 10
|
153
|
+
@client.limit_targets = "20"
|
154
|
+
@client.limit_targets.should == 20
|
155
|
+
@client.limit_targets = 1.1
|
156
|
+
@client.limit_targets.should == 1
|
157
|
+
@client.limit_targets = 1.7
|
158
|
+
@client.limit_targets.should == 1
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not invalid limits to be set" do
|
162
|
+
expect { @client.limit_targets = "a" }.to raise_error /Invalid/
|
163
|
+
expect { @client.limit_targets = "%1" }.to raise_error /Invalid/
|
164
|
+
expect { @client.limit_targets = "1.1" }.to raise_error /Invalid/
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#call_agent_batched" do
|
169
|
+
before do
|
170
|
+
@client = stub
|
171
|
+
|
172
|
+
@client.stubs("options=")
|
173
|
+
@client.stubs(:collective).returns("mcollective")
|
174
|
+
|
175
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
176
|
+
MCollective::Client.expects(:new).returns(@client)
|
177
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should require direct addressing" do
|
181
|
+
Config.any_instance.stubs(:direct_addressing).returns(false)
|
182
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
183
|
+
|
184
|
+
expect {
|
185
|
+
client.send(:call_agent_batched, "foo", {}, {}, 1, 1)
|
186
|
+
}.to raise_error("Batched requests requires direct addressing")
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should require that all results be processed" do
|
190
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
191
|
+
|
192
|
+
expect {
|
193
|
+
client.send(:call_agent_batched, "foo", {:process_results => false}, {}, 1, 1)
|
194
|
+
}.to raise_error("Cannot bypass result processing for batched requests")
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should only accept integer batch sizes" do
|
198
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
199
|
+
|
200
|
+
expect {
|
201
|
+
client.send(:call_agent_batched, "foo", {}, {}, "foo", 1)
|
202
|
+
}.to raise_error(/invalid value for Integer/)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should only accept float sleep times" do
|
206
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
207
|
+
|
208
|
+
expect {
|
209
|
+
client.send(:call_agent_batched, "foo", {}, {}, 1, "foo")
|
210
|
+
}.to raise_error(/invalid value for Float/)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should batch hosts in the correct size" do
|
214
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :stderr => StringIO.new}})
|
215
|
+
|
216
|
+
client.expects(:new_request).returns("req")
|
217
|
+
|
218
|
+
discovered = mock
|
219
|
+
discovered.stubs(:size).returns(1)
|
220
|
+
discovered.expects(:in_groups_of).with(10).raises("spec pass")
|
221
|
+
@client.stubs(:discover).returns(discovered)
|
222
|
+
|
223
|
+
expect { client.send(:call_agent_batched, "foo", {}, {}, 10, 1) }.to raise_error("spec pass")
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should force direct requests" do
|
227
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :stderr => StringIO.new}})
|
228
|
+
|
229
|
+
Message.expects(:new).with('req', nil, {:type => :direct_request, :agent => 'foo', :filter => nil, :options => {}, :collective => 'mcollective'}).raises("spec pass")
|
230
|
+
client.expects(:new_request).returns("req")
|
231
|
+
|
232
|
+
@client.stubs(:discover).returns(["test"])
|
233
|
+
|
234
|
+
expect { client.send(:call_agent_batched, "foo", {}, {}, 1, 1) }.to raise_error("spec pass")
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should process blocks correctly" do
|
238
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :stderr => StringIO.new}})
|
239
|
+
|
240
|
+
msg = mock
|
241
|
+
msg.expects(:discovered_hosts=).times(10)
|
242
|
+
|
243
|
+
stats = {:noresponsefrom => [], :responses => 0, :blocktime => 0, :totaltime => 0, :discoverytime => 0}
|
244
|
+
|
245
|
+
Message.expects(:new).with('req', nil, {:type => :direct_request, :agent => 'foo', :filter => nil, :options => {}, :collective => 'mcollective'}).returns(msg).times(10)
|
246
|
+
client.expects(:new_request).returns("req")
|
247
|
+
client.expects(:sleep).with(1.0).times(9)
|
248
|
+
|
249
|
+
@client.stubs(:discover).returns([1,2,3,4,5,6,7,8,9,0])
|
250
|
+
@client.expects(:req).with(msg).yields("result").times(10)
|
251
|
+
@client.stubs(:stats).returns stats
|
252
|
+
|
253
|
+
client.expects(:process_results_with_block).with("foo", "result", instance_of(Proc)).times(10)
|
254
|
+
|
255
|
+
result = client.send(:call_agent_batched, "foo", {}, {}, 1, 1) { }
|
256
|
+
result.class.should == Stats
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should return an array of results in array mode" do
|
260
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :stderr => StringIO.new}})
|
261
|
+
|
262
|
+
msg = mock
|
263
|
+
msg.expects(:discovered_hosts=).times(10)
|
264
|
+
|
265
|
+
stats = {:noresponsefrom => [], :responses => 0, :blocktime => 0, :totaltime => 0, :discoverytime => 0}
|
266
|
+
|
267
|
+
Progress.expects(:new).never
|
268
|
+
|
269
|
+
Message.expects(:new).with('req', nil, {:type => :direct_request, :agent => 'foo', :filter => nil, :options => {}, :collective => 'mcollective'}).returns(msg).times(10)
|
270
|
+
client.expects(:new_request).returns("req")
|
271
|
+
client.expects(:sleep).with(1.0).times(9)
|
272
|
+
|
273
|
+
@client.stubs(:discover).returns([1,2,3,4,5,6,7,8,9,0])
|
274
|
+
@client.expects(:req).with(msg).yields("result").times(10)
|
275
|
+
@client.stubs(:stats).returns stats
|
276
|
+
|
277
|
+
client.expects(:process_results_without_block).with("result", "foo").returns("rspec").times(10)
|
278
|
+
|
279
|
+
client.send(:call_agent_batched, "foo", {}, {}, 1, 1).should == ["rspec", "rspec", "rspec", "rspec", "rspec", "rspec", "rspec", "rspec", "rspec", "rspec"]
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe "#batch_sleep_time=" do
|
284
|
+
before do
|
285
|
+
@client = stub
|
286
|
+
|
287
|
+
@client.stubs("options=")
|
288
|
+
@client.stubs(:collective).returns("mcollective")
|
289
|
+
|
290
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
291
|
+
MCollective::Client.expects(:new).returns(@client)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should correctly set the sleep" do
|
295
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
296
|
+
|
297
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
298
|
+
client.batch_sleep_time = 5
|
299
|
+
client.batch_sleep_time.should == 5
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should only allow batch sleep to be set for direct addressing capable clients" do
|
303
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
304
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
305
|
+
|
306
|
+
expect { client.batch_sleep_time = 5 }.to raise_error("Can only set batch sleep time if direct addressing is supported")
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "#batch_size=" do
|
311
|
+
before do
|
312
|
+
@client = stub
|
313
|
+
|
314
|
+
@client.stubs("options=")
|
315
|
+
@client.stubs(:collective).returns("mcollective")
|
316
|
+
|
317
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
318
|
+
MCollective::Client.expects(:new).returns(@client)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should correctly set the size" do
|
322
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
323
|
+
|
324
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
325
|
+
client.batch_mode.should == false
|
326
|
+
client.batch_size = 5
|
327
|
+
client.batch_size.should == 5
|
328
|
+
client.batch_mode.should == true
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should only allow batch size to be set for direct addressing capable clients" do
|
332
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
333
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
334
|
+
|
335
|
+
expect { client.batch_size = 5 }.to raise_error("Can only set batch size if direct addressing is supported")
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should support disabling batch mode when supplied a batch size of 0" do
|
339
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
340
|
+
|
341
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
342
|
+
client.batch_size = 5
|
343
|
+
client.batch_mode.should == true
|
344
|
+
client.batch_size = 0
|
345
|
+
client.batch_mode.should == false
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
describe "#discover" do
|
350
|
+
before do
|
351
|
+
@client = stub
|
352
|
+
|
353
|
+
@client.stubs("options=")
|
354
|
+
@client.stubs(:collective).returns("mcollective")
|
355
|
+
|
356
|
+
@stderr = stub
|
357
|
+
@stdout = stub
|
358
|
+
|
359
|
+
Config.any_instance.stubs(:loadconfig).with("/nonexisting").returns(true)
|
360
|
+
MCollective::Client.expects(:new).returns(@client)
|
361
|
+
end
|
362
|
+
|
363
|
+
it "should not accept invalid flags" do
|
364
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
365
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
366
|
+
|
367
|
+
expect { client.discover(:rspec => :rspec) }.to raise_error("Unknown option rspec passed to discover")
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should reset when :json, :hosts or :nodes are provided" do
|
371
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
372
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
373
|
+
client.expects(:reset).times(3)
|
374
|
+
client.discover(:hosts => ["one"])
|
375
|
+
client.discover(:nodes => ["one"])
|
376
|
+
client.discover(:json => ["one"])
|
377
|
+
end
|
378
|
+
|
379
|
+
it "should only allow discovery data in direct addressing mode" do
|
380
|
+
Config.any_instance.stubs(:direct_addressing).returns(false)
|
381
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
382
|
+
client.expects(:reset).once
|
383
|
+
|
384
|
+
expect {
|
385
|
+
client.discover(:nodes => ["one"])
|
386
|
+
}.to raise_error("Can only supply discovery data if direct_addressing is enabled")
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should parse :nodes and :hosts and force direct requests" do
|
390
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
391
|
+
Helpers.expects(:extract_hosts_from_array).with(["one"]).returns(["one"]).twice
|
392
|
+
|
393
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
394
|
+
client.discover(:nodes => ["one"]).should == ["one"]
|
395
|
+
client.discover(:hosts => ["one"]).should == ["one"]
|
396
|
+
client.instance_variable_get("@force_direct_request").should == true
|
397
|
+
client.instance_variable_get("@discovered_agents").should == ["one"]
|
398
|
+
end
|
399
|
+
|
400
|
+
it "should parse :json and force direct requests" do
|
401
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
402
|
+
Helpers.expects(:extract_hosts_from_json).with('["one"]').returns(["one"]).once
|
403
|
+
|
404
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
|
405
|
+
client.discover(:json => '["one"]').should == ["one"]
|
406
|
+
client.instance_variable_get("@force_direct_request").should == true
|
407
|
+
client.instance_variable_get("@discovered_agents").should == ["one"]
|
408
|
+
end
|
409
|
+
|
410
|
+
it "should force direct mode for non regex identity filters" do
|
411
|
+
Config.any_instance.stubs(:direct_addressing).returns(true)
|
412
|
+
|
413
|
+
client = Client.new("foo", {:options => {:filter => {"identity" => ["foo"], "agent" => []}, :config => "/nonexisting"}})
|
414
|
+
client.discover
|
415
|
+
client.instance_variable_get("@discovered_agents").should == ["foo"]
|
416
|
+
client.instance_variable_get("@force_direct_request").should == true
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should not set direct mode if its disabled" do
|
420
|
+
Config.any_instance.stubs(:direct_addressing).returns(false)
|
421
|
+
|
422
|
+
client = Client.new("foo", {:options => {:filter => {"identity" => ["foo"], "agent" => []}, :config => "/nonexisting"}})
|
423
|
+
|
424
|
+
client.discover
|
425
|
+
client.instance_variable_get("@force_direct_request").should == false
|
426
|
+
client.instance_variable_get("@discovered_agents").should == ["foo"]
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should not set direct mode for regex identities" do
|
430
|
+
Config.any_instance.stubs(:direct_addressing).returns(false)
|
431
|
+
|
432
|
+
@client.expects(:discover).with({'identity' => ['/foo/'], 'agent' => ['foo']}, nil).once.returns(["foo"])
|
433
|
+
client = Client.new("foo", {:options => {:filter => {"identity" => ["/foo/"], "agent" => []}, :config => "/nonexisting"}})
|
434
|
+
|
435
|
+
client.discover
|
436
|
+
client.instance_variable_get("@force_direct_request").should == false
|
437
|
+
client.instance_variable_get("@discovered_agents").should == ["foo"]
|
438
|
+
end
|
439
|
+
|
440
|
+
it "should print status to stderr if in verbose mode" do
|
441
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
442
|
+
@stderr.expects(:print).with("Determining the amount of hosts matching filter for 2 seconds .... ")
|
443
|
+
@stderr.expects(:puts).with(1)
|
444
|
+
|
445
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => true, :disctimeout => 2, :stderr => @stderr, :stdout => @stdout}})
|
446
|
+
client.discover
|
447
|
+
end
|
448
|
+
|
449
|
+
it "should not print status to stderr if in verbose mode" do
|
450
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
451
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2, :stderr => @stderr, :stdout => @stdout}})
|
452
|
+
|
453
|
+
@stderr.expects(:print).never
|
454
|
+
@stderr.expects(:puts).never
|
455
|
+
|
456
|
+
client.discover
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should record the start and end times" do
|
460
|
+
Stats.any_instance.expects(:time_discovery).with(:start)
|
461
|
+
Stats.any_instance.expects(:time_discovery).with(:end)
|
462
|
+
|
463
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
464
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
465
|
+
|
466
|
+
client.discover
|
467
|
+
end
|
468
|
+
|
469
|
+
it "should discover using limits in :first rpclimit mode given a number" do
|
470
|
+
Config.any_instance.stubs(:rpclimitmethod).returns(:first)
|
471
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2, 1).returns(["foo"])
|
472
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
473
|
+
client.limit_targets = 1
|
474
|
+
|
475
|
+
client.discover
|
476
|
+
end
|
477
|
+
|
478
|
+
it "should not discover using limits in :first rpclimit mode given a string" do
|
479
|
+
Config.any_instance.stubs(:rpclimitmethod).returns(:first)
|
480
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
481
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
482
|
+
client.limit_targets = "10%"
|
483
|
+
|
484
|
+
client.discover
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should not discover using limits when not in :first mode" do
|
488
|
+
Config.any_instance.stubs(:rpclimitmethod).returns(:random)
|
489
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
490
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
491
|
+
client.limit_targets = 1
|
492
|
+
|
493
|
+
client.discover
|
494
|
+
end
|
495
|
+
|
496
|
+
it "should ensure force_direct mode is false when doing traditional discovery" do
|
497
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
498
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
499
|
+
|
500
|
+
client.instance_variable_set("@force_direct_request", true)
|
501
|
+
client.discover
|
502
|
+
client.instance_variable_get("@force_direct_request").should == false
|
503
|
+
end
|
504
|
+
|
505
|
+
it "should store discovered nodes in stats" do
|
506
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
507
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
508
|
+
|
509
|
+
client.discover
|
510
|
+
client.stats.discovered_nodes.should == ["foo"]
|
511
|
+
end
|
512
|
+
|
513
|
+
it "should save discovered nodes in RPC" do
|
514
|
+
@client.expects(:discover).with({'identity' => [], 'compound' => [], 'fact' => [], 'agent' => ['foo'], 'cf_class' => []}, 2).returns(["foo"])
|
515
|
+
client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting", :verbose => false, :disctimeout => 2}})
|
516
|
+
|
517
|
+
RPC.expects(:discovered).with(["foo"]).once
|
518
|
+
client.discover
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|