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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 210deedb95591e0f409fc3461af2d79bb8a384e8
4
- data.tar.gz: 8543b8a26df1cd6a80fcace0f7c7e54be175cf2e
3
+ metadata.gz: 6212e80eff0e3db1f5f86d14b2f3222f59a35dd6
4
+ data.tar.gz: f23623cebfda1902907cb4f9fb5a460a73e362bc
5
5
  SHA512:
6
- metadata.gz: df9c7fa5e10be322919f607a815c9fe899f05da6bb348c599e2d35390f5a10b1647ea0fe8ef60c8c05cfa524b7db3e39ae89fa256f832b5972f467c17a72c462
7
- data.tar.gz: d42eccdbab0331fc8e7e834e45fb0944e22eb9e1eb583782955bf34aa7cad8aab33fe9c6c9b29f43257992f11e4e5947cd177f83d4e10cc9fb6071d80880725a
6
+ metadata.gz: 4f19afa4d410887fc49f5ec8c5ac30e7ad7f345c79c7b17c1f3aed69654814d259d1e00205b668baa93ab30a4c88cf595fd3b9b84f44f8bcb133ecbca234b201
7
+ data.tar.gz: cbda68232c8f6a7f5eddbfee91bc94d5a4f86f1a317912d85413de16f69e63e486bfa5c35ca1a804623c3b45e7021162fcea9f7fb76fae232a6de4505161a476
@@ -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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012–2015 Elasticsearch <http://www.elastic.co>
1
+ Copyright (c) 2012–2016 Elasticsearch <http://www.elastic.co>
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
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"
@@ -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 # no-op
274
+ value
273
275
  end
274
276
  end
275
277
  end
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-input-jdbc'
3
- s.version = '3.0.2'
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 = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
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"
@@ -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.2
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-03-24 00:00:00.000000000 Z
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 logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
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: []