logstash-output-elasticsearch 10.8.1-java → 11.0.0-java
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +1 -1
- data/docs/index.asciidoc +282 -114
- data/lib/logstash/outputs/elasticsearch.rb +125 -65
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +233 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +59 -21
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +47 -34
- data/lib/logstash/outputs/elasticsearch/ilm.rb +11 -12
- data/lib/logstash/outputs/elasticsearch/license_checker.rb +19 -22
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +3 -5
- data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +157 -153
- data/lib/logstash/plugin_mixins/elasticsearch/common.rb +80 -60
- data/logstash-output-elasticsearch.gemspec +2 -2
- data/spec/es_spec_helper.rb +3 -6
- data/spec/integration/outputs/data_stream_spec.rb +61 -0
- data/spec/integration/outputs/ilm_spec.rb +22 -18
- data/spec/integration/outputs/ingest_pipeline_spec.rb +4 -2
- data/spec/integration/outputs/retry_spec.rb +14 -2
- data/spec/integration/outputs/sniffer_spec.rb +0 -1
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/http_client_builder_spec.rb +9 -9
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +542 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +1 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +27 -13
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +59 -41
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +1 -3
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +4 -5
- data/spec/unit/outputs/elasticsearch_spec.rb +228 -38
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +1 -2
- data/spec/unit/outputs/error_whitelist_spec.rb +4 -3
- data/spec/unit/outputs/license_check_spec.rb +0 -16
- metadata +23 -16
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '
|
3
|
+
s.version = '11.0.0'
|
4
4
|
|
5
5
|
s.licenses = ['apache-2.0']
|
6
6
|
s.summary = "Stores logs in Elasticsearch"
|
@@ -23,13 +23,13 @@ Gem::Specification.new do |s|
|
|
23
23
|
|
24
24
|
s.add_runtime_dependency "manticore", '>= 0.5.4', '< 1.0.0'
|
25
25
|
s.add_runtime_dependency 'stud', ['>= 0.0.17', '~> 0.0']
|
26
|
-
s.add_runtime_dependency 'cabin', ['~> 0.6']
|
27
26
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
28
27
|
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.0'
|
29
28
|
|
30
29
|
s.add_development_dependency 'logstash-codec-plain'
|
31
30
|
s.add_development_dependency 'logstash-devutils'
|
32
31
|
s.add_development_dependency 'flores'
|
32
|
+
s.add_development_dependency 'cabin', ['~> 0.6']
|
33
33
|
# Still used in some specs, we should remove this ASAP
|
34
34
|
s.add_development_dependency 'elasticsearch'
|
35
35
|
end
|
data/spec/es_spec_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
3
|
require 'elasticsearch'
|
4
4
|
require_relative "support/elasticsearch/api/actions/delete_ilm_policy"
|
5
5
|
require_relative "support/elasticsearch/api/actions/get_alias"
|
@@ -8,10 +8,7 @@ require_relative "support/elasticsearch/api/actions/get_ilm_policy"
|
|
8
8
|
require_relative "support/elasticsearch/api/actions/put_ilm_policy"
|
9
9
|
|
10
10
|
require 'json'
|
11
|
-
|
12
|
-
unless defined?(LogStash::OSS)
|
13
|
-
LogStash::OSS = ENV['DISTRIBUTION'] != "default"
|
14
|
-
end
|
11
|
+
require 'cabin'
|
15
12
|
|
16
13
|
module ESHelper
|
17
14
|
def get_host_port
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch"
|
3
|
+
|
4
|
+
describe "data streams", :integration => true do
|
5
|
+
|
6
|
+
let(:ds_name) { "logs-#{ds_dataset}-default" }
|
7
|
+
let(:ds_dataset) { 'integration_test' }
|
8
|
+
|
9
|
+
let(:options) do
|
10
|
+
{ "data_stream" => 'true', "data_stream_dataset" => ds_dataset, "hosts" => get_host_port() }
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { LogStash::Outputs::ElasticSearch.new(options) }
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
@es = get_client
|
17
|
+
@es.delete_by_query(index: ".ds-#{ds_name}-*", expand_wildcards: :all, body: { query: { match_all: {} } }) rescue nil
|
18
|
+
|
19
|
+
es_version = @es.info['version']['number']
|
20
|
+
if Gem::Version.create(es_version) < Gem::Version.create('7.9.0')
|
21
|
+
skip "ES version #{es_version} does not support data-streams"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "creates a new document" do
|
26
|
+
subject.register
|
27
|
+
subject.multi_receive([LogStash::Event.new("message" => "MSG 111")])
|
28
|
+
|
29
|
+
@es.indices.refresh
|
30
|
+
|
31
|
+
Stud::try(3.times) do
|
32
|
+
r = @es.search(index: ds_name)
|
33
|
+
|
34
|
+
expect( r['hits']['total']['value'] ).to eq 1
|
35
|
+
doc = r['hits']['hits'].first
|
36
|
+
expect( doc['_source'] ).to include "message"=>"MSG 111"
|
37
|
+
expect( doc['_source'] ).to include "data_stream"=>{"dataset"=>ds_dataset, "type"=>"logs", "namespace"=>"default"}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with document_id" do
|
42
|
+
|
43
|
+
let(:document_id) { '1234567890' }
|
44
|
+
let(:options) { super().merge("document_id" => document_id) }
|
45
|
+
|
46
|
+
it "creates a new document" do
|
47
|
+
subject.register
|
48
|
+
subject.multi_receive([LogStash::Event.new("message" => "foo")])
|
49
|
+
|
50
|
+
@es.indices.refresh
|
51
|
+
|
52
|
+
Stud::try(3.times) do
|
53
|
+
r = @es.search(index: ds_name, body: { query: { match: { _id: document_id } } })
|
54
|
+
expect( r['hits']['total']['value'] ).to eq 1
|
55
|
+
doc = r['hits']['hits'].first
|
56
|
+
expect( doc['_source'] ).to include "message"=>"foo"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -5,7 +5,7 @@ shared_examples_for 'an ILM enabled Logstash' do
|
|
5
5
|
context 'with a policy with a maximum number of documents' do
|
6
6
|
let (:policy) { small_max_doc_policy }
|
7
7
|
let (:ilm_policy_name) { "logstash-policy-custom"}
|
8
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
8
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
|
9
9
|
|
10
10
|
it 'should rollover when the policy max docs is reached' do
|
11
11
|
put_policy(@es, ilm_policy_name, policy)
|
@@ -54,7 +54,7 @@ shared_examples_for 'an ILM enabled Logstash' do
|
|
54
54
|
context 'with a policy where the maximum number of documents is not reached' do
|
55
55
|
let (:policy) { large_max_doc_policy }
|
56
56
|
let (:ilm_policy_name) { "logstash-policy-custom-policy"}
|
57
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
57
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
|
58
58
|
|
59
59
|
it 'should ingest into a single index when max docs is not reached' do
|
60
60
|
put_policy(@es,ilm_policy_name, policy)
|
@@ -119,7 +119,7 @@ shared_examples_for 'an ILM disabled Logstash' do
|
|
119
119
|
context 'with an existing policy that will roll over' do
|
120
120
|
let (:policy) { small_max_doc_policy }
|
121
121
|
let (:ilm_policy_name) { "logstash-policy-3_docs"}
|
122
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
122
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
|
123
123
|
|
124
124
|
it 'should not roll over indices' do
|
125
125
|
subject.register
|
@@ -155,7 +155,7 @@ shared_examples_for 'an ILM disabled Logstash' do
|
|
155
155
|
|
156
156
|
context 'with a custom template name' do
|
157
157
|
let (:template_name) { "logstash_custom_template_name" }
|
158
|
-
let (:settings) { super.merge('template_name' => template_name)}
|
158
|
+
let (:settings) { super().merge('template_name' => template_name)}
|
159
159
|
|
160
160
|
it 'should not write the ILM settings into the template' do
|
161
161
|
subject.register
|
@@ -195,28 +195,32 @@ shared_examples_for 'an Elasticsearch instance that does not support index lifec
|
|
195
195
|
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
196
196
|
|
197
197
|
context 'when ilm is enabled in Logstash' do
|
198
|
-
let (:settings) { super.merge!({ 'ilm_enabled' => true }) }
|
198
|
+
let (:settings) { super().merge!({ 'ilm_enabled' => true }) }
|
199
199
|
|
200
200
|
it 'should raise a configuration error' do
|
201
|
+
# TODO should be refactored not to rely on plugin internals
|
202
|
+
finish_register = subject.method(:finish_register)
|
203
|
+
expect(subject).to receive(:finish_register)
|
201
204
|
expect do
|
202
205
|
begin
|
203
206
|
subject.register
|
204
|
-
|
207
|
+
finish_register.call
|
208
|
+
sleep(1.5) # wait_for_successful_connection (for the thread to raise)
|
205
209
|
ensure
|
206
|
-
subject.
|
210
|
+
subject.send :stop_after_successful_connection_thread
|
207
211
|
end
|
208
212
|
end.to raise_error(LogStash::ConfigurationError)
|
209
213
|
end
|
210
214
|
end
|
211
215
|
|
212
216
|
context 'when ilm is disabled in Logstash' do
|
213
|
-
let (:settings) { super.merge!({ 'ilm_enabled' => false }) }
|
217
|
+
let (:settings) { super().merge!({ 'ilm_enabled' => false }) }
|
214
218
|
|
215
219
|
it_behaves_like 'an ILM disabled Logstash'
|
216
220
|
end
|
217
221
|
|
218
222
|
context 'when ilm is set to auto in Logstash' do
|
219
|
-
let (:settings) { super.merge!({ 'ilm_enabled' => 'auto' }) }
|
223
|
+
let (:settings) { super().merge!({ 'ilm_enabled' => 'auto' }) }
|
220
224
|
|
221
225
|
it_behaves_like 'an ILM disabled Logstash'
|
222
226
|
end
|
@@ -286,7 +290,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
286
290
|
|
287
291
|
context 'when using the default policy' do
|
288
292
|
context 'with a custom pattern' do
|
289
|
-
let (:settings) { super.merge("ilm_pattern" => "000001")}
|
293
|
+
let (:settings) { super().merge("ilm_pattern" => "000001")}
|
290
294
|
it 'should create a rollover alias' do
|
291
295
|
expect(@es.indices.exists_alias(name: "logstash")).to be_falsey
|
292
296
|
subject.register
|
@@ -346,7 +350,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
346
350
|
|
347
351
|
context 'when not using the default policy' do
|
348
352
|
let (:ilm_policy_name) {"logstash-policy-small"}
|
349
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
353
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
|
350
354
|
let (:policy) { small_max_doc_policy }
|
351
355
|
|
352
356
|
before do
|
@@ -363,7 +367,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
363
367
|
|
364
368
|
context 'when using a time based policy' do
|
365
369
|
let (:ilm_policy_name) {"logstash-policy-time"}
|
366
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
370
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name)}
|
367
371
|
let (:policy) { max_age_policy("1d") }
|
368
372
|
|
369
373
|
before do
|
@@ -409,7 +413,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
409
413
|
let (:template) { "spec/fixtures/template-with-policy-es6x.json" }
|
410
414
|
end
|
411
415
|
|
412
|
-
let (:settings) { super.merge("template" => template,
|
416
|
+
let (:settings) { super().merge("template" => template,
|
413
417
|
"index" => "overwrite-4")}
|
414
418
|
|
415
419
|
it 'should not overwrite the index patterns' do
|
@@ -426,7 +430,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
426
430
|
let (:ilm_rollover_alias) { "logstash_the_cat_in_the_hat" }
|
427
431
|
let (:index) { ilm_rollover_alias }
|
428
432
|
let(:expected_index) { index }
|
429
|
-
let (:settings) { super.merge("ilm_policy" => ilm_policy_name,
|
433
|
+
let (:settings) { super().merge("ilm_policy" => ilm_policy_name,
|
430
434
|
"template" => template,
|
431
435
|
"ilm_rollover_alias" => ilm_rollover_alias)}
|
432
436
|
|
@@ -480,7 +484,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
480
484
|
|
481
485
|
context 'with a different template_name' do
|
482
486
|
let (:template_name) { "logstash_custom_template_name" }
|
483
|
-
let (:settings) { super.merge('template_name' => template_name)}
|
487
|
+
let (:settings) { super().merge('template_name' => template_name)}
|
484
488
|
|
485
489
|
it_behaves_like 'an ILM enabled Logstash'
|
486
490
|
|
@@ -514,7 +518,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
514
518
|
end
|
515
519
|
|
516
520
|
context 'when ilm_enabled is the default' do
|
517
|
-
let (:settings) { super.tap{|x|x.delete('ilm_enabled')}}
|
521
|
+
let (:settings) { super().tap{|x|x.delete('ilm_enabled')}}
|
518
522
|
|
519
523
|
if ESHelper.es_version_satisfies?(">=7.0")
|
520
524
|
context 'when Elasticsearch is version 7 or above' do
|
@@ -530,13 +534,13 @@ if ESHelper.es_version_satisfies?(">= 6.6")
|
|
530
534
|
end
|
531
535
|
|
532
536
|
context 'with ilm disabled' do
|
533
|
-
let (:settings) { super.merge('ilm_enabled' => false )}
|
537
|
+
let (:settings) { super().merge('ilm_enabled' => false )}
|
534
538
|
|
535
539
|
it_behaves_like 'an ILM disabled Logstash'
|
536
540
|
end
|
537
541
|
|
538
542
|
context 'with ilm disabled using a string' do
|
539
|
-
let (:settings) { super.merge('ilm_enabled' => 'false' )}
|
543
|
+
let (:settings) { super().merge('ilm_enabled' => 'false' )}
|
540
544
|
|
541
545
|
it_behaves_like 'an ILM disabled Logstash'
|
542
546
|
end
|
@@ -6,7 +6,8 @@ if ESHelper.es_version_satisfies?(">= 5")
|
|
6
6
|
require "logstash/outputs/elasticsearch"
|
7
7
|
settings = {
|
8
8
|
"hosts" => "#{get_host_port()}",
|
9
|
-
"pipeline" => "apache-logs"
|
9
|
+
"pipeline" => "apache-logs",
|
10
|
+
"data_stream" => 'false'
|
10
11
|
}
|
11
12
|
next LogStash::Outputs::ElasticSearch.new(settings)
|
12
13
|
end
|
@@ -52,9 +53,10 @@ if ESHelper.es_version_satisfies?(">= 5")
|
|
52
53
|
@es.indices.refresh
|
53
54
|
|
54
55
|
#Wait or fail until everything's indexed.
|
55
|
-
Stud::try(
|
56
|
+
Stud::try(10.times) do
|
56
57
|
r = @es.search(index: 'logstash-*')
|
57
58
|
expect(r).to have_hits(1)
|
59
|
+
sleep(0.1)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
@@ -4,9 +4,21 @@ require_relative "../../../spec/es_spec_helper"
|
|
4
4
|
describe "failures in bulk class expected behavior", :integration => true do
|
5
5
|
let(:template) { '{"template" : "not important, will be updated by :index"}' }
|
6
6
|
let(:event1) { LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0}) }
|
7
|
-
let(:action1)
|
7
|
+
let(:action1) do
|
8
|
+
if ESHelper.es_version_satisfies?(">= 6", "< 7")
|
9
|
+
ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event1.to_hash])
|
10
|
+
else
|
11
|
+
ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17" }, event1.to_hash])
|
12
|
+
end
|
13
|
+
end
|
8
14
|
let(:event2) { LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0] }, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0}) }
|
9
|
-
let(:action2)
|
15
|
+
let(:action2) do
|
16
|
+
if ESHelper.es_version_satisfies?(">= 6", "< 7")
|
17
|
+
ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event2.to_hash])
|
18
|
+
else
|
19
|
+
ESHelper.action_for_version(["index", {:_id=>nil, routing_field_name =>nil, :_index=>"logstash-2014.11.17" }, event2.to_hash])
|
20
|
+
end
|
21
|
+
end
|
10
22
|
let(:invalid_event) { LogStash::Event.new("geoip" => { "location" => "notlatlon" }, "@timestamp" => "2014-11-17T20:37:17.223Z") }
|
11
23
|
|
12
24
|
def mock_actions_with_response(*resp)
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
|
3
|
+
unless defined?(LogStash::OSS)
|
4
|
+
LogStash::OSS = ENV['DISTRIBUTION'] != "default"
|
5
|
+
end
|
6
|
+
|
7
|
+
require "logstash/outputs/elasticsearch"
|
8
|
+
|
9
|
+
module LogStash::Outputs::ElasticSearch::SpecHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include LogStash::Outputs::ElasticSearch::SpecHelper
|
14
|
+
end
|
@@ -40,10 +40,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
40
40
|
|
41
41
|
context "when setting bulk_path" do
|
42
42
|
let(:bulk_path) { "/meh" }
|
43
|
-
let(:options) { super.merge("bulk_path" => bulk_path) }
|
43
|
+
let(:options) { super().merge("bulk_path" => bulk_path) }
|
44
44
|
|
45
45
|
context "when using path" do
|
46
|
-
let(:options) { super.merge("path" => "/path") }
|
46
|
+
let(:options) { super().merge("path" => "/path") }
|
47
47
|
it "ignores the path setting" do
|
48
48
|
expect(described_class).to receive(:create_http_client) do |options|
|
49
49
|
expect(options[:bulk_path]).to eq(bulk_path)
|
@@ -66,7 +66,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
66
66
|
|
67
67
|
context "when using path" do
|
68
68
|
let(:path) { "/meh" }
|
69
|
-
let(:options) { super.merge("path" => path) }
|
69
|
+
let(:options) { super().merge("path" => path) }
|
70
70
|
it "sets bulk_path to path+_bulk" do
|
71
71
|
expect(described_class).to receive(:create_http_client) do |options|
|
72
72
|
expect(options[:bulk_path]).to eq("#{path}/_bulk")
|
@@ -88,10 +88,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
88
88
|
describe "healthcheck_path" do
|
89
89
|
context "when setting healthcheck_path" do
|
90
90
|
let(:healthcheck_path) { "/meh" }
|
91
|
-
let(:options) { super.merge("healthcheck_path" => healthcheck_path) }
|
91
|
+
let(:options) { super().merge("healthcheck_path" => healthcheck_path) }
|
92
92
|
|
93
93
|
context "when using path" do
|
94
|
-
let(:options) { super.merge("path" => "/path") }
|
94
|
+
let(:options) { super().merge("path" => "/path") }
|
95
95
|
it "ignores the path setting" do
|
96
96
|
expect(described_class).to receive(:create_http_client) do |options|
|
97
97
|
expect(options[:healthcheck_path]).to eq(healthcheck_path)
|
@@ -114,7 +114,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
114
114
|
|
115
115
|
context "when using path" do
|
116
116
|
let(:path) { "/meh" }
|
117
|
-
let(:options) { super.merge("path" => path) }
|
117
|
+
let(:options) { super().merge("path" => path) }
|
118
118
|
it "sets healthcheck_path to path" do
|
119
119
|
expect(described_class).to receive(:create_http_client) do |options|
|
120
120
|
expect(options[:healthcheck_path]).to eq(path)
|
@@ -136,10 +136,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
136
136
|
describe "sniffing_path" do
|
137
137
|
context "when setting sniffing_path" do
|
138
138
|
let(:sniffing_path) { "/meh" }
|
139
|
-
let(:options) { super.merge("sniffing_path" => sniffing_path) }
|
139
|
+
let(:options) { super().merge("sniffing_path" => sniffing_path) }
|
140
140
|
|
141
141
|
context "when using path" do
|
142
|
-
let(:options) { super.merge("path" => "/path") }
|
142
|
+
let(:options) { super().merge("path" => "/path") }
|
143
143
|
it "ignores the path setting" do
|
144
144
|
expect(described_class).to receive(:create_http_client) do |options|
|
145
145
|
expect(options[:sniffing_path]).to eq(sniffing_path)
|
@@ -162,7 +162,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
|
162
162
|
|
163
163
|
context "when using path" do
|
164
164
|
let(:path) { "/meh" }
|
165
|
-
let(:options) { super.merge("path" => path) }
|
165
|
+
let(:options) { super().merge("path" => path) }
|
166
166
|
it "sets sniffing_path to path+_nodes/http" do
|
167
167
|
expect(described_class).to receive(:create_http_client) do |options|
|
168
168
|
expect(options[:sniffing_path]).to eq("#{path}/_nodes/http")
|
@@ -0,0 +1,542 @@
|
|
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
|
+
let(:options) { { 'hosts' => [ 'localhost:12345' ] } }
|
8
|
+
let(:es_version) { '7.10.1' }
|
9
|
+
|
10
|
+
let(:do_register) { false }
|
11
|
+
let(:stub_plugin_register!) do
|
12
|
+
allow(subject).to receive(:last_es_version).and_return(es_version)
|
13
|
+
|
14
|
+
allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(:start)
|
15
|
+
|
16
|
+
# stub-out unrelated (finish_register) setup:
|
17
|
+
allow(subject).to receive(:discover_cluster_uuid)
|
18
|
+
allow(subject).to receive(:install_template)
|
19
|
+
allow(subject).to receive(:ilm_in_use?).and_return nil
|
20
|
+
|
21
|
+
# emulate 'successful' ES connection on the same thread
|
22
|
+
allow(subject).to receive(:after_successful_connection) { |&block| block.call }
|
23
|
+
allow(subject).to receive(:stop_after_successful_connection_thread)
|
24
|
+
|
25
|
+
subject.register
|
26
|
+
|
27
|
+
allow(subject.client).to receive(:maximum_seen_major_version).and_return(Integer(es_version.split('.').first))
|
28
|
+
|
29
|
+
# allow( subject.logger ).to receive(:info) do |msg|
|
30
|
+
# expect(msg).to include "New Elasticsearch output"
|
31
|
+
# end
|
32
|
+
end
|
33
|
+
|
34
|
+
@@logstash_oss = LogStash::OSS
|
35
|
+
|
36
|
+
before(:each) do
|
37
|
+
change_constant :OSS, false, target: LogStash # assume non-OSS by default
|
38
|
+
|
39
|
+
stub_plugin_register! if do_register
|
40
|
+
end
|
41
|
+
|
42
|
+
after(:each) do
|
43
|
+
subject.close if do_register
|
44
|
+
|
45
|
+
change_constant :OSS, @@logstash_oss, target: LogStash
|
46
|
+
end
|
47
|
+
|
48
|
+
context "default configuration" do
|
49
|
+
|
50
|
+
let(:options) { {} }
|
51
|
+
|
52
|
+
before { allow(subject).to receive(:last_es_version).and_return(es_version) }
|
53
|
+
|
54
|
+
it "does not use data-streams on LS 7.x" do
|
55
|
+
change_constant :LOGSTASH_VERSION, '7.10.0' do
|
56
|
+
expect( subject.data_stream_config? ).to be false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "warns when configuration is data-stream compliant (LS 7.x)" do
|
61
|
+
expect( subject.logger ).to receive(:warn) do |msg|
|
62
|
+
expect(msg).to include "Configuration is data stream compliant but due backwards compatibility Logstash 7.x"
|
63
|
+
end
|
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 'non-compatible ES' do
|
76
|
+
|
77
|
+
let(:es_version) { '7.8.0' }
|
78
|
+
|
79
|
+
it "does not print an error (from after_successful_connection thread)" do
|
80
|
+
change_constant :LOGSTASH_VERSION, '7.8.1' do
|
81
|
+
expect( subject.logger ).to_not receive(:error)
|
82
|
+
expect( subject ).to receive(:finish_register).once.and_call_original
|
83
|
+
stub_plugin_register!
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
context "ds-compatible configuration" do
|
92
|
+
|
93
|
+
let(:options) do
|
94
|
+
{
|
95
|
+
'hosts' => [ 'http://127.0.0.1:12345' ],
|
96
|
+
'http_compression' => 'true', 'bulk_path' => '_bulk', 'timeout' => '30',
|
97
|
+
'user' => 'elastic', 'password' => 'ForSearch!', 'ssl' => 'false'
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
before { allow(subject).to receive(:last_es_version).and_return(es_version) }
|
102
|
+
|
103
|
+
it "does not use data-streams on LS 7.x" do
|
104
|
+
change_constant :LOGSTASH_VERSION, '7.10.0' do
|
105
|
+
expect( subject.data_stream_config? ).to be false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "defaults to using data-streams on LS 8.0" do
|
110
|
+
change_constant :LOGSTASH_VERSION, '8.0.1' do
|
111
|
+
expect( subject.data_stream_config? ).to be true
|
112
|
+
end
|
113
|
+
change_constant :LOGSTASH_VERSION, '8.1.0' do
|
114
|
+
expect( subject.send(:check_data_stream_config!) ).to be true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "uses data-streams on LS 8.0 (OSS)" do
|
119
|
+
change_constant :LOGSTASH_VERSION, '8.0.1' do
|
120
|
+
change_constant :OSS, true, target: LogStash do
|
121
|
+
expect( subject.data_stream_config? ).to be true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'old ES' do
|
127
|
+
|
128
|
+
let(:es_version) { '7.8.1' }
|
129
|
+
|
130
|
+
it "prints an error (from after_successful_connection thread) on LS 8.0" do
|
131
|
+
change_constant :LOGSTASH_VERSION, '8.0.0' do
|
132
|
+
expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
|
133
|
+
{:es_version=>"7.8.1"})
|
134
|
+
stub_plugin_register!
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
context "default (non data-stream) configuration (on 7.x)" do
|
143
|
+
|
144
|
+
let(:options) do
|
145
|
+
{ 'data_stream_dataset' => 'test', 'data_stream_auto_routing' => 'false', 'user' => 'elastic' }
|
146
|
+
end
|
147
|
+
|
148
|
+
before { allow(subject).to receive(:last_es_version).and_return(es_version) }
|
149
|
+
|
150
|
+
it "does not default to data-streams" do
|
151
|
+
expect( subject.logger ).to receive(:error) do |msg|
|
152
|
+
expect(msg).to include "Ambiguous configuration; data stream settings are present, but data streams are not enabled"
|
153
|
+
end
|
154
|
+
change_constant :LOGSTASH_VERSION, '7.10.2' do
|
155
|
+
expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'explicit data_stream => false' do
|
160
|
+
|
161
|
+
let(:options) { super().merge('data_stream' => 'false') }
|
162
|
+
|
163
|
+
it "raises a configuration error (due ds specific settings)" do
|
164
|
+
expect( subject.logger ).to receive(:error).with(/Ambiguous configuration; data stream settings must not be present when data streams is disabled/,
|
165
|
+
{"data_stream_auto_routing"=>"false", "data_stream_dataset"=>"test"})
|
166
|
+
change_constant :LOGSTASH_VERSION, '7.10.2' do
|
167
|
+
expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
context "(explicit) ds disabled configuration" do
|
176
|
+
|
177
|
+
let(:options) { super().merge('data_stream' => false.to_s) }
|
178
|
+
|
179
|
+
before { allow(subject).to receive(:last_es_version).and_return(es_version) }
|
180
|
+
|
181
|
+
it "does not use data-streams on LS 7.x" do
|
182
|
+
change_constant :LOGSTASH_VERSION, '7.10.0' do
|
183
|
+
expect( subject.data_stream_config? ).to be false
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
it "does not use data-streams on LS 8.0" do
|
188
|
+
change_constant :LOGSTASH_VERSION, '8.0.0' do
|
189
|
+
expect( subject.data_stream_config? ).to be false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
it "does not print a warning" do
|
194
|
+
expect( subject.logger ).to_not receive(:warn)
|
195
|
+
change_constant :LOGSTASH_VERSION, '7.10.2' do
|
196
|
+
expect( subject.data_stream_config? ).to be false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
context "(explicit) ds enabled configuration" do
|
203
|
+
|
204
|
+
let(:options) { super().merge('data_stream' => true.to_s) }
|
205
|
+
|
206
|
+
before { allow(subject).to receive(:last_es_version).and_return(es_version) }
|
207
|
+
|
208
|
+
it "does use data-streams on LS 7.x" do
|
209
|
+
change_constant :LOGSTASH_VERSION, '7.9.1' do
|
210
|
+
expect( subject.data_stream_config? ).to be true
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
it "does use data-streams on LS 8.0" do
|
215
|
+
change_constant :LOGSTASH_VERSION, '8.1.0' do
|
216
|
+
expect( subject.data_stream_config? ).to be true
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'non-compatible ES' do
|
221
|
+
|
222
|
+
let(:es_version) { '6.8.11' }
|
223
|
+
|
224
|
+
it "prints an error (from after_successful_connection thread) on LS 7.x" do
|
225
|
+
change_constant :LOGSTASH_VERSION, '7.12.0' do
|
226
|
+
expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
|
227
|
+
{:es_version=>"6.8.11"})
|
228
|
+
stub_plugin_register!
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
it "prints an error (from after_successful_connection thread) on LS 8.0" do
|
233
|
+
change_constant :LOGSTASH_VERSION, '8.0.5' do
|
234
|
+
expect( subject.logger ).to receive(:error).with(/Elasticsearch version does not support data streams/,
|
235
|
+
{:es_version=>"6.8.11"})
|
236
|
+
stub_plugin_register!
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "auto routing" do
|
245
|
+
|
246
|
+
let(:options) { super().merge('data_stream' => 'true') }
|
247
|
+
let(:do_register) { true }
|
248
|
+
|
249
|
+
let(:event) do
|
250
|
+
event = LogStash::Event.new
|
251
|
+
event.set '[host][hostname]', 'orangutan'
|
252
|
+
event
|
253
|
+
end
|
254
|
+
|
255
|
+
context 'with data_stream.* event data' do
|
256
|
+
|
257
|
+
let(:event) do
|
258
|
+
super().tap do |event|
|
259
|
+
event.set '[data_stream][type]', 'metrics'
|
260
|
+
event.set '[data_stream][dataset]', 'src1'
|
261
|
+
event.set '[data_stream][namespace]', 'test'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'uses event specified target' do
|
266
|
+
tuple = subject.map_events([ event ]).first
|
267
|
+
expect( tuple.size ).to eql 3
|
268
|
+
expect( tuple[0] ).to eql 'create'
|
269
|
+
expect( tuple[1] ).to include :_index => 'metrics-src1-test'
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'with routing turned off' do
|
275
|
+
|
276
|
+
let(:options) { super().merge('data_stream_auto_routing' => 'false') }
|
277
|
+
|
278
|
+
let(:event) do
|
279
|
+
super().tap do |event|
|
280
|
+
event.set '[data_stream][type]', 'metrics'
|
281
|
+
event.set '[data_stream][dataset]', 'src1'
|
282
|
+
event.set '[data_stream][namespace]', 'test'
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'uses event specified target' do
|
287
|
+
tuple = subject.map_events([ event ]).first
|
288
|
+
expect( tuple.size ).to eql 3
|
289
|
+
expect( tuple[0] ).to eql 'create'
|
290
|
+
expect( tuple[1] ).to include :_index => 'logs-generic-default'
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
context 'with partial data_stream.* data' do
|
296
|
+
|
297
|
+
let(:options) { super().merge('data_stream_dataset' => 'data') }
|
298
|
+
|
299
|
+
let(:event) do
|
300
|
+
super().tap do |event|
|
301
|
+
event.set '[data_stream][type]', 'metrics'
|
302
|
+
event.set '[data_stream][dataset]', 'src1'
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'uses event specified target' do
|
307
|
+
tuple = subject.map_events([ event ]).first
|
308
|
+
expect( tuple.size ).to eql 3
|
309
|
+
expect( tuple[0] ).to eql 'create'
|
310
|
+
expect( tuple[1] ).to include :_index => 'metrics-src1-default'
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'with no data_stream.* fields' do
|
316
|
+
|
317
|
+
let(:options) { super().merge('data_stream_dataset' => 'stats', 'data_stream_type' => 'metrics') }
|
318
|
+
|
319
|
+
it 'uses configuration target' do
|
320
|
+
tuple = subject.map_events([ event ]).first
|
321
|
+
expect( tuple.size ).to eql 3
|
322
|
+
expect( tuple[0] ).to eql 'create'
|
323
|
+
expect( tuple[1] ).to include :_index => 'metrics-stats-default'
|
324
|
+
end
|
325
|
+
|
326
|
+
end
|
327
|
+
|
328
|
+
context 'with default configuration' do
|
329
|
+
|
330
|
+
it 'uses default target' do
|
331
|
+
tuple = subject.map_events([ event ]).first
|
332
|
+
expect( tuple.size ).to eql 3
|
333
|
+
expect( tuple[0] ).to eql 'create'
|
334
|
+
expect( tuple[1] ).to include :_index => 'logs-generic-default'
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "field sync" do
|
342
|
+
|
343
|
+
let(:options) { super().merge('data_stream' => 'true') }
|
344
|
+
|
345
|
+
let(:do_register) { true }
|
346
|
+
|
347
|
+
let(:event) do
|
348
|
+
event = LogStash::Event.new
|
349
|
+
event.set '[host][hostname]', 'orangutan'
|
350
|
+
event
|
351
|
+
end
|
352
|
+
|
353
|
+
context 'enabled and no event data' do
|
354
|
+
|
355
|
+
let(:options) { super().merge('data_stream_sync_fields' => 'true') }
|
356
|
+
|
357
|
+
it 'fills in DS fields' do
|
358
|
+
tuple = subject.map_events([ event ]).first
|
359
|
+
expect( tuple.size ).to eql 3
|
360
|
+
expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "default"})
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
context 'enabled and some event data' do
|
366
|
+
|
367
|
+
let(:options) { super().merge('data_stream_dataset' => 'ds1', 'data_stream_sync_fields' => 'true') }
|
368
|
+
|
369
|
+
let(:event) do
|
370
|
+
super().tap do |event|
|
371
|
+
event.set '[data_stream][namespace]', 'custom'
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
it 'fills in missing fields' do
|
376
|
+
tuple = subject.map_events([ event ]).first
|
377
|
+
expect( tuple.size ).to eql 3
|
378
|
+
expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "ds1", "namespace" => "custom"})
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'does not mutate data_stream hash' do
|
382
|
+
data_stream = event.get('data_stream')
|
383
|
+
data_stream_dup = data_stream.dup
|
384
|
+
subject.map_events([ event ])
|
385
|
+
expect( data_stream ).to eql data_stream_dup
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
|
390
|
+
context 'enabled with invalid data' do
|
391
|
+
|
392
|
+
let(:options) { super().merge('data_stream_sync_fields' => 'true') }
|
393
|
+
|
394
|
+
let(:event) do
|
395
|
+
super().tap do |event|
|
396
|
+
event.set '[data_stream]', false
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'overwrites invalid data_stream field' do
|
401
|
+
tuple = subject.map_events([ event ]).first
|
402
|
+
expect( tuple.size ).to eql 3
|
403
|
+
expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "default"})
|
404
|
+
end
|
405
|
+
|
406
|
+
end
|
407
|
+
|
408
|
+
context 'enabled having invalid data with routing disabled' do
|
409
|
+
|
410
|
+
let(:options) do
|
411
|
+
super().merge('data_stream_sync_fields' => 'true', 'data_stream_auto_routing' => 'false', 'data_stream_namespace' => 'ns1')
|
412
|
+
end
|
413
|
+
|
414
|
+
let(:event) do
|
415
|
+
super().tap do |event|
|
416
|
+
event.set '[data_stream][type]', 'foo'
|
417
|
+
event.set '[data_stream][dataset]', false
|
418
|
+
event.set '[data_stream][extra]', 0
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'overwrites invalid data_stream sub-fields' do
|
423
|
+
tuple = subject.map_events([ event ]).first
|
424
|
+
expect( tuple.size ).to eql 3
|
425
|
+
expect( tuple[2]['data_stream'] ).to eql({"type" => "logs", "dataset" => "generic", "namespace" => "ns1", "extra" => 0})
|
426
|
+
end
|
427
|
+
|
428
|
+
end
|
429
|
+
|
430
|
+
context 'disabled and no event data' do
|
431
|
+
|
432
|
+
let(:options) { super().merge('data_stream_dataset' => 'ds1', 'data_stream_sync_fields' => 'false') }
|
433
|
+
|
434
|
+
it 'does not fill DS fields' do
|
435
|
+
tuple = subject.map_events([ event ]).first
|
436
|
+
expect( tuple.size ).to eql 3
|
437
|
+
expect( tuple[2].keys ).to_not include 'data_stream'
|
438
|
+
end
|
439
|
+
|
440
|
+
end
|
441
|
+
|
442
|
+
context 'disabled and some event data' do
|
443
|
+
|
444
|
+
let(:options) { super().merge('data_stream_sync_fields' => 'false') }
|
445
|
+
|
446
|
+
let(:event) do
|
447
|
+
super().tap do |event|
|
448
|
+
event.set '[data_stream][type]', 'logs'
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'does not fill DS fields' do
|
453
|
+
tuple = subject.map_events([ event ]).first
|
454
|
+
expect( tuple.size ).to eql 3
|
455
|
+
expect( tuple[2]['data_stream'] ).to eql({ 'type' => 'logs'})
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|
459
|
+
|
460
|
+
end
|
461
|
+
|
462
|
+
describe "validation" do
|
463
|
+
|
464
|
+
context 'with too long dataset name' do
|
465
|
+
|
466
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => 'x' * 120) }
|
467
|
+
|
468
|
+
it 'fails' do
|
469
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
470
|
+
end
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
context 'with empty dataset name' do
|
475
|
+
|
476
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => '') }
|
477
|
+
|
478
|
+
it 'fails' do
|
479
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
480
|
+
end
|
481
|
+
|
482
|
+
end
|
483
|
+
|
484
|
+
context 'with invalid dataset char' do
|
485
|
+
|
486
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_dataset' => 'foo/bar') }
|
487
|
+
|
488
|
+
it 'fails' do
|
489
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
490
|
+
end
|
491
|
+
|
492
|
+
end
|
493
|
+
|
494
|
+
context 'with invalid namespace char' do
|
495
|
+
|
496
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_namespace' => 'foo*') }
|
497
|
+
|
498
|
+
it 'fails' do
|
499
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
500
|
+
end
|
501
|
+
|
502
|
+
end
|
503
|
+
|
504
|
+
context 'with invalid "empty" namespace' do
|
505
|
+
|
506
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_namespace' => ' ') }
|
507
|
+
|
508
|
+
it 'fails' do
|
509
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
513
|
+
|
514
|
+
context 'with invalid type' do
|
515
|
+
|
516
|
+
let(:options) { super().merge('data_stream' => 'true', 'data_stream_type' => 'custom') }
|
517
|
+
|
518
|
+
it 'fails' do
|
519
|
+
expect { LogStash::Outputs::ElasticSearch.new(options) }.to raise_error LogStash::ConfigurationError
|
520
|
+
end
|
521
|
+
|
522
|
+
end
|
523
|
+
|
524
|
+
end
|
525
|
+
|
526
|
+
private
|
527
|
+
|
528
|
+
def change_constant(name, new_value, target: Object)
|
529
|
+
old_value = target.const_get name
|
530
|
+
begin
|
531
|
+
target.send :remove_const, name
|
532
|
+
target.const_set name, new_value
|
533
|
+
yield if block_given?
|
534
|
+
ensure
|
535
|
+
if block_given?
|
536
|
+
target.send :remove_const, name rescue nil
|
537
|
+
target.const_set name, old_value
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
end
|