logstash-output-elasticsearch-test 11.16.0-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +649 -0
  3. data/CONTRIBUTORS +34 -0
  4. data/Gemfile +16 -0
  5. data/LICENSE +202 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +106 -0
  8. data/docs/index.asciidoc +1369 -0
  9. data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +282 -0
  10. data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
  11. data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +155 -0
  12. data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +534 -0
  13. data/lib/logstash/outputs/elasticsearch/http_client.rb +497 -0
  14. data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +201 -0
  15. data/lib/logstash/outputs/elasticsearch/ilm.rb +92 -0
  16. data/lib/logstash/outputs/elasticsearch/license_checker.rb +52 -0
  17. data/lib/logstash/outputs/elasticsearch/template_manager.rb +131 -0
  18. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-6x.json +45 -0
  19. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-7x.json +44 -0
  20. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-8x.json +50 -0
  21. data/lib/logstash/outputs/elasticsearch.rb +699 -0
  22. data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +237 -0
  23. data/lib/logstash/plugin_mixins/elasticsearch/common.rb +409 -0
  24. data/lib/logstash/plugin_mixins/elasticsearch/noop_license_checker.rb +9 -0
  25. data/logstash-output-elasticsearch.gemspec +40 -0
  26. data/spec/es_spec_helper.rb +225 -0
  27. data/spec/fixtures/_nodes/6x.json +81 -0
  28. data/spec/fixtures/_nodes/7x.json +92 -0
  29. data/spec/fixtures/htpasswd +2 -0
  30. data/spec/fixtures/license_check/active.json +16 -0
  31. data/spec/fixtures/license_check/inactive.json +5 -0
  32. data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
  33. data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
  34. data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
  35. data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
  36. data/spec/fixtures/template-with-policy-es6x.json +48 -0
  37. data/spec/fixtures/template-with-policy-es7x.json +45 -0
  38. data/spec/fixtures/template-with-policy-es8x.json +50 -0
  39. data/spec/fixtures/test_certs/ca.crt +29 -0
  40. data/spec/fixtures/test_certs/ca.der.sha256 +1 -0
  41. data/spec/fixtures/test_certs/ca.key +51 -0
  42. data/spec/fixtures/test_certs/renew.sh +13 -0
  43. data/spec/fixtures/test_certs/test.crt +30 -0
  44. data/spec/fixtures/test_certs/test.der.sha256 +1 -0
  45. data/spec/fixtures/test_certs/test.key +51 -0
  46. data/spec/fixtures/test_certs/test.p12 +0 -0
  47. data/spec/fixtures/test_certs/test_invalid.crt +36 -0
  48. data/spec/fixtures/test_certs/test_invalid.key +51 -0
  49. data/spec/fixtures/test_certs/test_invalid.p12 +0 -0
  50. data/spec/fixtures/test_certs/test_self_signed.crt +32 -0
  51. data/spec/fixtures/test_certs/test_self_signed.key +54 -0
  52. data/spec/fixtures/test_certs/test_self_signed.p12 +0 -0
  53. data/spec/integration/outputs/compressed_indexing_spec.rb +70 -0
  54. data/spec/integration/outputs/create_spec.rb +67 -0
  55. data/spec/integration/outputs/data_stream_spec.rb +68 -0
  56. data/spec/integration/outputs/delete_spec.rb +63 -0
  57. data/spec/integration/outputs/ilm_spec.rb +534 -0
  58. data/spec/integration/outputs/index_spec.rb +421 -0
  59. data/spec/integration/outputs/index_version_spec.rb +98 -0
  60. data/spec/integration/outputs/ingest_pipeline_spec.rb +75 -0
  61. data/spec/integration/outputs/metrics_spec.rb +66 -0
  62. data/spec/integration/outputs/no_es_on_startup_spec.rb +78 -0
  63. data/spec/integration/outputs/painless_update_spec.rb +99 -0
  64. data/spec/integration/outputs/parent_spec.rb +94 -0
  65. data/spec/integration/outputs/retry_spec.rb +182 -0
  66. data/spec/integration/outputs/routing_spec.rb +61 -0
  67. data/spec/integration/outputs/sniffer_spec.rb +94 -0
  68. data/spec/integration/outputs/templates_spec.rb +133 -0
  69. data/spec/integration/outputs/unsupported_actions_spec.rb +75 -0
  70. data/spec/integration/outputs/update_spec.rb +114 -0
  71. data/spec/spec_helper.rb +10 -0
  72. data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
  73. data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
  74. data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
  75. data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
  76. data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
  77. data/spec/unit/http_client_builder_spec.rb +185 -0
  78. data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +612 -0
  79. data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +151 -0
  80. data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +501 -0
  81. data/spec/unit/outputs/elasticsearch/http_client_spec.rb +339 -0
  82. data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +189 -0
  83. data/spec/unit/outputs/elasticsearch_proxy_spec.rb +103 -0
  84. data/spec/unit/outputs/elasticsearch_spec.rb +1573 -0
  85. data/spec/unit/outputs/elasticsearch_ssl_spec.rb +197 -0
  86. data/spec/unit/outputs/error_whitelist_spec.rb +56 -0
  87. data/spec/unit/outputs/license_check_spec.rb +57 -0
  88. metadata +423 -0
@@ -0,0 +1,612 @@
1
+ require_relative '../../../../spec/spec_helper'
2
+ require "logstash/outputs/elasticsearch/data_stream_support"
3
+
4
+ describe LogStash::Outputs::ElasticSearch::DataStreamSupport do
5
+
6
+ subject { LogStash::Outputs::ElasticSearch.new(options) }
7
+
8
+ let(:options) { { 'hosts' => [ 'localhost:12345' ] } }
9
+ let(:es_version) { '7.10.1' }
10
+
11
+ # All data-streams features require that the plugin be run in a non-disabled ECS compatibility mode.
12
+ # We run the plugin in ECS by default, and add test scenarios specifically for it being disabled.
13
+ let(:ecs_compatibility) { :v1 }
14
+ before(:each) do
15
+ allow_any_instance_of(LogStash::Outputs::ElasticSearch).to receive(:ecs_compatibility).and_return(ecs_compatibility)
16
+ end
17
+
18
+ let(:do_register) { false }
19
+ let(:stub_plugin_register!) do
20
+ allow(subject).to receive(:last_es_version).and_return(es_version)
21
+
22
+ allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:start)
23
+
24
+ # stub-out unrelated (finish_register) setup:
25
+ allow(subject).to receive(:discover_cluster_uuid)
26
+ allow(subject).to receive(:install_template)
27
+ allow(subject).to receive(:ilm_in_use?).and_return nil
28
+
29
+ # emulate 'successful' ES connection on the same thread
30
+ allow(subject).to receive(:after_successful_connection) { |&block| block.call }
31
+ allow(subject).to receive(:stop_after_successful_connection_thread)
32
+
33
+ subject.register
34
+
35
+ allow(subject.client).to receive(:maximum_seen_major_version).and_return(Integer(es_version.split('.').first))
36
+
37
+ # allow( subject.logger ).to receive(:info) do |msg|
38
+ # expect(msg).to include "New Elasticsearch output"
39
+ # end
40
+ end
41
+
42
+ before(:each) do
43
+ stub_plugin_register! if do_register
44
+ end
45
+
46
+ after(:each) do
47
+ subject.close if do_register
48
+ end
49
+
50
+ context "default configuration" do
51
+
52
+ let(:options) { {} }
53
+
54
+ before { allow(subject).to receive(:last_es_version).and_return(es_version) }
55
+
56
+ it "does not use data-streams on LS 7.x" do
57
+ change_constant :LOGSTASH_VERSION, '7.10.0' do
58
+ expect( subject.data_stream_config? ).to be false
59
+ end
60
+ end
61
+
62
+ it "warns when configuration is data-stream compliant (LS 7.x)" do
63
+ expect( subject.logger ).to receive(:warn).with(a_string_including "Configuration is data stream compliant but due backwards compatibility Logstash 7.x")
64
+ change_constant :LOGSTASH_VERSION, '7.11.0' do
65
+ expect( subject.data_stream_config? ).to be false
66
+ end
67
+ end
68
+
69
+ it "defaults to using data-streams on LS 8.0" do
70
+ change_constant :LOGSTASH_VERSION, '8.0.0' do
71
+ expect( subject.data_stream_config? ).to be true
72
+ end
73
+ end
74
+
75
+ context 'ecs_compatibility disabled' do
76
+ let(:ecs_compatibility) { :disabled }
77
+
78
+ {
79
+ '7.x (pre-DS)' => '7.9.0',
80
+ '7.x (with DS)' => '7.11.0',
81
+ '8.0' => '8.0.0',
82
+ '8.x' => '8.1.2',
83
+ }.each do |ls_version_desc, ls_version|
84
+ context "on LS #{ls_version_desc}" do
85
+ around(:each) { |example| change_constant(:LOGSTASH_VERSION, ls_version, &example) }
86
+ it "does not use data-streams" do
87
+ expect( subject.logger ).to receive(:info).with(a_string_including "ecs_compatibility is not enabled")
88
+ expect( subject.logger ).to receive(:info).with(a_string_including "Data streams auto configuration (`data_stream => auto` or unset) resolved to `false`")
89
+ expect( subject.data_stream_config? ).to be false
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ context 'non-compatible ES' do
96
+
97
+ let(:es_version) { '7.8.0' }
98
+
99
+ it "does not print an error (from after_successful_connection thread)" do
100
+ change_constant :LOGSTASH_VERSION, '7.8.1' do
101
+ expect( subject.logger ).to_not receive(:error)
102
+ expect( subject ).to receive(:finish_register).once.and_call_original
103
+ stub_plugin_register!
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ context "ds-compatible configuration" do
112
+
113
+ let(:options) do
114
+ {
115
+ 'hosts' => [ 'http://127.0.0.1:12345' ],
116
+ 'http_compression' => 'true', 'bulk_path' => '_bulk', 'timeout' => '30',
117
+ 'user' => 'elastic', 'password' => 'ForSearch!', 'ssl_enabled' => 'false'
118
+ }
119
+ end
120
+
121
+ before { allow(subject).to receive(:last_es_version).and_return(es_version) }
122
+
123
+ it "does not use data-streams on LS 7.x" do
124
+ expect( subject.logger ).to receive(:warn).with(a_string_including "Logstash 7.x will not assume writing to a data-stream")
125
+ change_constant :LOGSTASH_VERSION, '7.10.0' do
126
+ expect( subject.data_stream_config? ).to be false
127
+ end
128
+ end
129
+
130
+ it "defaults to using data-streams on LS 8.0" do
131
+ change_constant :LOGSTASH_VERSION, '8.0.1' do
132
+ expect( subject.data_stream_config? ).to be true
133
+ end
134
+ change_constant :LOGSTASH_VERSION, '8.1.0' do
135
+ expect( subject.send(:check_data_stream_config!) ).to be true
136
+ end
137
+ end
138
+
139
+ context 'old ES' do
140
+
141
+ let(:es_version) { '7.8.1' }
142
+
143
+ it "prints an error (from after_successful_connection thread) on LS 8.0" do
144
+ change_constant :LOGSTASH_VERSION, '8.0.0' do
145
+ expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
146
+ {:es_version=>"7.8.1"})
147
+ stub_plugin_register!
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ end
154
+
155
+ context 'ds value-dependent configuration' do
156
+ context 'with valid values' do
157
+ let(:options) { super().merge(
158
+ 'action' => 'create',
159
+ 'routing' => 'any',
160
+ 'pipeline' => 'any',
161
+ 'manage_template' => 'false',
162
+ 'data_stream' => 'true',
163
+ 'data_stream_type' => 'logs',
164
+ 'data_stream_dataset' => 'any',
165
+ 'data_stream_namespace' => 'any',
166
+ 'data_stream_sync_fields' => true,
167
+ 'data_stream_auto_routing' => true,
168
+ 'dlq_custom_codes' => [ 404 ],
169
+ 'dlq_on_failed_indexname_interpolation' => false)
170
+ }
171
+
172
+ it 'should enable data-streams by default' do
173
+ expect( subject.data_stream_config? ).to be_truthy
174
+ end
175
+ end
176
+
177
+ context 'with invalid values' do
178
+ let(:options) { super().merge(
179
+ 'data_stream' => 'true',
180
+ 'action' => 'index',
181
+ 'manage_template' => 'true')
182
+ }
183
+
184
+ it 'should raise a configuration error' do
185
+ expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, 'Invalid data stream configuration: ["action", "manage_template"]')
186
+ end
187
+ end
188
+ end
189
+
190
+ context "default (non data-stream) configuration (on 7.x)" do
191
+
192
+ let(:options) do
193
+ { 'data_stream_dataset' => 'test', 'data_stream_auto_routing' => 'false', 'user' => 'elastic' }
194
+ end
195
+
196
+ before { allow(subject).to receive(:last_es_version).and_return(es_version) }
197
+
198
+ it "does not default to data-streams" do
199
+ expect( subject.logger ).to receive(:error) do |msg|
200
+ expect(msg).to include "Ambiguous configuration; data stream settings must not be present when data streams are disabled"
201
+ end
202
+ change_constant :LOGSTASH_VERSION, '7.10.2' do
203
+ expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
204
+ end
205
+ end
206
+
207
+ context 'explicit data_stream => false' do
208
+
209
+ let(:options) { super().merge('data_stream' => 'false') }
210
+
211
+ it "raises a configuration error (due ds specific settings)" do
212
+ expect( subject.logger ).to receive(:error).with(/Ambiguous configuration; data stream settings must not be present when data streams are disabled/,
213
+ {"data_stream_auto_routing"=>"false", "data_stream_dataset"=>"test"})
214
+ change_constant :LOGSTASH_VERSION, '7.10.2' do
215
+ expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
216
+ end
217
+ end
218
+
219
+ end
220
+
221
+ end
222
+
223
+ context "(explicit) ds disabled configuration" do
224
+
225
+ let(:options) { super().merge('data_stream' => false.to_s) }
226
+
227
+ before { allow(subject).to receive(:last_es_version).and_return(es_version) }
228
+
229
+ it "does not use data-streams on LS 7.x" do
230
+ change_constant :LOGSTASH_VERSION, '7.10.0' do
231
+ expect( subject.data_stream_config? ).to be false
232
+ end
233
+ end
234
+
235
+ it "does not use data-streams on LS 8.0" do
236
+ change_constant :LOGSTASH_VERSION, '8.0.0' do
237
+ expect( subject.data_stream_config? ).to be false
238
+ end
239
+ end
240
+
241
+ it "does not print a warning" do
242
+ expect( subject.logger ).to_not receive(:warn)
243
+ change_constant :LOGSTASH_VERSION, '7.10.2' do
244
+ expect( subject.data_stream_config? ).to be false
245
+ end
246
+ end
247
+
248
+ end
249
+
250
+ context "(explicit) ds enabled configuration" do
251
+
252
+ let(:options) { super().merge('data_stream' => true.to_s) }
253
+
254
+ before { allow(subject).to receive(:last_es_version).and_return(es_version) }
255
+
256
+ it "does use data-streams on LS 7.x" do
257
+ change_constant :LOGSTASH_VERSION, '7.9.1' do
258
+ expect( subject.data_stream_config? ).to be true
259
+ end
260
+ end
261
+
262
+ it "does use data-streams on LS 8.x" do
263
+ change_constant :LOGSTASH_VERSION, '8.1.0' do
264
+ expect( subject.data_stream_config? ).to be true
265
+ end
266
+ end
267
+
268
+ context 'with ecs_compatibility disabled' do
269
+ let(:ecs_compatibility) { :disabled }
270
+
271
+ context 'when running on LS 7.x' do
272
+ around(:each) { |example| change_constant(:LOGSTASH_VERSION, '7.15.1', &example) }
273
+
274
+ it "emits a deprecation warning and uses data streams anway" do
275
+ expect( subject.deprecation_logger ).to receive(:deprecated).with(a_string_including "`data_stream => true` will require the plugin to be run in ECS compatibility mode")
276
+ expect( subject.data_stream_config? ).to be true
277
+ end
278
+ end
279
+
280
+ context 'when running on LS 8.x' do
281
+ around(:each) { |example| change_constant(:LOGSTASH_VERSION, '8.0.0', &example) }
282
+
283
+ it "errors helpfully" do
284
+ expect{ subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, a_string_including("Invalid data stream configuration: `ecs_compatibility => disabled`"))
285
+ end
286
+ end
287
+
288
+ end
289
+
290
+ context 'non-compatible ES' do
291
+
292
+ let(:es_version) { '6.8.11' }
293
+
294
+ it "prints an error (from after_successful_connection thread) on LS 7.x" do
295
+ change_constant :LOGSTASH_VERSION, '7.12.0' do
296
+ expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
297
+ {:es_version=>"6.8.11"})
298
+ stub_plugin_register!
299
+ end
300
+ end
301
+
302
+ it "prints an error (from after_successful_connection thread) on LS 8.0" do
303
+ change_constant :LOGSTASH_VERSION, '8.0.5' do
304
+ expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
305
+ {:es_version=>"6.8.11"})
306
+ stub_plugin_register!
307
+ end
308
+ end
309
+
310
+ end
311
+
312
+ end
313
+
314
+ describe "auto routing" do
315
+
316
+ let(:options) { super().merge('data_stream' => 'true') }
317
+ let(:do_register) { true }
318
+
319
+ let(:event) do
320
+ event = LogStash::Event.new
321
+ event.set '[host][hostname]', 'orangutan'
322
+ event
323
+ end
324
+
325
+ context 'with data_stream.* event data' do
326
+
327
+ let(:event) do
328
+ super().tap do |event|
329
+ event.set '[data_stream][type]', 'metrics'
330
+ event.set '[data_stream][dataset]', 'src1'
331
+ event.set '[data_stream][namespace]', 'test'
332
+ end
333
+ end
334
+
335
+ it 'uses event specified target' do
336
+ tuple = subject.map_events([ event ]).first
337
+ expect( tuple.size ).to eql 3
338
+ expect( tuple[0] ).to eql 'create'
339
+ expect( tuple[1] ).to include :_index => 'metrics-src1-test'
340
+ end
341
+
342
+ end
343
+
344
+ context 'with routing turned off' do
345
+
346
+ let(:options) { super().merge('data_stream_auto_routing' => 'false') }
347
+
348
+ let(:event) do
349
+ super().tap do |event|
350
+ event.set '[data_stream][type]', 'metrics'
351
+ event.set '[data_stream][dataset]', 'src1'
352
+ event.set '[data_stream][namespace]', 'test'
353
+ end
354
+ end
355
+
356
+ it 'uses event specified target' do
357
+ tuple = subject.map_events([ event ]).first
358
+ expect( tuple.size ).to eql 3
359
+ expect( tuple[0] ).to eql 'create'
360
+ expect( tuple[1] ).to include :_index => 'logs-generic-default'
361
+ end
362
+
363
+ end
364
+
365
+ context 'with partial data_stream.* data' do
366
+
367
+ let(:options) { super().merge('data_stream_dataset' => 'data') }
368
+
369
+ let(:event) do
370
+ super().tap do |event|
371
+ event.set '[data_stream][type]', 'metrics'
372
+ event.set '[data_stream][dataset]', 'src1'
373
+ end
374
+ end
375
+
376
+ it 'uses event specified target' do
377
+ tuple = subject.map_events([ event ]).first
378
+ expect( tuple.size ).to eql 3
379
+ expect( tuple[0] ).to eql 'create'
380
+ expect( tuple[1] ).to include :_index => 'metrics-src1-default'
381
+ end
382
+
383
+ end
384
+
385
+ context 'with no data_stream.* fields' do
386
+
387
+ let(:options) { super().merge('data_stream_dataset' => 'stats', 'data_stream_type' => 'metrics') }
388
+
389
+ it 'uses configuration target' do
390
+ tuple = subject.map_events([ event ]).first
391
+ expect( tuple.size ).to eql 3
392
+ expect( tuple[0] ).to eql 'create'
393
+ expect( tuple[1] ).to include :_index => 'metrics-stats-default'
394
+ end
395
+
396
+ end
397
+
398
+ context 'with default configuration' do
399
+
400
+ it 'uses default target' do
401
+ tuple = subject.map_events([ event ]).first
402
+ expect( tuple.size ).to eql 3
403
+ expect( tuple[0] ).to eql 'create'
404
+ expect( tuple[1] ).to include :_index => 'logs-generic-default'
405
+ end
406
+
407
+ end
408
+
409
+ end
410
+
411
+ describe "field sync" do
412
+
413
+ let(:options) { super().merge('data_stream' => 'true') }
414
+
415
+ let(:do_register) { true }
416
+
417
+ let(:event) do
418
+ event = LogStash::Event.new
419
+ event.set '[host][hostname]', 'orangutan'
420
+ event
421
+ end
422
+
423
+ context 'enabled and no event data' do
424
+
425
+ let(:options) { super().merge('data_stream_sync_fields' => 'true') }
426
+
427
+ it 'fills in DS fields' do
428
+ tuple = subject.map_events([ event ]).first
429
+ expect( tuple.size ).to eql 3
430
+ expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "default"})
431
+ end
432
+
433
+ end
434
+
435
+ context 'enabled and some event data' do
436
+
437
+ let(:options) { super().merge('data_stream_dataset' => 'ds1', 'data_stream_sync_fields' => 'true') }
438
+
439
+ let(:event) do
440
+ super().tap do |event|
441
+ event.set '[data_stream][namespace]', 'custom'
442
+ end
443
+ end
444
+
445
+ it 'fills in missing fields' do
446
+ tuple = subject.map_events([ event ]).first
447
+ expect( tuple.size ).to eql 3
448
+ expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "ds1", "namespace" => "custom"})
449
+ end
450
+
451
+ it 'does not mutate data_stream hash' do
452
+ data_stream = event.get('data_stream')
453
+ data_stream_dup = data_stream.dup
454
+ subject.map_events([ event ])
455
+ expect( data_stream ).to eql data_stream_dup
456
+ end
457
+
458
+ end
459
+
460
+ context 'enabled with invalid data' do
461
+
462
+ let(:options) { super().merge('data_stream_sync_fields' => 'true') }
463
+
464
+ let(:event) do
465
+ super().tap do |event|
466
+ event.set '[data_stream]', false
467
+ end
468
+ end
469
+
470
+ it 'overwrites invalid data_stream field' do
471
+ tuple = subject.map_events([ event ]).first
472
+ expect( tuple.size ).to eql 3
473
+ expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "default"})
474
+ end
475
+
476
+ end
477
+
478
+ context 'enabled having invalid data with routing disabled' do
479
+
480
+ let(:options) do
481
+ super().merge('data_stream_sync_fields' => 'true', 'data_stream_auto_routing' => 'false', 'data_stream_namespace' => 'ns1')
482
+ end
483
+
484
+ let(:event) do
485
+ super().tap do |event|
486
+ event.set '[data_stream][type]', 'foo'
487
+ event.set '[data_stream][dataset]', false
488
+ event.set '[data_stream][extra]', 0
489
+ end
490
+ end
491
+
492
+ it 'overwrites invalid data_stream sub-fields' do
493
+ tuple = subject.map_events([ event ]).first
494
+ expect( tuple.size ).to eql 3
495
+ expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "ns1", "extra" => 0})
496
+ end
497
+
498
+ end
499
+
500
+ context 'disabled and no event data' do
501
+
502
+ let(:options) { super().merge('data_stream_dataset' => 'ds1', 'data_stream_sync_fields' => 'false') }
503
+
504
+ it 'does not fill DS fields' do
505
+ tuple = subject.map_events([ event ]).first
506
+ expect( tuple.size ).to eql 3
507
+ expect( tuple[2].keys ).to_not include 'data_stream'
508
+ end
509
+
510
+ end
511
+
512
+ context 'disabled and some event data' do
513
+
514
+ let(:options) { super().merge('data_stream_sync_fields' => 'false') }
515
+
516
+ let(:event) do
517
+ super().tap do |event|
518
+ event.set '[data_stream][type]', 'logs'
519
+ end
520
+ end
521
+
522
+ it 'does not fill DS fields' do
523
+ tuple = subject.map_events([ event ]).first
524
+ expect( tuple.size ).to eql 3
525
+ expect( tuple[2]['data_stream'] ).to eql({ 'type' => 'logs'})
526
+ end
527
+
528
+ end
529
+
530
+ end
531
+
532
+ describe "validation" do
533
+
534
+ context 'with too long dataset name' do
535
+
536
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => 'x' * 120) }
537
+
538
+ it 'fails' do
539
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
540
+ end
541
+
542
+ end
543
+
544
+ context 'with empty dataset name' do
545
+
546
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => '') }
547
+
548
+ it 'fails' do
549
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
550
+ end
551
+
552
+ end
553
+
554
+ context 'with invalid dataset char' do
555
+
556
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => 'foo/bar') }
557
+
558
+ it 'fails' do
559
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
560
+ end
561
+
562
+ end
563
+
564
+ context 'with invalid namespace char' do
565
+
566
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_namespace' => 'foo*') }
567
+
568
+ it 'fails' do
569
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
570
+ end
571
+
572
+ end
573
+
574
+ context 'with invalid "empty" namespace' do
575
+
576
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_namespace' => ' ') }
577
+
578
+ it 'fails' do
579
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
580
+ end
581
+
582
+ end
583
+
584
+ context 'with invalid type' do
585
+
586
+ let(:options) { super().merge('data_stream' => 'true', 'data_stream_type' => 'custom') }
587
+
588
+ it 'fails' do
589
+ expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
590
+ end
591
+
592
+ end
593
+
594
+ end
595
+
596
+ private
597
+
598
+ def change_constant(name, new_value, target: Object)
599
+ old_value = target.const_get name
600
+ begin
601
+ target.send :remove_const, name
602
+ target.const_set name, new_value
603
+ yield if block_given?
604
+ ensure
605
+ if block_given?
606
+ target.send :remove_const, name rescue nil
607
+ target.const_set name, old_value
608
+ end
609
+ end
610
+ end
611
+
612
+ end