fluent-plugin-elasticsearch 5.0.0 → 5.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +6 -0
  3. data/.github/workflows/linux.yml +5 -2
  4. data/.github/workflows/macos.yml +5 -2
  5. data/.github/workflows/windows.yml +5 -2
  6. data/Gemfile +1 -1
  7. data/History.md +65 -1
  8. data/README.Troubleshooting.md +91 -0
  9. data/README.md +129 -4
  10. data/fluent-plugin-elasticsearch.gemspec +2 -1
  11. data/lib/fluent/plugin/elasticsearch_compat.rb +30 -0
  12. data/lib/fluent/plugin/elasticsearch_error_handler.rb +19 -4
  13. data/lib/fluent/plugin/elasticsearch_fallback_selector.rb +2 -2
  14. data/lib/fluent/plugin/elasticsearch_index_lifecycle_management.rb +18 -4
  15. data/lib/fluent/plugin/elasticsearch_index_template.rb +20 -4
  16. data/lib/fluent/plugin/elasticsearch_simple_sniffer.rb +2 -1
  17. data/lib/fluent/plugin/filter_elasticsearch_genid.rb +1 -1
  18. data/lib/fluent/plugin/in_elasticsearch.rb +2 -1
  19. data/lib/fluent/plugin/oj_serializer.rb +2 -1
  20. data/lib/fluent/plugin/out_elasticsearch.rb +80 -19
  21. data/lib/fluent/plugin/out_elasticsearch_data_stream.rb +132 -62
  22. data/lib/fluent/plugin/out_elasticsearch_dynamic.rb +3 -1
  23. data/test/plugin/mock_chunk.dat +0 -0
  24. data/test/plugin/test_elasticsearch_error_handler.rb +130 -23
  25. data/test/plugin/test_elasticsearch_fallback_selector.rb +16 -8
  26. data/test/plugin/test_elasticsearch_index_lifecycle_management.rb +55 -15
  27. data/test/plugin/test_filter_elasticsearch_genid.rb +16 -16
  28. data/test/plugin/test_in_elasticsearch.rb +20 -0
  29. data/test/plugin/test_out_elasticsearch.rb +795 -134
  30. data/test/plugin/test_out_elasticsearch_data_stream.rb +717 -117
  31. data/test/plugin/test_out_elasticsearch_dynamic.rb +150 -18
  32. metadata +21 -5
  33. data/.travis.yml +0 -40
  34. data/appveyor.yml +0 -20
@@ -28,6 +28,8 @@ module Fluent::Plugin
28
28
  @dynamic_config[key] = value.to_s
29
29
  }
30
30
  # end eval all configs
31
+
32
+ log.warn "Elasticsearch dynamic plugin will be deprecated and removed in the future. Please consider to use normal Elasticsearch plugin"
31
33
  end
32
34
 
33
35
  def create_meta_config_map
@@ -53,7 +55,7 @@ module Fluent::Plugin
53
55
  end
54
56
  headers = { 'Content-Type' => @content_type.to_s, }.merge(gzip_headers)
55
57
  ssl_options = { verify: @ssl_verify, ca_file: @ca_file}.merge(@ssl_version_options)
56
- transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new(connection_options.merge(
58
+ transport = TRANSPORT_CLASS::Transport::HTTP::Faraday.new(connection_options.merge(
57
59
  options: {
58
60
  reload_connections: @reload_connections,
59
61
  reload_on_failure: @reload_on_failure,
Binary file
@@ -2,6 +2,7 @@ require_relative '../helper'
2
2
  require 'fluent/plugin/out_elasticsearch'
3
3
  require 'fluent/plugin/elasticsearch_error_handler'
4
4
  require 'json'
5
+ require 'msgpack'
5
6
 
6
7
  class TestElasticsearchErrorHandler < Test::Unit::TestCase
7
8
 
@@ -27,13 +28,18 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
27
28
  @error_events << {:tag => tag, :time=>time, :record=>record, :error=>e}
28
29
  end
29
30
 
30
- def process_message(tag, meta, header, time, record, extracted_values)
31
+ def process_message(tag, meta, header, time, record, affinity_target_indices, extracted_values)
31
32
  return [meta, header, record]
32
33
  end
33
34
 
35
+ def get_affinity_target_indices(chunk)
36
+ indices = Hash.new
37
+ indices
38
+ end
39
+
34
40
  def append_record_to_messages(op, meta, header, record, msgs)
35
41
  if record.has_key?('raise') && record['raise']
36
- raise Exception('process_message')
42
+ raise 'process_message'
37
43
  end
38
44
  return true
39
45
  end
@@ -49,6 +55,27 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
49
55
  end
50
56
  end
51
57
 
58
+ class MockMsgpackChunk
59
+ def initialize(chunk)
60
+ @chunk = chunk
61
+ @factory = MessagePack::Factory.new
62
+ @factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
63
+ end
64
+
65
+ def msgpack_each
66
+ @factory.unpacker(@chunk).each { |time, record| yield(time, record) }
67
+ end
68
+ end
69
+
70
+ class MockUnpackedMsg
71
+ def initialize(records)
72
+ @records = records
73
+ end
74
+ def each
75
+ @records.each { |item| yield({:time => item[:time], :record => item[:record]}) }
76
+ end
77
+ end
78
+
52
79
  def setup
53
80
  Fluent::Test.setup
54
81
  @log_device = Fluent::Test::DummyLogDevice.new
@@ -93,8 +120,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
93
120
  ]
94
121
  }))
95
122
  chunk = MockChunk.new(records)
123
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
96
124
  dummy_extracted_values = []
97
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
125
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
98
126
  assert_equal(1, @plugin.error_events.size)
99
127
  expected_log = "failed to parse"
100
128
  exception_message = @plugin.error_events.first[:error].message
@@ -135,8 +163,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
135
163
  ]
136
164
  }))
137
165
  chunk = MockChunk.new(records)
166
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
138
167
  dummy_extracted_values = []
139
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
168
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
140
169
  assert_equal(1, @plugin.error_events.size)
141
170
  expected_log = "failed to parse"
142
171
  exception_message = @plugin.error_events.first[:error].message
@@ -154,8 +183,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
154
183
  "items" : [{}]
155
184
  }))
156
185
  chunk = MockChunk.new(records)
186
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
157
187
  dummy_extracted_values = []
158
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
188
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
159
189
  assert_equal(0, @plugin.error_events.size)
160
190
  assert_nil(@plugin.error_events[0])
161
191
  end
@@ -176,8 +206,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
176
206
  ]
177
207
  }))
178
208
  chunk = MockChunk.new(records)
209
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
179
210
  dummy_extracted_values = []
180
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
211
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
181
212
  assert_equal(1, @plugin.error_events.size)
182
213
  assert_true(@plugin.error_events[0][:error].respond_to?(:backtrace))
183
214
  end
@@ -199,8 +230,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
199
230
  ]
200
231
  }))
201
232
  chunk = MockChunk.new(records)
233
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
202
234
  dummy_extracted_values = []
203
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
235
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
204
236
  assert_equal(1, @plugin.error_events.size)
205
237
  assert_true(@plugin.error_events[0][:error].respond_to?(:backtrace))
206
238
  end
@@ -225,10 +257,11 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
225
257
  ]
226
258
  }))
227
259
 
228
- chunk = MockChunk.new(records)
229
- dummy_extracted_values = []
260
+ chunk = MockChunk.new(records)
261
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
262
+ dummy_extracted_values = []
230
263
  assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError) do
231
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
264
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
232
265
  end
233
266
  end
234
267
 
@@ -252,10 +285,11 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
252
285
  ]
253
286
  }))
254
287
 
255
- chunk = MockChunk.new(records)
256
- dummy_extracted_values = []
288
+ chunk = MockChunk.new(records)
289
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
290
+ dummy_extracted_values = []
257
291
  assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError) do
258
- @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values)
292
+ @handler.handle_error(response, 'atag', chunk, records.length, dummy_extracted_values, unpacked_msg_arr)
259
293
  end
260
294
  end
261
295
 
@@ -285,8 +319,9 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
285
319
  begin
286
320
  failed = false
287
321
  chunk = MockChunk.new(records)
322
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
288
323
  dummy_extracted_values = []
289
- handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values)
324
+ handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values, unpacked_msg_arr)
290
325
  rescue Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError, Fluent::Plugin::ElasticsearchOutput::RetryStreamError=>e
291
326
  failed = true
292
327
  records = [].tap do |records|
@@ -302,11 +337,12 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
302
337
  def test_retry_error
303
338
  records = []
304
339
  error_records = Hash.new(false)
305
- error_records.merge!({0=>true, 4=>true, 9=>true})
340
+ error_records.merge!({0=>true, 4=>true})
306
341
  10.times do |i|
307
342
  records << {time: 12345, record: {"message"=>"record #{i}","_id"=>i,"raise"=>error_records[i]}}
308
343
  end
309
344
  chunk = MockChunk.new(records)
345
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
310
346
 
311
347
  response = parse_response(%({
312
348
  "took" : 1,
@@ -386,6 +422,18 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
386
422
  "reason":"unrecognized error"
387
423
  }
388
424
  }
425
+ },
426
+ {
427
+ "create" : {
428
+ "_index" : "foo",
429
+ "_type" : "bar",
430
+ "_id" : "9",
431
+ "status" : 500,
432
+ "error" : {
433
+ "type" : "json_parse_exception",
434
+ "reason":"Invalid UTF-8 start byte 0x92\\n at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@204fe9c9; line: 1, column: 81]"
435
+ }
436
+ }
389
437
  }
390
438
  ]
391
439
  }))
@@ -393,19 +441,19 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
393
441
  begin
394
442
  failed = false
395
443
  dummy_extracted_values = []
396
- @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values)
444
+ @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values, unpacked_msg_arr)
397
445
  rescue Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError, Fluent::Plugin::ElasticsearchOutput::RetryStreamError=>e
398
446
  failed = true
399
447
  records = [].tap do |records|
400
448
  next unless e.respond_to?(:retry_stream)
401
449
  e.retry_stream.each {|time, record| records << record}
402
450
  end
403
- assert_equal 2, records.length
404
- assert_equal 2, records[0]['_id']
405
- assert_equal 8, records[1]['_id']
451
+ assert_equal 2, records.length, "Exp. retry_stream to contain records"
452
+ assert_equal 2, records[0]['_id'], "Exp record with given ID to in retry_stream"
453
+ assert_equal 8, records[1]['_id'], "Exp record with given ID to in retry_stream"
406
454
  error_ids = @plugin.error_events.collect {|h| h[:record]['_id']}
407
- assert_equal 3, error_ids.length
408
- assert_equal [5, 6, 7], error_ids
455
+ assert_equal 4, error_ids.length, "Exp. a certain number of records to be dropped from retry_stream"
456
+ assert_equal [5, 6, 7, 9], error_ids, "Exp. specific records to be dropped from retry_stream"
409
457
  @plugin.error_events.collect {|h| h[:error]}.each do |e|
410
458
  assert_true e.respond_to?(:backtrace)
411
459
  end
@@ -422,6 +470,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
422
470
  records << {time: 12345, record: {"message"=>"record #{i}","_id"=>i,"raise"=>error_records[i]}}
423
471
  end
424
472
  chunk = MockChunk.new(records)
473
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
425
474
 
426
475
  response = parse_response(%({
427
476
  "took" : 1,
@@ -509,7 +558,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
509
558
  begin
510
559
  failed = false
511
560
  dummy_extracted_values = []
512
- @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values)
561
+ @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values, unpacked_msg_arr)
513
562
  rescue Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError, Fluent::Plugin::ElasticsearchOutput::RetryStreamError=>e
514
563
  failed = true
515
564
  records = [].tap do |records|
@@ -532,6 +581,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
532
581
  records << {time: 12345, record: {"message"=>"record #{i}","_id"=>i,"raise"=>error_records[i]}}
533
582
  end
534
583
  chunk = MockChunk.new(records)
584
+ unpacked_msg_arr = MockUnpackedMsg.new(records)
535
585
 
536
586
  response = parse_response(%({
537
587
  "took" : 1,
@@ -622,7 +672,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
622
672
  begin
623
673
  failed = false
624
674
  dummy_extracted_values = []
625
- @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values)
675
+ @handler.handle_error(response, 'atag', chunk, response['items'].length, dummy_extracted_values, unpacked_msg_arr)
626
676
  rescue Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchRequestAbortError, Fluent::Plugin::ElasticsearchOutput::RetryStreamError=>e
627
677
  failed = true
628
678
  records = [].tap do |records|
@@ -643,4 +693,61 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
643
693
  end
644
694
  assert_true failed
645
695
  end
696
+
697
+ def test_nested_msgpack_each
698
+ cwd = File.dirname(__FILE__)
699
+ chunk_path = File.join(cwd, 'mock_chunk.dat')
700
+ chunk_file = File.open(chunk_path, 'rb', 0644)
701
+ chunk_file.seek(0, IO::SEEK_SET)
702
+
703
+ chunk = MockMsgpackChunk.new(chunk_file)
704
+
705
+ unpacked_msg_arr = []
706
+ msg_count = 0
707
+ count_to_trigger_error_handle = 0
708
+ chunk.msgpack_each do |time, record|
709
+ next unless record.is_a? Hash
710
+
711
+ unpacked_msg_arr << {:time => time, :record => record}
712
+ msg_count += 1
713
+
714
+ record.each_key do |k|
715
+ if k != 'aaa' && k != 'bbb' && k != 'ccc' && k != 'log_path'
716
+ assert_equal(:impossible, k)
717
+ end
718
+ end
719
+
720
+ if msg_count % 55 == 0
721
+ if count_to_trigger_error_handle == 1
722
+ begin
723
+ response = {}
724
+ response['errors'] = true
725
+ response['items'] = []
726
+ item = {}
727
+ item['index'] = {}
728
+ item['index']['status'] = 429
729
+ item['index']['error'] = {}
730
+ item['index']['error']['type'] = "es_rejected_execution_exception"
731
+ abc = 0
732
+ while abc < unpacked_msg_arr.length
733
+ abc += 1
734
+ response['items'] << item
735
+ end
736
+
737
+ dummy_extracted_values = []
738
+ @handler.handle_error(response, 'atag', chunk, unpacked_msg_arr.length, dummy_extracted_values, unpacked_msg_arr)
739
+ assert_equal(0, @plugin.error_events.size)
740
+ assert_nil(@plugin.error_events[0])
741
+ rescue => e
742
+ # capture ElasticsearchRequestAbortError, beacuse es_rejected_execution_exception is unrecoverable.
743
+ end
744
+ end
745
+
746
+ count_to_trigger_error_handle += 1
747
+ unpacked_msg_arr.clear
748
+ end # end if
749
+ end # end chunk.msgpack_each
750
+
751
+ chunk_file.close
752
+ end
646
753
  end
@@ -18,17 +18,25 @@ class ElasticsearchFallbackSelectorTest < Test::Unit::TestCase
18
18
  end
19
19
  end
20
20
 
21
- def stub_elastic_info(url="http://localhost:9200/", version="6.4.2")
22
- body ="{\"version\":{\"number\":\"#{version}\"}}"
23
- stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json' } })
21
+ def elasticsearch_version
22
+ if Gem::Version.new(TRANSPORT_CLASS::VERSION) >= Gem::Version.new("7.14.0")
23
+ TRANSPORT_CLASS::VERSION
24
+ else
25
+ '6.4.2'.freeze
26
+ end
27
+ end
28
+
29
+ def stub_elastic_info(url="http://localhost:9200/", version=elasticsearch_version)
30
+ body ="{\"version\":{\"number\":\"#{version}\", \"build_flavor\":\"default\"},\"tagline\" : \"You Know, for Search\"}"
31
+ stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json', 'x-elastic-product' => 'Elasticsearch' } })
24
32
  end
25
33
 
26
- def stub_elastic_info_not_found(url="http://localhost:9200/", version="6.4.2")
27
- stub_request(:get, url).to_return(:status => [404, "Not Found"])
34
+ def stub_elastic_info_not_found(url="http://localhost:9200/", version=elasticsearch_version)
35
+ stub_request(:get, url).to_return(:status => [404, "Not Found"], headers: {'x-elastic-product' => 'Elasticsearch' })
28
36
  end
29
37
 
30
- def stub_elastic_info_unavailable(url="http://localhost:9200/", version="6.4.2")
31
- stub_request(:get, url).to_return(:status => [503, "Service Unavailable"])
38
+ def stub_elastic_info_unavailable(url="http://localhost:9200/", version=elasticsearch_version)
39
+ stub_request(:get, url).to_return(:status => [503, "Service Unavailable"], headers: {'x-elastic-product' => 'Elasticsearch' })
32
40
  end
33
41
 
34
42
  def sample_record(content={})
@@ -60,7 +68,7 @@ class ElasticsearchFallbackSelectorTest < Test::Unit::TestCase
60
68
  reload_after 10
61
69
  catch_transport_exception_on_retry false # For fallback testing
62
70
  ]
63
- assert_raise(Elasticsearch::Transport::Transport::Errors::NotFound) do
71
+ assert_raise(TRANSPORT_CLASS::Transport::Errors::NotFound) do
64
72
  driver(config)
65
73
  end
66
74
  driver.run(default_tag: 'test') do
@@ -6,12 +6,14 @@ class TestElasticsearchIndexLifecycleManagement < Test::Unit::TestCase
6
6
  include Fluent::Plugin::ElasticsearchIndexLifecycleManagement
7
7
 
8
8
  def setup
9
- begin
10
- require "elasticsearch/xpack"
11
- rescue LoadError
12
- omit "ILM testcase needs elasticsearch-xpack gem."
9
+ if Gem::Version.new(Elasticsearch::VERSION) < Gem::Version.new("7.14.0")
10
+ begin
11
+ require "elasticsearch/xpack"
12
+ rescue LoadError
13
+ omit "ILM testcase needs elasticsearch-xpack gem."
14
+ end
13
15
  end
14
- if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.4.0")
16
+ if Gem::Version.create(::TRANSPORT_CLASS::VERSION) < Gem::Version.create("7.4.0")
15
17
  omit "elastisearch-ruby v7.4.0 or later is needed for ILM."
16
18
  end
17
19
  Fluent::Plugin::ElasticsearchIndexLifecycleManagement.module_eval(<<-CODE)
@@ -27,40 +29,78 @@ class TestElasticsearchIndexLifecycleManagement < Test::Unit::TestCase
27
29
  CODE
28
30
  end
29
31
 
32
+ def elasticsearch_version
33
+ if Gem::Version.new(TRANSPORT_CLASS::VERSION) >= Gem::Version.new("8.0.0")
34
+ TRANSPORT_CLASS::VERSION
35
+ else
36
+ '6.4.2'.freeze
37
+ end
38
+ end
39
+
40
+ def ilm_existence_endpoint(policy_id)
41
+ if Gem::Version.new(TRANSPORT_CLASS::VERSION) >= Gem::Version.new("8.0.0")
42
+ "_enrich/policy/#{policy_id}"
43
+ else
44
+ "_ilm/policy/%7B:policy_id=%3E%22#{policy_id}%22%7D"
45
+ end
46
+ end
47
+
48
+ def ilm_creation_endpoint(policy_id)
49
+ if Gem::Version.new(TRANSPORT_CLASS::VERSION) >= Gem::Version.new("8.0.0")
50
+ "_enrich/policy/#{policy_id}"
51
+ else
52
+ "_ilm/policy/#{policy_id}"
53
+ end
54
+ end
55
+
56
+ def stub_elastic_info(url="http://localhost:9200/", version=elasticsearch_version)
57
+ body ="{\"version\":{\"number\":\"#{version}\", \"build_flavor\":\"default\"},\"tagline\" : \"You Know, for Search\"}"
58
+ stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json', 'x-elastic-product' => 'Elasticsearch' } })
59
+ end
60
+
30
61
  def test_xpack_info
31
62
  stub_request(:get, "http://localhost:9200/_xpack").
32
- to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
63
+ to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json" })
64
+ stub_elastic_info
33
65
  expected = {"features"=>{"ilm"=>{"available"=>true, "enabled"=>true}}}
34
- assert_equal(expected, xpack_info)
66
+ if xpack_info.is_a?(Elasticsearch::API::Response)
67
+ assert_equal(expected, xpack_info.body)
68
+ else
69
+ assert_equal(expected, xpack_info)
70
+ end
35
71
  end
36
72
 
37
73
  def test_verify_ilm_working
38
74
  stub_request(:get, "http://localhost:9200/_xpack").
39
- to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
75
+ to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json" })
76
+ stub_elastic_info
40
77
  assert_nothing_raised { verify_ilm_working }
41
78
  end
42
79
 
43
80
  def test_ilm_policy_doesnt_exists
44
- stub_request(:get, "http://localhost:9200/_ilm/policy/%7B:policy_id=%3E%22fluentd-policy%22%7D").
81
+ stub_request(:get, "http://localhost:9200/#{ilm_existence_endpoint("fluentd-policy")}").
45
82
  to_return(:status => 404, :body => "", :headers => {})
46
- assert_false(ilm_policy_exists?(policy_id: "fluentd-policy"))
83
+ stub_elastic_info
84
+ assert_false(ilm_policy_exists?("fluentd-policy"))
47
85
  end
48
86
 
49
87
  def test_ilm_policy_exists
50
- stub_request(:get, "http://localhost:9200/_ilm/policy/%7B:policy_id=%3E%22fluent-policy%22%7D").
88
+ stub_request(:get, "http://localhost:9200/#{ilm_existence_endpoint("fluent-policy")}").
51
89
  to_return(:status => 200, :body => "", :headers => {})
52
- assert_true(ilm_policy_exists?(policy_id: "fluent-policy"))
90
+ stub_elastic_info
91
+ assert_true(ilm_policy_exists?("fluent-policy"))
53
92
  end
54
93
 
55
94
  def test_create_ilm_policy
56
- stub_request(:get, "http://localhost:9200/_ilm/policy/fluent-policy").
95
+ stub_request(:get, "http://localhost:9200/#{ilm_creation_endpoint("fluent-policy")}").
57
96
  to_return(:status => 404, :body => "", :headers => {})
58
- stub_request(:put, "http://localhost:9200/_ilm/policy/fluent-policy").
97
+ stub_request(:put, "http://localhost:9200/#{ilm_creation_endpoint("fluent-policy")}").
59
98
  with(:body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"50gb\",\"max_age\":\"30d\"}}}}}}",
60
99
  :headers => {'Content-Type'=>'application/json'}).
61
100
  to_return(:status => 200, :body => "", :headers => {})
101
+ stub_elastic_info
62
102
  create_ilm_policy("fluent-policy")
63
103
 
64
- assert_requested(:put, "http://localhost:9200/_ilm/policy/fluent-policy", times: 1)
104
+ assert_requested(:put, "http://localhost:9200/#{ilm_creation_endpoint("fluent-policy")}", times: 1)
65
105
  end
66
106
  end
@@ -132,10 +132,10 @@ class ElasticsearchGenidFilterTest < Test::Unit::TestCase
132
132
  end
133
133
 
134
134
  class UseEntireRecordAsSeedTest < self
135
- data("md5" => ["md5", "MuMU0gHOP1cWvvg/J4aEFg=="],
136
- "sha1" => ["sha1", "GZ6Iup9Ywyk5spCWtPQbtZnfK0U="],
137
- "sha256" => ["sha256", "O4YN0RiXCUAYeaR97UUULRLxgra/R2dvTV47viir5l4="],
138
- "sha512" => ["sha512", "FtbwO1xsLUq0KcO0mj0l80rbwFH5rGE3vL+Vgh90+4R/9j+/Ni/ipwhiOoUcetDxj1r5Vf/92B54La+QTu3eMA=="],)
135
+ data("md5" => ["md5", "OAod7J0DR9s9/rOQnkeSFw=="],
136
+ "sha1" => ["sha1", "0CT4aMJ4gxMT3TKaYPCYApiVsq8="],
137
+ "sha256" => ["sha256", "mbAuKF5can0TTj/JBk71AXtOyoVqw5W5gMPUxx6pxLk="],
138
+ "sha512" => ["sha512", "f7kz5KVuDy+riENePDzqBjGQfbuRNpRBSQMzT2/6hrljXbYtBy3YFmxB86ofIf3zz4ZBao2QM2W7YvcwbRtK1w=="],)
139
139
  def test_record
140
140
  hash_type, expected = data
141
141
  d = create_driver(%[
@@ -151,10 +151,10 @@ class ElasticsearchGenidFilterTest < Test::Unit::TestCase
151
151
  d.filtered.map {|e| e.last}.first[d.instance.hash_id_key])
152
152
  end
153
153
 
154
- data("md5" => ["md5", "GJfpWe8ofiGzn97bc9Gh0Q=="],
155
- "sha1" => ["sha1", "AVaK67Tz0bEJ8xNEzjOQ6r9fAu4="],
156
- "sha256" => ["sha256", "WIXWAuf/Z94Uw95mudloo2bgjhSsSduQIwkKTQsNFgU="],
157
- "sha512" => ["sha512", "yjMGGxy8uc7gCrPgm8W6MzJGLFk0GtUwJ6w/91laf6WNywuvG/7T6kNHLagAV8rSW8xzxmtEfyValBO5scuoKw=="],)
154
+ data("md5" => ["md5", "Hb0jwxofNQP+ufQTKK1U4g=="],
155
+ "sha1" => ["sha1", "BakTtlotl/u+yOON6YcViTz6nms="],
156
+ "sha256" => ["sha256", "eLuTCsFqDlk6PfABNyD39r36+yNIBeDTHyNKfJ8fZQw="],
157
+ "sha512" => ["sha512", "PhPCNGalM4H4xT19DnCBnpwr56lbvCo8wJGyCiH9dWcyhn1nA5l1diYSZlF2fNiq1+wzMqfGvJILIjgQrlAPcg=="],)
158
158
  def test_record_with_tag
159
159
  hash_type, expected = data
160
160
  d = create_driver(%[
@@ -171,10 +171,10 @@ class ElasticsearchGenidFilterTest < Test::Unit::TestCase
171
171
  d.filtered.map {|e| e.last}.first[d.instance.hash_id_key])
172
172
  end
173
173
 
174
- data("md5" => ["md5", "5nQSaJ4F1p9rDFign13Lfg=="],
175
- "sha1" => ["sha1", "hyo9+0ZFBpizKl2NShs3C8yQcGw="],
176
- "sha256" => ["sha256", "romVsZSIksbqYsOSnUzolZQw76ankcy0DgvDZ3CayTo="],
177
- "sha512" => ["sha512", "RPU7K2Pt0iVyvV7p5usqcUIIOmfTajD1aa7pkR9qZ89UARH/lpm6ESY9iwuYJj92lxOUuF5OxlEwvV7uXJ07iA=="],)
174
+ data("md5" => ["md5", "C8vfhC4kecNCNutFCuC6MA=="],
175
+ "sha1" => ["sha1", "+YWVqUEL90wpKJRrionUJwNgXHg="],
176
+ "sha256" => ["sha256", "eSqGZqjnO6Uum/4CNfJaolX49+2XKogiGMHGNHiO91Q="],
177
+ "sha512" => ["sha512", "iVmuD0D+i/WtBwNza09ZXSIW8Xg8/yrUwK/M/EZaCMjz/x5FyyCiVkb1VVKsgNnJy0SYt4w21dhHewu1aXM6HA=="],)
178
178
  def test_record_with_time
179
179
  hash_type, expected = data
180
180
  d = create_driver(%[
@@ -191,10 +191,10 @@ class ElasticsearchGenidFilterTest < Test::Unit::TestCase
191
191
  d.filtered.map {|e| e.last}.first[d.instance.hash_id_key])
192
192
  end
193
193
 
194
- data("md5" => ["md5", "zGQF35KlMUibJAcgkgQDtw=="],
195
- "sha1" => ["sha1", "1x9RZO1xEuWps090qq4DUIsU9x8="],
196
- "sha256" => ["sha256", "eulMz0eF56lBEf31aIs0OG2TGCH/aoPfZbRqfEOkAwk="],
197
- "sha512" => ["sha512", "mIiYATtpdUFEFCIZg1FdKssIs7oWY0gJjhSSbet0ddUmqB+CiQAcAMTmrXO6AVSH0vsMvao/8vtC8AsIPfF1fA=="],)
194
+ data("md5" => ["md5", "lU7d4EiF+2M1zxWcsmBbjg=="],
195
+ "sha1" => ["sha1", "nghmz1y3KTEFxalfS2/Oe4n4yfQ="],
196
+ "sha256" => ["sha256", "d0le9UOnUeuGPF/2yEBRM1YzOYeHtxYOE1UU6JgJrvU="],
197
+ "sha512" => ["sha512", "n7rhisGHUBne6c4Cs9DRMbPror8O5Y/vYajDqAtOaiUTys/Z1EKBMnZQA0iVNFw7joX33cenBW3Yyccct3xSew=="],)
198
198
  def test_record_with_tag_and_time
199
199
  hash_type, expected = data
200
200
  d = create_driver(%[
@@ -31,6 +31,19 @@ class ElasticsearchInputTest < Test::Unit::TestCase
31
31
  @driver ||= Fluent::Test::Driver::Input.new(Fluent::Plugin::ElasticsearchInput).configure(conf)
32
32
  end
33
33
 
34
+ def elasticsearch_version
35
+ if Gem::Version.new(TRANSPORT_CLASS::VERSION) >= Gem::Version.new("7.14.0")
36
+ TRANSPORT_CLASS::VERSION
37
+ else
38
+ '7.9.0'.freeze
39
+ end
40
+ end
41
+
42
+ def stub_elastic_info(url="http://localhost:9200/", version=elasticsearch_version)
43
+ body ="{\"version\":{\"number\":\"#{version}\", \"build_flavor\":\"default\"},\"tagline\" : \"You Know, for Search\"}"
44
+ stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json', 'x-elastic-product' => 'Elasticsearch' } })
45
+ end
46
+
34
47
  def sample_response(index_name="fluentd")
35
48
  {
36
49
  "took"=>4,
@@ -322,6 +335,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
322
335
  with(body: "{\"sort\":[\"_doc\"]}").
323
336
  to_return(status: 200, body: sample_response.to_s,
324
337
  headers: {'Content-Type' => 'application/json'})
338
+ stub_elastic_info
325
339
 
326
340
  driver(CONFIG)
327
341
  driver.run(expect_emits: 1, timeout: 10)
@@ -337,6 +351,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
337
351
  with(body: "{\"sort\":[\"_doc\"]}").
338
352
  to_return(status: 200, body: sample_response(index_name).to_s,
339
353
  headers: {'Content-Type' => 'application/json'})
354
+ stub_elastic_info
340
355
 
341
356
  driver(CONFIG + %[index_name #{index_name}])
342
357
  driver.run(expect_emits: 1, timeout: 10)
@@ -352,6 +367,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
352
367
  with(body: "{\"sort\":[\"_doc\"]}").
353
368
  to_return(status: 200, body: sample_response(index_name).to_s,
354
369
  headers: {'Content-Type' => 'application/json'})
370
+ stub_elastic_info
355
371
 
356
372
  driver(CONFIG + %[parse_timestamp])
357
373
  driver.run(expect_emits: 1, timeout: 10)
@@ -370,6 +386,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
370
386
  with(body: "{\"sort\":[\"_doc\"]}").
371
387
  to_return(status: 200, body: sample_response(index_name).to_s,
372
388
  headers: {'Content-Type' => 'application/json'})
389
+ stub_elastic_info
373
390
 
374
391
  driver(CONFIG + %[parse_timestamp true
375
392
  timestamp_key_format %Y-%m-%dT%H:%M:%S.%N%z
@@ -389,6 +406,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
389
406
  with(body: "{\"sort\":[\"_doc\"]}").
390
407
  to_return(status: 200, body: sample_response.to_s,
391
408
  headers: {'Content-Type' => 'application/json'})
409
+ stub_elastic_info
392
410
 
393
411
  driver(CONFIG + %[docinfo true])
394
412
  driver.run(expect_emits: 1, timeout: 10)
@@ -412,6 +430,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
412
430
  with(body: "{\"sort\":[\"_doc\"],\"slice\":{\"id\":1,\"max\":2}}").
413
431
  to_return(status: 200, body: sample_response.to_s,
414
432
  headers: {'Content-Type' => 'application/json'})
433
+ stub_elastic_info
415
434
 
416
435
  driver(CONFIG + %[num_slices 2])
417
436
  driver.run(expect_emits: 1, timeout: 10)
@@ -434,6 +453,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
434
453
  body: "{\"scroll_id\":\"WomkoUKG0QPB679Ulo6TqQgh3pIGRUmrl9qXXGK3EeiQh9rbYNasTkspZQcJ01uz\"}") do
435
454
  connection += 1
436
455
  end
456
+ stub_elastic_info
437
457
  scroll_request.to_return(lambda do |req|
438
458
  if connection <= 1
439
459
  {status: 200, body: sample_scroll_response_2.to_s,