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.

Files changed (103) hide show
  1. data/bin/mc-call-agent +54 -0
  2. data/bin/mco +27 -0
  3. data/lib/mcollective.rb +70 -0
  4. data/lib/mcollective/agents.rb +160 -0
  5. data/lib/mcollective/application.rb +354 -0
  6. data/lib/mcollective/applications.rb +145 -0
  7. data/lib/mcollective/client.rb +292 -0
  8. data/lib/mcollective/config.rb +202 -0
  9. data/lib/mcollective/connector.rb +18 -0
  10. data/lib/mcollective/connector/base.rb +24 -0
  11. data/lib/mcollective/facts.rb +39 -0
  12. data/lib/mcollective/facts/base.rb +86 -0
  13. data/lib/mcollective/log.rb +103 -0
  14. data/lib/mcollective/logger.rb +5 -0
  15. data/lib/mcollective/logger/base.rb +73 -0
  16. data/lib/mcollective/logger/console_logger.rb +61 -0
  17. data/lib/mcollective/logger/file_logger.rb +46 -0
  18. data/lib/mcollective/logger/syslog_logger.rb +53 -0
  19. data/lib/mcollective/matcher.rb +16 -0
  20. data/lib/mcollective/matcher/parser.rb +93 -0
  21. data/lib/mcollective/matcher/scanner.rb +123 -0
  22. data/lib/mcollective/message.rb +201 -0
  23. data/lib/mcollective/monkey_patches.rb +104 -0
  24. data/lib/mcollective/optionparser.rb +164 -0
  25. data/lib/mcollective/pluginmanager.rb +180 -0
  26. data/lib/mcollective/pluginpackager.rb +26 -0
  27. data/lib/mcollective/pluginpackager/agent_definition.rb +79 -0
  28. data/lib/mcollective/pluginpackager/standard_definition.rb +59 -0
  29. data/lib/mcollective/registration.rb +16 -0
  30. data/lib/mcollective/registration/base.rb +75 -0
  31. data/lib/mcollective/rpc.rb +188 -0
  32. data/lib/mcollective/rpc/actionrunner.rb +142 -0
  33. data/lib/mcollective/rpc/agent.rb +441 -0
  34. data/lib/mcollective/rpc/audit.rb +38 -0
  35. data/lib/mcollective/rpc/client.rb +793 -0
  36. data/lib/mcollective/rpc/ddl.rb +258 -0
  37. data/lib/mcollective/rpc/helpers.rb +339 -0
  38. data/lib/mcollective/rpc/progress.rb +63 -0
  39. data/lib/mcollective/rpc/reply.rb +61 -0
  40. data/lib/mcollective/rpc/request.rb +51 -0
  41. data/lib/mcollective/rpc/result.rb +41 -0
  42. data/lib/mcollective/rpc/stats.rb +185 -0
  43. data/lib/mcollective/runnerstats.rb +90 -0
  44. data/lib/mcollective/security.rb +26 -0
  45. data/lib/mcollective/security/base.rb +237 -0
  46. data/lib/mcollective/shell.rb +87 -0
  47. data/lib/mcollective/ssl.rb +246 -0
  48. data/lib/mcollective/unix_daemon.rb +37 -0
  49. data/lib/mcollective/util.rb +274 -0
  50. data/lib/mcollective/vendor.rb +41 -0
  51. data/lib/mcollective/vendor/require_vendored.rb +2 -0
  52. data/lib/mcollective/windows_daemon.rb +25 -0
  53. data/spec/Rakefile +16 -0
  54. data/spec/fixtures/application/test.rb +7 -0
  55. data/spec/fixtures/test-cert.pem +15 -0
  56. data/spec/fixtures/test-private.pem +15 -0
  57. data/spec/fixtures/test-public.pem +6 -0
  58. data/spec/monkey_patches/instance_variable_defined.rb +7 -0
  59. data/spec/spec.opts +1 -0
  60. data/spec/spec_helper.rb +25 -0
  61. data/spec/unit/agents_spec.rb +280 -0
  62. data/spec/unit/application_spec.rb +636 -0
  63. data/spec/unit/applications_spec.rb +155 -0
  64. data/spec/unit/array.rb +30 -0
  65. data/spec/unit/config_spec.rb +148 -0
  66. data/spec/unit/facts/base_spec.rb +118 -0
  67. data/spec/unit/facts_spec.rb +39 -0
  68. data/spec/unit/log_spec.rb +71 -0
  69. data/spec/unit/logger/base_spec.rb +110 -0
  70. data/spec/unit/logger/syslog_logger_spec.rb +86 -0
  71. data/spec/unit/matcher/parser_spec.rb +106 -0
  72. data/spec/unit/matcher/scanner_spec.rb +71 -0
  73. data/spec/unit/message_spec.rb +401 -0
  74. data/spec/unit/optionparser_spec.rb +113 -0
  75. data/spec/unit/pluginmanager_spec.rb +173 -0
  76. data/spec/unit/pluginpackager/agent_definition_spec.rb +130 -0
  77. data/spec/unit/pluginpackager/standard_definition_spec.rb +75 -0
  78. data/spec/unit/plugins/mcollective/connector/activemq_spec.rb +533 -0
  79. data/spec/unit/plugins/mcollective/connector/stomp/eventlogger_spec.rb +34 -0
  80. data/spec/unit/plugins/mcollective/connector/stomp_spec.rb +417 -0
  81. data/spec/unit/plugins/mcollective/packagers/ospackage_spec.rb +229 -0
  82. data/spec/unit/plugins/mcollective/security/psk_spec.rb +156 -0
  83. data/spec/unit/registration/base_spec.rb +77 -0
  84. data/spec/unit/rpc/actionrunner_spec.rb +213 -0
  85. data/spec/unit/rpc/agent_spec.rb +155 -0
  86. data/spec/unit/rpc/client_spec.rb +523 -0
  87. data/spec/unit/rpc/ddl_spec.rb +388 -0
  88. data/spec/unit/rpc/helpers_spec.rb +55 -0
  89. data/spec/unit/rpc/reply_spec.rb +143 -0
  90. data/spec/unit/rpc/request_spec.rb +115 -0
  91. data/spec/unit/rpc/result_spec.rb +66 -0
  92. data/spec/unit/rpc/stats_spec.rb +288 -0
  93. data/spec/unit/runnerstats_spec.rb +40 -0
  94. data/spec/unit/security/base_spec.rb +279 -0
  95. data/spec/unit/shell_spec.rb +144 -0
  96. data/spec/unit/ssl_spec.rb +244 -0
  97. data/spec/unit/symbol.rb +11 -0
  98. data/spec/unit/unix_daemon.rb +41 -0
  99. data/spec/unit/util_spec.rb +342 -0
  100. data/spec/unit/vendor_spec.rb +34 -0
  101. data/spec/unit/windows_daemon.rb +43 -0
  102. data/spec/windows_spec.opts +1 -0
  103. metadata +242 -0
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ module MCollective
6
+ describe PluginManager do
7
+ before do
8
+ class MCollective::Foo; end
9
+
10
+ PluginManager.pluginlist.each {|p| PluginManager.delete p}
11
+ end
12
+
13
+ describe "#<<" do
14
+ it "should store a plugin by name" do
15
+ PluginManager << {:type => "foo", :class => "MCollective::Foo"}
16
+ PluginManager.instance_variable_get("@plugins").include?("foo").should == true
17
+ end
18
+
19
+ it "should store a plugin instance" do
20
+ f = MCollective::Foo.new
21
+
22
+ PluginManager << {:type => "foo", :class => f}
23
+ PluginManager.instance_variable_get("@plugins")["foo"][:instance].object_id.should == f.object_id
24
+ end
25
+
26
+ it "should detect duplicate plugins" do
27
+ PluginManager << {:type => "foo", :class => "MCollective::Foo"}
28
+
29
+ expect {
30
+ PluginManager << {:type => "foo", :class => "MCollective::Foo"}
31
+ }.to raise_error("Plugin foo already loaded")
32
+ end
33
+
34
+ it "should store single instance preference correctly" do
35
+ PluginManager << {:type => "foo", :class => "MCollective::Foo", :single_instance => false}
36
+ PluginManager.instance_variable_get("@plugins")["foo"][:single].should == false
37
+ end
38
+
39
+ it "should always set single to true when supplied an instance" do
40
+ PluginManager << {:type => "foo", :class => MCollective::Foo.new, :single_instance => false}
41
+ PluginManager.instance_variable_get("@plugins")["foo"][:single].should == true
42
+ end
43
+ end
44
+
45
+ describe "#delete" do
46
+ it "should remove plugins" do
47
+ PluginManager << {:type => "foo", :class => MCollective::Foo.new}
48
+ PluginManager.instance_variable_get("@plugins").include?("foo").should == true
49
+ PluginManager.delete("foo")
50
+ PluginManager.instance_variable_get("@plugins").include?("foo").should == false
51
+ end
52
+ end
53
+
54
+ describe "#include?" do
55
+ it "should correctly check if plugins were added" do
56
+ PluginManager << {:type => "foo", :class => MCollective::Foo.new}
57
+ PluginManager.include?("foo").should == true
58
+ PluginManager.include?("bar").should == false
59
+ end
60
+ end
61
+
62
+ describe "#pluginlist" do
63
+ it "should return the correct list of plugins" do
64
+ PluginManager << {:type => "foo", :class => MCollective::Foo.new}
65
+ PluginManager << {:type => "bar", :class => MCollective::Foo.new}
66
+
67
+ PluginManager.pluginlist.sort.should == ["bar", "foo"]
68
+ end
69
+ end
70
+
71
+ describe "#[]" do
72
+ it "should detect if the requested plugin does not exist" do
73
+ expect {
74
+ PluginManager["foo"]
75
+ }.to raise_error("No plugin foo defined")
76
+ end
77
+
78
+ it "should create new instances on demand" do
79
+ PluginManager << {:type => "foo", :class => "MCollective::Foo"}
80
+ PluginManager["foo"].class.should == MCollective::Foo
81
+ end
82
+
83
+ it "should return the cached instance" do
84
+ f = MCollective::Foo.new
85
+
86
+ PluginManager << {:type => "foo", :class => f}
87
+ PluginManager["foo"].object_id.should == f.object_id
88
+ end
89
+
90
+ it "should create new instances on every request if requested" do
91
+ PluginManager << {:type => "foo", :class => "MCollective::Foo", :single_instance => false}
92
+ PluginManager["foo"].object_id.should_not == PluginManager["foo"].object_id
93
+ end
94
+ end
95
+
96
+ describe "#find" do
97
+ before do
98
+ @config.stubs(:libdir).returns(["/libdir/"])
99
+ Config.stubs(:instance).returns(@config)
100
+ end
101
+
102
+ it "should find all plugins in configured libdirs" do
103
+ File.expects(:join).with(["/libdir/", "mcollective", "test"]).returns("/plugindir/")
104
+ File.expects(:directory?).with("/plugindir/").returns(true)
105
+ Dir.expects(:new).with("/plugindir/").returns(["plugin.rb"])
106
+ PluginManager.find("test").should == ["plugin"]
107
+ end
108
+
109
+ it "should find all plugins with a given file extension" do
110
+ File.expects(:join).with(["/libdir/", "mcollective", "test"]).returns("/plugindir/")
111
+ File.expects(:directory?).with("/plugindir/").returns(true)
112
+ Dir.expects(:new).with("/plugindir/").returns(["plugin.ddl"])
113
+ PluginManager.find("test", "ddl").should == ["plugin"]
114
+ end
115
+
116
+ it "should skip libdirs that do not have the plugin type directories" do
117
+ @config.stubs(:libdir).returns(["/plugindir/", "/tmp/"])
118
+ File.expects(:join).with(["/plugindir/", "mcollective", "test"]).returns("/plugindir/")
119
+ File.expects(:join).with(["/tmp/", "mcollective", "test"]).returns("/tmpdir/")
120
+ File.expects(:directory?).with("/plugindir/").returns(true)
121
+ File.expects(:directory?).with("/tmpdir/").returns(false)
122
+ Dir.expects(:new).with("/plugindir/").returns(["plugin.ddl"])
123
+ PluginManager.find("test", "ddl").should == ["plugin"]
124
+ end
125
+ end
126
+
127
+ describe "#find_and_load" do
128
+ before do
129
+ @config.stubs(:libdir).returns(["/libdir/"])
130
+ Config.stubs(:instance).returns(@config)
131
+ PluginManager.expects(:loadclass).with("MCollective::Test::Testplugin", true)
132
+ end
133
+
134
+ it "should find and load all plugins from all libdirs that match the type" do
135
+ PluginManager.expects(:find).with("test", ".rb").returns(["testplugin"])
136
+ PluginManager.find_and_load("test")
137
+ end
138
+
139
+ it "should exclude plugins who do not match criteria if block is given" do
140
+ PluginManager.expects(:find).with("test", ".rb").returns(["testplugin", "failplugin"])
141
+ PluginManager.find_and_load("test") {|plugin| plugin.match(/^test/)}
142
+ end
143
+ end
144
+
145
+ describe "#loadclass" do
146
+ it "should load the correct filename given a ruby class name" do
147
+ PluginManager.stubs(:load).with("mcollective/foo.rb").once
148
+ PluginManager.loadclass("MCollective::Foo")
149
+ end
150
+
151
+ it "should raise errors for load errors" do
152
+ PluginManager.stubs(:load).raises("load failure")
153
+ Log.expects(:error)
154
+ expect { PluginManager.loadclass("foo") }.to raise_error(/load failure/)
155
+ end
156
+
157
+ it "should support squashing load errors" do
158
+ PluginManager.stubs(:load).raises("load failure")
159
+ Log.expects(:error)
160
+ PluginManager.loadclass("foo", true)
161
+ end
162
+ end
163
+
164
+ describe "#grep" do
165
+ it "should return matching plugins from the list" do
166
+ PluginManager << {:type => "foo", :class => MCollective::Foo.new}
167
+ PluginManager << {:type => "bar", :class => MCollective::Foo.new}
168
+
169
+ PluginManager.grep(/oo/).should == ["foo"]
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ module MCollective
6
+ module PluginPackager
7
+ describe AgentDefinition do
8
+ before :each do
9
+ PluginPackager.expects(:get_metadata).once.returns({:name => "foo"})
10
+ end
11
+
12
+ it "should replace spaces in the package name with underscores" do
13
+ agent = AgentDefinition.new(".", "test package", nil, nil, nil, "agent")
14
+ agent.metadata[:name].should == "test_package"
15
+ end
16
+
17
+ describe "#identify_packages" do
18
+ it "should attempt to identify all agent packages" do
19
+ AgentDefinition.any_instance.expects(:common).once.returns(:check)
20
+ AgentDefinition.any_instance.expects(:agent).once.returns(:check)
21
+ AgentDefinition.any_instance.expects(:client).once.returns(:check)
22
+
23
+ agent = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
24
+ agent.packagedata[:common].should == :check
25
+ agent.packagedata[:agent].should == :check
26
+ agent.packagedata[:client].should == :check
27
+ end
28
+ end
29
+
30
+ describe "#agent" do
31
+ before do
32
+ AgentDefinition.any_instance.expects(:client).once
33
+ end
34
+
35
+ it "should not populate the agent files if the agent directory is empty" do
36
+ AgentDefinition.any_instance.expects(:common).returns(nil)
37
+ PluginPackager.expects(:check_dir_present).returns(false)
38
+ agent = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
39
+ agent.packagedata[:agent].should == nil
40
+ end
41
+
42
+ it "should populate the agent files if the agent directory is present and not empty" do
43
+ AgentDefinition.any_instance.expects(:common).returns(nil)
44
+ PluginPackager.expects(:check_dir_present).returns(true)
45
+ File.stubs(:join).returns("tmpdir")
46
+ Dir.stubs(:glob).returns(["file.rb", "implementation.rb"])
47
+
48
+ agent = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
49
+ agent.packagedata[:agent][:files].should == ["file.rb", "implementation.rb"]
50
+ end
51
+
52
+ it "should add common package as dependency if present" do
53
+ AgentDefinition.any_instance.expects(:common).returns(true)
54
+ PluginPackager.expects(:check_dir_present).returns(true)
55
+ File.stubs(:join).returns("tmpdir")
56
+ Dir.stubs(:glob).returns([])
57
+
58
+ agent = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
59
+ agent.packagedata[:agent][:dependencies].should == ["mcollective", "mcollective-foo-common"]
60
+ end
61
+ end
62
+
63
+ describe "#common" do
64
+ before do
65
+ AgentDefinition.any_instance.expects(:agent)
66
+ AgentDefinition.any_instance.expects(:client)
67
+ end
68
+
69
+ it "should not populate the commong files if the util directory is empty" do
70
+ PluginPackager.expects(:check_dir_present).returns(false)
71
+ common = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
72
+ common.packagedata[:common].should == nil
73
+ end
74
+
75
+ it "should populate the common files if the common directory is present and not empty" do
76
+ PluginPackager.expects(:check_dir_present).returns(true)
77
+ File.stubs(:join).returns("tmpdir")
78
+ Dir.stubs(:glob).returns(["file.rb"])
79
+ common = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
80
+ common.packagedata[:common][:files].should == ["file.rb"]
81
+ end
82
+ end
83
+
84
+ describe "#client" do
85
+ before do
86
+ AgentDefinition.any_instance.expects(:agent).returns(nil)
87
+ File.expects(:join).with(".", "application").returns("clientdir")
88
+ File.expects(:join).with(".", "bin").returns("bindir")
89
+ File.expects(:join).with(".", "agent").returns("agentdir")
90
+ end
91
+
92
+ it "should populate client files if all directories are present" do
93
+ AgentDefinition.any_instance.expects(:common).returns(nil)
94
+ PluginPackager.expects(:check_dir_present).times(3).returns(true)
95
+ File.expects(:join).with("clientdir", "*").returns("clientdir/*")
96
+ File.expects(:join).with("bindir", "*").returns("bindir/*")
97
+ File.expects(:join).with("agentdir", "*.ddl").returns("agentdir/*.ddl")
98
+ Dir.expects(:glob).with("clientdir/*").returns(["client.rb"])
99
+ Dir.expects(:glob).with("bindir/*").returns(["bin.rb"])
100
+ Dir.expects(:glob).with("agentdir/*.ddl").returns(["agent.ddl"])
101
+
102
+ client = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
103
+ client.packagedata[:client][:files].should == ["client.rb", "bin.rb", "agent.ddl"]
104
+ end
105
+
106
+ it "should not populate client files if directories are not present" do
107
+ AgentDefinition.any_instance.expects(:common).returns(nil)
108
+ PluginPackager.expects(:check_dir_present).times(3).returns(false)
109
+
110
+ client = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
111
+ client.packagedata[:client].should == nil
112
+ end
113
+
114
+ it "should add common package as dependency if present" do
115
+ AgentDefinition.any_instance.expects(:common).returns("common")
116
+ PluginPackager.expects(:check_dir_present).times(3).returns(true)
117
+ File.expects(:join).with("clientdir", "*").returns("clientdir/*")
118
+ File.expects(:join).with("bindir", "*").returns("bindir/*")
119
+ File.expects(:join).with("agentdir", "*.ddl").returns("agentdir/*.ddl")
120
+ Dir.expects(:glob).with("clientdir/*").returns(["client.rb"])
121
+ Dir.expects(:glob).with("bindir/*").returns(["bin.rb"])
122
+ Dir.expects(:glob).with("agentdir/*.ddl").returns(["agent.ddl"])
123
+
124
+ client = AgentDefinition.new(".", nil, nil, nil, nil, "agent")
125
+ client.packagedata[:client][:dependencies].should == ["mcollective-client", "mcollective-foo-common"]
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ module MCollective
6
+ module PluginPackager
7
+ describe StandardDefinition do
8
+ before :each do
9
+ PluginPackager.expects(:get_metadata).once.returns({:name => "foo"})
10
+ end
11
+
12
+ it "should replace spaces in the package name with underscores" do
13
+ plugin = StandardDefinition.new(".", "test plugin", nil, nil, nil, :fooplugin)
14
+ plugin.metadata[:name].should == "test_plugin"
15
+ end
16
+
17
+ describe "#identify_packages" do
18
+ it "should attempt to identify all packages" do
19
+ StandardDefinition.any_instance.expects(:common).once.returns(:check)
20
+ StandardDefinition.any_instance.expects(:plugin).once.returns(:check)
21
+
22
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
23
+ plugin.packagedata[:common].should == :check
24
+ plugin.packagedata[:fooplugin].should == :check
25
+ end
26
+ end
27
+
28
+ describe "#plugin" do
29
+
30
+ it "should return nil if the plugin doesn't contain any files" do
31
+ StandardDefinition.any_instance.expects(:common).returns(nil)
32
+ PluginPackager.expects(:check_dir_present).returns(false)
33
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
34
+ plugin.packagedata[:fooplugin].should == nil
35
+ end
36
+
37
+ it "should add plugin files to the file list" do
38
+ StandardDefinition.any_instance.expects(:common).returns(nil)
39
+ PluginPackager.expects(:check_dir_present).returns(true)
40
+ Dir.expects(:glob).with("./fooplugin/*").returns(["file.rb"])
41
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
42
+ plugin.packagedata[:fooplugin][:files].should == ["file.rb"]
43
+ end
44
+
45
+ it "should add common package as dependency if present" do
46
+ StandardDefinition.any_instance.expects(:common).returns(true)
47
+ PluginPackager.expects(:check_dir_present).returns(true)
48
+ Dir.expects(:glob).with("./fooplugin/*").returns(["file.rb"])
49
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
50
+ plugin.packagedata[:fooplugin][:files].should == ["file.rb"]
51
+ plugin.packagedata[:fooplugin][:dependencies].should == ["mcollective", "mcollective-foo-common"]
52
+ end
53
+ end
54
+
55
+ describe "#common" do
56
+ before do
57
+ StandardDefinition.any_instance.expects(:plugin).returns(false)
58
+ end
59
+
60
+ it "should return nil if common doesn't contain any files" do
61
+ PluginPackager.expects(:check_dir_present).returns(false)
62
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
63
+ plugin.packagedata[:common].should == nil
64
+ end
65
+
66
+ it "should add common files to the file list" do
67
+ PluginPackager.expects(:check_dir_present).returns(true)
68
+ Dir.expects(:glob).with("./util/*").returns(["common.rb"])
69
+ plugin = StandardDefinition.new(".", nil, nil, nil, nil, :fooplugin)
70
+ plugin.packagedata[:common][:files].should == ["common.rb"]
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,533 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ MCollective::PluginManager.clear
6
+
7
+ require File.dirname(__FILE__) + '/../../../../../plugins/mcollective/connector/activemq.rb'
8
+
9
+ # create the stomp error class here as it does not always exist
10
+ # all versions of the stomp gem and we do not want to tie tests
11
+ # to the stomp gem
12
+ module Stomp
13
+ module Error
14
+ class DuplicateSubscription < RuntimeError; end
15
+ end
16
+ end
17
+
18
+ module MCollective
19
+ module Connector
20
+ describe Activemq do
21
+ before do
22
+ unless ::Stomp::Error.constants.map{|c| c.to_s}.include?("NoCurrentConnection")
23
+ class ::Stomp::Error::NoCurrentConnection < RuntimeError ; end
24
+ end
25
+
26
+ @config = mock
27
+ @config.stubs(:configured).returns(true)
28
+ @config.stubs(:identity).returns("rspec")
29
+ @config.stubs(:collectives).returns(["mcollective"])
30
+
31
+ logger = mock
32
+ logger.stubs(:log)
33
+ logger.stubs(:start)
34
+ Log.configure(logger)
35
+
36
+ Config.stubs(:instance).returns(@config)
37
+
38
+ @msg = mock
39
+ @msg.stubs(:base64_encode!)
40
+ @msg.stubs(:payload).returns("msg")
41
+ @msg.stubs(:agent).returns("agent")
42
+ @msg.stubs(:type).returns(:reply)
43
+ @msg.stubs(:collective).returns("mcollective")
44
+
45
+ @subscription = mock
46
+ @subscription.stubs("<<").returns(true)
47
+ @subscription.stubs("include?").returns(false)
48
+ @subscription.stubs("delete").returns(false)
49
+
50
+ @connection = mock
51
+ @connection.stubs(:subscribe).returns(true)
52
+ @connection.stubs(:unsubscribe).returns(true)
53
+
54
+ @c = Activemq.new
55
+ @c.instance_variable_set("@subscriptions", @subscription)
56
+ @c.instance_variable_set("@connection", @connection)
57
+ end
58
+
59
+ describe "#initialize" do
60
+ it "should set the @config variable" do
61
+ c = Activemq.new
62
+ c.instance_variable_get("@config").should == @config
63
+ end
64
+
65
+ it "should set @subscriptions to an empty list" do
66
+ c = Activemq.new
67
+ c.instance_variable_get("@subscriptions").should == []
68
+ end
69
+ end
70
+
71
+ describe "#connect" do
72
+ it "should not try to reconnect if already connected" do
73
+ Log.expects(:debug).with("Already connection, not re-initializing connection").once
74
+ @c.connect
75
+ end
76
+
77
+ it "should support new style config" do
78
+ pluginconf = {"activemq.pool.size" => "2",
79
+ "activemq.pool.1.host" => "host1",
80
+ "activemq.pool.1.port" => "6163",
81
+ "activemq.pool.1.user" => "user1",
82
+ "activemq.pool.1.password" => "password1",
83
+ "activemq.pool.1.ssl" => "false",
84
+ "activemq.pool.2.host" => "host2",
85
+ "activemq.pool.2.port" => "6164",
86
+ "activemq.pool.2.user" => "user2",
87
+ "activemq.pool.2.password" => "password2",
88
+ "activemq.pool.2.ssl" => "true",
89
+ "activemq.pool.2.ssl.fallback" => "true",
90
+ "activemq.initial_reconnect_delay" => "0.02",
91
+ "activemq.max_reconnect_delay" => "40",
92
+ "activemq.use_exponential_back_off" => "false",
93
+ "activemq.back_off_multiplier" => "3",
94
+ "activemq.max_reconnect_attempts" => "5",
95
+ "activemq.randomize" => "true",
96
+ "activemq.backup" => "true",
97
+ "activemq.timeout" => "1",
98
+ "activemq.connect_timeout" => "5"}
99
+
100
+
101
+ ENV.delete("STOMP_USER")
102
+ ENV.delete("STOMP_PASSWORD")
103
+
104
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
105
+
106
+ Activemq::EventLogger.expects(:new).returns("logger")
107
+
108
+ connector = mock
109
+ connector.expects(:new).with(:backup => true,
110
+ :back_off_multiplier => 3,
111
+ :max_reconnect_delay => 40.0,
112
+ :timeout => 1,
113
+ :connect_timeout => 5,
114
+ :use_exponential_back_off => false,
115
+ :max_reconnect_attempts => 5,
116
+ :initial_reconnect_delay => 0.02,
117
+ :randomize => true,
118
+ :reliable => true,
119
+ :logger => "logger",
120
+ :hosts => [{:passcode => 'password1',
121
+ :host => 'host1',
122
+ :port => 6163,
123
+ :ssl => false,
124
+ :login => 'user1'},
125
+ {:passcode => 'password2',
126
+ :host => 'host2',
127
+ :port => 6164,
128
+ :ssl => true,
129
+ :login => 'user2'}
130
+ ])
131
+
132
+ @c.expects(:ssl_parameters).with(2, true).returns(true)
133
+
134
+ @c.instance_variable_set("@connection", nil)
135
+ @c.connect(connector)
136
+ end
137
+ end
138
+
139
+ describe "#ssl_paramaters" do
140
+ it "should ensure all settings are provided" do
141
+ pluginconf = {"activemq.pool.1.host" => "host1",
142
+ "activemq.pool.1.port" => "6164",
143
+ "activemq.pool.1.user" => "user1",
144
+ "activemq.pool.1.password" => "password1",
145
+ "activemq.pool.1.ssl" => "true",
146
+ "activemq.pool.1.ssl.cert" => "rspec"}
147
+
148
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
149
+
150
+ expect { @c.ssl_parameters(1, false) }.to raise_error("cert, key and ca has to be supplied for verified SSL mode")
151
+ end
152
+
153
+ it "should verify the ssl files exist" do
154
+ pluginconf = {"activemq.pool.1.host" => "host1",
155
+ "activemq.pool.1.port" => "6164",
156
+ "activemq.pool.1.user" => "user1",
157
+ "activemq.pool.1.password" => "password1",
158
+ "activemq.pool.1.ssl" => "true",
159
+ "activemq.pool.1.ssl.cert" => "rspec.cert",
160
+ "activemq.pool.1.ssl.key" => "rspec.key",
161
+ "activemq.pool.1.ssl.ca" => "rspec1.ca,rspec2.ca"}
162
+
163
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
164
+
165
+ File.expects(:exist?).with("rspec.cert").twice.returns(true)
166
+ File.expects(:exist?).with("rspec.key").twice.returns(true)
167
+ File.expects(:exist?).with("rspec1.ca").twice.returns(true)
168
+ File.expects(:exist?).with("rspec2.ca").twice.returns(false)
169
+
170
+ expect { @c.ssl_parameters(1, false) }.to raise_error("Cannot find CA file rspec2.ca")
171
+
172
+ @c.ssl_parameters(1, true).should == true
173
+ end
174
+
175
+ it "should support fallback mode when there are errors" do
176
+ pluginconf = {"activemq.pool.1.host" => "host1",
177
+ "activemq.pool.1.port" => "6164",
178
+ "activemq.pool.1.user" => "user1",
179
+ "activemq.pool.1.password" => "password1",
180
+ "activemq.pool.1.ssl" => "true"}
181
+
182
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
183
+
184
+ @c.ssl_parameters(1, true).should == true
185
+ end
186
+
187
+ it "should fail if fallback isnt enabled" do
188
+ pluginconf = {"activemq.pool.1.host" => "host1",
189
+ "activemq.pool.1.port" => "6164",
190
+ "activemq.pool.1.user" => "user1",
191
+ "activemq.pool.1.password" => "password1",
192
+ "activemq.pool.1.ssl" => "true"}
193
+
194
+ @config.expects(:pluginconf).returns(pluginconf).at_least_once
195
+
196
+ expect { @c.ssl_parameters(1, false) }.to raise_error
197
+ end
198
+ end
199
+
200
+ describe "#receive" do
201
+ it "should receive from the middleware" do
202
+ payload = mock
203
+ payload.stubs(:body).returns("msg")
204
+ payload.stubs(:headers).returns("headers")
205
+
206
+ @connection.expects(:receive).returns(payload)
207
+
208
+ Message.expects(:new).with("msg", payload, :base64 => true, :headers => "headers").returns("message")
209
+ @c.instance_variable_set("@base64", true)
210
+
211
+ received = @c.receive
212
+ received.should == "message"
213
+ end
214
+
215
+ it "should sleep and retry if recieving while disconnected" do
216
+ payload = mock
217
+ payload.stubs(:body).returns("msg")
218
+ payload.stubs(:headers).returns("headers")
219
+
220
+ Message.stubs(:new).returns("rspec")
221
+ @connection.expects(:receive).raises(::Stomp::Error::NoCurrentConnection).returns(payload).twice
222
+ @c.expects(:sleep).with(1)
223
+
224
+ @c.receive.should == "rspec"
225
+ end
226
+ end
227
+
228
+ describe "#publish" do
229
+ before do
230
+ @connection.stubs(:publish).with("test", "msg", {}).returns(true)
231
+ end
232
+
233
+ it "should base64 encode a message if configured to do so" do
234
+ @c.instance_variable_set("@base64", true)
235
+ @c.expects(:headers_for).returns({})
236
+ @c.expects(:target_for).returns({:name => "test", :headers => {}})
237
+ @connection.expects(:publish).with("test", "msg", {})
238
+ @msg.expects(:base64_encode!)
239
+
240
+ @c.publish(@msg)
241
+ end
242
+
243
+ it "should not base64 encode if not configured to do so" do
244
+ @c.instance_variable_set("@base64", false)
245
+ @c.expects(:headers_for).returns({})
246
+ @c.expects(:target_for).returns({:name => "test", :headers => {}})
247
+ @connection.expects(:publish).with("test", "msg", {})
248
+ @msg.expects(:base64_encode!).never
249
+
250
+ @c.publish(@msg)
251
+ end
252
+
253
+ it "should publish the correct message to the correct target with msgheaders" do
254
+ @connection.expects(:publish).with("test", "msg", {"test" => "test"}).once
255
+ @c.expects(:headers_for).returns({"test" => "test"})
256
+ @c.expects(:target_for).returns({:name => "test", :headers => {}})
257
+
258
+ @c.publish(@msg)
259
+ end
260
+
261
+ it "should publish direct messages based on discovered_hosts" do
262
+ msg = mock
263
+ msg.stubs(:base64_encode!)
264
+ msg.stubs(:payload).returns("msg")
265
+ msg.stubs(:agent).returns("agent")
266
+ msg.stubs(:collective).returns("mcollective")
267
+ msg.stubs(:type).returns(:direct_request)
268
+ msg.expects(:discovered_hosts).returns(["one", "two"])
269
+
270
+ @c.expects(:headers_for).with(msg, "one")
271
+ @c.expects(:headers_for).with(msg, "two")
272
+ @connection.expects(:publish).with('/queue/mcollective.nodes', 'msg', nil).twice
273
+
274
+ @c.publish(msg)
275
+ end
276
+ end
277
+
278
+ describe "#subscribe" do
279
+ it "should handle duplicate subscription errors" do
280
+ @connection.expects(:subscribe).raises(::Stomp::Error::DuplicateSubscription)
281
+ Log.expects(:error).with(regexp_matches(/already had a matching subscription, ignoring/))
282
+ @c.subscribe("test", :broadcast, "mcollective")
283
+ end
284
+
285
+ it "should use the make_target correctly" do
286
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
287
+ @c.subscribe("test", :broadcast, "mcollective")
288
+ end
289
+
290
+ it "should check for existing subscriptions" do
291
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
292
+ @subscription.expects("include?").with("rspec").returns(false)
293
+ @connection.expects(:subscribe).never
294
+
295
+ @c.subscribe("test", :broadcast, "mcollective")
296
+ end
297
+
298
+ it "should subscribe to the middleware" do
299
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
300
+ @connection.expects(:subscribe).with("test", {}, "rspec")
301
+ @c.subscribe("test", :broadcast, "mcollective")
302
+ end
303
+
304
+ it "should add to the list of subscriptions" do
305
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
306
+ @subscription.expects("<<").with("rspec")
307
+ @c.subscribe("test", :broadcast, "mcollective")
308
+ end
309
+ end
310
+
311
+ describe "#unsubscribe" do
312
+ it "should use make_target correctly" do
313
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}})
314
+ @c.unsubscribe("test", :broadcast, "mcollective")
315
+ end
316
+
317
+ it "should unsubscribe from the target" do
318
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
319
+ @connection.expects(:unsubscribe).with("test", {}, "rspec").once
320
+
321
+ @c.unsubscribe("test", :broadcast, "mcollective")
322
+ end
323
+
324
+ it "should delete the source from subscriptions" do
325
+ @c.expects("make_target").with("test", :broadcast, "mcollective").returns({:name => "test", :headers => {}, :id => "rspec"})
326
+ @subscription.expects(:delete).with("rspec").once
327
+
328
+ @c.unsubscribe("test", :broadcast, "mcollective")
329
+ end
330
+ end
331
+
332
+ describe "#target_for" do
333
+ it "should create reply targets based on reply-to headers in requests" do
334
+ message = mock
335
+ message.expects(:type).returns(:reply)
336
+
337
+ request = mock
338
+ request.expects(:headers).returns({"reply-to" => "foo"})
339
+
340
+ message.expects(:request).returns(request)
341
+
342
+ @c.target_for(message).should == {:name => "foo", :headers => {}}
343
+ end
344
+
345
+ it "should create new request targets" do
346
+ message = mock
347
+ message.expects(:type).returns(:request).times(3)
348
+ message.expects(:agent).returns("rspecagent")
349
+ message.expects(:collective).returns("mcollective")
350
+
351
+ @c.expects(:make_target).with("rspecagent", :request, "mcollective")
352
+ @c.target_for(message)
353
+ end
354
+
355
+ it "should support direct requests" do
356
+ message = mock
357
+ message.expects(:type).returns(:direct_request).times(3)
358
+ message.expects(:agent).returns("rspecagent")
359
+ message.expects(:collective).returns("mcollective")
360
+
361
+ @c.expects(:make_target).with("rspecagent", :direct_request, "mcollective")
362
+ @c.target_for(message)
363
+ end
364
+
365
+ it "should fail for unknown message types" do
366
+ message = mock
367
+ message.stubs(:type).returns(:fail)
368
+
369
+ expect {
370
+ @c.target_for(message)
371
+ }.to raise_error("Don't now how to create a target for message type fail")
372
+ end
373
+ end
374
+
375
+ describe "#disconnect" do
376
+ it "should disconnect from the stomp connection" do
377
+ @connection.expects(:disconnect)
378
+ @c.disconnect
379
+ end
380
+ end
381
+
382
+ describe "#headers_for" do
383
+ it "should return empty headers if priority is 0" do
384
+ message = mock
385
+ message.expects(:type).returns(:foo)
386
+
387
+ @c.instance_variable_set("@msgpriority", 0)
388
+ @c.headers_for(message).should == {}
389
+ end
390
+
391
+ it "should return a priority if priority is non 0" do
392
+ message = mock
393
+ message.expects(:type).returns(:foo)
394
+
395
+ @c.instance_variable_set("@msgpriority", 1)
396
+ @c.headers_for(message).should == {"priority" => 1}
397
+ end
398
+
399
+ it "should set mc_identity for direct requests" do
400
+ message = mock
401
+ message.expects(:type).returns(:direct_request).twice
402
+ message.expects(:agent).returns("rspecagent")
403
+ message.expects(:collective).returns("mcollective")
404
+ message.expects(:reply_to).returns(nil)
405
+
406
+ @c.instance_variable_set("@msgpriority", 0)
407
+ @c.expects(:make_target).with("rspecagent", :reply, "mcollective").returns({:name => "test"})
408
+ @c.headers_for(message, "some.node").should == {"mc_identity"=>"some.node", "reply-to"=>"test"}
409
+ end
410
+
411
+ it "should set a reply-to header for :request type messages" do
412
+ message = mock
413
+ message.expects(:type).returns(:request).twice
414
+ message.expects(:agent).returns("rspecagent")
415
+ message.expects(:collective).returns("mcollective")
416
+ message.expects(:reply_to).returns(nil)
417
+
418
+ @c.instance_variable_set("@msgpriority", 0)
419
+ @c.expects(:make_target).with("rspecagent", :reply, "mcollective").returns({:name => "test"})
420
+ @c.headers_for(message).should == {"reply-to" => "test"}
421
+ end
422
+
423
+ it "should set reply-to correctly if the message defines it" do
424
+ message = mock
425
+ message.expects(:type).returns(:request).twice
426
+ message.expects(:agent).returns("rspecagent")
427
+ message.expects(:collective).returns("mcollective")
428
+ message.expects(:reply_to).returns("rspec").twice
429
+
430
+ @c.headers_for(message).should == {"reply-to" => "rspec"}
431
+
432
+ end
433
+ end
434
+
435
+ describe "#make_target" do
436
+ it "should create correct targets" do
437
+ @c.make_target("test", :reply, "mcollective").should == {:name => "/queue/mcollective.reply.rspec_#{$$}", :headers => {}, :id => "/queue/mcollective.reply.rspec_#{$$}"}
438
+ @c.make_target("test", :broadcast, "mcollective").should == {:name => "/topic/mcollective.test.agent", :headers => {}, :id => "/topic/mcollective.test.agent"}
439
+ @c.make_target("test", :request, "mcollective").should == {:name => "/topic/mcollective.test.agent", :headers => {}, :id => "/topic/mcollective.test.agent"}
440
+ @c.make_target("test", :direct_request, "mcollective").should == {:headers=>{}, :name=>"/queue/mcollective.nodes", :id => "/queue/mcollective.nodes"}
441
+ @c.make_target("test", :directed, "mcollective").should == {:name => "/queue/mcollective.nodes", :headers=>{"selector"=>"mc_identity = 'rspec'"}, :id => "directed_to_identity"}
442
+ end
443
+
444
+ it "should raise an error for unknown collectives" do
445
+ expect {
446
+ @c.make_target("test", :broadcast, "foo")
447
+ }.to raise_error("Unknown collective 'foo' known collectives are 'mcollective'")
448
+ end
449
+
450
+ it "should raise an error for unknown types" do
451
+ expect {
452
+ @c.make_target("test", :test, "mcollective")
453
+ }.to raise_error("Unknown target type test")
454
+ end
455
+ end
456
+
457
+
458
+ describe "#get_env_or_option" do
459
+ it "should return the environment variable if set" do
460
+ ENV["test"] = "rspec_env_test"
461
+
462
+ @c.get_env_or_option("test", nil, nil).should == "rspec_env_test"
463
+
464
+ ENV.delete("test")
465
+ end
466
+
467
+ it "should return the config option if set" do
468
+ @config.expects(:pluginconf).returns({"test" => "rspec_test"}).twice
469
+ @c.get_env_or_option("test", "test", "test").should == "rspec_test"
470
+ end
471
+
472
+ it "should return default if nothing else matched" do
473
+ @config.expects(:pluginconf).returns({}).once
474
+ @c.get_env_or_option("test", "test", "test").should == "test"
475
+ end
476
+
477
+ it "should raise an error if no default is supplied" do
478
+ @config.expects(:pluginconf).returns({}).once
479
+
480
+ expect {
481
+ @c.get_env_or_option("test", "test")
482
+ }.to raise_error("No test environment or plugin.test configuration option given")
483
+ end
484
+ end
485
+
486
+ describe "#get_option" do
487
+ it "should return the config option if set" do
488
+ @config.expects(:pluginconf).returns({"test" => "rspec_test"}).twice
489
+ @c.get_option("test").should == "rspec_test"
490
+ end
491
+
492
+ it "should return default option was not found" do
493
+ @config.expects(:pluginconf).returns({}).once
494
+ @c.get_option("test", "test").should == "test"
495
+ end
496
+
497
+ it "should raise an error if no default is supplied" do
498
+ @config.expects(:pluginconf).returns({}).once
499
+
500
+ expect {
501
+ @c.get_option("test")
502
+ }.to raise_error("No plugin.test configuration option given")
503
+ end
504
+ end
505
+
506
+ describe "#get_bool_option" do
507
+ it "should return the default if option isnt set" do
508
+ @config.expects(:pluginconf).returns({}).once
509
+ @c.get_bool_option("test", "default").should == "default"
510
+ end
511
+
512
+ ["1", "yes", "true"].each do |boolean|
513
+ it "should map options to true correctly" do
514
+ @config.expects(:pluginconf).returns({"test" => boolean}).twice
515
+ @c.get_bool_option("test", "default").should == true
516
+ end
517
+ end
518
+
519
+ ["0", "no", "false"].each do |boolean|
520
+ it "should map options to false correctly" do
521
+ @config.expects(:pluginconf).returns({"test" => boolean}).twice
522
+ @c.get_bool_option("test", "default").should == false
523
+ end
524
+ end
525
+
526
+ it "should return default for non boolean options" do
527
+ @config.expects(:pluginconf).returns({"test" => "foo"}).twice
528
+ @c.get_bool_option("test", "default").should == "default"
529
+ end
530
+ end
531
+ end
532
+ end
533
+ end