logstash-input-jdbc 3.0.2 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/LICENSE +1 -1
- data/README.md +1 -0
- data/lib/logstash/inputs/jdbc.rb +60 -0
- data/lib/logstash/plugin_mixins/jdbc.rb +4 -2
- data/logstash-input-jdbc.gemspec +2 -2
- data/spec/inputs/jdbc_spec.rb +142 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6212e80eff0e3db1f5f86d14b2f3222f59a35dd6
|
4
|
+
data.tar.gz: f23623cebfda1902907cb4f9fb5a460a73e362bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f19afa4d410887fc49f5ec8c5ac30e7ad7f345c79c7b17c1f3aed69654814d259d1e00205b668baa93ab30a4c88cf595fd3b9b84f44f8bcb133ecbca234b201
|
7
|
+
data.tar.gz: cbda68232c8f6a7f5eddbfee91bc94d5a4f86f1a317912d85413de16f69e63e486bfa5c35ca1a804623c3b45e7021162fcea9f7fb76fae232a6de4505161a476
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# 3.1.0
|
2
|
+
- Add an option to select the encoding data should be transform from, this will make sure all strings read from the jdbc connector are noremalized to be UTF-8 so no causing issues with later filters in LS.
|
3
|
+
# 3.0.3
|
4
|
+
- Added feature to read password from external file (#120).
|
1
5
|
# 3.0.2
|
2
6
|
- Depend on logstash-core-plugin-api instead of logstash-core, removing the need to mass update plugins on major releases of logstash
|
3
7
|
# 3.0.1
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -95,6 +95,7 @@ Reading data from MySQL:
|
|
95
95
|
jdbc_connection_string => "jdbc:mysql://host:port/database"
|
96
96
|
jdbc_user => "user"
|
97
97
|
jdbc_password => "password"
|
98
|
+
# or jdbc_password_filepath => "/path/to/my/password_file"
|
98
99
|
statement => "SELECT ..."
|
99
100
|
jdbc_paging_enabled => "true"
|
100
101
|
jdbc_page_size => "50000"
|
data/lib/logstash/inputs/jdbc.rb
CHANGED
@@ -160,6 +160,26 @@ class LogStash::Inputs::Jdbc < LogStash::Inputs::Base
|
|
160
160
|
# Whether to force the lowercasing of identifier fields
|
161
161
|
config :lowercase_column_names, :validate => :boolean, :default => true
|
162
162
|
|
163
|
+
# The character encoding of all columns, leave empty if the columns are already properly UTF-8
|
164
|
+
# encoded. Specific columns charsets using :columns_charset can override this setting.
|
165
|
+
config :charset, :validate => :string
|
166
|
+
|
167
|
+
# The character encoding for specific columns. This option will override the `:charset` option
|
168
|
+
# for the specified columns.
|
169
|
+
#
|
170
|
+
# Example:
|
171
|
+
# [source,ruby]
|
172
|
+
# ----------------------------------
|
173
|
+
# input {
|
174
|
+
# jdbc {
|
175
|
+
# ...
|
176
|
+
# columns_charset => { "column0" => "ISO-8859-1" }
|
177
|
+
# ...
|
178
|
+
# }
|
179
|
+
# }
|
180
|
+
# this will only convert column0 that has ISO-8859-1 as an original encoding.
|
181
|
+
config :columns_charset, :validate => :hash, :default => {}
|
182
|
+
|
163
183
|
public
|
164
184
|
|
165
185
|
def register
|
@@ -173,6 +193,8 @@ class LogStash::Inputs::Jdbc < LogStash::Inputs::Base
|
|
173
193
|
end
|
174
194
|
end
|
175
195
|
|
196
|
+
@enable_encoding = !@charset.nil? || !@columns_charset.empty?
|
197
|
+
|
176
198
|
# load sql_last_value from file if exists
|
177
199
|
if @clean_run && File.exist?(@last_run_metadata_path)
|
178
200
|
File.delete(@last_run_metadata_path)
|
@@ -185,6 +207,20 @@ class LogStash::Inputs::Jdbc < LogStash::Inputs::Base
|
|
185
207
|
end
|
186
208
|
|
187
209
|
@statement = File.read(@statement_filepath) if @statement_filepath
|
210
|
+
|
211
|
+
if (@jdbc_password_filepath and @jdbc_password)
|
212
|
+
raise(LogStash::ConfigurationError, "Only one of :jdbc_password, :jdbc_password_filepath may be set at a time.")
|
213
|
+
end
|
214
|
+
|
215
|
+
@jdbc_password = File.read(@jdbc_password_filepath).strip if @jdbc_password_filepath
|
216
|
+
|
217
|
+
if enable_encoding?
|
218
|
+
@converters = {}
|
219
|
+
@columns_charset.each do |column_name, encoding|
|
220
|
+
@converters[encoding] = LogStash::Util::Charset.new(encoding)
|
221
|
+
end
|
222
|
+
@converters[@charset] = LogStash::Util::Charset.new(@charset) if @charset
|
223
|
+
end
|
188
224
|
end # def register
|
189
225
|
|
190
226
|
def run(queue)
|
@@ -214,6 +250,10 @@ class LogStash::Inputs::Jdbc < LogStash::Inputs::Base
|
|
214
250
|
# update default parameters
|
215
251
|
@parameters['sql_last_value'] = @sql_last_value
|
216
252
|
execute_statement(@statement, @parameters) do |row|
|
253
|
+
if enable_encoding?
|
254
|
+
## do the necessary conversions to string elements
|
255
|
+
row = Hash[row.map { |k, v| [k.to_s, convert(k, v)] }]
|
256
|
+
end
|
217
257
|
event = LogStash::Event.new(row)
|
218
258
|
decorate(event)
|
219
259
|
queue << event
|
@@ -226,4 +266,24 @@ class LogStash::Inputs::Jdbc < LogStash::Inputs::Base
|
|
226
266
|
end
|
227
267
|
end
|
228
268
|
|
269
|
+
private
|
270
|
+
|
271
|
+
def enable_encoding?
|
272
|
+
@enable_encoding
|
273
|
+
end
|
274
|
+
|
275
|
+
# make sure the encoding is uniform over fields
|
276
|
+
def convert(column_name, value)
|
277
|
+
return value unless value.is_a?(String)
|
278
|
+
column_charset = @columns_charset[column_name]
|
279
|
+
if column_charset
|
280
|
+
converter = @converters[column_charset]
|
281
|
+
converter.convert(value)
|
282
|
+
elsif @charset
|
283
|
+
converter = @converters[@charset]
|
284
|
+
converter.convert(value)
|
285
|
+
else
|
286
|
+
value
|
287
|
+
end
|
288
|
+
end
|
229
289
|
end # class LogStash::Inputs::Jdbc
|
@@ -40,6 +40,9 @@ module LogStash::PluginMixins::Jdbc
|
|
40
40
|
# JDBC password
|
41
41
|
config :jdbc_password, :validate => :password
|
42
42
|
|
43
|
+
# JDBC password filename
|
44
|
+
config :jdbc_password_filepath, :validate => :path
|
45
|
+
|
43
46
|
# JDBC enable paging
|
44
47
|
#
|
45
48
|
# This will cause a sql statement to be broken up into multiple queries.
|
@@ -260,7 +263,6 @@ module LogStash::PluginMixins::Jdbc
|
|
260
263
|
|
261
264
|
private
|
262
265
|
def decorate_value(value)
|
263
|
-
|
264
266
|
if value.is_a?(Time)
|
265
267
|
# transform it to LogStash::Timestamp as required by LS
|
266
268
|
LogStash::Timestamp.new(value)
|
@@ -269,7 +271,7 @@ module LogStash::PluginMixins::Jdbc
|
|
269
271
|
# This is slower, so we put it in as a conditional case.
|
270
272
|
LogStash::Timestamp.new(Time.parse(value.to_s))
|
271
273
|
else
|
272
|
-
value
|
274
|
+
value
|
273
275
|
end
|
274
276
|
end
|
275
277
|
end
|
data/logstash-input-jdbc.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-input-jdbc'
|
3
|
-
s.version = '3.0
|
3
|
+
s.version = '3.1.0'
|
4
4
|
s.licenses = ['Apache License (2.0)']
|
5
5
|
s.summary = "This example input streams a string at a definable interval."
|
6
|
-
s.description
|
6
|
+
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"
|
7
7
|
s.authors = ["Elastic"]
|
8
8
|
s.email = 'info@elastic.co'
|
9
9
|
s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
|
data/spec/inputs/jdbc_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require "logstash/devutils/rspec/spec_helper"
|
2
3
|
require "logstash/inputs/jdbc"
|
3
4
|
require "jdbc/derby"
|
@@ -29,6 +30,7 @@ describe LogStash::Inputs::Jdbc do
|
|
29
30
|
db.create_table :test_table do
|
30
31
|
DateTime :created_at
|
31
32
|
Integer :num
|
33
|
+
String :string
|
32
34
|
DateTime :custom_time
|
33
35
|
end
|
34
36
|
end
|
@@ -81,6 +83,41 @@ describe LogStash::Inputs::Jdbc do
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
86
|
+
context "when both jdbc_password and jdbc_password_filepath arguments are passed" do
|
87
|
+
let(:statement) { "SELECT * from test_table" }
|
88
|
+
let(:jdbc_password) { "secret" }
|
89
|
+
let(:jdbc_password_file_path) { Stud::Temporary.pathname }
|
90
|
+
let(:settings) { { "jdbc_password_filepath" => jdbc_password_file_path,
|
91
|
+
"jdbc_password" => jdbc_password,
|
92
|
+
"statement" => statement } }
|
93
|
+
|
94
|
+
it "should fail to register" do
|
95
|
+
expect{ plugin.register }.to raise_error(LogStash::ConfigurationError)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when jdbc_password is passed in from a file" do
|
100
|
+
let(:statement) { "SELECT * from test_table" }
|
101
|
+
let(:jdbc_password) { "secret" }
|
102
|
+
let(:jdbc_password_file_path) { Stud::Temporary.pathname }
|
103
|
+
let(:settings) { { "jdbc_password_filepath" => jdbc_password_file_path,
|
104
|
+
"statement" => statement } }
|
105
|
+
|
106
|
+
before do
|
107
|
+
File.write(jdbc_password_file_path, jdbc_password)
|
108
|
+
plugin.register
|
109
|
+
end
|
110
|
+
|
111
|
+
after do
|
112
|
+
plugin.stop
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should read in jdbc_password from file" do
|
116
|
+
expect(plugin.jdbc_password).to eq(jdbc_password)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
84
121
|
context "when neither statement and statement_filepath arguments are passed" do
|
85
122
|
it "should fail to register" do
|
86
123
|
expect{ plugin.register }.to raise_error(LogStash::ConfigurationError)
|
@@ -837,4 +874,109 @@ describe LogStash::Inputs::Jdbc do
|
|
837
874
|
plugin.stop
|
838
875
|
end
|
839
876
|
end
|
877
|
+
|
878
|
+
context "when encoding of some columns need to be changed" do
|
879
|
+
|
880
|
+
let(:settings) {{ "statement" => "SELECT * from test_table" }}
|
881
|
+
let(:events) { [] }
|
882
|
+
let(:row) do
|
883
|
+
{
|
884
|
+
"column0" => "foo",
|
885
|
+
"column1" => "bar".force_encoding(Encoding::ISO_8859_1),
|
886
|
+
"column2" => 3
|
887
|
+
}
|
888
|
+
end
|
889
|
+
|
890
|
+
before(:each) do
|
891
|
+
allow_any_instance_of(Sequel::JDBC::Derby::Dataset).to receive(:each).and_yield(row)
|
892
|
+
plugin.register
|
893
|
+
end
|
894
|
+
|
895
|
+
after(:each) do
|
896
|
+
plugin.stop
|
897
|
+
end
|
898
|
+
|
899
|
+
it "should not convert any column by default" do
|
900
|
+
encoded_row = {
|
901
|
+
"column0" => "foo",
|
902
|
+
"column1" => "bar".force_encoding(Encoding::ISO_8859_1),
|
903
|
+
"column2" => 3
|
904
|
+
}
|
905
|
+
expect(LogStash::Event).to receive(:new) do |row|
|
906
|
+
row.each do |k, v|
|
907
|
+
next unless v.is_a?(String)
|
908
|
+
expect(row[k].encoding).to eq(encoded_row[k].encoding)
|
909
|
+
end
|
910
|
+
end
|
911
|
+
plugin.run(events)
|
912
|
+
end
|
913
|
+
|
914
|
+
context "when all string columns should be encoded" do
|
915
|
+
|
916
|
+
let(:settings) do
|
917
|
+
{
|
918
|
+
"statement" => "SELECT * from test_table",
|
919
|
+
"charset" => "ISO-8859-1"
|
920
|
+
}
|
921
|
+
end
|
922
|
+
|
923
|
+
let(:row) do
|
924
|
+
{
|
925
|
+
"column0" => "foo".force_encoding(Encoding::ISO_8859_1),
|
926
|
+
"column1" => "bar".force_encoding(Encoding::ISO_8859_1),
|
927
|
+
"column2" => 3
|
928
|
+
}
|
929
|
+
end
|
930
|
+
|
931
|
+
it "should transform all column string to UTF-8, default encoding" do
|
932
|
+
encoded_row = {
|
933
|
+
"column0" => "foo",
|
934
|
+
"column1" => "bar",
|
935
|
+
"column2" => 3
|
936
|
+
}
|
937
|
+
expect(LogStash::Event).to receive(:new) do |row|
|
938
|
+
row.each do |k, v|
|
939
|
+
next unless v.is_a?(String)
|
940
|
+
expect(row[k].encoding).to eq(encoded_row[k].encoding)
|
941
|
+
end
|
942
|
+
end
|
943
|
+
plugin.run(events)
|
944
|
+
end
|
945
|
+
end
|
946
|
+
|
947
|
+
context "when only an specific column should be converted" do
|
948
|
+
|
949
|
+
let(:settings) do
|
950
|
+
{
|
951
|
+
"statement" => "SELECT * from test_table",
|
952
|
+
"columns_charset" => { "column1" => "ISO-8859-1" }
|
953
|
+
}
|
954
|
+
end
|
955
|
+
|
956
|
+
let(:row) do
|
957
|
+
{
|
958
|
+
"column0" => "foo",
|
959
|
+
"column1" => "bar".force_encoding(Encoding::ISO_8859_1),
|
960
|
+
"column2" => 3,
|
961
|
+
"column3" => "berlin".force_encoding(Encoding::ASCII_8BIT)
|
962
|
+
}
|
963
|
+
end
|
964
|
+
|
965
|
+
it "should only convert the selected column" do
|
966
|
+
encoded_row = {
|
967
|
+
"column0" => "foo",
|
968
|
+
"column1" => "bar",
|
969
|
+
"column2" => 3,
|
970
|
+
"column3" => "berlin".force_encoding(Encoding::ASCII_8BIT)
|
971
|
+
}
|
972
|
+
expect(LogStash::Event).to receive(:new) do |row|
|
973
|
+
row.each do |k, v|
|
974
|
+
next unless v.is_a?(String)
|
975
|
+
expect(row[k].encoding).to eq(encoded_row[k].encoding)
|
976
|
+
end
|
977
|
+
end
|
978
|
+
plugin.run(events)
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
840
982
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-jdbc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,7 +150,7 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
description: This gem is a
|
153
|
+
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
|
154
154
|
email: info@elastic.co
|
155
155
|
executables: []
|
156
156
|
extensions: []
|