mcollective-client 2.5.3 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/lib/mcollective.rb +1 -1
  2. data/lib/mcollective/application.rb +21 -6
  3. data/lib/mcollective/client.rb +7 -0
  4. data/lib/mcollective/config.rb +13 -1
  5. data/lib/mcollective/connector/base.rb +2 -0
  6. data/lib/mcollective/facts/base.rb +18 -5
  7. data/lib/mcollective/log.rb +7 -0
  8. data/lib/mcollective/logger/base.rb +12 -8
  9. data/lib/mcollective/logger/file_logger.rb +7 -0
  10. data/lib/mcollective/message.rb +1 -1
  11. data/lib/mcollective/optionparser.rb +4 -0
  12. data/lib/mcollective/registration/base.rb +24 -10
  13. data/lib/mcollective/rpc/agent.rb +7 -1
  14. data/lib/mcollective/rpc/client.rb +89 -35
  15. data/lib/mcollective/rpc/helpers.rb +8 -3
  16. data/lib/mcollective/rpc/result.rb +4 -0
  17. data/lib/mcollective/rpc/stats.rb +6 -2
  18. data/lib/mcollective/shell.rb +2 -0
  19. data/lib/mcollective/ssl.rb +5 -0
  20. data/lib/mcollective/util.rb +29 -1
  21. data/lib/mcollective/validator.rb +9 -4
  22. data/spec/spec_helper.rb +6 -0
  23. data/spec/unit/config_spec.rb +10 -0
  24. data/spec/unit/connector/base_spec.rb +28 -0
  25. data/spec/unit/facts/base_spec.rb +35 -0
  26. data/spec/unit/log_spec.rb +9 -0
  27. data/spec/unit/logger/base_spec.rb +12 -2
  28. data/spec/unit/logger/file_logger_spec.rb +82 -0
  29. data/spec/unit/plugins/mcollective/application/plugin_spec.rb +1 -0
  30. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +44 -17
  31. data/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +20 -19
  32. data/spec/unit/plugins/mcollective/data/fact_data_spec.rb +92 -0
  33. data/spec/unit/registration/base_spec.rb +46 -0
  34. data/spec/unit/rpc/agent_spec.rb +37 -0
  35. data/spec/unit/rpc/client_spec.rb +68 -15
  36. data/spec/unit/rpc/result_spec.rb +21 -0
  37. data/spec/unit/runner_spec.rb +97 -19
  38. data/spec/unit/shell_spec.rb +5 -0
  39. data/spec/unit/ssl_spec.rb +5 -0
  40. data/spec/unit/util_spec.rb +163 -1
  41. metadata +215 -209
@@ -47,9 +47,9 @@ module MCollective
47
47
 
48
48
  let(:subscription) do
49
49
  sub = mock
50
- sub.stubs("<<").returns(true)
51
- sub.stubs("include?").returns(false)
52
- sub.stubs("delete").returns(false)
50
+ sub.stubs(:<<).returns(true)
51
+ sub.stubs(:include?).returns(false)
52
+ sub.stubs(:delete).returns(false)
53
53
  sub
54
54
  end
55
55
 
@@ -432,8 +432,8 @@ module MCollective
432
432
  msg.stubs(:ttl).returns(60)
433
433
  msg.expects(:discovered_hosts).returns(["one", "two"])
434
434
 
435
- connection.expects(:publish).with('/exchange/mcollective_directed/one', 'msg', {'reply-to' => '/temp-queue/mcollective_reply_agent', 'expiration' => '70000'})
436
- connection.expects(:publish).with('/exchange/mcollective_directed/two', 'msg', {'reply-to' => '/temp-queue/mcollective_reply_agent', 'expiration' => '70000'})
435
+ connection.expects(:publish).with('/exchange/mcollective_directed/one', 'msg', {'reply-to' => '/topic/mcollective', 'expiration' => '70000'})
436
+ connection.expects(:publish).with('/exchange/mcollective_directed/two', 'msg', {'reply-to' => '/topic/mcollective', 'expiration' => '70000'})
437
437
 
438
438
  connector.publish(msg)
439
439
  end
@@ -447,12 +447,12 @@ module MCollective
447
447
  end
448
448
 
449
449
  it "should use the make_target correctly" do
450
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
450
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
451
451
  connector.subscribe("test", :broadcast, "mcollective")
452
452
  end
453
453
 
454
454
  it "should check for existing subscriptions" do
455
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
455
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
456
456
  subscription.expects("include?").with("rspec").returns(false)
457
457
  connection.expects(:subscribe).never
458
458
 
@@ -460,14 +460,14 @@ module MCollective
460
460
  end
461
461
 
462
462
  it "should subscribe to the middleware" do
463
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
463
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
464
464
  connection.expects(:subscribe).with("test", {}, "rspec")
465
465
  connector.subscribe("test", :broadcast, "mcollective")
466
466
  end
467
467
 
468
468
  it "should add to the list of subscriptions" do
469
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
470
- subscription.expects("<<").with("rspec")
469
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
470
+ subscription.expects(:<<).with("rspec")
471
471
  connector.subscribe("test", :broadcast, "mcollective")
472
472
  end
473
473
 
@@ -478,7 +478,7 @@ module MCollective
478
478
 
479
479
  it "should subscribe to :reply messages when use_reply_exchange is set" do
480
480
  Rabbitmq.any_instance.stubs(:get_bool_option).with("rabbitmq.use_reply_exchange", false).returns(true)
481
- connector.expects("make_target").with("test", :reply, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
481
+ connector.expects(:make_target).with("test", :reply, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
482
482
  connection.expects(:subscribe).with("test", {}, "rspec").once
483
483
 
484
484
  connector.subscribe("test", :reply, "mcollective")
@@ -487,19 +487,19 @@ module MCollective
487
487
 
488
488
  describe "#unsubscribe" do
489
489
  it "should use make_target correctly" do
490
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
490
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
491
491
  connector.unsubscribe("test", :broadcast, "mcollective")
492
492
  end
493
493
 
494
494
  it "should unsubscribe from the target" do
495
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
495
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
496
496
  connection.expects(:unsubscribe).with("test", {}, "rspec").once
497
497
 
498
498
  connector.unsubscribe("test", :broadcast, "mcollective")
499
499
  end
500
500
 
501
501
  it "should delete the source from subscriptions" do
502
- connector.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
502
+ connector.expects(:make_target).with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
503
503
  subscription.expects(:delete).with("rspec").once
504
504
 
505
505
  connector.unsubscribe("test", :broadcast, "mcollective")
@@ -512,7 +512,7 @@ module MCollective
512
512
 
513
513
  it "should unsubscribe from :reply messages when use_reply_exchange is set" do
514
514
  Rabbitmq.any_instance.stubs(:get_bool_option).with("rabbitmq.use_reply_exchange", false).returns(true)
515
- connector.expects("make_target").with("test", :reply, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
515
+ connector.expects(:make_target).with("test", :reply, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
516
516
  connection.expects(:unsubscribe).with("test", {}, "rspec").once
517
517
 
518
518
  connector.unsubscribe("test", :reply, "mcollective")
@@ -618,23 +618,24 @@ module MCollective
618
618
  end
619
619
 
620
620
  it "should create correct targets" do
621
+ Client.stubs(:request_sequence).returns(42)
621
622
  connector.make_target("test", :reply, "mcollective").should eq({
622
- :name => "/exchange/mcollective_reply/rspec_#{$$}",
623
+ :name => "/exchange/mcollective_reply/rspec_#{$$}_42",
623
624
  :headers => {},
624
625
  :id => "mcollective_test_replies",
625
626
  })
626
627
  connector.make_target("test", :broadcast, "mcollective").should eq({
627
628
  :name => "/exchange/mcollective_broadcast/test",
628
- :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}" },
629
+ :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}_42" },
629
630
  :id => "mcollective_broadcast_test"
630
631
  })
631
632
  connector.make_target("test", :request, "mcollective").should eq({
632
633
  :name => "/exchange/mcollective_broadcast/test",
633
- :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}" },
634
+ :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}_42" },
634
635
  :id => "mcollective_broadcast_test",
635
636
  })
636
637
  connector.make_target("test", :direct_request, "mcollective", nil, "rspec").should eq({
637
- :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}" },
638
+ :headers => { "reply-to" => "/exchange/mcollective_reply/rspec_#{$$}_42" },
638
639
  :name => "/exchange/mcollective_directed/rspec",
639
640
  :id => nil
640
641
  })
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ require File.dirname(__FILE__) + "/../../../../../plugins/mcollective/data/fact_data.rb"
6
+
7
+ module MCollective
8
+ module Data
9
+ describe Fact_data do
10
+ describe "#query_data" do
11
+ before :each do
12
+ @ddl = mock('DDL')
13
+ @ddl.stubs(:dataquery_interface).returns({:output => {}})
14
+ @ddl.stubs(:meta).returns({:timeout => 1})
15
+ DDL.stubs(:new).returns(@ddl)
16
+ @plugin = Fact_data.new
17
+
18
+ facts_plugin = mock('fact_plugin')
19
+ PluginManager.stubs(:[]).with('facts_plugin').returns(facts_plugin)
20
+
21
+ facts_plugin.expects(:get_facts).returns({
22
+ "foo" => "foo-value",
23
+ "one" => {
24
+ "one" => "one-one",
25
+ "two" => {
26
+ "one" => "one-two-one",
27
+ "two" => "one-two-two",
28
+ },
29
+ },
30
+ "some_array" => [
31
+ "a",
32
+ "b",
33
+ ],
34
+ })
35
+ end
36
+
37
+ it 'should return an unfound fact as false' do
38
+ @plugin.query_data("bar")
39
+
40
+ @plugin.result[:exists].should == false
41
+ @plugin.result[:value].should == false
42
+ @plugin.result[:value_encoding].should == false
43
+ end
44
+
45
+ it "should be able to find a value at top level" do
46
+ @plugin.query_data("foo")
47
+
48
+ @plugin.result[:exists].should == true
49
+ @plugin.result[:value].should == "foo-value"
50
+ @plugin.result[:value_encoding].should == 'text/plain'
51
+ end
52
+
53
+ it 'should be able to walk down to a hash element' do
54
+ @plugin.query_data("one.one")
55
+
56
+ @plugin.result[:exists].should == true
57
+ @plugin.result[:value].should == "one-one"
58
+ @plugin.result[:value_encoding].should == 'text/plain'
59
+ end
60
+
61
+ it 'should be able to walk down to a hash' do
62
+ @plugin.query_data("one.two")
63
+
64
+ @plugin.result[:exists].should == true
65
+
66
+ @plugin.result[:value].should == {
67
+ "one" => "one-two-one",
68
+ "two" => "one-two-two",
69
+ }.to_json
70
+ @plugin.result[:value_encoding].should == 'application/json'
71
+
72
+ end
73
+
74
+ it 'should be able to walk down to an array' do
75
+ @plugin.query_data("some_array")
76
+
77
+ @plugin.result[:exists].should == true
78
+ @plugin.result[:value].should == [ "a", "b" ].to_json
79
+ @plugin.result[:value_encoding].should == 'application/json'
80
+ end
81
+
82
+ it 'should be able to walk down to an array element' do
83
+ @plugin.query_data("some_array.0")
84
+
85
+ @plugin.result[:exists].should == true
86
+ @plugin.result[:value].should == "a"
87
+ @plugin.result[:value_encoding].should == 'text/plain'
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -5,6 +5,9 @@ require 'spec_helper'
5
5
  module MCollective
6
6
  module Registration
7
7
  describe Base do
8
+
9
+ let(:connection) { mock }
10
+
8
11
  before do
9
12
  @config = mock
10
13
  @config.stubs(:identity).returns("rspec")
@@ -18,7 +21,20 @@ module MCollective
18
21
  it "should provide access the main configuration class" do
19
22
  @reg.config.should == @config
20
23
  end
24
+ end
25
+
26
+ describe "#run" do
27
+ it "should not start the publish_thread if the registration interval is 0" do
28
+ @reg.stubs(:interval).returns(0)
29
+ Thread.expects(:new).never
30
+ @reg.run(connection).should == false
31
+ end
21
32
 
33
+ it "should start the publish_thread" do
34
+ @reg.stubs(:interval).returns(1)
35
+ Thread.expects(:new).returns(true)
36
+ @reg.run(connection).should be_true
37
+ end
22
38
  end
23
39
 
24
40
  describe "#identity" do
@@ -72,6 +88,36 @@ module MCollective
72
88
  @reg.publish("message")
73
89
  end
74
90
  end
91
+
92
+ describe "#body" do
93
+ it "should fail if body hasn't been implemented" do
94
+ expect {
95
+ @reg.body
96
+ }.to raise_error
97
+ end
98
+ end
99
+
100
+ describe "#publish_thread" do
101
+ before(:each) do
102
+ @reg.expects(:loop).returns("looping")
103
+ end
104
+
105
+ it "should splay if splay is set" do
106
+ @reg.stubs(:interval).returns(1)
107
+ @config.stubs(:registration_splay).returns(true)
108
+ Log.expects(:debug)
109
+ @reg.expects(:sleep)
110
+ @reg.send(:publish_thread, connection)
111
+ end
112
+
113
+ it "should not splay if splay isn't set" do
114
+ @reg.stubs(:interval).returns(1)
115
+ @config.stubs(:registration_splay).returns(false)
116
+ Log.expects(:debug).never
117
+ @reg.expects(:sleep).never
118
+ @reg.send(:publish_thread, connection)
119
+ end
120
+ end
75
121
  end
76
122
  end
77
123
  end
@@ -151,6 +151,43 @@ module MCollective
151
151
  end
152
152
  end
153
153
 
154
+ describe "#activate?" do
155
+ class Test < MCollective::RPC::Agent;end
156
+
157
+ let(:config) do
158
+ conf = mock
159
+ conf.stubs(:pluginconf).returns({})
160
+ conf
161
+ end
162
+
163
+ before(:each) do
164
+ Config.stubs(:instance).returns(config)
165
+ Log.stubs(:debug)
166
+ end
167
+
168
+ it "should return true if plugins are globally enabled" do
169
+ config.stubs(:activate_agents).returns(true)
170
+ Test.activate?.should == true
171
+ end
172
+
173
+ it "should return true if plugins are globally disabled but locally enabled" do
174
+ config.stubs(:activate_agents).returns(false)
175
+ config.pluginconf['test.activate_agent'] = true
176
+ Test.activate?.should == true
177
+ end
178
+
179
+ it "should return false if plugins are globally disabled" do
180
+ config.stubs(:activate_agents).returns(false)
181
+ Test.activate?.should == false
182
+ end
183
+
184
+ it "should return false if plugins are globally enabled but locally disabled" do
185
+ config.stubs(:activate_agents).returns(true)
186
+ config.pluginconf['test.activate_agent'] = false
187
+ Test.activate?.should == false
188
+ end
189
+ end
190
+
154
191
  describe "#load_ddl" do
155
192
  it "should load the correct DDL" do
156
193
  ddl = stub
@@ -102,18 +102,6 @@ module MCollective
102
102
  @client.process_results_with_block("rspec", response, blk, nil)
103
103
  end
104
104
 
105
- it "should raise correct exceptions on failure" do
106
- blk = Proc.new {}
107
-
108
- @client.stubs(:rpc_result_from_reply)
109
-
110
- [[2, UnknownRPCAction], [3, MissingRPCData], [4, InvalidRPCData], [5, UnknownRPCError]].each do |err|
111
- response = {:senderid => "rspec", :body => {:statuscode => err[0]}}
112
-
113
- expect { @client.process_results_with_block("rspec", response, blk, nil) }.to raise_error(err[1])
114
- end
115
- end
116
-
117
105
  it "should pass raw results for single arity blocks" do
118
106
  response = {:senderid => "rspec", :body => {:statuscode => 1}}
119
107
  blk = Proc.new {|r| r.should == response}
@@ -560,11 +548,21 @@ module MCollective
560
548
  @client.limit_targets.should == 1
561
549
  end
562
550
 
563
- it "should not invalid limits to be set" do
551
+ it "should not allow invalid limits to be set" do
564
552
  expect { @client.limit_targets = "a" }.to raise_error(/Invalid/)
565
553
  expect { @client.limit_targets = "%1" }.to raise_error(/Invalid/)
566
554
  expect { @client.limit_targets = "1.1" }.to raise_error(/Invalid/)
567
555
  end
556
+
557
+ it "should reset @limit_targets" do
558
+ @client.limit_targets = 10
559
+ @client.limit_targets.should == 10
560
+ @client.limit_targets = nil
561
+ @client.limit_targets.should == nil
562
+ @client.limit_targets = 10
563
+ @client.limit_targets = false
564
+ @client.limit_targets.should == nil
565
+ end
568
566
  end
569
567
 
570
568
  describe "#fire_and_forget_request" do
@@ -686,12 +684,12 @@ module MCollective
686
684
  }.to raise_error("Cannot bypass result processing for batched requests")
687
685
  end
688
686
 
689
- it "should only accept integer batch sizes" do
687
+ it "should only accept valid batch sizes" do
690
688
  client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
691
689
 
692
690
  expect {
693
691
  client.send(:call_agent_batched, "foo", {}, {}, "foo", 1)
694
- }.to raise_error(/invalid value for Integer/)
692
+ }.to raise_error("batch_size must be an integer or match a percentage string (e.g. '24%'")
695
693
  end
696
694
 
697
695
  it "should only accept float sleep times" do
@@ -825,6 +823,12 @@ module MCollective
825
823
  expect { client.batch_size = 5 }.to raise_error("Can only set batch size if direct addressing is supported")
826
824
  end
827
825
 
826
+ it "should accept batch sizes as percentage strings" do
827
+ client = Client.new("foo", {:options => {:filter => Util.empty_filter, :config => "/nonexisting"}})
828
+ client.batch_size = "50%"
829
+ client.batch_size.should == "50%"
830
+ end
831
+
828
832
  it "should support disabling batch mode when supplied a batch size of 0" do
829
833
  Config.instance.stubs(:direct_addressing).returns(true)
830
834
 
@@ -1011,6 +1015,55 @@ module MCollective
1011
1015
  rpcclient.discover
1012
1016
  end
1013
1017
  end
1018
+
1019
+ describe "#determine_batch_mode" do
1020
+ let(:rpcclient) do
1021
+ rpcclient = Client.new("foo",
1022
+ {:options => {:filter => Util.empty_filter,
1023
+ :config => "/nonexisting",
1024
+ :verbose => false,
1025
+ :disctimeout => 2}})
1026
+ end
1027
+
1028
+ it "should return true when batch_mode should be set" do
1029
+ rpcclient.send(:determine_batch_mode, "1").should == true
1030
+ rpcclient.send(:determine_batch_mode, 1).should == true
1031
+ rpcclient.send(:determine_batch_mode, "1%").should == true
1032
+ end
1033
+
1034
+ it "should return false when batch_mode shouldn't be set" do
1035
+ rpcclient.send(:determine_batch_mode, "0").should == false
1036
+ rpcclient.send(:determine_batch_mode, 0).should == false
1037
+ end
1038
+ end
1039
+
1040
+ describe "#validate_batch_size" do
1041
+ let(:rpcclient) do
1042
+ rpcclient = Client.new("foo",
1043
+ {:options => {:filter => Util.empty_filter,
1044
+ :config => "/nonexisting",
1045
+ :verbose => false,
1046
+ :disctimeout => 2}})
1047
+ end
1048
+
1049
+ it "should fail when batch size is an invalid string" do
1050
+ expect {
1051
+ rpcclient.send(:validate_batch_size, "foo")
1052
+ }.to raise_error
1053
+ end
1054
+
1055
+ it "should fail when batch size is 0%" do
1056
+ expect {
1057
+ rpcclient.send(:validate_batch_size, "0%")
1058
+ }.to raise_error
1059
+ end
1060
+
1061
+ it "should fail when batch size is not a valid string or integer" do
1062
+ expect {
1063
+ rpcclient.send(:validate_batch_size, true)
1064
+ }.to raise_error
1065
+ end
1066
+ end
1014
1067
  end
1015
1068
  end
1016
1069
  end