fluent-plugin-elasticsearch2 3.5.5 → 3.5.6

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.
@@ -1,1001 +1,1001 @@
1
- require 'helper'
2
- require 'date'
3
- require 'fluent/test/helpers'
4
- require 'fluent/test/driver/output'
5
- require 'flexmock/test_unit'
6
-
7
- class ElasticsearchOutputDynamic < Test::Unit::TestCase
8
- include FlexMock::TestCase
9
- include Fluent::Test::Helpers
10
-
11
- attr_accessor :index_cmds, :index_command_counts
12
-
13
- def setup
14
- Fluent::Test.setup
15
- require 'fluent/plugin/out_elasticsearch_dynamic'
16
- @driver = nil
17
- end
18
-
19
- def driver(conf='', es_version=5)
20
- # For request stub to detect compatibility.
21
- @es_version ||= es_version
22
- Fluent::Plugin::ElasticsearchOutputDynamic.module_eval(<<-CODE)
23
- def detect_es_major_version
24
- #{@es_version}
25
- end
26
- CODE
27
- @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDynamic) {
28
- # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
29
- if !defined?(Fluent::Plugin::Output)
30
- def format(tag, time, record)
31
- [time, record].to_msgpack
32
- end
33
- end
34
- }.configure(conf)
35
- end
36
-
37
- def default_type_name
38
- Fluent::Plugin::ElasticsearchOutput::DEFAULT_TYPE_NAME
39
- end
40
-
41
- def sample_record
42
- {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
43
- end
44
-
45
- def nested_sample_record
46
- {'nested' =>
47
- {'age' => 26, 'parent_id' => 'parent', 'routing_id' => 'routing', 'request_id' => '42'}
48
- }
49
- end
50
-
51
- def stub_elastic(url="http://localhost:9200/_bulk")
52
- stub_request(:post, url).with do |req|
53
- @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
54
- end
55
- end
56
-
57
- def stub_elastic_unavailable(url="http://localhost:9200/_bulk")
58
- stub_request(:post, url).to_return(:status => [503, "Service Unavailable"])
59
- end
60
-
61
- def stub_elastic_timeout(url="http://localhost:9200/_bulk")
62
- stub_request(:post, url).to_timeout
63
- end
64
-
65
- def stub_elastic_with_store_index_command_counts(url="http://localhost:9200/_bulk")
66
- if @index_command_counts == nil
67
- @index_command_counts = {}
68
- @index_command_counts.default = 0
69
- end
70
-
71
- stub_request(:post, url).with do |req|
72
- index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
73
- @index_command_counts[url] += index_cmds.size
74
- end
75
- end
76
-
77
- def assert_logs_include(logs, msg, exp_matches=1)
78
- matches = logs.grep /#{msg}/
79
- assert_equal(exp_matches, matches.length, "Logs do not contain '#{msg}' '#{logs}'")
80
- end
81
-
82
- def test_configure
83
- config = %{
84
- host logs.google.com
85
- port 777
86
- scheme https
87
- path /es/
88
- user john
89
- password doe
90
- }
91
- instance = driver(config).instance
92
-
93
- conf = instance.dynamic_config
94
- assert_equal 'logs.google.com', conf['host']
95
- assert_equal "777", conf['port']
96
- assert_equal :https, instance.scheme
97
- assert_equal 'john', instance.user
98
- assert_equal 'doe', instance.password
99
- assert_equal '/es/', instance.path
100
- assert_equal :TLSv1, instance.ssl_version
101
- assert_nil instance.client_key
102
- assert_nil instance.client_cert
103
- assert_nil instance.client_key_pass
104
- assert_false instance.with_transporter_log
105
- assert_equal :"application/json", instance.content_type
106
- assert_equal :excon, instance.http_backend
107
- end
108
-
109
- test 'configure Content-Type' do
110
- config = %{
111
- content_type application/x-ndjson
112
- }
113
- instance = driver(config).instance
114
- assert_equal :"application/x-ndjson", instance.content_type
115
- end
116
-
117
- test 'invalid Content-Type' do
118
- config = %{
119
- content_type nonexistent/invalid
120
- }
121
- assert_raise(Fluent::ConfigError) {
122
- driver(config)
123
- }
124
- end
125
-
126
- test 'Detected Elasticsearch 7' do
127
- config = %{
128
- type_name changed
129
- }
130
- instance = driver(config, 7).instance
131
- assert_equal '_doc', instance.type_name
132
- end
133
-
134
- sub_test_case 'connection exceptions' do
135
- test 'default connection exception' do
136
- driver(Fluent::Config::Element.new(
137
- 'ROOT', '', {
138
- '@type' => 'elasticsearch',
139
- 'host' => 'log.google.com',
140
- 'port' => 777,
141
- 'scheme' => 'https',
142
- 'path' => '/es/',
143
- 'user' => 'john',
144
- 'password' => 'doe',
145
- }, [
146
- Fluent::Config::Element.new('buffer', 'tag', {
147
- }, [])
148
- ]
149
- ))
150
- logs = driver.logs
151
- assert_logs_include(logs, /you should specify 2 or more 'flush_thread_count'/, 1)
152
- end
153
- end
154
-
155
- def test_defaults
156
- config = %{
157
- host logs.google.com
158
- scheme https
159
- path /es/
160
- user john
161
- password doe
162
- }
163
- instance = driver(config).instance
164
-
165
- conf = instance.dynamic_config
166
- assert_equal "9200", conf['port']
167
- assert_equal "false", conf['logstash_format']
168
- assert_equal "true", conf['utc_index']
169
- assert_equal false, instance.time_key_exclude_timestamp
170
- end
171
-
172
- def test_legacy_hosts_list
173
- config = %{
174
- hosts host1:50,host2:100,host3
175
- scheme https
176
- path /es/
177
- port 123
178
- }
179
- instance = driver(config).instance
180
-
181
- assert_equal 3, instance.get_connection_options(nil)[:hosts].length
182
- host1, host2, host3 = instance.get_connection_options(nil)[:hosts]
183
-
184
- assert_equal 'host1', host1[:host]
185
- assert_equal 50, host1[:port]
186
- assert_equal 'https', host1[:scheme]
187
- assert_equal '/es/', host2[:path]
188
- assert_equal 'host3', host3[:host]
189
- assert_equal 123, host3[:port]
190
- assert_equal 'https', host3[:scheme]
191
- assert_equal '/es/', host3[:path]
192
- end
193
-
194
- def test_hosts_list
195
- config = %{
196
- hosts https://john:password@host1:443/elastic/,http://host2
197
- path /default_path
198
- user default_user
199
- password default_password
200
- }
201
- instance = driver(config).instance
202
-
203
- assert_equal 2, instance.get_connection_options(nil)[:hosts].length
204
- host1, host2 = instance.get_connection_options(nil)[:hosts]
205
-
206
- assert_equal 'host1', host1[:host]
207
- assert_equal 443, host1[:port]
208
- assert_equal 'https', host1[:scheme]
209
- assert_equal 'john', host1[:user]
210
- assert_equal 'password', host1[:password]
211
- assert_equal '/elastic/', host1[:path]
212
-
213
- assert_equal 'host2', host2[:host]
214
- assert_equal 'http', host2[:scheme]
215
- assert_equal 'default_user', host2[:user]
216
- assert_equal 'default_password', host2[:password]
217
- assert_equal '/default_path', host2[:path]
218
- end
219
-
220
- def test_hosts_list_with_escape_placeholders
221
- config = %{
222
- hosts https://%{j+hn}:%{passw@rd}@host1:443/elastic/,http://host2
223
- path /default_path
224
- user default_user
225
- password default_password
226
- }
227
- instance = driver(config).instance
228
-
229
- assert_equal 2, instance.get_connection_options(nil)[:hosts].length
230
- host1, host2 = instance.get_connection_options(nil)[:hosts]
231
-
232
- assert_equal 'host1', host1[:host]
233
- assert_equal 443, host1[:port]
234
- assert_equal 'https', host1[:scheme]
235
- assert_equal 'j%2Bhn', host1[:user]
236
- assert_equal 'passw%40rd', host1[:password]
237
- assert_equal '/elastic/', host1[:path]
238
-
239
- assert_equal 'host2', host2[:host]
240
- assert_equal 'http', host2[:scheme]
241
- assert_equal 'default_user', host2[:user]
242
- assert_equal 'default_password', host2[:password]
243
- assert_equal '/default_path', host2[:path]
244
- end
245
-
246
- def test_single_host_params_and_defaults
247
- config = %{
248
- host logs.google.com
249
- user john
250
- password doe
251
- }
252
- instance = driver(config).instance
253
-
254
- assert_equal 1, instance.get_connection_options(nil)[:hosts].length
255
- host1 = instance.get_connection_options(nil)[:hosts][0]
256
-
257
- assert_equal 'logs.google.com', host1[:host]
258
- assert_equal 9200, host1[:port]
259
- assert_equal 'http', host1[:scheme]
260
- assert_equal 'john', host1[:user]
261
- assert_equal 'doe', host1[:password]
262
- assert_equal nil, host1[:path]
263
- end
264
-
265
- def test_single_host_params_and_defaults_with_escape_placeholders
266
- config = %{
267
- host logs.google.com
268
- user %{j+hn}
269
- password %{d@e}
270
- }
271
- instance = driver(config).instance
272
-
273
- assert_equal 1, instance.get_connection_options(nil)[:hosts].length
274
- host1 = instance.get_connection_options(nil)[:hosts][0]
275
-
276
- assert_equal 'logs.google.com', host1[:host]
277
- assert_equal 9200, host1[:port]
278
- assert_equal 'http', host1[:scheme]
279
- assert_equal 'j%2Bhn', host1[:user]
280
- assert_equal 'd%40e', host1[:password]
281
- assert_equal nil, host1[:path]
282
- end
283
-
284
- def test_content_type_header
285
- stub_request(:head, "http://localhost:9200/").
286
- to_return(:status => 200, :body => "", :headers => {})
287
- if Elasticsearch::VERSION >= "6.0.2"
288
- elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
289
- with(headers: { "Content-Type" => "application/x-ndjson" })
290
- else
291
- elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
292
- with(headers: { "Content-Type" => "application/json" })
293
- end
294
- driver.run(default_tag: 'test') do
295
- driver.feed(sample_record)
296
- end
297
- assert_requested(elastic_request)
298
- end
299
-
300
- def test_writes_to_default_index
301
- stub_elastic
302
- driver.run(default_tag: 'test') do
303
- driver.feed(sample_record)
304
- end
305
- assert_equal('fluentd', index_cmds.first['index']['_index'])
306
- end
307
-
308
- def test_writes_to_default_type
309
- stub_elastic
310
- driver.run(default_tag: 'test') do
311
- driver.feed(sample_record)
312
- end
313
- assert_equal(default_type_name, index_cmds.first['index']['_type'])
314
- end
315
-
316
- def test_writes_to_specified_index
317
- driver.configure("index_name myindex\n")
318
- stub_elastic
319
- driver.run(default_tag: 'test') do
320
- driver.feed(sample_record)
321
- end
322
- assert_equal('myindex', index_cmds.first['index']['_index'])
323
- end
324
-
325
- def test_writes_to_specified_index_uppercase
326
- driver.configure("index_name MyIndex\n")
327
- stub_elastic
328
- driver.run(default_tag: 'test') do
329
- driver.feed(sample_record)
330
- end
331
- assert_equal('myindex', index_cmds.first['index']['_index'])
332
- end
333
-
334
- def test_writes_to_specified_type
335
- driver.configure("type_name mytype\n")
336
- stub_elastic
337
- driver.run(default_tag: 'test') do
338
- driver.feed(sample_record)
339
- end
340
- assert_equal('mytype', index_cmds.first['index']['_type'])
341
- end
342
-
343
- def test_writes_to_specified_host
344
- driver.configure("host 192.168.33.50\n")
345
- elastic_request = stub_elastic("http://192.168.33.50:9200/_bulk")
346
- driver.run(default_tag: 'test') do
347
- driver.feed(sample_record)
348
- end
349
- assert_requested(elastic_request)
350
- end
351
-
352
- def test_writes_to_specified_port
353
- driver.configure("port 9201\n")
354
- elastic_request = stub_elastic("http://localhost:9201/_bulk")
355
- driver.run(default_tag: 'test') do
356
- driver.feed(sample_record)
357
- end
358
- assert_requested(elastic_request)
359
- end
360
-
361
- def test_writes_to_multi_hosts
362
- hosts = [['192.168.33.50', 9201], ['192.168.33.51', 9201], ['192.168.33.52', 9201]]
363
- hosts_string = hosts.map {|x| "#{x[0]}:#{x[1]}"}.compact.join(',')
364
-
365
- driver.configure("hosts #{hosts_string}")
366
-
367
- hosts.each do |host_info|
368
- host, port = host_info
369
- stub_elastic_with_store_index_command_counts("http://#{host}:#{port}/_bulk")
370
- end
371
-
372
- driver.run(default_tag: 'test') do
373
- 1000.times do
374
- driver.feed(sample_record.merge('age'=>rand(100)))
375
- end
376
- end
377
- # @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
378
- # it's Fluentd test driver's constraint
379
- # so @index_command_counts.size is always 1
380
-
381
- assert(@index_command_counts.size > 0, "not working with hosts options")
382
-
383
- total = 0
384
- @index_command_counts.each do |url, count|
385
- total += count
386
- end
387
- assert_equal(2000, total)
388
- end
389
-
390
- def test_makes_bulk_request
391
- stub_elastic
392
- driver.run(default_tag: 'test') do
393
- driver.feed(sample_record)
394
- driver.feed(sample_record.merge('age' => 27))
395
- end
396
- assert_equal(4, index_cmds.count)
397
- end
398
-
399
- def test_all_records_are_preserved_in_bulk
400
- stub_elastic
401
- driver.run(default_tag: 'test') do
402
- driver.feed(sample_record)
403
- driver.feed(sample_record.merge('age' => 27))
404
- end
405
- assert_equal(26, index_cmds[1]['age'])
406
- assert_equal(27, index_cmds[3]['age'])
407
- end
408
-
409
- def test_writes_to_logstash_index
410
- driver.configure("logstash_format true\n")
411
- time = Time.parse Date.today.iso8601
412
- logstash_index = "logstash-#{time.getutc.strftime("%Y.%m.%d")}"
413
- stub_elastic
414
- driver.run(default_tag: 'test') do
415
- driver.feed(time.to_i, sample_record)
416
- end
417
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
418
- end
419
-
420
- def test_writes_to_logstash_utc_index
421
- driver.configure("logstash_format true
422
- utc_index false")
423
- time = Time.parse Date.today.iso8601
424
- utc_index = "logstash-#{time.strftime("%Y.%m.%d")}"
425
- stub_elastic
426
- driver.run(default_tag: 'test') do
427
- driver.feed(time.to_i, sample_record)
428
- end
429
- assert_equal(utc_index, index_cmds.first['index']['_index'])
430
- end
431
-
432
- def test_writes_to_logstash_index_with_specified_prefix
433
- driver.configure("logstash_format true
434
- logstash_prefix myprefix")
435
- time = Time.parse Date.today.iso8601
436
- logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
437
- stub_elastic
438
- driver.run(default_tag: 'test') do
439
- driver.feed(time.to_i, sample_record)
440
- end
441
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
442
- end
443
-
444
- def test_writes_to_logstash_index_with_specified_prefix_and_separator
445
- separator = '_'
446
- driver.configure("logstash_format true
447
- logstash_prefix_separator #{separator}
448
- logstash_prefix myprefix")
449
- time = Time.parse Date.today.iso8601
450
- logstash_index = "myprefix#{separator}#{time.getutc.strftime("%Y.%m.%d")}"
451
- stub_elastic
452
- driver.run(default_tag: 'test') do
453
- driver.feed(time.to_i, sample_record)
454
- end
455
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
456
- end
457
-
458
- def test_writes_to_logstash_index_with_specified_prefix_uppercase
459
- driver.configure("logstash_format true
460
- logstash_prefix MyPrefix")
461
- time = Time.parse Date.today.iso8601
462
- logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
463
- stub_elastic
464
- driver.run(default_tag: 'test') do
465
- driver.feed(time.to_i, sample_record)
466
- end
467
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
468
- end
469
-
470
- def test_writes_to_logstash_index_with_specified_dateformat
471
- driver.configure("logstash_format true
472
- logstash_dateformat %Y.%m")
473
- time = Time.parse Date.today.iso8601
474
- logstash_index = "logstash-#{time.getutc.strftime("%Y.%m")}"
475
- stub_elastic
476
- driver.run(default_tag: 'test') do
477
- driver.feed(time.to_i, sample_record)
478
- end
479
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
480
- end
481
-
482
- def test_writes_to_logstash_index_with_specified_prefix_and_dateformat
483
- driver.configure("logstash_format true
484
- logstash_prefix myprefix
485
- logstash_dateformat %Y.%m")
486
- time = Time.parse Date.today.iso8601
487
- logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m")}"
488
- stub_elastic
489
- driver.run(default_tag: 'test') do
490
- driver.feed(time.to_i, sample_record)
491
- end
492
- assert_equal(logstash_index, index_cmds.first['index']['_index'])
493
- end
494
-
495
- def test_doesnt_add_logstash_timestamp_by_default
496
- stub_elastic
497
- driver.run(default_tag: 'test') do
498
- driver.feed(sample_record)
499
- end
500
- assert_nil(index_cmds[1]['@timestamp'])
501
- end
502
-
503
- def test_adds_logstash_timestamp_when_configured
504
- driver.configure("logstash_format true\n")
505
- stub_elastic
506
- time = Fluent::EventTime.new(Time.now.to_i, 123456789)
507
- driver.run(default_tag: 'test') do
508
- driver.feed(time, sample_record)
509
- end
510
- assert(index_cmds[1].has_key? '@timestamp')
511
- assert_equal(Time.at(time).iso8601(9), index_cmds[1]['@timestamp'])
512
- end
513
-
514
- def test_uses_subsecond_precision_when_configured
515
- driver.configure("logstash_format true
516
- time_precision 3\n")
517
- stub_elastic
518
- time = Fluent::EventTime.new(Time.now.to_i, 123456789)
519
- driver.run(default_tag: 'test') do
520
- driver.feed(time, sample_record)
521
- end
522
- assert(index_cmds[1].has_key? '@timestamp')
523
- assert_equal(Time.at(time).iso8601(3), index_cmds[1]['@timestamp'])
524
- end
525
-
526
- def test_uses_custom_timestamp_when_included_in_record
527
- driver.configure("include_timestamp true\n")
528
- stub_elastic
529
- ts = DateTime.new(2001,2,3).iso8601
530
- driver.run(default_tag: 'test') do
531
- driver.feed(sample_record.merge!('@timestamp' => ts))
532
- end
533
- assert(index_cmds[1].has_key? '@timestamp')
534
- assert_equal(ts, index_cmds[1]['@timestamp'])
535
- end
536
-
537
- def test_uses_custom_timestamp_when_included_in_record_logstash
538
- driver.configure("logstash_format true\n")
539
- stub_elastic
540
- ts = DateTime.new(2001,2,3).iso8601
541
- driver.run(default_tag: 'test') do
542
- driver.feed(sample_record.merge!('@timestamp' => ts))
543
- end
544
- assert(index_cmds[1].has_key? '@timestamp')
545
- assert_equal(ts, index_cmds[1]['@timestamp'])
546
- end
547
-
548
- def test_uses_custom_time_key_logstash
549
- driver.configure("logstash_format true
550
- time_key vtm\n")
551
- stub_elastic
552
- ts = DateTime.new(2001,2,3).iso8601
553
- driver.run(default_tag: 'test') do
554
- driver.feed(sample_record.merge!('vtm' => ts))
555
- end
556
- assert(index_cmds[1].has_key? '@timestamp')
557
- assert_equal(ts, index_cmds[1]['@timestamp'])
558
- end
559
-
560
- def test_uses_custom_time_key_timestamp
561
- driver.configure("include_timestamp true
562
- time_key vtm\n")
563
- stub_elastic
564
- ts = DateTime.new(2001,2,3).iso8601
565
- driver.run(default_tag: 'test') do
566
- driver.feed(sample_record.merge!('vtm' => ts))
567
- end
568
- assert(index_cmds[1].has_key? '@timestamp')
569
- assert_equal(ts, index_cmds[1]['@timestamp'])
570
- end
571
-
572
- def test_uses_custom_time_key_timestamp_custom_index
573
- driver.configure("include_timestamp true
574
- index_name test
575
- time_key vtm\n")
576
- stub_elastic
577
- ts = DateTime.new(2001,2,3).iso8601
578
- driver.run(default_tag: 'test') do
579
- driver.feed(sample_record.merge!('vtm' => ts))
580
- end
581
- assert(index_cmds[1].has_key? '@timestamp')
582
- assert_equal(ts, index_cmds[1]['@timestamp'])
583
- assert_equal('test', index_cmds.first['index']['_index'])
584
- end
585
-
586
- def test_uses_custom_time_key_exclude_timestamp
587
- driver.configure("include_timestamp true
588
- time_key vtm
589
- time_key_exclude_timestamp true\n")
590
- stub_elastic
591
- ts = DateTime.new(2001,2,3).iso8601
592
- driver.run(default_tag: 'test') do
593
- driver.feed(sample_record.merge!('vtm' => ts))
594
- end
595
- assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
596
- end
597
-
598
- def test_uses_custom_time_key_exclude_timestamp_logstash
599
- driver.configure("logstash_format true
600
- time_key vtm
601
- time_key_exclude_timestamp true\n")
602
- stub_elastic
603
- ts = DateTime.new(2001,2,3).iso8601
604
- driver.run(default_tag: 'test') do
605
- driver.feed(sample_record.merge!('vtm' => ts))
606
- end
607
- assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
608
- end
609
-
610
- def test_doesnt_add_tag_key_by_default
611
- stub_elastic
612
- driver.run(default_tag: 'test') do
613
- driver.feed(sample_record)
614
- end
615
- assert_nil(index_cmds[1]['tag'])
616
- end
617
-
618
- def test_adds_tag_key_when_configured
619
- driver.configure("include_tag_key true\n")
620
- stub_elastic
621
- driver.run(default_tag: 'mytag') do
622
- driver.feed(sample_record)
623
- end
624
- assert(index_cmds[1].has_key?('tag'))
625
- assert_equal('mytag', index_cmds[1]['tag'])
626
- end
627
-
628
- def test_adds_id_key_when_configured
629
- driver.configure("id_key request_id\n")
630
- stub_elastic
631
- driver.run(default_tag: 'test') do
632
- driver.feed(sample_record)
633
- end
634
- assert_equal('42', index_cmds[0]['index']['_id'])
635
- end
636
-
637
- class NestedIdKeyTest < self
638
- def test_adds_nested_id_key_with_dot
639
- driver.configure("id_key nested.request_id\n")
640
- stub_elastic
641
- driver.run(default_tag: 'test') do
642
- driver.feed(nested_sample_record)
643
- end
644
- assert_equal('42', index_cmds[0]['index']['_id'])
645
- end
646
-
647
- def test_adds_nested_id_key_with_dollar_dot
648
- driver.configure("id_key $.nested.request_id\n")
649
- stub_elastic
650
- driver.run(default_tag: 'test') do
651
- driver.feed(nested_sample_record)
652
- end
653
- assert_equal('42', index_cmds[0]['index']['_id'])
654
- end
655
-
656
- def test_adds_nested_id_key_with_bracket
657
- driver.configure("id_key $['nested']['request_id']\n")
658
- stub_elastic
659
- driver.run(default_tag: 'test') do
660
- driver.feed(nested_sample_record)
661
- end
662
- assert_equal('42', index_cmds[0]['index']['_id'])
663
- end
664
- end
665
-
666
- def test_doesnt_add_id_key_if_missing_when_configured
667
- driver.configure("id_key another_request_id\n")
668
- stub_elastic
669
- driver.run(default_tag: 'test') do
670
- driver.feed(sample_record)
671
- end
672
- assert(!index_cmds[0]['index'].has_key?('_id'))
673
- end
674
-
675
- def test_adds_id_key_when_not_configured
676
- stub_elastic
677
- driver.run(default_tag: 'test') do
678
- driver.feed(sample_record)
679
- end
680
- assert(!index_cmds[0]['index'].has_key?('_id'))
681
- end
682
-
683
- def test_adds_parent_key_when_configured
684
- driver.configure("parent_key parent_id\n")
685
- stub_elastic
686
- driver.run(default_tag: 'test') do
687
- driver.feed(sample_record)
688
- end
689
- assert_equal('parent', index_cmds[0]['index']['_parent'])
690
- end
691
-
692
- class NestedParentKeyTest < self
693
- def test_adds_nested_parent_key_with_dot
694
- driver.configure("parent_key nested.parent_id\n")
695
- stub_elastic
696
- driver.run(default_tag: 'test') do
697
- driver.feed(nested_sample_record)
698
- end
699
- assert_equal('parent', index_cmds[0]['index']['_parent'])
700
- end
701
-
702
- def test_adds_nested_parent_key_with_dollar_dot
703
- driver.configure("parent_key $.nested.parent_id\n")
704
- stub_elastic
705
- driver.run(default_tag: 'test') do
706
- driver.feed(nested_sample_record)
707
- end
708
- assert_equal('parent', index_cmds[0]['index']['_parent'])
709
- end
710
-
711
- def test_adds_nested_parent_key_with_bracket
712
- driver.configure("parent_key $['nested']['parent_id']\n")
713
- stub_elastic
714
- driver.run(default_tag: 'test') do
715
- driver.feed(nested_sample_record)
716
- end
717
- assert_equal('parent', index_cmds[0]['index']['_parent'])
718
- end
719
- end
720
-
721
- def test_doesnt_add_parent_key_if_missing_when_configured
722
- driver.configure("parent_key another_parent_id\n")
723
- stub_elastic
724
- driver.run(default_tag: 'test') do
725
- driver.feed(sample_record)
726
- end
727
- assert(!index_cmds[0]['index'].has_key?('_parent'))
728
- end
729
-
730
- def test_adds_parent_key_when_not_configured
731
- stub_elastic
732
- driver.run(default_tag: 'test') do
733
- driver.feed(sample_record)
734
- end
735
- assert(!index_cmds[0]['index'].has_key?('_parent'))
736
- end
737
-
738
- class AddsRoutingKeyWhenConfiguredTest < self
739
- def test_es6
740
- driver("routing_key routing_id\n", 6)
741
- stub_elastic
742
- driver.run(default_tag: 'test') do
743
- driver.feed(sample_record)
744
- end
745
- assert_equal('routing', index_cmds[0]['index']['_routing'])
746
- end
747
-
748
- def test_es7
749
- driver("routing_key routing_id\n", 7)
750
- stub_elastic
751
- driver.run(default_tag: 'test') do
752
- driver.feed(sample_record)
753
- end
754
- assert_equal('routing', index_cmds[0]['index']['routing'])
755
- end
756
- end
757
-
758
- class NestedRoutingKeyTest < self
759
- def test_adds_nested_routing_key_with_dot
760
- driver.configure("routing_key nested.routing_id\n")
761
- stub_elastic
762
- driver.run(default_tag: 'test') do
763
- driver.feed(nested_sample_record)
764
- end
765
- assert_equal('routing', index_cmds[0]['index']['_routing'])
766
- end
767
-
768
- def test_adds_nested_routing_key_with_dollar_dot
769
- driver.configure("routing_key $.nested.routing_id\n")
770
- stub_elastic
771
- driver.run(default_tag: 'test') do
772
- driver.feed(nested_sample_record)
773
- end
774
- assert_equal('routing', index_cmds[0]['index']['_routing'])
775
- end
776
-
777
- def test_adds_nested_routing_key_with_bracket
778
- driver.configure("routing_key $['nested']['routing_id']\n")
779
- stub_elastic
780
- driver.run(default_tag: 'test') do
781
- driver.feed(nested_sample_record)
782
- end
783
- assert_equal('routing', index_cmds[0]['index']['_routing'])
784
- end
785
- end
786
-
787
- def test_doesnt_add_routing_key_if_missing_when_configured
788
- driver.configure("routing_key another_routing_id\n")
789
- stub_elastic
790
- driver.run(default_tag: 'test') do
791
- driver.feed(sample_record)
792
- end
793
- assert(!index_cmds[0]['index'].has_key?('_routing'))
794
- end
795
-
796
- def test_adds_routing_key_when_not_configured
797
- stub_elastic
798
- driver.run(default_tag: 'test') do
799
- driver.feed(sample_record)
800
- end
801
- assert(!index_cmds[0]['index'].has_key?('_routing'))
802
- end
803
-
804
- def test_remove_one_key
805
- driver.configure("remove_keys key1\n")
806
- stub_elastic
807
- driver.run(default_tag: 'test') do
808
- driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
809
- end
810
- assert(!index_cmds[1].has_key?('key1'))
811
- assert(index_cmds[1].has_key?('key2'))
812
- end
813
-
814
- def test_remove_multi_keys
815
- driver.configure("remove_keys key1, key2\n")
816
- stub_elastic
817
- driver.run(default_tag: 'test') do
818
- driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
819
- end
820
- assert(!index_cmds[1].has_key?('key1'))
821
- assert(!index_cmds[1].has_key?('key2'))
822
- end
823
-
824
- def test_request_error
825
- stub_elastic_unavailable
826
- assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
827
- driver.run(default_tag: 'test', shutdown: false) do
828
- driver.feed(sample_record)
829
- end
830
- }
831
- end
832
-
833
- def test_request_forever
834
- omit("retry_forever test is unstable.") if ENV["CI"]
835
-
836
- stub_elastic
837
- driver.configure(Fluent::Config::Element.new(
838
- 'ROOT', '', {
839
- '@type' => 'elasticsearch',
840
- }, [
841
- Fluent::Config::Element.new('buffer', '', {
842
- 'retry_forever' => true
843
- }, [])
844
- ]
845
- ))
846
- stub_elastic_timeout
847
- assert_raise(Timeout::Error) {
848
- driver.run(default_tag: 'test', timeout: 10, force_flush_retry: true) do
849
- driver.feed(sample_record)
850
- end
851
- }
852
- end
853
-
854
- def test_tag_parts_index_error_event
855
- stub_elastic
856
- driver.configure("logstash_prefix ${tag_parts[1]}\n")
857
- flexmock(driver.instance.router).should_receive(:emit_error_event)
858
- .with('test', Fluent::EventTime, Hash, TypeError).once
859
- driver.run(default_tag: 'test') do
860
- driver.feed(sample_record)
861
- end
862
- end
863
-
864
- def test_connection_failed
865
- connection_resets = 0
866
-
867
- stub_request(:post, "http://localhost:9200/_bulk").with do |req|
868
- connection_resets += 1
869
- raise Faraday::ConnectionFailed, "Test message"
870
- end
871
-
872
- assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
873
- driver.run(default_tag: 'test', shutdown: false) do
874
- driver.feed(sample_record)
875
- end
876
- }
877
- assert_equal(1, connection_resets)
878
- end
879
-
880
- def test_reconnect_on_error_enabled
881
- connection_resets = 0
882
-
883
- stub_request(:post, "http://localhost:9200/_bulk").with do |req|
884
- connection_resets += 1
885
- raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
886
- end
887
-
888
- driver.configure("reconnect_on_error true\n")
889
-
890
- assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
891
- driver.run(default_tag: 'test', shutdown: false) do
892
- driver.feed(sample_record)
893
- end
894
- }
895
-
896
- assert_raise(Timeout::Error) {
897
- driver.run(default_tag: 'test', shutdown: false) do
898
- driver.feed(sample_record)
899
- end
900
- }
901
- # FIXME: Consider keywords arguments in #run and how to test this later.
902
- # Because v0.14 test driver does not have 1 to 1 correspondence between #run and #flush in tests.
903
- assert_equal(1, connection_resets)
904
- end
905
-
906
- def test_reconnect_on_error_disabled
907
- connection_resets = 0
908
-
909
- stub_request(:post, "http://localhost:9200/_bulk").with do |req|
910
- connection_resets += 1
911
- raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
912
- end
913
-
914
- driver.configure("reconnect_on_error false\n")
915
-
916
- assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
917
- driver.run(default_tag: 'test', shutdown: false) do
918
- driver.feed(sample_record)
919
- end
920
- }
921
-
922
- assert_raise(Timeout::Error) {
923
- driver.run(default_tag: 'test', shutdown: false) do
924
- driver.feed(sample_record)
925
- end
926
- }
927
- assert_equal(1, connection_resets)
928
- end
929
-
930
- def test_update_should_not_write_if_theres_no_id
931
- driver.configure("write_operation update\n")
932
- stub_elastic
933
- driver.run(default_tag: 'test') do
934
- driver.feed(sample_record)
935
- end
936
- assert_nil(index_cmds)
937
- end
938
-
939
- def test_upsert_should_not_write_if_theres_no_id
940
- driver.configure("write_operation upsert\n")
941
- stub_elastic
942
- driver.run(default_tag: 'test') do
943
- driver.feed(sample_record)
944
- end
945
- assert_nil(index_cmds)
946
- end
947
-
948
- def test_create_should_not_write_if_theres_no_id
949
- driver.configure("write_operation create\n")
950
- stub_elastic
951
- driver.run(default_tag: 'test') do
952
- driver.feed(sample_record)
953
- end
954
- assert_nil(index_cmds)
955
- end
956
-
957
- def test_update_should_write_update_op_and_doc_as_upsert_is_false
958
- driver.configure("write_operation update
959
- id_key request_id")
960
- stub_elastic
961
- driver.run(default_tag: 'test') do
962
- driver.feed(sample_record)
963
- end
964
- assert(index_cmds[0].has_key?("update"))
965
- assert(!index_cmds[1]["doc_as_upsert"])
966
- end
967
-
968
- def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
969
- driver.configure("write_operation upsert
970
- id_key request_id")
971
- stub_elastic
972
- driver.run(default_tag: 'test') do
973
- driver.feed(sample_record)
974
- end
975
- assert(index_cmds[0].has_key?("update"))
976
- assert(index_cmds[1]["doc_as_upsert"])
977
- end
978
-
979
- def test_create_should_write_create_op
980
- driver.configure("write_operation create
981
- id_key request_id")
982
- stub_elastic
983
- driver.run(default_tag: 'test') do
984
- driver.feed(sample_record)
985
- end
986
- assert(index_cmds[0].has_key?("create"))
987
- end
988
-
989
- def test_include_index_in_url
990
- stub_elastic('http://localhost:9200/logstash-2018.01.01/_bulk')
991
-
992
- driver.configure("index_name logstash-2018.01.01
993
- include_index_in_url true")
994
- driver.run(default_tag: 'test') do
995
- driver.feed(sample_record)
996
- end
997
-
998
- assert_equal(2, index_cmds.length)
999
- assert_equal(nil, index_cmds.first['index']['_index'])
1000
- end
1001
- end
1
+ require 'helper'
2
+ require 'date'
3
+ require 'fluent/test/helpers'
4
+ require 'fluent/test/driver/output'
5
+ require 'flexmock/test_unit'
6
+
7
+ class ElasticsearchOutputDynamic < Test::Unit::TestCase
8
+ include FlexMock::TestCase
9
+ include Fluent::Test::Helpers
10
+
11
+ attr_accessor :index_cmds, :index_command_counts
12
+
13
+ def setup
14
+ Fluent::Test.setup
15
+ require 'fluent/plugin/out_elasticsearch2_dynamic'
16
+ @driver = nil
17
+ end
18
+
19
+ def driver(conf='', es_version=5)
20
+ # For request stub to detect compatibility.
21
+ @es_version ||= es_version
22
+ Fluent::Plugin::ElasticsearchOutputDynamic.module_eval(<<-CODE)
23
+ def detect_es_major_version
24
+ #{@es_version}
25
+ end
26
+ CODE
27
+ @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDynamic) {
28
+ # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
29
+ if !defined?(Fluent::Plugin::Output)
30
+ def format(tag, time, record)
31
+ [time, record].to_msgpack
32
+ end
33
+ end
34
+ }.configure(conf)
35
+ end
36
+
37
+ def default_type_name
38
+ Fluent::Plugin::ElasticsearchOutput::DEFAULT_TYPE_NAME
39
+ end
40
+
41
+ def sample_record
42
+ {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
43
+ end
44
+
45
+ def nested_sample_record
46
+ {'nested' =>
47
+ {'age' => 26, 'parent_id' => 'parent', 'routing_id' => 'routing', 'request_id' => '42'}
48
+ }
49
+ end
50
+
51
+ def stub_elastic(url="http://localhost:9200/_bulk")
52
+ stub_request(:post, url).with do |req|
53
+ @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
54
+ end
55
+ end
56
+
57
+ def stub_elastic_unavailable(url="http://localhost:9200/_bulk")
58
+ stub_request(:post, url).to_return(:status => [503, "Service Unavailable"])
59
+ end
60
+
61
+ def stub_elastic_timeout(url="http://localhost:9200/_bulk")
62
+ stub_request(:post, url).to_timeout
63
+ end
64
+
65
+ def stub_elastic_with_store_index_command_counts(url="http://localhost:9200/_bulk")
66
+ if @index_command_counts == nil
67
+ @index_command_counts = {}
68
+ @index_command_counts.default = 0
69
+ end
70
+
71
+ stub_request(:post, url).with do |req|
72
+ index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
73
+ @index_command_counts[url] += index_cmds.size
74
+ end
75
+ end
76
+
77
+ def assert_logs_include(logs, msg, exp_matches=1)
78
+ matches = logs.grep /#{msg}/
79
+ assert_equal(exp_matches, matches.length, "Logs do not contain '#{msg}' '#{logs}'")
80
+ end
81
+
82
+ def test_configure
83
+ config = %{
84
+ host logs.google.com
85
+ port 777
86
+ scheme https
87
+ path /es/
88
+ user john
89
+ password doe
90
+ }
91
+ instance = driver(config).instance
92
+
93
+ conf = instance.dynamic_config
94
+ assert_equal 'logs.google.com', conf['host']
95
+ assert_equal "777", conf['port']
96
+ assert_equal :https, instance.scheme
97
+ assert_equal 'john', instance.user
98
+ assert_equal 'doe', instance.password
99
+ assert_equal '/es/', instance.path
100
+ assert_equal :TLSv1, instance.ssl_version
101
+ assert_nil instance.client_key
102
+ assert_nil instance.client_cert
103
+ assert_nil instance.client_key_pass
104
+ assert_false instance.with_transporter_log
105
+ assert_equal :"application/json", instance.content_type
106
+ assert_equal :excon, instance.http_backend
107
+ end
108
+
109
+ test 'configure Content-Type' do
110
+ config = %{
111
+ content_type application/x-ndjson
112
+ }
113
+ instance = driver(config).instance
114
+ assert_equal :"application/x-ndjson", instance.content_type
115
+ end
116
+
117
+ test 'invalid Content-Type' do
118
+ config = %{
119
+ content_type nonexistent/invalid
120
+ }
121
+ assert_raise(Fluent::ConfigError) {
122
+ driver(config)
123
+ }
124
+ end
125
+
126
+ test 'Detected Elasticsearch 7' do
127
+ config = %{
128
+ type_name changed
129
+ }
130
+ instance = driver(config, 7).instance
131
+ assert_equal '_doc', instance.type_name
132
+ end
133
+
134
+ sub_test_case 'connection exceptions' do
135
+ test 'default connection exception' do
136
+ driver(Fluent::Config::Element.new(
137
+ 'ROOT', '', {
138
+ '@type' => 'elasticsearch',
139
+ 'host' => 'log.google.com',
140
+ 'port' => 777,
141
+ 'scheme' => 'https',
142
+ 'path' => '/es/',
143
+ 'user' => 'john',
144
+ 'password' => 'doe',
145
+ }, [
146
+ Fluent::Config::Element.new('buffer', 'tag', {
147
+ }, [])
148
+ ]
149
+ ))
150
+ logs = driver.logs
151
+ assert_logs_include(logs, /you should specify 2 or more 'flush_thread_count'/, 1)
152
+ end
153
+ end
154
+
155
+ def test_defaults
156
+ config = %{
157
+ host logs.google.com
158
+ scheme https
159
+ path /es/
160
+ user john
161
+ password doe
162
+ }
163
+ instance = driver(config).instance
164
+
165
+ conf = instance.dynamic_config
166
+ assert_equal "9200", conf['port']
167
+ assert_equal "false", conf['logstash_format']
168
+ assert_equal "true", conf['utc_index']
169
+ assert_equal false, instance.time_key_exclude_timestamp
170
+ end
171
+
172
+ def test_legacy_hosts_list
173
+ config = %{
174
+ hosts host1:50,host2:100,host3
175
+ scheme https
176
+ path /es/
177
+ port 123
178
+ }
179
+ instance = driver(config).instance
180
+
181
+ assert_equal 3, instance.get_connection_options(nil)[:hosts].length
182
+ host1, host2, host3 = instance.get_connection_options(nil)[:hosts]
183
+
184
+ assert_equal 'host1', host1[:host]
185
+ assert_equal 50, host1[:port]
186
+ assert_equal 'https', host1[:scheme]
187
+ assert_equal '/es/', host2[:path]
188
+ assert_equal 'host3', host3[:host]
189
+ assert_equal 123, host3[:port]
190
+ assert_equal 'https', host3[:scheme]
191
+ assert_equal '/es/', host3[:path]
192
+ end
193
+
194
+ def test_hosts_list
195
+ config = %{
196
+ hosts https://john:password@host1:443/elastic/,http://host2
197
+ path /default_path
198
+ user default_user
199
+ password default_password
200
+ }
201
+ instance = driver(config).instance
202
+
203
+ assert_equal 2, instance.get_connection_options(nil)[:hosts].length
204
+ host1, host2 = instance.get_connection_options(nil)[:hosts]
205
+
206
+ assert_equal 'host1', host1[:host]
207
+ assert_equal 443, host1[:port]
208
+ assert_equal 'https', host1[:scheme]
209
+ assert_equal 'john', host1[:user]
210
+ assert_equal 'password', host1[:password]
211
+ assert_equal '/elastic/', host1[:path]
212
+
213
+ assert_equal 'host2', host2[:host]
214
+ assert_equal 'http', host2[:scheme]
215
+ assert_equal 'default_user', host2[:user]
216
+ assert_equal 'default_password', host2[:password]
217
+ assert_equal '/default_path', host2[:path]
218
+ end
219
+
220
+ def test_hosts_list_with_escape_placeholders
221
+ config = %{
222
+ hosts https://%{j+hn}:%{passw@rd}@host1:443/elastic/,http://host2
223
+ path /default_path
224
+ user default_user
225
+ password default_password
226
+ }
227
+ instance = driver(config).instance
228
+
229
+ assert_equal 2, instance.get_connection_options(nil)[:hosts].length
230
+ host1, host2 = instance.get_connection_options(nil)[:hosts]
231
+
232
+ assert_equal 'host1', host1[:host]
233
+ assert_equal 443, host1[:port]
234
+ assert_equal 'https', host1[:scheme]
235
+ assert_equal 'j%2Bhn', host1[:user]
236
+ assert_equal 'passw%40rd', host1[:password]
237
+ assert_equal '/elastic/', host1[:path]
238
+
239
+ assert_equal 'host2', host2[:host]
240
+ assert_equal 'http', host2[:scheme]
241
+ assert_equal 'default_user', host2[:user]
242
+ assert_equal 'default_password', host2[:password]
243
+ assert_equal '/default_path', host2[:path]
244
+ end
245
+
246
+ def test_single_host_params_and_defaults
247
+ config = %{
248
+ host logs.google.com
249
+ user john
250
+ password doe
251
+ }
252
+ instance = driver(config).instance
253
+
254
+ assert_equal 1, instance.get_connection_options(nil)[:hosts].length
255
+ host1 = instance.get_connection_options(nil)[:hosts][0]
256
+
257
+ assert_equal 'logs.google.com', host1[:host]
258
+ assert_equal 9200, host1[:port]
259
+ assert_equal 'http', host1[:scheme]
260
+ assert_equal 'john', host1[:user]
261
+ assert_equal 'doe', host1[:password]
262
+ assert_equal nil, host1[:path]
263
+ end
264
+
265
+ def test_single_host_params_and_defaults_with_escape_placeholders
266
+ config = %{
267
+ host logs.google.com
268
+ user %{j+hn}
269
+ password %{d@e}
270
+ }
271
+ instance = driver(config).instance
272
+
273
+ assert_equal 1, instance.get_connection_options(nil)[:hosts].length
274
+ host1 = instance.get_connection_options(nil)[:hosts][0]
275
+
276
+ assert_equal 'logs.google.com', host1[:host]
277
+ assert_equal 9200, host1[:port]
278
+ assert_equal 'http', host1[:scheme]
279
+ assert_equal 'j%2Bhn', host1[:user]
280
+ assert_equal 'd%40e', host1[:password]
281
+ assert_equal nil, host1[:path]
282
+ end
283
+
284
+ def test_content_type_header
285
+ stub_request(:head, "http://localhost:9200/").
286
+ to_return(:status => 200, :body => "", :headers => {})
287
+ if Elasticsearch::VERSION >= "6.0.2"
288
+ elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
289
+ with(headers: { "Content-Type" => "application/x-ndjson" })
290
+ else
291
+ elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
292
+ with(headers: { "Content-Type" => "application/json" })
293
+ end
294
+ driver.run(default_tag: 'test') do
295
+ driver.feed(sample_record)
296
+ end
297
+ assert_requested(elastic_request)
298
+ end
299
+
300
+ def test_writes_to_default_index
301
+ stub_elastic
302
+ driver.run(default_tag: 'test') do
303
+ driver.feed(sample_record)
304
+ end
305
+ assert_equal('fluentd', index_cmds.first['index']['_index'])
306
+ end
307
+
308
+ def test_writes_to_default_type
309
+ stub_elastic
310
+ driver.run(default_tag: 'test') do
311
+ driver.feed(sample_record)
312
+ end
313
+ assert_equal(default_type_name, index_cmds.first['index']['_type'])
314
+ end
315
+
316
+ def test_writes_to_specified_index
317
+ driver.configure("index_name myindex\n")
318
+ stub_elastic
319
+ driver.run(default_tag: 'test') do
320
+ driver.feed(sample_record)
321
+ end
322
+ assert_equal('myindex', index_cmds.first['index']['_index'])
323
+ end
324
+
325
+ def test_writes_to_specified_index_uppercase
326
+ driver.configure("index_name MyIndex\n")
327
+ stub_elastic
328
+ driver.run(default_tag: 'test') do
329
+ driver.feed(sample_record)
330
+ end
331
+ assert_equal('myindex', index_cmds.first['index']['_index'])
332
+ end
333
+
334
+ def test_writes_to_specified_type
335
+ driver.configure("type_name mytype\n")
336
+ stub_elastic
337
+ driver.run(default_tag: 'test') do
338
+ driver.feed(sample_record)
339
+ end
340
+ assert_equal('mytype', index_cmds.first['index']['_type'])
341
+ end
342
+
343
+ def test_writes_to_specified_host
344
+ driver.configure("host 192.168.33.50\n")
345
+ elastic_request = stub_elastic("http://192.168.33.50:9200/_bulk")
346
+ driver.run(default_tag: 'test') do
347
+ driver.feed(sample_record)
348
+ end
349
+ assert_requested(elastic_request)
350
+ end
351
+
352
+ def test_writes_to_specified_port
353
+ driver.configure("port 9201\n")
354
+ elastic_request = stub_elastic("http://localhost:9201/_bulk")
355
+ driver.run(default_tag: 'test') do
356
+ driver.feed(sample_record)
357
+ end
358
+ assert_requested(elastic_request)
359
+ end
360
+
361
+ def test_writes_to_multi_hosts
362
+ hosts = [['192.168.33.50', 9201], ['192.168.33.51', 9201], ['192.168.33.52', 9201]]
363
+ hosts_string = hosts.map {|x| "#{x[0]}:#{x[1]}"}.compact.join(',')
364
+
365
+ driver.configure("hosts #{hosts_string}")
366
+
367
+ hosts.each do |host_info|
368
+ host, port = host_info
369
+ stub_elastic_with_store_index_command_counts("http://#{host}:#{port}/_bulk")
370
+ end
371
+
372
+ driver.run(default_tag: 'test') do
373
+ 1000.times do
374
+ driver.feed(sample_record.merge('age'=>rand(100)))
375
+ end
376
+ end
377
+ # @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
378
+ # it's Fluentd test driver's constraint
379
+ # so @index_command_counts.size is always 1
380
+
381
+ assert(@index_command_counts.size > 0, "not working with hosts options")
382
+
383
+ total = 0
384
+ @index_command_counts.each do |url, count|
385
+ total += count
386
+ end
387
+ assert_equal(2000, total)
388
+ end
389
+
390
+ def test_makes_bulk_request
391
+ stub_elastic
392
+ driver.run(default_tag: 'test') do
393
+ driver.feed(sample_record)
394
+ driver.feed(sample_record.merge('age' => 27))
395
+ end
396
+ assert_equal(4, index_cmds.count)
397
+ end
398
+
399
+ def test_all_records_are_preserved_in_bulk
400
+ stub_elastic
401
+ driver.run(default_tag: 'test') do
402
+ driver.feed(sample_record)
403
+ driver.feed(sample_record.merge('age' => 27))
404
+ end
405
+ assert_equal(26, index_cmds[1]['age'])
406
+ assert_equal(27, index_cmds[3]['age'])
407
+ end
408
+
409
+ def test_writes_to_logstash_index
410
+ driver.configure("logstash_format true\n")
411
+ time = Time.parse Date.today.iso8601
412
+ logstash_index = "logstash-#{time.getutc.strftime("%Y.%m.%d")}"
413
+ stub_elastic
414
+ driver.run(default_tag: 'test') do
415
+ driver.feed(time.to_i, sample_record)
416
+ end
417
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
418
+ end
419
+
420
+ def test_writes_to_logstash_utc_index
421
+ driver.configure("logstash_format true
422
+ utc_index false")
423
+ time = Time.parse Date.today.iso8601
424
+ utc_index = "logstash-#{time.strftime("%Y.%m.%d")}"
425
+ stub_elastic
426
+ driver.run(default_tag: 'test') do
427
+ driver.feed(time.to_i, sample_record)
428
+ end
429
+ assert_equal(utc_index, index_cmds.first['index']['_index'])
430
+ end
431
+
432
+ def test_writes_to_logstash_index_with_specified_prefix
433
+ driver.configure("logstash_format true
434
+ logstash_prefix myprefix")
435
+ time = Time.parse Date.today.iso8601
436
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
437
+ stub_elastic
438
+ driver.run(default_tag: 'test') do
439
+ driver.feed(time.to_i, sample_record)
440
+ end
441
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
442
+ end
443
+
444
+ def test_writes_to_logstash_index_with_specified_prefix_and_separator
445
+ separator = '_'
446
+ driver.configure("logstash_format true
447
+ logstash_prefix_separator #{separator}
448
+ logstash_prefix myprefix")
449
+ time = Time.parse Date.today.iso8601
450
+ logstash_index = "myprefix#{separator}#{time.getutc.strftime("%Y.%m.%d")}"
451
+ stub_elastic
452
+ driver.run(default_tag: 'test') do
453
+ driver.feed(time.to_i, sample_record)
454
+ end
455
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
456
+ end
457
+
458
+ def test_writes_to_logstash_index_with_specified_prefix_uppercase
459
+ driver.configure("logstash_format true
460
+ logstash_prefix MyPrefix")
461
+ time = Time.parse Date.today.iso8601
462
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
463
+ stub_elastic
464
+ driver.run(default_tag: 'test') do
465
+ driver.feed(time.to_i, sample_record)
466
+ end
467
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
468
+ end
469
+
470
+ def test_writes_to_logstash_index_with_specified_dateformat
471
+ driver.configure("logstash_format true
472
+ logstash_dateformat %Y.%m")
473
+ time = Time.parse Date.today.iso8601
474
+ logstash_index = "logstash-#{time.getutc.strftime("%Y.%m")}"
475
+ stub_elastic
476
+ driver.run(default_tag: 'test') do
477
+ driver.feed(time.to_i, sample_record)
478
+ end
479
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
480
+ end
481
+
482
+ def test_writes_to_logstash_index_with_specified_prefix_and_dateformat
483
+ driver.configure("logstash_format true
484
+ logstash_prefix myprefix
485
+ logstash_dateformat %Y.%m")
486
+ time = Time.parse Date.today.iso8601
487
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m")}"
488
+ stub_elastic
489
+ driver.run(default_tag: 'test') do
490
+ driver.feed(time.to_i, sample_record)
491
+ end
492
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
493
+ end
494
+
495
+ def test_doesnt_add_logstash_timestamp_by_default
496
+ stub_elastic
497
+ driver.run(default_tag: 'test') do
498
+ driver.feed(sample_record)
499
+ end
500
+ assert_nil(index_cmds[1]['@timestamp'])
501
+ end
502
+
503
+ def test_adds_logstash_timestamp_when_configured
504
+ driver.configure("logstash_format true\n")
505
+ stub_elastic
506
+ time = Fluent::EventTime.new(Time.now.to_i, 123456789)
507
+ driver.run(default_tag: 'test') do
508
+ driver.feed(time, sample_record)
509
+ end
510
+ assert(index_cmds[1].has_key? '@timestamp')
511
+ assert_equal(Time.at(time).iso8601(9), index_cmds[1]['@timestamp'])
512
+ end
513
+
514
+ def test_uses_subsecond_precision_when_configured
515
+ driver.configure("logstash_format true
516
+ time_precision 3\n")
517
+ stub_elastic
518
+ time = Fluent::EventTime.new(Time.now.to_i, 123456789)
519
+ driver.run(default_tag: 'test') do
520
+ driver.feed(time, sample_record)
521
+ end
522
+ assert(index_cmds[1].has_key? '@timestamp')
523
+ assert_equal(Time.at(time).iso8601(3), index_cmds[1]['@timestamp'])
524
+ end
525
+
526
+ def test_uses_custom_timestamp_when_included_in_record
527
+ driver.configure("include_timestamp true\n")
528
+ stub_elastic
529
+ ts = DateTime.new(2001,2,3).iso8601
530
+ driver.run(default_tag: 'test') do
531
+ driver.feed(sample_record.merge!('@timestamp' => ts))
532
+ end
533
+ assert(index_cmds[1].has_key? '@timestamp')
534
+ assert_equal(ts, index_cmds[1]['@timestamp'])
535
+ end
536
+
537
+ def test_uses_custom_timestamp_when_included_in_record_logstash
538
+ driver.configure("logstash_format true\n")
539
+ stub_elastic
540
+ ts = DateTime.new(2001,2,3).iso8601
541
+ driver.run(default_tag: 'test') do
542
+ driver.feed(sample_record.merge!('@timestamp' => ts))
543
+ end
544
+ assert(index_cmds[1].has_key? '@timestamp')
545
+ assert_equal(ts, index_cmds[1]['@timestamp'])
546
+ end
547
+
548
+ def test_uses_custom_time_key_logstash
549
+ driver.configure("logstash_format true
550
+ time_key vtm\n")
551
+ stub_elastic
552
+ ts = DateTime.new(2001,2,3).iso8601
553
+ driver.run(default_tag: 'test') do
554
+ driver.feed(sample_record.merge!('vtm' => ts))
555
+ end
556
+ assert(index_cmds[1].has_key? '@timestamp')
557
+ assert_equal(ts, index_cmds[1]['@timestamp'])
558
+ end
559
+
560
+ def test_uses_custom_time_key_timestamp
561
+ driver.configure("include_timestamp true
562
+ time_key vtm\n")
563
+ stub_elastic
564
+ ts = DateTime.new(2001,2,3).iso8601
565
+ driver.run(default_tag: 'test') do
566
+ driver.feed(sample_record.merge!('vtm' => ts))
567
+ end
568
+ assert(index_cmds[1].has_key? '@timestamp')
569
+ assert_equal(ts, index_cmds[1]['@timestamp'])
570
+ end
571
+
572
+ def test_uses_custom_time_key_timestamp_custom_index
573
+ driver.configure("include_timestamp true
574
+ index_name test
575
+ time_key vtm\n")
576
+ stub_elastic
577
+ ts = DateTime.new(2001,2,3).iso8601
578
+ driver.run(default_tag: 'test') do
579
+ driver.feed(sample_record.merge!('vtm' => ts))
580
+ end
581
+ assert(index_cmds[1].has_key? '@timestamp')
582
+ assert_equal(ts, index_cmds[1]['@timestamp'])
583
+ assert_equal('test', index_cmds.first['index']['_index'])
584
+ end
585
+
586
+ def test_uses_custom_time_key_exclude_timestamp
587
+ driver.configure("include_timestamp true
588
+ time_key vtm
589
+ time_key_exclude_timestamp true\n")
590
+ stub_elastic
591
+ ts = DateTime.new(2001,2,3).iso8601
592
+ driver.run(default_tag: 'test') do
593
+ driver.feed(sample_record.merge!('vtm' => ts))
594
+ end
595
+ assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
596
+ end
597
+
598
+ def test_uses_custom_time_key_exclude_timestamp_logstash
599
+ driver.configure("logstash_format true
600
+ time_key vtm
601
+ time_key_exclude_timestamp true\n")
602
+ stub_elastic
603
+ ts = DateTime.new(2001,2,3).iso8601
604
+ driver.run(default_tag: 'test') do
605
+ driver.feed(sample_record.merge!('vtm' => ts))
606
+ end
607
+ assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
608
+ end
609
+
610
+ def test_doesnt_add_tag_key_by_default
611
+ stub_elastic
612
+ driver.run(default_tag: 'test') do
613
+ driver.feed(sample_record)
614
+ end
615
+ assert_nil(index_cmds[1]['tag'])
616
+ end
617
+
618
+ def test_adds_tag_key_when_configured
619
+ driver.configure("include_tag_key true\n")
620
+ stub_elastic
621
+ driver.run(default_tag: 'mytag') do
622
+ driver.feed(sample_record)
623
+ end
624
+ assert(index_cmds[1].has_key?('tag'))
625
+ assert_equal('mytag', index_cmds[1]['tag'])
626
+ end
627
+
628
+ def test_adds_id_key_when_configured
629
+ driver.configure("id_key request_id\n")
630
+ stub_elastic
631
+ driver.run(default_tag: 'test') do
632
+ driver.feed(sample_record)
633
+ end
634
+ assert_equal('42', index_cmds[0]['index']['_id'])
635
+ end
636
+
637
+ class NestedIdKeyTest < self
638
+ def test_adds_nested_id_key_with_dot
639
+ driver.configure("id_key nested.request_id\n")
640
+ stub_elastic
641
+ driver.run(default_tag: 'test') do
642
+ driver.feed(nested_sample_record)
643
+ end
644
+ assert_equal('42', index_cmds[0]['index']['_id'])
645
+ end
646
+
647
+ def test_adds_nested_id_key_with_dollar_dot
648
+ driver.configure("id_key $.nested.request_id\n")
649
+ stub_elastic
650
+ driver.run(default_tag: 'test') do
651
+ driver.feed(nested_sample_record)
652
+ end
653
+ assert_equal('42', index_cmds[0]['index']['_id'])
654
+ end
655
+
656
+ def test_adds_nested_id_key_with_bracket
657
+ driver.configure("id_key $['nested']['request_id']\n")
658
+ stub_elastic
659
+ driver.run(default_tag: 'test') do
660
+ driver.feed(nested_sample_record)
661
+ end
662
+ assert_equal('42', index_cmds[0]['index']['_id'])
663
+ end
664
+ end
665
+
666
+ def test_doesnt_add_id_key_if_missing_when_configured
667
+ driver.configure("id_key another_request_id\n")
668
+ stub_elastic
669
+ driver.run(default_tag: 'test') do
670
+ driver.feed(sample_record)
671
+ end
672
+ assert(!index_cmds[0]['index'].has_key?('_id'))
673
+ end
674
+
675
+ def test_adds_id_key_when_not_configured
676
+ stub_elastic
677
+ driver.run(default_tag: 'test') do
678
+ driver.feed(sample_record)
679
+ end
680
+ assert(!index_cmds[0]['index'].has_key?('_id'))
681
+ end
682
+
683
+ def test_adds_parent_key_when_configured
684
+ driver.configure("parent_key parent_id\n")
685
+ stub_elastic
686
+ driver.run(default_tag: 'test') do
687
+ driver.feed(sample_record)
688
+ end
689
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
690
+ end
691
+
692
+ class NestedParentKeyTest < self
693
+ def test_adds_nested_parent_key_with_dot
694
+ driver.configure("parent_key nested.parent_id\n")
695
+ stub_elastic
696
+ driver.run(default_tag: 'test') do
697
+ driver.feed(nested_sample_record)
698
+ end
699
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
700
+ end
701
+
702
+ def test_adds_nested_parent_key_with_dollar_dot
703
+ driver.configure("parent_key $.nested.parent_id\n")
704
+ stub_elastic
705
+ driver.run(default_tag: 'test') do
706
+ driver.feed(nested_sample_record)
707
+ end
708
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
709
+ end
710
+
711
+ def test_adds_nested_parent_key_with_bracket
712
+ driver.configure("parent_key $['nested']['parent_id']\n")
713
+ stub_elastic
714
+ driver.run(default_tag: 'test') do
715
+ driver.feed(nested_sample_record)
716
+ end
717
+ assert_equal('parent', index_cmds[0]['index']['_parent'])
718
+ end
719
+ end
720
+
721
+ def test_doesnt_add_parent_key_if_missing_when_configured
722
+ driver.configure("parent_key another_parent_id\n")
723
+ stub_elastic
724
+ driver.run(default_tag: 'test') do
725
+ driver.feed(sample_record)
726
+ end
727
+ assert(!index_cmds[0]['index'].has_key?('_parent'))
728
+ end
729
+
730
+ def test_adds_parent_key_when_not_configured
731
+ stub_elastic
732
+ driver.run(default_tag: 'test') do
733
+ driver.feed(sample_record)
734
+ end
735
+ assert(!index_cmds[0]['index'].has_key?('_parent'))
736
+ end
737
+
738
+ class AddsRoutingKeyWhenConfiguredTest < self
739
+ def test_es6
740
+ driver("routing_key routing_id\n", 6)
741
+ stub_elastic
742
+ driver.run(default_tag: 'test') do
743
+ driver.feed(sample_record)
744
+ end
745
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
746
+ end
747
+
748
+ def test_es7
749
+ driver("routing_key routing_id\n", 7)
750
+ stub_elastic
751
+ driver.run(default_tag: 'test') do
752
+ driver.feed(sample_record)
753
+ end
754
+ assert_equal('routing', index_cmds[0]['index']['routing'])
755
+ end
756
+ end
757
+
758
+ class NestedRoutingKeyTest < self
759
+ def test_adds_nested_routing_key_with_dot
760
+ driver.configure("routing_key nested.routing_id\n")
761
+ stub_elastic
762
+ driver.run(default_tag: 'test') do
763
+ driver.feed(nested_sample_record)
764
+ end
765
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
766
+ end
767
+
768
+ def test_adds_nested_routing_key_with_dollar_dot
769
+ driver.configure("routing_key $.nested.routing_id\n")
770
+ stub_elastic
771
+ driver.run(default_tag: 'test') do
772
+ driver.feed(nested_sample_record)
773
+ end
774
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
775
+ end
776
+
777
+ def test_adds_nested_routing_key_with_bracket
778
+ driver.configure("routing_key $['nested']['routing_id']\n")
779
+ stub_elastic
780
+ driver.run(default_tag: 'test') do
781
+ driver.feed(nested_sample_record)
782
+ end
783
+ assert_equal('routing', index_cmds[0]['index']['_routing'])
784
+ end
785
+ end
786
+
787
+ def test_doesnt_add_routing_key_if_missing_when_configured
788
+ driver.configure("routing_key another_routing_id\n")
789
+ stub_elastic
790
+ driver.run(default_tag: 'test') do
791
+ driver.feed(sample_record)
792
+ end
793
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
794
+ end
795
+
796
+ def test_adds_routing_key_when_not_configured
797
+ stub_elastic
798
+ driver.run(default_tag: 'test') do
799
+ driver.feed(sample_record)
800
+ end
801
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
802
+ end
803
+
804
+ def test_remove_one_key
805
+ driver.configure("remove_keys key1\n")
806
+ stub_elastic
807
+ driver.run(default_tag: 'test') do
808
+ driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
809
+ end
810
+ assert(!index_cmds[1].has_key?('key1'))
811
+ assert(index_cmds[1].has_key?('key2'))
812
+ end
813
+
814
+ def test_remove_multi_keys
815
+ driver.configure("remove_keys key1, key2\n")
816
+ stub_elastic
817
+ driver.run(default_tag: 'test') do
818
+ driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
819
+ end
820
+ assert(!index_cmds[1].has_key?('key1'))
821
+ assert(!index_cmds[1].has_key?('key2'))
822
+ end
823
+
824
+ def test_request_error
825
+ stub_elastic_unavailable
826
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
827
+ driver.run(default_tag: 'test', shutdown: false) do
828
+ driver.feed(sample_record)
829
+ end
830
+ }
831
+ end
832
+
833
+ def test_request_forever
834
+ omit("retry_forever test is unstable.") if ENV["CI"]
835
+
836
+ stub_elastic
837
+ driver.configure(Fluent::Config::Element.new(
838
+ 'ROOT', '', {
839
+ '@type' => 'elasticsearch',
840
+ }, [
841
+ Fluent::Config::Element.new('buffer', '', {
842
+ 'retry_forever' => true
843
+ }, [])
844
+ ]
845
+ ))
846
+ stub_elastic_timeout
847
+ assert_raise(Timeout::Error) {
848
+ driver.run(default_tag: 'test', timeout: 10, force_flush_retry: true) do
849
+ driver.feed(sample_record)
850
+ end
851
+ }
852
+ end
853
+
854
+ def test_tag_parts_index_error_event
855
+ stub_elastic
856
+ driver.configure("logstash_prefix ${tag_parts[1]}\n")
857
+ flexmock(driver.instance.router).should_receive(:emit_error_event)
858
+ .with('test', Fluent::EventTime, Hash, TypeError).once
859
+ driver.run(default_tag: 'test') do
860
+ driver.feed(sample_record)
861
+ end
862
+ end
863
+
864
+ def test_connection_failed
865
+ connection_resets = 0
866
+
867
+ stub_request(:post, "http://localhost:9200/_bulk").with do |req|
868
+ connection_resets += 1
869
+ raise Faraday::ConnectionFailed, "Test message"
870
+ end
871
+
872
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
873
+ driver.run(default_tag: 'test', shutdown: false) do
874
+ driver.feed(sample_record)
875
+ end
876
+ }
877
+ assert_equal(1, connection_resets)
878
+ end
879
+
880
+ def test_reconnect_on_error_enabled
881
+ connection_resets = 0
882
+
883
+ stub_request(:post, "http://localhost:9200/_bulk").with do |req|
884
+ connection_resets += 1
885
+ raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
886
+ end
887
+
888
+ driver.configure("reconnect_on_error true\n")
889
+
890
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
891
+ driver.run(default_tag: 'test', shutdown: false) do
892
+ driver.feed(sample_record)
893
+ end
894
+ }
895
+
896
+ assert_raise(Timeout::Error) {
897
+ driver.run(default_tag: 'test', shutdown: false) do
898
+ driver.feed(sample_record)
899
+ end
900
+ }
901
+ # FIXME: Consider keywords arguments in #run and how to test this later.
902
+ # Because v0.14 test driver does not have 1 to 1 correspondence between #run and #flush in tests.
903
+ assert_equal(1, connection_resets)
904
+ end
905
+
906
+ def test_reconnect_on_error_disabled
907
+ connection_resets = 0
908
+
909
+ stub_request(:post, "http://localhost:9200/_bulk").with do |req|
910
+ connection_resets += 1
911
+ raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
912
+ end
913
+
914
+ driver.configure("reconnect_on_error false\n")
915
+
916
+ assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
917
+ driver.run(default_tag: 'test', shutdown: false) do
918
+ driver.feed(sample_record)
919
+ end
920
+ }
921
+
922
+ assert_raise(Timeout::Error) {
923
+ driver.run(default_tag: 'test', shutdown: false) do
924
+ driver.feed(sample_record)
925
+ end
926
+ }
927
+ assert_equal(1, connection_resets)
928
+ end
929
+
930
+ def test_update_should_not_write_if_theres_no_id
931
+ driver.configure("write_operation update\n")
932
+ stub_elastic
933
+ driver.run(default_tag: 'test') do
934
+ driver.feed(sample_record)
935
+ end
936
+ assert_nil(index_cmds)
937
+ end
938
+
939
+ def test_upsert_should_not_write_if_theres_no_id
940
+ driver.configure("write_operation upsert\n")
941
+ stub_elastic
942
+ driver.run(default_tag: 'test') do
943
+ driver.feed(sample_record)
944
+ end
945
+ assert_nil(index_cmds)
946
+ end
947
+
948
+ def test_create_should_not_write_if_theres_no_id
949
+ driver.configure("write_operation create\n")
950
+ stub_elastic
951
+ driver.run(default_tag: 'test') do
952
+ driver.feed(sample_record)
953
+ end
954
+ assert_nil(index_cmds)
955
+ end
956
+
957
+ def test_update_should_write_update_op_and_doc_as_upsert_is_false
958
+ driver.configure("write_operation update
959
+ id_key request_id")
960
+ stub_elastic
961
+ driver.run(default_tag: 'test') do
962
+ driver.feed(sample_record)
963
+ end
964
+ assert(index_cmds[0].has_key?("update"))
965
+ assert(!index_cmds[1]["doc_as_upsert"])
966
+ end
967
+
968
+ def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
969
+ driver.configure("write_operation upsert
970
+ id_key request_id")
971
+ stub_elastic
972
+ driver.run(default_tag: 'test') do
973
+ driver.feed(sample_record)
974
+ end
975
+ assert(index_cmds[0].has_key?("update"))
976
+ assert(index_cmds[1]["doc_as_upsert"])
977
+ end
978
+
979
+ def test_create_should_write_create_op
980
+ driver.configure("write_operation create
981
+ id_key request_id")
982
+ stub_elastic
983
+ driver.run(default_tag: 'test') do
984
+ driver.feed(sample_record)
985
+ end
986
+ assert(index_cmds[0].has_key?("create"))
987
+ end
988
+
989
+ def test_include_index_in_url
990
+ stub_elastic('http://localhost:9200/logstash-2018.01.01/_bulk')
991
+
992
+ driver.configure("index_name logstash-2018.01.01
993
+ include_index_in_url true")
994
+ driver.run(default_tag: 'test') do
995
+ driver.feed(sample_record)
996
+ end
997
+
998
+ assert_equal(2, index_cmds.length)
999
+ assert_equal(nil, index_cmds.first['index']['_index'])
1000
+ end
1001
+ end