logstash-input-jdbc 3.0.2 → 3.1.0
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 +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: []
|