fluent-plugin-input-opensearch 1.2.3 → 1.2.5

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/fluent/plugin/in_opensearch.rb +8 -6
  4. data/lib/fluent/plugin/out_opensearch.rb +5 -1
  5. metadata +5 -55
  6. data/.coveralls.yml +0 -1
  7. data/.editorconfig +0 -9
  8. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -29
  9. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -24
  10. data/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -9
  11. data/.github/workflows/coverage.yaml +0 -22
  12. data/.github/workflows/issue-auto-closer.yml +0 -12
  13. data/.github/workflows/linux.yml +0 -26
  14. data/.github/workflows/macos.yml +0 -26
  15. data/.github/workflows/windows.yml +0 -26
  16. data/.gitignore +0 -18
  17. data/CONTRIBUTING.md +0 -24
  18. data/Gemfile +0 -10
  19. data/History.md +0 -67
  20. data/README.OpenSearchGenID.md +0 -116
  21. data/README.OpenSearchInput.md +0 -396
  22. data/README.Troubleshooting.md +0 -482
  23. data/Rakefile +0 -37
  24. data/fluent-plugin-opensearch.gemspec +0 -39
  25. data/gemfiles/Gemfile.elasticsearch.v6 +0 -12
  26. data/test/helper.rb +0 -60
  27. data/test/plugin/datastream_template.json +0 -4
  28. data/test/plugin/test_alias_template.json +0 -9
  29. data/test/plugin/test_filter_opensearch_genid.rb +0 -241
  30. data/test/plugin/test_in_opensearch.rb +0 -500
  31. data/test/plugin/test_index_alias_template.json +0 -11
  32. data/test/plugin/test_index_template.json +0 -25
  33. data/test/plugin/test_oj_serializer.rb +0 -45
  34. data/test/plugin/test_opensearch_error_handler.rb +0 -770
  35. data/test/plugin/test_opensearch_fallback_selector.rb +0 -100
  36. data/test/plugin/test_opensearch_tls.rb +0 -171
  37. data/test/plugin/test_out_opensearch.rb +0 -3980
  38. data/test/plugin/test_out_opensearch_data_stream.rb +0 -746
  39. data/test/plugin/test_template.json +0 -23
  40. data/test/test_log-ext.rb +0 -61
@@ -1,746 +0,0 @@
1
- require_relative '../helper'
2
- require 'date'
3
- require 'fluent/test/helpers'
4
- require 'fluent/test/driver/output'
5
- require 'flexmock/test_unit'
6
- require 'fluent/plugin/out_opensearch_data_stream'
7
-
8
- class OpenSearchOutputDataStreamTest < Test::Unit::TestCase
9
- include FlexMock::TestCase
10
- include Fluent::Test::Helpers
11
-
12
- attr_accessor :bulk_records, :index_cmds
13
-
14
- OPENSEARCH_DATA_STREAM_TYPE = "opensearch_data_stream"
15
-
16
- def setup
17
- Fluent::Test.setup
18
- @driver = nil
19
- log = Fluent::Engine.log
20
- log.out.logs.slice!(0, log.out.logs.length)
21
- @bulk_records = 0
22
- end
23
-
24
- def driver(conf='', os_version=1, client_version="\"1.0\"")
25
- # For request stub to detect compatibility.
26
- @os_version ||= os_version
27
- @client_version ||= client_version
28
- Fluent::Plugin::OpenSearchOutputDataStream.module_eval(<<-CODE)
29
- def detect_os_major_version
30
- #{@os_version}
31
- end
32
- CODE
33
- @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::OpenSearchOutputDataStream) {
34
- # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
35
- if !defined?(Fluent::Plugin::Output)
36
- def format(tag, time, record)
37
- [time, record].to_msgpack
38
- end
39
- end
40
- }.configure(conf)
41
- end
42
-
43
- def sample_data_stream
44
- {
45
- 'data_streams': [
46
- {
47
- 'name' => 'foo',
48
- 'timestamp_field' => {
49
- 'name' => '@timestamp'
50
- }
51
- }
52
- ]
53
- }
54
- end
55
-
56
- def sample_record
57
- {'@timestamp' => Time.now.iso8601, 'message' => 'Sample record'}
58
- end
59
-
60
- RESPONSE_ACKNOWLEDGED = {"acknowledged": true}
61
- DUPLICATED_DATA_STREAM_EXCEPTION = {"error": {}, "status": 400}
62
- NONEXISTENT_DATA_STREAM_EXCEPTION = {"error": {}, "status": 404}
63
-
64
- def stub_index_template(name="foo_tpl", url="http://localhost:9200")
65
- stub_request(:put, "#{url}/_index_template/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
66
- end
67
-
68
- def stub_data_stream(name="foo", url="localhost:9200")
69
- stub_request(:put, "#{url}/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
70
- end
71
-
72
- def stub_existent_data_stream?(name="foo", url="localhost:9200")
73
- stub_request(:get, "#{url}/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
74
- end
75
-
76
- def stub_existent_template?(name="foo_tpl", url="localhost:9200")
77
- stub_request(:get, "#{url}/_index_template/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
78
- end
79
-
80
- def stub_nonexistent_data_stream?(name="foo", url="localhost:9200")
81
- stub_request(:get, "#{url}/_data_stream/#{name}").to_return(:status => [404, OpenSearch::Transport::Transport::Errors::NotFound])
82
- end
83
-
84
- def stub_nonexistent_template?(name="foo_tpl", url="http://localhost:9200")
85
- stub_request(:get, "#{url}/_index_template/#{name}").to_return(:status => [404, OpenSearch::Transport::Transport::Errors::NotFound])
86
- end
87
-
88
- def stub_nonexistent_template_retry?(name="foo_tpl", url="http://localhost:9200")
89
- stub_request(:get, "#{url}/_index_template/#{name}").
90
- to_return({ status: 500, body: 'Internal Server Error' }, { status: 404, body: '{}' })
91
- end
92
-
93
- def stub_bulk_feed(datastream_name="foo", template_name="foo_tpl", url="http://localhost:9200")
94
- stub_request(:post, "#{url}/#{datastream_name}/_bulk").with do |req|
95
- # bulk data must be pair of OP and records
96
- # {"create": {}}\nhttp://localhost:9200/_data_stream/foo_bar
97
- # {"@timestamp": ...}
98
- @bulk_records += req.body.split("\n").size / 2
99
- @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
100
- end
101
- stub_request(:post, "http://#{url}#{template_name}/_bulk").with do |req|
102
- # bulk data must be pair of OP and records
103
- # {"create": {}}\nhttp://localhost:9200/_data_stream/foo_bar
104
- # {"@timestamp": ...}
105
- @bulk_records += req.body.split("\n").size / 2
106
- @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
107
- end
108
- end
109
-
110
- def stub_opensearch_info(url="http://localhost:9200/", version="1.2.2", headers={})
111
- body ="{\"version\":{\"number\":\"#{version}\", \"distribution\":\"opensearch\"},\"tagline\":\"The OpenSearch Project: https://opensearch.org/\"}"
112
- stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json' }.merge(headers) })
113
- end
114
-
115
- def stub_default(datastream_name="foo", template_name="foo_tpl", host="http://localhost:9200")
116
- stub_opensearch_info(host)
117
- stub_nonexistent_template?(template_name)
118
- stub_index_template(template_name)
119
- stub_nonexistent_data_stream?(datastream_name)
120
- stub_data_stream(datastream_name)
121
- end
122
-
123
- def stub_opensearch_with_store_index_command_counts(url="http://localhost:9200/_bulk")
124
- if @index_command_counts == nil
125
- @index_command_counts = {}
126
- @index_command_counts.default = 0
127
- end
128
-
129
- stub_request(:post, url).with do |req|
130
- index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
131
- @index_command_counts[url] += index_cmds.size
132
- end
133
- end
134
-
135
- # ref. https://opensearch.org/docs/latest/opensearch/data-streams/
136
- class DataStreamNameTest < self
137
-
138
- def test_missing_data_stream_name
139
- conf = config_element(
140
- 'ROOT', '', {
141
- '@type' => 'opensearch_datastream'
142
- })
143
- assert_raise Fluent::ConfigError.new("'data_stream_name' parameter is required") do
144
- driver(conf).run
145
- end
146
- end
147
-
148
- sub_test_case "invalid uppercase" do
149
- def test_stream_name
150
- conf = config_element(
151
- 'ROOT', '', {
152
- '@type' => 'opensearch_datastream',
153
- 'data_stream_name' => 'TEST',
154
- 'data_stream_template_name' => 'template'
155
- })
156
- assert_raise Fluent::ConfigError.new("'data_stream_name' must be lowercase only: <TEST>") do
157
- driver(conf)
158
- end
159
- end
160
- def test_stream_template_name
161
- conf = config_element(
162
- 'ROOT', '', {
163
- '@type' => 'opensearch_datastream',
164
- 'data_stream_name' => 'default',
165
- 'data_stream_template_name' => 'TEST-TPL'
166
- })
167
- assert_raise Fluent::ConfigError.new("'data_stream_template_name' must be lowercase only: <TEST-TPL>") do
168
- driver(conf)
169
- end
170
- end
171
- end
172
-
173
- sub_test_case "invalid parameters" do
174
- data("backslash" => "\\",
175
- "slash" => "/",
176
- "asterisk" => "*",
177
- "question" => "?",
178
- "doublequote" => "\"",
179
- "lt" => "<",
180
- "gt" => ">",
181
- "bar" => "|",
182
- "space" => " ",
183
- "comma" => ",",
184
- "sharp" => "#",
185
- "colon" => ":")
186
- def test_stream_name(data)
187
- c, _ = data
188
- conf = config_element(
189
- 'ROOT', '', {
190
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
191
- 'data_stream_name' => "TEST#{c}",
192
- 'data_stream_template_name' => "data_stream"
193
- })
194
- label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_CHARACTERS.join(',')
195
- assert_raise Fluent::ConfigError.new("'data_stream_name' must not contain invalid characters #{label}: <TEST#{c}>") do
196
- driver(conf)
197
- end
198
- end
199
-
200
- data("backslash" => "\\",
201
- "slash" => "/",
202
- "asterisk" => "*",
203
- "question" => "?",
204
- "doublequote" => "\"",
205
- "lt" => "<",
206
- "gt" => ">",
207
- "bar" => "|",
208
- "space" => " ",
209
- "comma" => ",",
210
- "sharp" => "#",
211
- "colon" => ":")
212
- def test_stream_template_name(data)
213
- c, _ = data
214
- conf = config_element(
215
- 'ROOT', '', {
216
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
217
- 'data_stream_name' => "default",
218
- 'data_stream_template_name' => "TEST#{c}"
219
- })
220
- label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_CHARACTERS.join(',')
221
- assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not contain invalid characters #{label}: <TEST#{c}>") do
222
- driver(conf)
223
- end
224
- end
225
- end
226
-
227
- sub_test_case "invalid start characters" do
228
- data("hyphen" => "-",
229
- "underscore" => "_",
230
- "plus" => "+",
231
- "period" => ".")
232
- def test_stream_name(data)
233
- c, _ = data
234
- conf = config_element(
235
- 'ROOT', '', {
236
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
237
- 'data_stream_name' => "#{c}TEST",
238
- 'data_stream_template_name' => "template"
239
- })
240
- label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_START_CHRACTERS.join(',')
241
- assert_raise Fluent::ConfigError.new("'data_stream_name' must not start with #{label}: <#{c}TEST>") do
242
- driver(conf)
243
- end
244
- end
245
-
246
- data("hyphen" => "-",
247
- "underscore" => "_",
248
- "plus" => "+",
249
- "period" => ".")
250
- def test_stream_template_name(data)
251
- c, _ = data
252
- conf = config_element(
253
- 'ROOT', '', {
254
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
255
- 'data_stream_name' => "default",
256
- 'data_stream_template_name' => "#{c}TEST"
257
- })
258
- label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_START_CHRACTERS.join(',')
259
- assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not start with #{label}: <#{c}TEST>") do
260
- driver(conf)
261
- end
262
- end
263
- end
264
-
265
- sub_test_case "invalid dots" do
266
- data("current" => ".",
267
- "parents" => "..")
268
- def test_stream_name
269
- c, _ = data
270
- conf = config_element(
271
- 'ROOT', '', {
272
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
273
- 'data_stream_name' => "#{c}",
274
- 'data_stream_template_name' => "template"
275
- })
276
- assert_raise Fluent::ConfigError.new("'data_stream_name' must not be . or ..: <#{c}>") do
277
- driver(conf)
278
- end
279
- end
280
-
281
- data("current" => ".",
282
- "parents" => "..")
283
- def test_stream_template_name
284
- c, _ = data
285
- conf = config_element(
286
- 'ROOT', '', {
287
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
288
- 'data_stream_name' => "default",
289
- 'data_stream_template_name' => "#{c}"
290
- })
291
- assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not be . or ..: <#{c}>") do
292
- driver(conf)
293
- end
294
- end
295
- end
296
-
297
- sub_test_case "invalid length" do
298
- def test_stream_name
299
- c = "a" * 256
300
- conf = config_element(
301
- 'ROOT', '', {
302
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
303
- 'data_stream_name' => "#{c}",
304
- 'data_stream_template_name' => "template"
305
- })
306
- assert_raise Fluent::ConfigError.new("'data_stream_name' must not be longer than 255 bytes: <#{c}>") do
307
- driver(conf)
308
- end
309
- end
310
-
311
- def test_stream_template_name
312
- c = "a" * 256
313
- conf = config_element(
314
- 'ROOT', '', {
315
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
316
- 'data_stream_name' => "default",
317
- 'data_stream_template_name' => "#{c}"
318
- })
319
- assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not be longer than 255 bytes: <#{c}>") do
320
- driver(conf)
321
- end
322
- end
323
- end
324
- end
325
-
326
- def test_datastream_configure
327
- stub_default
328
- conf = config_element(
329
- 'ROOT', '', {
330
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
331
- 'data_stream_name' => 'foo',
332
- 'data_stream_template_name' => "foo_tpl"
333
- })
334
- assert_equal "foo", driver(conf).instance.data_stream_name
335
- end
336
-
337
- def test_hosts_list_configure
338
- config = %{
339
- hosts https://john:password@host1:443/elastic/,http://host2
340
- path /default_path
341
- user default_user
342
- password default_password
343
- data_stream_name default
344
- }
345
- stub_opensearch_info("https://host1:443/elastic//", "1.2.2",
346
- {'Authorization'=>"Basic #{Base64.encode64('john:password').split.first}"})
347
- stub_opensearch_info("http://host2/default_path/_data_stream/default", "1.2.2",
348
- {'Authorization'=>"Basic #{Base64.encode64('john:password').split.first}"})
349
- stub_existent_data_stream?("default", "https://host1/elastic/")
350
- instance = driver(config).instance
351
-
352
- assert_equal 2, instance.get_connection_options[:hosts].length
353
- host1, host2 = instance.get_connection_options[:hosts]
354
-
355
- assert_equal 'host1', host1[:host]
356
- assert_equal 443, host1[:port]
357
- assert_equal 'https', host1[:scheme]
358
- assert_equal 'john', host1[:user]
359
- assert_equal 'password', host1[:password]
360
- assert_equal '/elastic/', host1[:path]
361
-
362
- assert_equal 'host2', host2[:host]
363
- assert_equal 'http', host2[:scheme]
364
- assert_equal 'default_user', host2[:user]
365
- assert_equal 'default_password', host2[:password]
366
- assert_equal '/default_path', host2[:path]
367
- end
368
-
369
- def test_datastream_configure_retry
370
- stub_opensearch_info
371
- stub_nonexistent_template_retry?
372
- stub_index_template
373
- stub_nonexistent_data_stream?
374
- stub_data_stream
375
- conf = config_element(
376
- 'ROOT', '', {
377
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
378
- 'data_stream_name' => 'foo',
379
- 'data_stream_template_name' => "foo_tpl"
380
- })
381
- assert_equal "foo", driver(conf).instance.data_stream_name
382
- end
383
-
384
- def test_template_file
385
- stub_default
386
- cwd = File.dirname(__FILE__)
387
- conf = config_element(
388
- 'ROOT', '', {
389
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
390
- 'data_stream_name' => 'foo',
391
- 'data_stream_template_name' => "foo_tpl",
392
- 'template_file' => File.join(cwd, 'datastream_template.json')
393
- })
394
- assert_equal "foo", driver(conf).instance.data_stream_name
395
- end
396
-
397
- def test_existent_data_stream
398
- stub_index_template
399
- stub_existent_data_stream?
400
- stub_data_stream
401
- stub_opensearch_info
402
- conf = config_element(
403
- 'ROOT', '', {
404
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
405
- 'data_stream_name' => 'foo',
406
- 'data_stream_template_name' => "foo_tpl"
407
- })
408
- assert_equal "foo", driver(conf).instance.data_stream_name
409
- end
410
-
411
- def test_template_unset
412
- stub_index_template
413
- stub_existent_data_stream?
414
- stub_data_stream
415
- stub_opensearch_info
416
- conf = config_element(
417
- 'ROOT', '', {
418
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
419
- 'data_stream_name' => 'foo',
420
- })
421
- assert_equal "foo", driver(conf).instance.data_stream_name
422
- assert_equal "foo_template", driver(conf).instance.data_stream_template_name
423
- end
424
-
425
- def test_placeholder
426
- dsname = "foo_test"
427
- tplname = "foo_tpl_test"
428
- stub_default(dsname, tplname)
429
- stub_bulk_feed(dsname, tplname)
430
- conf = config_element(
431
- 'ROOT', '', {
432
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
433
- 'data_stream_name' => 'foo_${tag}',
434
- 'data_stream_template_name' => "foo_tpl_${tag}"
435
- })
436
- driver(conf).run(default_tag: 'test') do
437
- driver.feed(sample_record)
438
- end
439
- assert_equal 1, @bulk_records
440
- end
441
-
442
- def test_placeholder_with_capital_letters
443
- dsname = "foo_test.capital_letters"
444
- tplname = "foo_tpl_test.capital_letters"
445
- stub_default(dsname, tplname)
446
- stub_bulk_feed(dsname, tplname)
447
- conf = config_element(
448
- 'ROOT', '', {
449
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
450
- 'data_stream_name' => 'foo_${tag}',
451
- 'data_stream_template_name' => "foo_tpl_${tag}"
452
- })
453
- driver(conf).run(default_tag: 'TEST.CAPITAL_LETTERS') do
454
- driver.feed(sample_record)
455
- end
456
- assert_equal 1, @bulk_records
457
- end
458
-
459
- def test_placeholder_params_unset
460
- dsname = "foo_test"
461
- tplname = "foo_test_template"
462
- stub_default(dsname, tplname)
463
- stub_bulk_feed(dsname, tplname)
464
- conf = config_element(
465
- 'ROOT', '', {
466
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
467
- 'data_stream_name' => 'foo_${tag}',
468
- })
469
- driver(conf).run(default_tag: 'test') do
470
- driver.feed(sample_record)
471
- end
472
- assert_equal 1, @bulk_records
473
- end
474
-
475
-
476
- def test_time_placeholder
477
- time = Time.now
478
- dsname = "foo_#{time.strftime("%Y%m%d")}"
479
- tplname = "foo_tpl_#{time.strftime("%Y%m%d")}"
480
- stub_default(dsname, tplname)
481
- stub_bulk_feed(dsname, tplname)
482
- conf = config_element(
483
- 'ROOT', '', {
484
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
485
- 'data_stream_name' => 'foo_%Y%m%d',
486
- 'data_stream_template_name' => 'foo_tpl_%Y%m%d'
487
- }, [config_element('buffer', 'time', {
488
- 'timekey' => '1d'
489
- }, [])]
490
- )
491
- driver(conf).run(default_tag: 'test') do
492
- driver.feed(sample_record)
493
- end
494
- assert_equal 1, @bulk_records
495
- end
496
-
497
- def test_custom_record_placeholder
498
- keys = ["bar", "baz"]
499
- keys.each do |key|
500
- dsname = "foo_#{key}"
501
- tplname = "foo_tpl_#{key}"
502
- stub_default(dsname, tplname)
503
- stub_bulk_feed(dsname, tplname)
504
- end
505
- conf = config_element(
506
- 'ROOT', '', {
507
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
508
- 'data_stream_name' => 'foo_${key1}',
509
- 'data_stream_template_name' => 'foo_tpl_${key1}'
510
- }, [config_element('buffer', 'tag,key1', {
511
- 'timekey' => '1d'
512
- }, [])]
513
- )
514
- driver(conf).run(default_tag: 'test') do
515
- keys.each do |key|
516
- record = sample_record.merge({"key1" => key})
517
- driver.feed(record)
518
- end
519
- end
520
- assert_equal keys.count, @bulk_records
521
- end
522
-
523
- def test_bulk_insert_feed
524
- stub_default
525
- stub_bulk_feed
526
- conf = config_element(
527
- 'ROOT', '', {
528
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
529
- 'data_stream_name' => 'foo',
530
- 'data_stream_template_name' => 'foo_tpl'
531
- })
532
- driver(conf).run(default_tag: 'test') do
533
- driver.feed(sample_record)
534
- end
535
- assert_equal 1, @bulk_records
536
- end
537
-
538
- def test_placeholder_writes_to_multi_hosts
539
- stub_default("foo_bar", "foo_tpl_bar")
540
- hosts = [['192.168.33.50', 9201], ['192.168.33.51', 9201], ['192.168.33.52', 9201]]
541
- hosts_string = hosts.map {|x| "#{x[0]}:#{x[1]}"}.compact.join(',')
542
- hosts.each do |host_info|
543
- host, port = host_info
544
- stub_opensearch_with_store_index_command_counts("http://#{host}:#{port}/foo_bar/_bulk")
545
- stub_opensearch_info("http://#{host}:#{port}/")
546
- stub_request(:get, "http://#{host}:#{port}/_data_stream/foo_bar").
547
- to_return(status: 200, body: "", headers: {})
548
- end
549
-
550
- conf = config_element(
551
- 'ROOT', '', {
552
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
553
- 'data_stream_name' => 'foo_${key1}',
554
- 'data_stream_template_name' => 'foo_tpl_${key1}',
555
- 'hosts' => "#{hosts_string}"
556
- }, [config_element('buffer', 'tag,key1', {
557
- 'timekey' => '1d'
558
- }, [])])
559
- driver(conf).run(default_tag: 'test') do
560
- hashes = {
561
- 'age' => rand(100),
562
- 'key1' => 'bar'
563
- }
564
- 1000.times do
565
- driver.feed(sample_record.merge(hashes))
566
- end
567
- end
568
-
569
- # @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
570
- # it's Fluentd test driver's constraint
571
- # so @index_command_counts.size is always 1
572
- assert(@index_command_counts.size > 0, "not working with hosts options")
573
-
574
- total = 0
575
- @index_command_counts.each do |_, count|
576
- total += count
577
- end
578
- assert_equal(2000, total)
579
- end
580
-
581
- def test_template_retry_install_fails
582
- cwd = File.dirname(__FILE__)
583
- template_file = File.join(cwd, 'test_index_template.json')
584
-
585
- config = %{
586
- host logs.google.com
587
- port 778
588
- scheme https
589
- data_stream_name foo
590
- data_stream_template_name foo_tpl
591
- user john
592
- password doe
593
- template_name logstash
594
- template_file #{template_file}
595
- max_retry_putting_template 3
596
- }
597
-
598
- connection_resets = 0
599
- # check if template exists
600
- stub_request(:get, "https://logs.google.com:778/_index_template/logstash")
601
- .with(basic_auth: ['john', 'doe']) do |req|
602
- connection_resets += 1
603
- raise Faraday::ConnectionFailed, "Test message"
604
- end
605
- stub_opensearch_info("https://logs.google.com:778/")
606
-
607
- assert_raise(Fluent::Plugin::OpenSearchError::RetryableOperationExhaustedFailure) do
608
- driver(config)
609
- end
610
-
611
- assert_equal(4, connection_resets)
612
- end
613
-
614
- def test_uses_custom_time_key
615
- stub_default
616
- stub_bulk_feed
617
- conf = config_element(
618
- 'ROOT', '', {
619
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
620
- 'data_stream_name' => 'foo',
621
- 'data_stream_template_name' => 'foo_tpl',
622
- 'time_key' => 'vtm'
623
- })
624
-
625
- ts = DateTime.new(2021,2,3).iso8601(9)
626
- record = {
627
- 'vtm' => ts,
628
- 'message' => 'Sample Record'
629
- }
630
-
631
- driver(conf).run(default_tag: 'test') do
632
- driver.feed(record)
633
- end
634
- assert(index_cmds[1].has_key? '@timestamp')
635
- assert_equal(ts, index_cmds[1]['@timestamp'])
636
- end
637
-
638
- def test_uses_custom_time_key_with_format
639
- stub_default
640
- stub_bulk_feed
641
- conf = config_element(
642
- 'ROOT', '', {
643
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
644
- 'data_stream_name' => 'foo',
645
- 'data_stream_template_name' => 'foo_tpl',
646
- 'time_key' => 'vtm',
647
- 'time_key_format' => '%Y-%m-%d %H:%M:%S.%N%z'
648
- })
649
- ts = "2021-02-03 13:14:01.673+02:00"
650
- record = {
651
- 'vtm' => ts,
652
- 'message' => 'Sample Record'
653
- }
654
- driver(conf).run(default_tag: 'test') do
655
- driver.feed(record)
656
- end
657
- assert(index_cmds[1].has_key? '@timestamp')
658
- assert_equal(DateTime.parse(ts).iso8601(9), index_cmds[1]['@timestamp'])
659
- end
660
-
661
- def test_record_no_timestamp
662
- stub_default
663
- stub_bulk_feed
664
- stub_default
665
- stub_bulk_feed
666
- conf = config_element(
667
- 'ROOT', '', {
668
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
669
- 'data_stream_name' => 'foo',
670
- 'data_stream_template_name' => 'foo_tpl'
671
- })
672
- record = {
673
- 'message' => 'Sample Record'
674
- }
675
- driver(conf).run(default_tag: 'test') do
676
- driver.feed(record)
677
- end
678
- assert(index_cmds[1].has_key? '@timestamp')
679
- end
680
-
681
- def test_record_with_include_tag_key
682
- stub_default
683
- stub_bulk_feed
684
- stub_default
685
- stub_bulk_feed
686
- conf = config_element(
687
- 'ROOT', '', {
688
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
689
- 'data_stream_name' => 'foo',
690
- 'data_stream_template_name' => 'foo_tpl',
691
- 'include_tag_key' => true,
692
- 'tag_key' => 'test_tag'
693
- })
694
- record = {
695
- 'message' => 'Sample Record'
696
- }
697
- driver(conf).run(default_tag: 'test') do
698
- driver.feed(record)
699
- end
700
- assert(index_cmds[1].has_key?('test_tag'))
701
- end
702
-
703
- def test_record_without_include_tag_key
704
- stub_default
705
- stub_bulk_feed
706
- stub_default
707
- stub_bulk_feed
708
- conf = config_element(
709
- 'ROOT', '', {
710
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
711
- 'data_stream_name' => 'foo',
712
- 'data_stream_template_name' => 'foo_tpl',
713
- 'include_tag_key' => false
714
- })
715
- record = {
716
- 'message' => 'Sample Record'
717
- }
718
- driver(conf).run(default_tag: 'test') do
719
- driver.feed(record)
720
- end
721
- assert(!index_cmds[1].has_key?('test'))
722
- end
723
-
724
- def test_record_with_remove_keys
725
- stub_default
726
- stub_bulk_feed
727
- stub_default
728
- stub_bulk_feed
729
- conf = config_element(
730
- 'ROOT', '', {
731
- '@type' => OPENSEARCH_DATA_STREAM_TYPE,
732
- 'data_stream_name' => 'foo',
733
- 'data_stream_template_name' => 'foo_tpl',
734
- 'remove_keys' => 'remove_me'
735
- })
736
- record = {
737
- 'message' => 'Sample Record',
738
- 'remove_me' => 'foo'
739
- }
740
- driver(conf).run(default_tag: 'test') do
741
- driver.feed(record)
742
- end
743
- assert(!index_cmds[1].has_key?('remove_me'))
744
- end
745
-
746
- end