logstash-input-jms 3.0.6-java → 3.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/docs/index.asciidoc +453 -48
- data/lib/logstash/inputs/jms.rb +184 -115
- data/logstash-input-jms.gemspec +1 -1
- data/spec/inputs/fixtures/activemq_plaintext.xml +132 -0
- data/spec/inputs/fixtures/activemq_ssl.xml +137 -0
- data/spec/inputs/fixtures/jms.yml +14 -0
- data/spec/inputs/fixtures/jndijms.yml +22 -0
- data/spec/inputs/fixtures/keystore.jks +0 -0
- data/spec/inputs/integration/jms_spec.rb +284 -0
- data/spec/inputs/spec_helper.rb +37 -0
- data/spec/inputs/unit/jms_spec.rb +256 -0
- metadata +18 -6
- data/spec/inputs/jms.yml +0 -18
- data/spec/inputs/jms_spec.rb +0 -30
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/devutils/rspec/spec_helper"
|
3
|
+
|
4
|
+
def fixture_path(file)
|
5
|
+
File.join(File.dirname(__FILE__),"fixtures/#{file}")
|
6
|
+
end
|
7
|
+
|
8
|
+
def send_message(&block)
|
9
|
+
input.register
|
10
|
+
|
11
|
+
tt = Thread.new do
|
12
|
+
sleep 1
|
13
|
+
properties_before_send = java.lang.System.getProperties
|
14
|
+
|
15
|
+
begin
|
16
|
+
input.load_ssl_properties
|
17
|
+
config = input.jms_config_from_yaml(fixture_path('jms.yml'), yaml_section)
|
18
|
+
raise "JMS Provider option:#{jms_provider} not found in jms.yml file" unless config
|
19
|
+
destination_key = pub_sub ? :topic_name : :queue_name
|
20
|
+
JMS::Connection.session(config) do |session|
|
21
|
+
session.producer(destination_key => queue_name) do |producer|
|
22
|
+
msg = yield session unless block.nil?
|
23
|
+
msg ||= session.message(message)
|
24
|
+
producer.send(msg)
|
25
|
+
end
|
26
|
+
session.close
|
27
|
+
end
|
28
|
+
input.do_stop
|
29
|
+
ensure
|
30
|
+
java.lang.System.setProperties(properties_before_send)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
input.run(queue)
|
34
|
+
|
35
|
+
destination = "#{pub_sub ? 'topic' : 'queue'}://#{queue_name}"
|
36
|
+
tt.join(3)
|
37
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'logstash/inputs/jms'
|
3
|
+
require 'jms'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
describe "inputs/jms" do
|
7
|
+
let (:queue_name) {SecureRandom.hex(8)}
|
8
|
+
let (:jms_config) {{'destination' => queue_name}}
|
9
|
+
|
10
|
+
subject(:plugin) { LogStash::Inputs::Jms.new(jms_config) }
|
11
|
+
|
12
|
+
describe 'initialization' do
|
13
|
+
|
14
|
+
context 'with System properties' do
|
15
|
+
let (:jms_config) {{ 'system_properties' => system_properties, 'destination' => 'ExampleQueue'}}
|
16
|
+
let (:system_properties) { { 'JNDI_Connection_Retries_Per_Host' => 7,
|
17
|
+
'JNDI_Connect_Retries' => 5 }}
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
subject.register
|
21
|
+
end
|
22
|
+
|
23
|
+
after :each do
|
24
|
+
system_properties.each do |k, v|
|
25
|
+
java.lang.System.clear_property(k)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should populate the system properties' do
|
30
|
+
system_properties.each do |k,v|
|
31
|
+
expect(java.lang.System.get_property(k)).to_not be_nil
|
32
|
+
expect(java.lang.System.get_property(k)).to eq(v.to_s)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'configuration check' do
|
38
|
+
context 'if threads is > 1' do
|
39
|
+
let(:thread_count) { 2 }
|
40
|
+
let(:jms_config) { super.merge({'threads' => thread_count})}
|
41
|
+
|
42
|
+
context 'with pub_sub set to true' do
|
43
|
+
let(:jms_config) { super.merge({'pub_sub' => true})}
|
44
|
+
|
45
|
+
it 'should raise a configuration error' do
|
46
|
+
expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with pub_sub set to false' do
|
51
|
+
let(:jms_config) { super.merge({'pub_sub' => false})}
|
52
|
+
|
53
|
+
it 'should not raise a configuration error' do
|
54
|
+
plugin.register
|
55
|
+
expect(plugin.threads).to eq(thread_count)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with durable_subscriber set' do
|
61
|
+
let(:jms_config) { super.merge({ 'pub_sub' => true,
|
62
|
+
'durable_subscriber' => true,
|
63
|
+
'durable_subscriber_name' => SecureRandom.hex(8),
|
64
|
+
'durable_subscriber_client_id' => SecureRandom.hex(8)})}
|
65
|
+
|
66
|
+
context 'if durable_subscriber_client_id is not set' do
|
67
|
+
let(:jms_config) { super.tap { |h| h.delete('durable_subscriber_client_id') } }
|
68
|
+
|
69
|
+
it 'should set client_id to Logstash' do
|
70
|
+
plugin.register
|
71
|
+
expect(plugin.durable_subscriber_client_id).to eq('Logstash')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'if durable_subscriber_name is not set' do
|
76
|
+
let(:jms_config) { super.tap { |h| h.delete('durable_subscriber_name') } }
|
77
|
+
|
78
|
+
it 'should set name to the topic name' do
|
79
|
+
plugin.register
|
80
|
+
expect(plugin.durable_subscriber_name).to eq(queue_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
context 'if pub_sub is set to false' do
|
86
|
+
let(:jms_config) { super.merge({'pub_sub' => false})}
|
87
|
+
it 'should raise a configuration error' do
|
88
|
+
expect { plugin.register }.to raise_error(LogStash::ConfigurationError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
context 'via yaml file' do
|
96
|
+
let (:yaml_section) { 'activemq' }
|
97
|
+
let (:jms_config) {{'yaml_file' => fixture_path(file), 'yaml_section' => yaml_section, 'destination' => SecureRandom.hex(8)}}
|
98
|
+
|
99
|
+
context 'simple yaml configuration' do
|
100
|
+
let (:file) { "jms.yml" }
|
101
|
+
let (:password) { 'the_password' }
|
102
|
+
|
103
|
+
it 'should populate jms config from the yaml file' do
|
104
|
+
expect(plugin.jms_config).to include({:broker_url => "tcp://localhost:61616",
|
105
|
+
:password => password,
|
106
|
+
:factory=>"org.apache.activemq.ActiveMQConnectionFactory",
|
107
|
+
:require_jars=>["activemq-all.jar"]})
|
108
|
+
end
|
109
|
+
it 'should not log the password in plaintext' do
|
110
|
+
expect(plugin.logger).to receive(:debug) do |_, params|
|
111
|
+
expect(params[:context]).to include(:password)
|
112
|
+
expect(params[:context][:password]).not_to eq(password)
|
113
|
+
end
|
114
|
+
|
115
|
+
plugin.register
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'jndi yaml configuration' do
|
121
|
+
let (:file) { "jndijms.yml" }
|
122
|
+
let (:yaml_section) { 'solace' }
|
123
|
+
|
124
|
+
it 'should populate jms config from the yaml file' do
|
125
|
+
expect(plugin.jms_config).to include({:jndi_context=>{
|
126
|
+
"java.naming.factory.initial"=>"com.solacesystems.jndi.SolJNDIInitialContextFactory",
|
127
|
+
"java.naming.security.principal"=>"username",
|
128
|
+
"java.naming.provider.url"=>"tcp://localhost:20608",
|
129
|
+
"java.naming.security.credentials"=>"password"},
|
130
|
+
:jndi_name => "/jms/cf/default",
|
131
|
+
:require_jars => ["commons-lang-2.6.jar",
|
132
|
+
"sol-jms-10.5.0.jar",
|
133
|
+
"geronimo-jms_1.1_spec-1.1.1.jar",
|
134
|
+
"commons-lang-2.6.jar"]})
|
135
|
+
end
|
136
|
+
it 'should not log the password in plaintext' do
|
137
|
+
expect(plugin.logger).to receive(:debug) do |_, params|
|
138
|
+
expect(params[:context]).not_to include(:password)
|
139
|
+
end
|
140
|
+
plugin.register
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'simple configuration' do
|
146
|
+
let (:password) { 'the_password' }
|
147
|
+
let (:jms_config) {{
|
148
|
+
'destination' => 'ExampleQueue',
|
149
|
+
'username' => 'user',
|
150
|
+
'password' => password,
|
151
|
+
'broker_url' => 'tcp://localhost:61616',
|
152
|
+
'pub_sub' => true,
|
153
|
+
'factory' => 'org.apache.activemq.ActiveMQConnectionFactory',
|
154
|
+
'require_jars' => ['activemq-all-5.15.8.jar']
|
155
|
+
}}
|
156
|
+
it 'should populate jms config from the configuration' do
|
157
|
+
expect(plugin.jms_config).to include({:broker_url => "tcp://localhost:61616",
|
158
|
+
:factory=>"org.apache.activemq.ActiveMQConnectionFactory",
|
159
|
+
:require_jars=>["activemq-all-5.15.8.jar"]})
|
160
|
+
end
|
161
|
+
it 'should not log the password in plaintext' do
|
162
|
+
expect(plugin.logger).to receive(:debug) do |_, params|
|
163
|
+
expect(params[:context]).to include(:password)
|
164
|
+
expect(params[:context][:password]).not_to eq(password)
|
165
|
+
end
|
166
|
+
|
167
|
+
plugin.register
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'simple configuration with jndi' do
|
172
|
+
let (:jms_config) {{
|
173
|
+
'destination' => 'ExampleQueue',
|
174
|
+
'jndi_name' => "/jms/cf/default",
|
175
|
+
"jndi_context" => {
|
176
|
+
"java.naming.factory.initial"=>"com.solacesystems.jndi.SolJNDIInitialContextFactory",
|
177
|
+
"java.naming.security.principal"=>"username",
|
178
|
+
"java.naming.provider.url"=>"tcp://localhost:20608",
|
179
|
+
"java.naming.security.credentials"=>"password"},
|
180
|
+
'pub_sub' => true,
|
181
|
+
"require_jars" => ["commons-lang-2.6.jar",
|
182
|
+
"sol-jms-10.5.0.jar",
|
183
|
+
"geronimo-jms_1.1_spec-1.1.1.jar",
|
184
|
+
"commons-lang-2.6.jar"]}}
|
185
|
+
|
186
|
+
|
187
|
+
it 'should populate jms config from the configuration' do
|
188
|
+
expect(plugin.jms_config).to include({:jndi_context=>{
|
189
|
+
"java.naming.factory.initial"=>"com.solacesystems.jndi.SolJNDIInitialContextFactory",
|
190
|
+
"java.naming.security.principal"=>"username",
|
191
|
+
"java.naming.provider.url"=>"tcp://localhost:20608",
|
192
|
+
"java.naming.security.credentials"=>"password"},
|
193
|
+
:jndi_name => "/jms/cf/default",
|
194
|
+
:require_jars => ["commons-lang-2.6.jar",
|
195
|
+
"sol-jms-10.5.0.jar",
|
196
|
+
"geronimo-jms_1.1_spec-1.1.1.jar",
|
197
|
+
"commons-lang-2.6.jar"]})
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#error_hash' do
|
203
|
+
context 'should handle Java exceptions with a chain of causes' do
|
204
|
+
let (:raised) { java.lang.Exception.new("Outer", java.lang.RuntimeException.new("middle", java.io.IOException.new("Inner")))}
|
205
|
+
|
206
|
+
it 'should find contain the root cause of a java exception cause chain' do
|
207
|
+
expect(plugin.error_hash(raised)[:exception].to_s).to eql("Java::JavaLang::Exception")
|
208
|
+
expect(plugin.error_hash(raised)[:exception_message].to_s).to eql("Outer")
|
209
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception]).to eql("Java::JavaIo::IOException")
|
210
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception_message]).to eql("Inner")
|
211
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception_loop]).to be_falsey
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'should handle Java Exceptions with a cause chain loop' do
|
216
|
+
let (:inner) { java.io.IOException.new("Inner") }
|
217
|
+
let (:middle) { java.lang.RuntimeException.new("Middle", inner) }
|
218
|
+
let (:raised) { java.lang.Exception.new("Outer", middle)}
|
219
|
+
|
220
|
+
before :each do
|
221
|
+
inner.init_cause(middle)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should not go into an infinite loop' do
|
225
|
+
expect(plugin.error_hash(raised)[:exception].to_s).to eql("Java::JavaLang::Exception")
|
226
|
+
expect(plugin.error_hash(raised)[:exception_message].to_s).to eql("Outer")
|
227
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception]).to eql("Java::JavaLang::RuntimeException")
|
228
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception_message]).to eql("Middle")
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should report that an exception loop was detected' do
|
232
|
+
expect(plugin.error_hash(raised)[:root_cause][:exception_loop]).to be_truthy
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'should handle Java Exceptions with no cause' do
|
237
|
+
let (:raised) { java.lang.Exception.new("Only")}
|
238
|
+
|
239
|
+
it 'should populate exception, exception_message but not root_cause' do
|
240
|
+
expect(plugin.error_hash(raised)[:exception].to_s).to eql("Java::JavaLang::Exception")
|
241
|
+
expect(plugin.error_hash(raised)[:exception_message].to_s).to eql("Only")
|
242
|
+
expect(plugin.error_hash(raised)[:root_cause]).to be_nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'should handle Ruby Errors' do
|
247
|
+
let (:raised) { StandardError.new("Ruby") }
|
248
|
+
|
249
|
+
it 'should populate exception, exception_message but not root_cause' do
|
250
|
+
expect(plugin.error_hash(raised)[:exception].to_s).to eql("StandardError")
|
251
|
+
expect(plugin.error_hash(raised)[:exception_message].to_s).to eql("Ruby")
|
252
|
+
expect(plugin.error_hash(raised)[:root_cause]).to be_nil
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-jms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elasticsearch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,8 +115,14 @@ files:
|
|
115
115
|
- docs/index.asciidoc
|
116
116
|
- lib/logstash/inputs/jms.rb
|
117
117
|
- logstash-input-jms.gemspec
|
118
|
-
- spec/inputs/
|
119
|
-
- spec/inputs/
|
118
|
+
- spec/inputs/fixtures/activemq_plaintext.xml
|
119
|
+
- spec/inputs/fixtures/activemq_ssl.xml
|
120
|
+
- spec/inputs/fixtures/jms.yml
|
121
|
+
- spec/inputs/fixtures/jndijms.yml
|
122
|
+
- spec/inputs/fixtures/keystore.jks
|
123
|
+
- spec/inputs/integration/jms_spec.rb
|
124
|
+
- spec/inputs/spec_helper.rb
|
125
|
+
- spec/inputs/unit/jms_spec.rb
|
120
126
|
homepage: http://www.elasticsearch.org/guide/en/logstash/current/index.html
|
121
127
|
licenses:
|
122
128
|
- Apache License (2.0)
|
@@ -144,5 +150,11 @@ signing_key:
|
|
144
150
|
specification_version: 4
|
145
151
|
summary: Reads events from a Jms Broker
|
146
152
|
test_files:
|
147
|
-
- spec/inputs/
|
148
|
-
- spec/inputs/
|
153
|
+
- spec/inputs/fixtures/activemq_plaintext.xml
|
154
|
+
- spec/inputs/fixtures/activemq_ssl.xml
|
155
|
+
- spec/inputs/fixtures/jms.yml
|
156
|
+
- spec/inputs/fixtures/jndijms.yml
|
157
|
+
- spec/inputs/fixtures/keystore.jks
|
158
|
+
- spec/inputs/integration/jms_spec.rb
|
159
|
+
- spec/inputs/spec_helper.rb
|
160
|
+
- spec/inputs/unit/jms_spec.rb
|
data/spec/inputs/jms.yml
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
---
|
2
|
-
# HornetQ Broker
|
3
|
-
hornetq:
|
4
|
-
# Connect to a local HornetQ Broker using JNDI
|
5
|
-
:jndi_name: /ConnectionFactory
|
6
|
-
:jndi_context:
|
7
|
-
java.naming.factory.initial: org.jnp.interfaces.NamingContextFactory
|
8
|
-
java.naming.provider.url: jnp://localhost:1099
|
9
|
-
java.naming.factory.url.pkgs: org.jboss.naming:org.jnp.interfaces
|
10
|
-
java.naming.security.principal: guest
|
11
|
-
java.naming.security.credentials: guest
|
12
|
-
:require_jars:
|
13
|
-
- /Applications/hornetq-2.4.0.Final/lib/hornetq-commons.jar
|
14
|
-
- /Applications/hornetq-2.4.0.Final/lib/hornetq-core-client.jar
|
15
|
-
- /Applications/hornetq-2.4.0.Final/lib/hornetq-jms-client.jar
|
16
|
-
- /Applications/hornetq-2.4.0.Final/lib/jboss-jms-api.jar
|
17
|
-
- /Applications/hornetq-2.4.0.Final/lib/jnp-client.jar
|
18
|
-
- /Applications/hornetq-2.4.0.Final/lib/netty.jar
|
data/spec/inputs/jms_spec.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require "logstash/devutils/rspec/spec_helper"
|
2
|
-
require "logstash/inputs/jms"
|
3
|
-
require "jms"
|
4
|
-
|
5
|
-
describe LogStash::Inputs::Jms do
|
6
|
-
let(:queue) { Queue.new }
|
7
|
-
let(:jms_config) {{:require_jars => ["some.jar"], :jndi_name => "", :jndi_context => {}}}
|
8
|
-
let(:config) do
|
9
|
-
config = { "destination" => "ExampleQueue" }
|
10
|
-
jms_config.each {|k, v| config[k.to_s] = v }
|
11
|
-
config
|
12
|
-
end
|
13
|
-
subject { LogStash::Inputs::Jms.new(config.dup) }
|
14
|
-
|
15
|
-
context "using default runner (consumer)" do
|
16
|
-
before :each do
|
17
|
-
subject.register
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should call the consumer runner" do
|
21
|
-
expect(subject).to receive(:run_consumer).with(queue)
|
22
|
-
subject.run(queue)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should create a JMS session based on JMS config" do
|
26
|
-
expect(JMS::Connection).to receive(:session).with(jms_config)
|
27
|
-
subject.run(queue)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|