fluent-plugin-elasticsearch 2.10.2 → 2.10.3

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