logstash-input-beats 3.1.24-java → 5.1.9-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 +5 -5
- data/CHANGELOG.md +111 -14
- data/Gemfile +3 -2
- data/LICENSE +1 -1
- data/VERSION +1 -1
- data/docs/index.asciidoc +74 -41
- data/lib/logstash/inputs/beats/event_transform_common.rb +1 -0
- data/lib/logstash/inputs/beats/message_listener.rb +63 -5
- data/lib/logstash/inputs/beats.rb +31 -21
- data/lib/logstash-input-beats_jars.rb +9 -9
- data/logstash-input-beats.gemspec +2 -2
- data/spec/inputs/beats/message_listener_spec.rb +103 -12
- data/spec/inputs/beats_spec.rb +15 -26
- data/spec/integration/logstash_forwarder_spec.rb +0 -1
- data/spec/support/client_process_helpers.rb +6 -4
- data/spec/support/helpers.rb +8 -1
- data/spec/support/shared_examples.rb +111 -16
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-annotations/2.9.9/jackson-annotations-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.9.9.3/jackson-databind-2.9.9.3.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/module/jackson-module-afterburner/2.9.9/jackson-module-afterburner-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.12.Final/netty-tcnative-boringssl-static-2.0.12.Final.jar +0 -0
- data/vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.11.1/log4j-api-2.11.1.jar +0 -0
- data/vendor/jar-dependencies/org/javassist/javassist/3.24.0-GA/javassist-3.24.0-GA.jar +0 -0
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/5.1.9/logstash-input-beats-5.1.9.jar +0 -0
- metadata +22 -14
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-annotations/2.7.5/jackson-annotations-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.7.5/jackson-core-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.7.5/jackson-databind-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/module/jackson-module-afterburner/2.7.5/jackson-module-afterburner-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-all/4.1.3.Final/netty-all-4.1.3.Final.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/1.1.33.Fork23/netty-tcnative-boringssl-static-1.1.33.Fork23.jar +0 -0
- data/vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar +0 -0
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/3.1.24/logstash-input-beats-3.1.24.jar +0 -0
@@ -2,7 +2,6 @@
|
|
2
2
|
require "logstash/inputs/base"
|
3
3
|
require "logstash/namespace"
|
4
4
|
require "logstash/timestamp"
|
5
|
-
require "logstash/codecs/identity_map_codec"
|
6
5
|
require "logstash/codecs/multiline"
|
7
6
|
require "logstash/util"
|
8
7
|
require "logstash-input-beats_jars"
|
@@ -40,8 +39,7 @@ require_relative "beats/patch"
|
|
40
39
|
# IMPORTANT: If you are shipping events that span multiple lines, you need to
|
41
40
|
# use the configuration options available in Filebeat to handle multiline events
|
42
41
|
# before sending the event data to Logstash. You cannot use the
|
43
|
-
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
44
|
-
# result in the mixing of streams and corrupted event data.
|
42
|
+
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
45
43
|
#
|
46
44
|
class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
47
45
|
require "logstash/inputs/beats/codec_callback_listener"
|
@@ -84,6 +82,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
84
82
|
#
|
85
83
|
config :ssl_certificate_authorities, :validate => :array, :default => []
|
86
84
|
|
85
|
+
# Flag to determine whether to add host information (provided by the beat in the 'hostname' field) to the event
|
86
|
+
config :add_hostname, :validate => :boolean, :default => true, :deprecated => 'Host field will not be automatically populated by future version of the Beats input'
|
87
|
+
|
88
|
+
|
87
89
|
# By default the server doesn't do any client verification.
|
88
90
|
#
|
89
91
|
# `peer` will make the server ask the client to provide a certificate.
|
@@ -95,6 +97,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
95
97
|
# This option needs to be used with `ssl_certificate_authorities` and a defined list of CAs.
|
96
98
|
config :ssl_verify_mode, :validate => ["none", "peer", "force_peer"], :default => "none"
|
97
99
|
|
100
|
+
# Enables storing client certificate information in event's metadata. You need
|
101
|
+
# to configure the `ssl_verify_mode` to `peer` or `force_peer` to enable this.
|
102
|
+
config :ssl_peer_metadata, :validate => :boolean, :default => false
|
103
|
+
|
98
104
|
config :include_codec_tag, :validate => :boolean, :default => true
|
99
105
|
|
100
106
|
# Time in milliseconds for an incomplete ssl handshake to timeout
|
@@ -102,10 +108,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
102
108
|
|
103
109
|
# The number of seconds before we raise a timeout.
|
104
110
|
# This option is useful to control how much time to wait if something is blocking the pipeline.
|
105
|
-
config :congestion_threshold, :validate => :number, :
|
111
|
+
config :congestion_threshold, :validate => :number, :obsolete => "This option is obsolete since congestion control is done automatically"
|
106
112
|
|
107
113
|
# This is the default field to which the specified codec will be applied.
|
108
|
-
config :target_field_for_codec, :validate => :string, :
|
114
|
+
config :target_field_for_codec, :validate => :string, :obsolete => "This option is obsolete"
|
109
115
|
|
110
116
|
# The minimum TLS version allowed for the encrypted connections. The value must be one of the following:
|
111
117
|
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2
|
@@ -121,6 +127,9 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
121
127
|
# Close Idle clients after X seconds of inactivity.
|
122
128
|
config :client_inactivity_timeout, :validate => :number, :default => 60
|
123
129
|
|
130
|
+
# Beats handler executor thread
|
131
|
+
config :executor_threads, :validate => :number, :default => LogStash::Config::CpuCoreStrategy.maximum
|
132
|
+
|
124
133
|
def register
|
125
134
|
# For Logstash 2.4 we need to make sure that the logger is correctly set for the
|
126
135
|
# java classes before actually loading them.
|
@@ -147,26 +156,22 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
147
156
|
raise LogStash::ConfigurationError, "Using `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `certificate_authorities`"
|
148
157
|
end
|
149
158
|
|
159
|
+
if client_authentication_metadata? && !require_certificate_authorities?
|
160
|
+
raise LogStash::ConfigurationError, "Enabling `peer_metadata` requires using `verify_mode` set to PEER or FORCE_PEER"
|
161
|
+
end
|
162
|
+
|
163
|
+
# Logstash 6.x breaking change (introduced with 4.0.0 of this gem)
|
150
164
|
if @codec.kind_of? LogStash::Codecs::Multiline
|
151
|
-
|
165
|
+
raise LogStash::ConfigurationError, "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html"
|
152
166
|
end
|
153
167
|
|
154
168
|
@logger.info("Beats inputs: Starting input listener", :address => "#{@host}:#{@port}")
|
155
169
|
|
156
|
-
# wrap the configured codec to support identity stream
|
157
|
-
# from the producers if running with the multiline codec.
|
158
|
-
#
|
159
|
-
# If they dont need an identity map, codec are stateless and can be reused
|
160
|
-
# accross multiples connections.
|
161
|
-
if need_identity_map?
|
162
|
-
@codec = LogStash::Codecs::IdentityMapCodec.new(@codec)
|
163
|
-
end
|
164
|
-
|
165
170
|
@server = create_server
|
166
171
|
end # def register
|
167
172
|
|
168
173
|
def create_server
|
169
|
-
server = org.logstash.beats.Server.new(@host, @port, @client_inactivity_timeout)
|
174
|
+
server = org.logstash.beats.Server.new(@host, @port, @client_inactivity_timeout, @executor_threads)
|
170
175
|
if @ssl
|
171
176
|
|
172
177
|
begin
|
@@ -182,13 +187,14 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
182
187
|
if client_authentification?
|
183
188
|
if @ssl_verify_mode.upcase == "FORCE_PEER"
|
184
189
|
ssl_builder.setVerifyMode(org.logstash.netty.SslSimpleBuilder::SslClientVerifyMode::FORCE_PEER)
|
190
|
+
elsif @ssl_verify_mode.upcase == "PEER"
|
191
|
+
ssl_builder.setVerifyMode(org.logstash.netty.SslSimpleBuilder::SslClientVerifyMode::VERIFY_PEER)
|
185
192
|
end
|
186
193
|
ssl_builder.setCertificateAuthorities(@ssl_certificate_authorities)
|
187
194
|
end
|
188
195
|
|
189
196
|
server.enableSSL(ssl_builder)
|
190
197
|
end
|
191
|
-
|
192
198
|
server
|
193
199
|
end
|
194
200
|
|
@@ -210,14 +216,18 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
210
216
|
@server.stop unless @server.nil?
|
211
217
|
end
|
212
218
|
|
213
|
-
def need_identity_map?
|
214
|
-
@codec.kind_of?(LogStash::Codecs::Multiline)
|
215
|
-
end
|
216
|
-
|
217
219
|
def client_authentification?
|
218
220
|
@ssl_certificate_authorities && @ssl_certificate_authorities.size > 0
|
219
221
|
end
|
220
222
|
|
223
|
+
def client_authentication_metadata?
|
224
|
+
@ssl_peer_metadata && ssl_configured? && client_authentification?
|
225
|
+
end
|
226
|
+
|
227
|
+
def client_authentication_required?
|
228
|
+
@ssl_verify_mode == "force_peer"
|
229
|
+
end
|
230
|
+
|
221
231
|
def require_certificate_authorities?
|
222
232
|
@ssl_verify_mode == "force_peer" || @ssl_verify_mode == "peer"
|
223
233
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# AUTOGENERATED BY THE GRADLE SCRIPT. DO NOT EDIT.
|
2
2
|
|
3
3
|
require 'jar_dependencies'
|
4
|
-
require_jar('io.netty', 'netty-all', '4.1.
|
5
|
-
require_jar('io.netty', 'netty-tcnative-boringssl-static', '
|
6
|
-
require_jar('org.javassist', 'javassist', '3.
|
7
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.
|
8
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.
|
9
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.
|
10
|
-
require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.
|
11
|
-
require_jar('org.apache.logging.log4j', 'log4j-api', '2.
|
12
|
-
require_jar('org.logstash.beats', 'logstash-input-beats', '
|
4
|
+
require_jar('io.netty', 'netty-all', '4.1.30.Final')
|
5
|
+
require_jar('io.netty', 'netty-tcnative-boringssl-static', '2.0.12.Final')
|
6
|
+
require_jar('org.javassist', 'javassist', '3.24.0-GA')
|
7
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.9.9')
|
8
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.9.9')
|
9
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.9.9.3')
|
10
|
+
require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.9.9')
|
11
|
+
require_jar('org.apache.logging.log4j', 'log4j-api', '2.11.1')
|
12
|
+
require_jar('org.logstash.beats', 'logstash-input-beats', '5.1.9')
|
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.name = "logstash-input-beats"
|
5
5
|
s.version = BEATS_VERSION
|
6
6
|
s.licenses = ["Apache License (2.0)"]
|
7
|
-
s.summary = "
|
7
|
+
s.summary = "Receives events from the Elastic Beats framework"
|
8
8
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
9
9
|
s.authors = ["Elastic"]
|
10
10
|
s.email = "info@elastic.co"
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
27
27
|
s.add_runtime_dependency "thread_safe", "~> 0.3.5"
|
28
28
|
s.add_runtime_dependency "logstash-codec-multiline", ">= 2.0.5"
|
29
|
-
s.add_runtime_dependency 'jar-dependencies', '~> 0.3.4'
|
29
|
+
s.add_runtime_dependency 'jar-dependencies', '~> 0.3', '>= 0.3.4'
|
30
30
|
|
31
31
|
s.add_development_dependency "flores", "~>0.0.6"
|
32
32
|
s.add_development_dependency "rspec"
|
@@ -6,7 +6,10 @@ require "logstash/inputs/beats/message_listener"
|
|
6
6
|
require "logstash/instrument/namespaced_null_metric"
|
7
7
|
require "thread"
|
8
8
|
|
9
|
+
java_import java.util.HashMap
|
10
|
+
|
9
11
|
class MockMessage
|
12
|
+
|
10
13
|
def initialize(identity_stream, data = {})
|
11
14
|
@identity_stream = identity_stream
|
12
15
|
@data = data
|
@@ -21,6 +24,22 @@ class MockMessage
|
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
27
|
+
# General purpose single method mock class. Will keep generating mocks until requested method name (no args) is found.
|
28
|
+
class OngoingMethodMock
|
29
|
+
def initialize(method_name, return_value)
|
30
|
+
@method_name = method_name
|
31
|
+
@return_value = return_value
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(method)
|
35
|
+
if(method.to_s.eql? @method_name)
|
36
|
+
return @return_value
|
37
|
+
else
|
38
|
+
return OngoingMethodMock.new(@method_name, @return_value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
24
43
|
class DummyCodec < LogStash::Codecs::Base
|
25
44
|
DUMMY_EVENT = LogStash::Event.new
|
26
45
|
|
@@ -37,7 +56,11 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
37
56
|
let(:queue) { Queue.new }
|
38
57
|
let(:codec) { DummyCodec.new }
|
39
58
|
let(:input) { LogStash::Inputs::Beats.new({ "port" => 5555, "codec" => codec }) }
|
40
|
-
|
59
|
+
|
60
|
+
let(:ip_address) { "10.0.0.1" }
|
61
|
+
let(:remote_address) { OngoingMethodMock.new("getHostAddress", ip_address) }
|
62
|
+
let(:ctx) {OngoingMethodMock.new("remoteAddress", remote_address)}
|
63
|
+
|
41
64
|
let(:message) { MockMessage.new("abc", { "message" => "hello world"}) }
|
42
65
|
|
43
66
|
subject { described_class.new(queue, input) }
|
@@ -47,28 +70,54 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
47
70
|
end
|
48
71
|
|
49
72
|
context "onNewConnection" do
|
50
|
-
|
51
|
-
|
73
|
+
let(:second_ip_address) { "10.0.0.2" }
|
74
|
+
let(:second_ctx) {OngoingMethodMock.new("getHostAddress", second_ip_address)}
|
75
|
+
|
76
|
+
shared_examples 'a valid new connection' do
|
77
|
+
it "register the connection to the connection list" do
|
78
|
+
expect { subject.onNewConnection(second_ctx) }.to change { subject.connections_list.count }.by(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it_behaves_like 'a valid new connection'
|
83
|
+
|
84
|
+
context 'with a nil remote address' do
|
85
|
+
let(:second_ip_address) { nil}
|
86
|
+
|
87
|
+
it_behaves_like 'a valid new connection'
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when the channel throws retrieving remote address' do
|
91
|
+
before do
|
92
|
+
allow(second_ctx).to receive(:channel).and_raise('nope')
|
93
|
+
end
|
94
|
+
|
95
|
+
it_behaves_like 'a valid new connection'
|
52
96
|
end
|
53
97
|
|
54
98
|
describe "metrics" do
|
55
99
|
it "new connection should increment connection count" do
|
56
100
|
expect(subject).to receive(:increment_connection_count).once
|
57
|
-
subject.onNewConnection(
|
101
|
+
subject.onNewConnection(second_ctx)
|
58
102
|
end
|
59
103
|
|
60
104
|
describe "peak connections" do
|
105
|
+
let (:ctxes) { [1, 2, 3, 4].inject([]) do |result, element|
|
106
|
+
result << OngoingMethodMock.new("getHostAddress", "10.0.0.#{element}")
|
107
|
+
result
|
108
|
+
end
|
109
|
+
}
|
61
110
|
it "closing and open connections should keep highest count" do
|
62
111
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(1)
|
63
|
-
subject.onNewConnection(
|
112
|
+
subject.onNewConnection(ctxes[0])
|
64
113
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(2)
|
65
|
-
subject.onNewConnection(
|
114
|
+
subject.onNewConnection(ctxes[1])
|
66
115
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
67
|
-
subject.onConnectionClose(
|
116
|
+
subject.onConnectionClose(ctxes[1])
|
68
117
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
69
|
-
subject.onNewConnection(
|
118
|
+
subject.onNewConnection(ctxes[2])
|
70
119
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
71
|
-
subject.onNewConnection(
|
120
|
+
subject.onNewConnection(ctxes[3])
|
72
121
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(4)
|
73
122
|
end
|
74
123
|
end
|
@@ -78,7 +127,7 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
78
127
|
|
79
128
|
context "onNewMessage" do
|
80
129
|
context "when the message is from filebeat" do
|
81
|
-
let(:message) { MockMessage.new("abc", { "message" => "hello world" } )}
|
130
|
+
let(:message) { MockMessage.new("abc", { "message" => "hello world", "@metadata" => {} } )}
|
82
131
|
|
83
132
|
it "extract the event" do
|
84
133
|
subject.onNewMessage(ctx, message)
|
@@ -88,7 +137,7 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
88
137
|
end
|
89
138
|
|
90
139
|
context "when the message is from LSF" do
|
91
|
-
let(:message) { MockMessage.new("abc", { "line" => "hello world" } )}
|
140
|
+
let(:message) { MockMessage.new("abc", { "line" => "hello world", '@metadata' => {} } )}
|
92
141
|
|
93
142
|
it "extract the event" do
|
94
143
|
subject.onNewMessage(ctx, message)
|
@@ -98,7 +147,16 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
98
147
|
end
|
99
148
|
|
100
149
|
context "when the message is from any libbeat" do
|
101
|
-
|
150
|
+
#Requires data modeled as Java, not Ruby since the actual code pulls from Java backed (Netty) object
|
151
|
+
let(:data) do
|
152
|
+
d = HashMap.new
|
153
|
+
d.put('@metadata', HashMap.new)
|
154
|
+
d.put('metric', 1)
|
155
|
+
d.put('name', "super-stats")
|
156
|
+
d
|
157
|
+
end
|
158
|
+
|
159
|
+
let(:message) { MockMessage.new("abc", data)}
|
102
160
|
|
103
161
|
it "extract the event" do
|
104
162
|
subject.onNewMessage(ctx, message)
|
@@ -106,7 +164,40 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
106
164
|
expect(event.get("message")).to be_nil
|
107
165
|
expect(event.get("metric")).to eq(1)
|
108
166
|
expect(event.get("name")).to eq("super-stats")
|
167
|
+
expect(event.get("[@metadata][ip_address]")).to eq(ip_address)
|
109
168
|
end
|
169
|
+
|
170
|
+
context 'when the remote address is nil' do
|
171
|
+
let(:ctx) { OngoingMethodMock.new("remoteAddress", nil)}
|
172
|
+
|
173
|
+
it 'extracts the event' do
|
174
|
+
subject.onNewMessage(ctx, message)
|
175
|
+
event = queue.pop
|
176
|
+
expect(event.get("message")).to be_nil
|
177
|
+
expect(event.get("metric")).to eq(1)
|
178
|
+
expect(event.get("name")).to eq("super-stats")
|
179
|
+
expect(event.get("[@metadata][ip_address]")).to eq(nil)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'when getting the remote address raises' do
|
184
|
+
let(:raising_ctx) { double("context")}
|
185
|
+
|
186
|
+
before do
|
187
|
+
allow(raising_ctx).to receive(:channel).and_raise("nope")
|
188
|
+
subject.onNewConnection(raising_ctx)
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'extracts the event' do
|
192
|
+
subject.onNewMessage(raising_ctx, message)
|
193
|
+
event = queue.pop
|
194
|
+
expect(event.get("message")).to be_nil
|
195
|
+
expect(event.get("metric")).to eq(1)
|
196
|
+
expect(event.get("name")).to eq("super-stats")
|
197
|
+
expect(event.get("[@metadata][ip_address]")).to eq(nil)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
110
201
|
end
|
111
202
|
end
|
112
203
|
|
data/spec/inputs/beats_spec.rb
CHANGED
@@ -16,43 +16,20 @@ describe LogStash::Inputs::Beats do
|
|
16
16
|
|
17
17
|
context "#register" do
|
18
18
|
context "host related configuration" do
|
19
|
-
let(:config) { super.merge!({ "host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout }) }
|
19
|
+
let(:config) { super.merge!({ "host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout, "executor_threads" => threads }) }
|
20
20
|
let(:host) { "192.168.1.20" }
|
21
21
|
let(:port) { 9000 }
|
22
22
|
let(:client_inactivity_timeout) { 400 }
|
23
|
+
let(:threads) { 10 }
|
23
24
|
|
24
25
|
subject(:plugin) { LogStash::Inputs::Beats.new(config) }
|
25
26
|
|
26
27
|
it "sends the required options to the server" do
|
27
|
-
expect(org.logstash.beats.Server).to receive(:new).with(host, port, client_inactivity_timeout)
|
28
|
+
expect(org.logstash.beats.Server).to receive(:new).with(host, port, client_inactivity_timeout, threads)
|
28
29
|
subject.register
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
context "identity map" do
|
33
|
-
subject(:plugin) { LogStash::Inputs::Beats.new(config) }
|
34
|
-
before { plugin.register }
|
35
|
-
|
36
|
-
context "when using the multiline codec" do
|
37
|
-
let(:codec) { LogStash::Codecs::Multiline.new("pattern" => '^2015',
|
38
|
-
"what" => "previous",
|
39
|
-
"negate" => true) }
|
40
|
-
let(:config) { super.merge({ "codec" => codec }) }
|
41
|
-
|
42
|
-
it "wraps the codec with the identity_map" do
|
43
|
-
expect(plugin.codec).to be_kind_of(LogStash::Codecs::IdentityMapCodec)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context "when using non buffered codecs" do
|
48
|
-
let(:config) { super.merge({ "codec" => "json" }) }
|
49
|
-
|
50
|
-
it "doesnt wrap the codec with the identity map" do
|
51
|
-
expect(plugin.codec).to be_kind_of(LogStash::Codecs::JSON)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
33
|
it "raise no exception" do
|
57
34
|
plugin = LogStash::Inputs::Beats.new(config)
|
58
35
|
expect { plugin.register }.not_to raise_error
|
@@ -146,6 +123,18 @@ describe LogStash::Inputs::Beats do
|
|
146
123
|
end
|
147
124
|
end
|
148
125
|
end
|
126
|
+
|
127
|
+
context "with multiline codec" do
|
128
|
+
let(:codec) { LogStash::Codecs::Multiline.new("pattern" => '^2015',
|
129
|
+
"what" => "previous",
|
130
|
+
"negate" => true) }
|
131
|
+
let(:config) { super.merge({ "codec" => codec }) }
|
132
|
+
|
133
|
+
it "raise a ConfigurationError when multiline codec is set" do
|
134
|
+
plugin = LogStash::Inputs::Beats.new(config)
|
135
|
+
expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html")
|
136
|
+
end
|
137
|
+
end
|
149
138
|
end
|
150
139
|
|
151
140
|
context "when interrupting the plugin" do
|
@@ -32,10 +32,12 @@ module ClientProcessHelpers
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def stop_client
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
unless @process.nil?
|
36
|
+
begin
|
37
|
+
@process.poll_for_exit(5)
|
38
|
+
rescue ChildProcess::TimeoutError
|
39
|
+
Process.kill("KILL", @process.pid)
|
40
|
+
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -11,6 +11,13 @@ OPEN_SSL_TOPK8 = "openssl pkcs8 -nocrypt -topk8 -inform PEM -outform PEM"
|
|
11
11
|
#
|
12
12
|
def convert_to_pkcs8(key)
|
13
13
|
out, e, s = Open3.capture3(OPEN_SSL_TOPK8, :stdin_data => key.to_s)
|
14
|
-
|
14
|
+
# attempt to address random failures by trying again
|
15
|
+
unless s.success?
|
16
|
+
sleep 1
|
17
|
+
out, e, s = Open3.capture3(OPEN_SSL_TOPK8, :stdin_data => key.to_s)
|
18
|
+
raise e if e != ""
|
19
|
+
out
|
20
|
+
end
|
21
|
+
|
15
22
|
out
|
16
23
|
end
|
@@ -25,31 +25,126 @@ shared_examples "Common Event Transformation" do
|
|
25
25
|
expect(subject.get("tags")).to include(tag)
|
26
26
|
end
|
27
27
|
|
28
|
-
context
|
29
|
-
let(:
|
30
|
-
let(:event_map) { super.merge({ "host" => already_exist }) }
|
28
|
+
context 'when add_hostname is true' do
|
29
|
+
let(:config) { super.merge({'add_hostname' => true})}
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
context 'when a host is provided in beat.host.name' do
|
32
|
+
let(:already_exist) { "already_exist" }
|
33
|
+
let(:producer_host) { "newhost01" }
|
34
|
+
let(:event_map) { super.merge({ "beat" => { "host" => {"name" => producer_host }}}) }
|
35
|
+
|
36
|
+
context "when no `host` key already exists on the event" do
|
37
|
+
it "does not set the host value" do
|
38
|
+
expect(subject.get("host")).to be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when `host` key exists on the event" do
|
43
|
+
let(:already_exist) { "already_exist" }
|
44
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
45
|
+
|
46
|
+
it "doesn't override it" do
|
47
|
+
expect(subject.get("host")).to eq(already_exist)
|
48
|
+
end
|
49
|
+
end
|
34
50
|
end
|
35
|
-
end
|
36
51
|
|
37
|
-
|
38
|
-
|
39
|
-
|
52
|
+
context "when a host is set in `beat.hostname`" do
|
53
|
+
let(:producer_host) { "newhost01" }
|
54
|
+
let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
|
40
55
|
|
41
|
-
|
42
|
-
|
43
|
-
|
56
|
+
context "when no `host` key already exists on the event" do
|
57
|
+
it "copies the value in `beat.hostname` to `host`" do
|
58
|
+
expect(subject.get("host")).to eq(producer_host)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when `host` key exists on the event" do
|
63
|
+
let(:already_exist) { "already_exist" }
|
64
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
65
|
+
|
66
|
+
it "doesn't override it" do
|
67
|
+
expect(subject.get("host")).to eq(already_exist)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when no host is provided in beat" do
|
73
|
+
context "when no `host` key already exists on the event" do
|
74
|
+
it "does not set the host" do
|
75
|
+
expect(subject.get("host")).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when `host` key already exists on the event" do
|
80
|
+
let(:already_exist) { "already_exist" }
|
81
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
82
|
+
|
83
|
+
it "doesn't override it" do
|
84
|
+
expect(subject.get("host")).to eq(already_exist)
|
85
|
+
end
|
44
86
|
end
|
45
87
|
end
|
88
|
+
end
|
46
89
|
|
47
|
-
|
90
|
+
context 'when add hostname is false' do
|
91
|
+
let(:config) { super.merge({'add_hostname' => false})}
|
92
|
+
|
93
|
+
context 'when a host is provided in beat.host.name' do
|
48
94
|
let(:already_exist) { "already_exist" }
|
49
|
-
let(:
|
95
|
+
let(:producer_host) { "newhost01" }
|
96
|
+
let(:event_map) { super.merge({ "beat" => { "host" => {"name" => producer_host }}}) }
|
97
|
+
|
98
|
+
context "when no `host` key already exists on the event" do
|
99
|
+
it "does not set the host" do
|
100
|
+
expect(subject.get("host")).to be_nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when `host` key already exists on the event" do
|
105
|
+
let(:already_exist) { "already_exist" }
|
106
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
107
|
+
|
108
|
+
it "doesn't override it" do
|
109
|
+
expect(subject.get("host")).to eq(already_exist)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when a host is provided in `beat.hostname`" do
|
115
|
+
let(:producer_host) { "newhost01" }
|
116
|
+
let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
|
117
|
+
|
118
|
+
context "when no `host` key already exists on the event" do
|
119
|
+
it "does not set the host" do
|
120
|
+
expect(subject.get("host")).to be_nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when `host` key already exists on the event" do
|
125
|
+
let(:already_exist) { "already_exist" }
|
126
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
127
|
+
|
128
|
+
it "doesn't override it" do
|
129
|
+
expect(subject.get("host")).to eq(already_exist)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when no host is provided in beat" do
|
135
|
+
context "when no `host` key already exists on the event" do
|
136
|
+
it "does not set the host" do
|
137
|
+
expect(subject.get("host")).to be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "when `host` key already exists on the event" do
|
142
|
+
let(:already_exist) { "already_exist" }
|
143
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
50
144
|
|
51
|
-
|
52
|
-
|
145
|
+
it "doesn't override it" do
|
146
|
+
expect(subject.get("host")).to eq(already_exist)
|
147
|
+
end
|
53
148
|
end
|
54
149
|
end
|
55
150
|
end
|
Binary file
|
data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|