logstash-output-elasticsearch 11.12.4-java → 11.15.9-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.
@@ -50,6 +50,143 @@ describe LogStash::Outputs::ElasticSearch do
50
50
  subject.close
51
51
  end
52
52
 
53
+ context "check aborting of a batch" do
54
+ context "on an unreachable ES instance" do
55
+ let(:events) { [ ::LogStash::Event.new("foo" => "bar1"), ::LogStash::Event.new("foo" => "bar2") ] }
56
+
57
+ let(:shutdown_value) { true }
58
+
59
+ let(:logger) { double("logger") }
60
+
61
+ let(:never_ending) { Thread.new { sleep 1 while true } }
62
+
63
+ let(:do_register) { false }
64
+
65
+ before(:each) do
66
+ spy_http_client_builder!
67
+ stub_http_client_pool!
68
+
69
+ allow(subject).to receive(:finish_register) # stub-out thread completion (to avoid error log entries)
70
+
71
+ # emulate 'failed' ES connection, which sleeps forever
72
+ allow(subject).to receive(:after_successful_connection) { |&block| never_ending }
73
+ allow(subject).to receive(:stop_after_successful_connection_thread)
74
+
75
+ subject.register
76
+
77
+ allow(subject.client).to receive(:maximum_seen_major_version).at_least(:once).and_return(maximum_seen_major_version)
78
+ allow(subject.client).to receive(:get_xpack_info)
79
+
80
+ subject.client.pool.adapter.manticore.respond_with(:body => "{}")
81
+
82
+ allow(subject).to receive(:logger).and_return(logger)
83
+ allow(logger).to receive(:info)
84
+
85
+ allow(subject).to receive(:pipeline_shutdown_requested?) do
86
+ shutdown_value
87
+ end
88
+ end
89
+
90
+ it "the #multi_receive abort while waiting on unreachable and a shutdown is requested" do
91
+ expect { subject.multi_receive(events) }.to raise_error(org.logstash.execution.AbortedBatchException)
92
+ expect(logger).to have_received(:info).with(/Aborting the batch due to shutdown request while waiting for connections to become live/i)
93
+ end
94
+ end
95
+
96
+ context "on a reachable ES instance" do
97
+ let(:events) { [ ::LogStash::Event.new("foo" => "bar1"), ::LogStash::Event.new("foo" => "bar2") ] }
98
+
99
+ let(:logger) { double("logger") }
100
+
101
+ before(:each) do
102
+ allow(subject).to receive(:logger).and_return(logger)
103
+ allow(logger).to receive(:info)
104
+
105
+ allow(subject).to receive(:pipeline_shutdown_requested?).and_return(true)
106
+ allow(subject).to receive(:retrying_submit)
107
+ end
108
+
109
+ it "the #multi_receive doesn't abort when waiting for a connection on alive ES and a shutdown is requested" do
110
+ subject.multi_receive(events)
111
+ expect(logger).to_not have_received(:info).with(/Aborting the batch due to shutdown request while waiting for connections to become live/i)
112
+ end
113
+ end
114
+
115
+ context "when a connected ES becomes unreachable" do
116
+ # let(:error) do
117
+ # ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
118
+ # 429, double("url").as_null_object, request_body, double("response body")
119
+ # )
120
+ # end
121
+
122
+ shared_examples 'raise an abort error' do
123
+ let(:options) {
124
+ {
125
+ "index" => "my-index",
126
+ "hosts" => ["localhost","localhost:9202"],
127
+ "path" => "some-path",
128
+ "manage_template" => false
129
+ }
130
+ }
131
+
132
+ let(:manticore_urls) { subject.client.pool.urls }
133
+ let(:manticore_url) { manticore_urls.first }
134
+
135
+ let(:stub_http_client_pool!) do
136
+ [:start_resurrectionist, :start_sniffer, :healthcheck!].each do |method|
137
+ allow_any_instance_of(LogStash::Outputs::ElasticSearch::HttpClient::Pool).to receive(method)
138
+ end
139
+ end
140
+
141
+ let(:event) { ::LogStash::Event.new("foo" => "bar") }
142
+
143
+ let(:logger) { double("logger").as_null_object }
144
+ let(:response) { { :errors => [], :items => [] } }
145
+
146
+ let(:request_body) { double(:request_body, :bytesize => 1023) }
147
+
148
+ before(:each) do
149
+ bulk_param = [["index", anything, event.to_hash]]
150
+
151
+ allow(subject).to receive(:logger).and_return(logger)
152
+
153
+ # fail consistently for ever
154
+ allow(subject.client).to receive(:bulk).with(bulk_param).and_raise(error)
155
+ end
156
+
157
+ it "should exit the retry with an abort exception if shutdown is requested" do
158
+ # trigger the shutdown signal
159
+ allow(subject).to receive(:pipeline_shutdown_requested?) { true }
160
+
161
+ # execute in another thread because it blocks in a retry loop until the shutdown is triggered
162
+ th = Thread.new do
163
+ subject.multi_receive([event])
164
+ rescue org.logstash.execution.AbortedBatchException => e
165
+ # return exception's class so that it can be verified when retrieving the thread's value
166
+ e.class
167
+ end
168
+
169
+ expect(th.value).to eq(org.logstash.execution.AbortedBatchException)
170
+ end
171
+ end
172
+
173
+ context "with 429 error" do
174
+ let(:error) do
175
+ ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
176
+ 429, double("url").as_null_object, request_body, double("response body")
177
+ )
178
+ end
179
+
180
+ it_behaves_like 'raise an abort error'
181
+ end
182
+
183
+ context "with 'no connections' error" do
184
+ let(:error) { ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::NoConnectionAvailableError.new }
185
+
186
+ it_behaves_like 'raise an abort error'
187
+ end
188
+ end
189
+ end if LOGSTASH_VERSION >= '8.8'
53
190
 
54
191
  context "with an active instance" do
55
192
  let(:options) {
@@ -590,7 +727,7 @@ describe LogStash::Outputs::ElasticSearch do
590
727
 
591
728
  let(:event) { LogStash::Event.new("pipeline" => "my-ingest-pipeline") }
592
729
 
593
- it "should interpolate the pipeline value and set it" do
730
+ it "interpolate the pipeline value and set it" do
594
731
  expect(subject.send(:event_action_tuple, event)[1]).to include(:pipeline => "my-ingest-pipeline")
595
732
  end
596
733
  end
@@ -600,7 +737,66 @@ describe LogStash::Outputs::ElasticSearch do
600
737
 
601
738
  let(:event) { LogStash::Event.new("pipeline" => "") }
602
739
 
603
- it "should interpolate the pipeline value but not set it because it is empty" do
740
+ it "interpolates the pipeline value but not set it because it is empty" do
741
+ expect(subject.send(:event_action_tuple, event)[1]).not_to include(:pipeline)
742
+ end
743
+ end
744
+
745
+ context "with both pipeline and target_ingest_pipeline" do
746
+ let(:options) { {"pipeline" => "%{pipeline}" } }
747
+ let(:event) { LogStash::Event.new({"pipeline" => "my-ingest-pipeline", "[@metadata][target_ingest_pipeline]" => "meta-ingest-pipeline"}) }
748
+
749
+ it "interpolates the plugin's pipeline value" do
750
+ expect(subject.send(:event_action_tuple, event)[1]).to include(:pipeline => "my-ingest-pipeline")
751
+ end
752
+
753
+ context "when the plugin's `pipeline` is constant" do
754
+ let(:options) { super().merge("pipeline" => "my-constant-pipeline") }
755
+ it "uses plugin's pipeline value" do
756
+ expect(subject.send(:event_action_tuple, event)[1]).to include(:pipeline => "my-constant-pipeline")
757
+ end
758
+ end
759
+
760
+ context "when the plugin's `pipeline` includes an unresolvable sprintf placeholder" do
761
+ let(:options) { super().merge("pipeline" => "reference-%{unset}-field") }
762
+ it "does not use the target_ingest_pipeline" do
763
+ # when sprintf doesn't resolve a placeholder, the behaviour of our `pipeline` is UNSPECIFIED.
764
+ # here we only validate that the presence of the magic field does not
765
+ # override an explicitly-configured pipeline.
766
+ expect(subject.send(:event_action_tuple, event)[1]).to_not include(:pipeline => "my-ingest-pipeline")
767
+ end
768
+ end
769
+ end
770
+
771
+ context "with empty pipeline and target_ingest_pipeline" do
772
+ let(:options) { {"pipeline" => "%{pipeline}" } }
773
+ let(:event) { LogStash::Event.new({"pipeline" => "", "[@metadata][target_ingest_pipeline]" => "meta-ingest-pipeline"}) }
774
+
775
+ it "interpolates the pipeline value but not set it because pipeline is empty" do
776
+ expect(subject.send(:event_action_tuple, event)[1]).not_to include(:pipeline)
777
+ end
778
+ end
779
+
780
+ context "with target_ingest_pipeline" do
781
+ let(:event) { LogStash::Event.new({"pipeline" => "", "@metadata" => {"target_ingest_pipeline" => "meta-ingest-pipeline"}}) }
782
+
783
+ it "interpolates the target_ingest_pipeline value and set it" do
784
+ expect(subject.send(:event_action_tuple, event)[1]).to include(:pipeline => "meta-ingest-pipeline")
785
+ end
786
+ end
787
+
788
+ context "with empty target_ingest_pipeline" do
789
+ let(:event) { LogStash::Event.new({"pipeline" => "", "@metadata" => {"host" => "elastic"}}) }
790
+
791
+ it "does not set pipeline" do
792
+ expect(subject.send(:event_action_tuple, event)[1]).not_to include(:pipeline)
793
+ end
794
+ end
795
+
796
+ context "with empty pipeline and empty target_ingest_pipeline" do
797
+ let(:event) { LogStash::Event.new }
798
+
799
+ it "does not set pipeline" do
604
800
  expect(subject.send(:event_action_tuple, event)[1]).not_to include(:pipeline)
605
801
  end
606
802
  end
@@ -640,9 +836,8 @@ describe LogStash::Outputs::ElasticSearch do
640
836
  end
641
837
  end
642
838
 
643
-
644
- context "With the 'ssl' option" do
645
- let(:options) { {"ssl" => true}}
839
+ context "With the 'ssl_enabled' option" do
840
+ let(:options) { {"ssl_enabled" => true}}
646
841
 
647
842
  include_examples("an encrypted client connection")
648
843
  end
@@ -653,6 +848,81 @@ describe LogStash::Outputs::ElasticSearch do
653
848
  end
654
849
  end
655
850
 
851
+ describe "SSL deprecated settings" do
852
+ let(:base_options) { {"ssl" => "true"} }
853
+
854
+ context "with client certificate" do
855
+ let(:do_register) { true }
856
+ let(:cacert) { Stud::Temporary.file.path }
857
+ let(:options) { base_options.merge(
858
+ "cacert" => cacert,
859
+ "ssl_certificate_verification" => false
860
+ ) }
861
+
862
+ after :each do
863
+ File.delete(cacert)
864
+ end
865
+
866
+ it "should map new configs into params" do
867
+ expect(subject.params).to match hash_including(
868
+ "ssl_enabled" => true,
869
+ "ssl_verification_mode" => "none",
870
+ "ssl_certificate_authorities" => [cacert]
871
+ )
872
+ end
873
+
874
+ it "should set new configs variables" do
875
+ expect(subject.instance_variable_get(:@ssl_enabled)).to eql(true)
876
+ expect(subject.instance_variable_get(:@ssl_verification_mode)).to eql("none")
877
+ expect(subject.instance_variable_get(:@ssl_certificate_authorities)).to eql([cacert])
878
+ end
879
+ end
880
+
881
+ context "with java stores" do
882
+ let(:do_register) { true }
883
+ let(:keystore) { Stud::Temporary.file.path }
884
+ let(:truststore) { Stud::Temporary.file.path }
885
+ let(:options) { base_options.merge(
886
+ "keystore" => keystore,
887
+ "keystore_password" => "keystore",
888
+ "truststore" => truststore,
889
+ "truststore_password" => "truststore",
890
+ "ssl_certificate_verification" => true
891
+ ) }
892
+
893
+ let(:spy_http_client_builder!) do
894
+ allow(described_class::HttpClientBuilder).to receive(:build).with(any_args).and_call_original
895
+ allow(described_class::HttpClientBuilder).to receive(:setup_ssl).with(any_args).and_return({})
896
+ end
897
+
898
+ after :each do
899
+ File.delete(keystore)
900
+ File.delete(truststore)
901
+ end
902
+
903
+ it "should map new configs into params" do
904
+ expect(subject.params).to match hash_including(
905
+ "ssl_enabled" => true,
906
+ "ssl_keystore_path" => keystore,
907
+ "ssl_truststore_path" => truststore,
908
+ "ssl_verification_mode" => "full"
909
+ )
910
+
911
+ expect(subject.params["ssl_keystore_password"].value).to eql("keystore")
912
+ expect(subject.params["ssl_truststore_password"].value).to eql("truststore")
913
+ end
914
+
915
+ it "should set new configs variables" do
916
+ expect(subject.instance_variable_get(:@ssl_enabled)).to eql(true)
917
+ expect(subject.instance_variable_get(:@ssl_keystore_path)).to eql(keystore)
918
+ expect(subject.instance_variable_get(:@ssl_keystore_password).value).to eql("keystore")
919
+ expect(subject.instance_variable_get(:@ssl_truststore_path)).to eql(truststore)
920
+ expect(subject.instance_variable_get(:@ssl_truststore_password).value).to eql("truststore")
921
+ expect(subject.instance_variable_get(:@ssl_verification_mode)).to eql("full")
922
+ end
923
+ end
924
+ end
925
+
656
926
  describe "retry_on_conflict" do
657
927
  let(:num_retries) { 123 }
658
928
  let(:event) { LogStash::Event.new("myactionfield" => "update", "message" => "blah") }
@@ -890,41 +1160,63 @@ describe LogStash::Outputs::ElasticSearch do
890
1160
  end if LOGSTASH_VERSION > '6.0'
891
1161
 
892
1162
  context 'handling elasticsearch document-level status meant for the DLQ' do
1163
+ let(:es_api_action) { "CUSTOM_ACTION" }
1164
+ let(:es_api_params) { Hash['_index' => 'MY_INDEX'] }
1165
+
893
1166
  let(:options) { { "manage_template" => false, "data_stream" => 'false' } }
894
- let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, LogStash::Event.new("foo" => "bar")) }
1167
+ let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(es_api_action, es_api_params, LogStash::Event.new("foo" => "bar")) }
1168
+
1169
+ let(:logger) { double('logger').as_null_object }
1170
+ before(:each) { subject.instance_variable_set(:@logger, logger) }
895
1171
 
896
1172
  context 'when @dlq_writer is nil' do
897
1173
  before { subject.instance_variable_set '@dlq_writer', nil }
898
- let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, LogStash::Event.new("foo" => "bar")) }
899
1174
 
900
1175
  context 'resorting to previous behaviour of logging the error' do
901
1176
  context 'getting an invalid_index_name_exception' do
902
1177
  it 'should log at ERROR level' do
903
- subject.instance_variable_set(:@logger, double("logger").as_null_object)
1178
+ # logger = double("logger").as_null_object
1179
+ # subject.instance_variable_set(:@logger, logger)
1180
+
904
1181
  mock_response = { 'index' => { 'error' => { 'type' => 'invalid_index_name_exception' } } }
905
1182
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
1183
+
1184
+ expect(logger).to have_received(:error).with(a_string_including("Could not index event to Elasticsearch"),
1185
+ a_hash_including(:status => :some_status,
1186
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1187
+ :response => mock_response))
906
1188
  end
907
1189
  end
908
1190
 
909
1191
  context 'when getting any other exception' do
910
1192
  it 'should log at WARN level' do
911
- logger = double("logger").as_null_object
912
- subject.instance_variable_set(:@logger, logger)
913
- expect(logger).to receive(:warn).with(a_string_including "Could not index event to Elasticsearch. status: some_status, action: [:action, :params, {")
1193
+ # logger = double("logger").as_null_object
1194
+ # subject.instance_variable_set(:@logger, logger)
1195
+
914
1196
  mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
915
1197
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
1198
+
1199
+ expect(logger).to have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"),
1200
+ a_hash_including(:status => :some_status,
1201
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1202
+ :response => mock_response))
916
1203
  end
917
1204
  end
918
1205
 
919
1206
  context 'when the response does not include [error]' do
920
1207
  it 'should not fail, but just log a warning' do
921
- logger = double("logger").as_null_object
922
- subject.instance_variable_set(:@logger, logger)
923
- expect(logger).to receive(:warn).with(a_string_including "Could not index event to Elasticsearch. status: some_status, action: [:action, :params, {")
1208
+ # logger = double("logger").as_null_object
1209
+ # subject.instance_variable_set(:@logger, logger)
1210
+
924
1211
  mock_response = { 'index' => {} }
925
1212
  expect do
926
1213
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, :some_status, mock_response)
927
1214
  end.to_not raise_error
1215
+
1216
+ expect(logger).to have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"),
1217
+ a_hash_including(:status => :some_status,
1218
+ :action => [es_api_action, es_api_params, action.event.to_hash],
1219
+ :response => mock_response))
928
1220
  end
929
1221
  end
930
1222
  end
@@ -944,6 +1236,8 @@ describe LogStash::Outputs::ElasticSearch do
944
1236
  mock_response = { 'index' => { 'error' => { 'type' => 'illegal_argument_exception' } } }
945
1237
  action = LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, event)
946
1238
  subject.handle_dlq_response("Could not index event to Elasticsearch.", action, 404, mock_response)
1239
+
1240
+ expect(logger).to_not have_received(:warn).with(a_string_including("Could not index event to Elasticsearch"))
947
1241
  end
948
1242
  end
949
1243
 
@@ -1034,12 +1328,12 @@ describe LogStash::Outputs::ElasticSearch do
1034
1328
  it 'adds the appropriate Authorization header to the manticore client' do
1035
1329
  expect(manticore_options[:headers]).to eq({ "Authorization" => base64_api_key })
1036
1330
  end
1037
- it 'is provides ssl=>true to the http client builder' do; aggregate_failures do
1038
- expect(described_class::HttpClientBuilder).to have_received(:build).with(anything, anything, hash_including('ssl'=>true))
1331
+ it 'is provides ssl_enabled=>true to the http client builder' do; aggregate_failures do
1332
+ expect(described_class::HttpClientBuilder).to have_received(:build).with(anything, anything, hash_including('ssl_enabled'=>true))
1039
1333
  end; end
1040
1334
  end
1041
1335
 
1042
- context "when set without ssl => true" do
1336
+ context "when set without ssl_enabled => true" do
1043
1337
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1044
1338
  let(:options) { { "api_key" => api_key } }
1045
1339
 
@@ -1055,14 +1349,14 @@ describe LogStash::Outputs::ElasticSearch do
1055
1349
  end
1056
1350
  end
1057
1351
 
1058
- context "when set without ssl specified but with an https host" do
1352
+ context "when set without ssl_enabled specified but with an https host" do
1059
1353
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1060
1354
  let(:options) { { "hosts" => ["https://some.host.com"], "api_key" => api_key } }
1061
1355
 
1062
1356
  it_behaves_like 'secure api-key authenticated client'
1063
1357
  end
1064
1358
 
1065
- context "when set without ssl specified but with an http host`" do
1359
+ context "when set without ssl_enabled specified but with an http host`" do
1066
1360
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1067
1361
  let(:options) { { "hosts" => ["http://some.host.com"], "api_key" => api_key } }
1068
1362
 
@@ -1071,9 +1365,9 @@ describe LogStash::Outputs::ElasticSearch do
1071
1365
  end
1072
1366
  end
1073
1367
 
1074
- context "when set with `ssl => false`" do
1368
+ context "when set with `ssl_enabled => false`" do
1075
1369
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1076
- let(:options) { { "ssl" => "false", "api_key" => api_key } }
1370
+ let(:options) { { "ssl_enabled" => "false", "api_key" => api_key } }
1077
1371
 
1078
1372
  it "should raise a configuration error" do
1079
1373
  expect { subject.register }.to raise_error LogStash::ConfigurationError, /requires SSL\/TLS/
@@ -1083,13 +1377,13 @@ describe LogStash::Outputs::ElasticSearch do
1083
1377
  context "when set" do
1084
1378
  let(:options) { { "api_key" => ::LogStash::Util::Password.new(api_key) } }
1085
1379
 
1086
- context "with ssl => true" do
1087
- let(:options) { super().merge("ssl" => true) }
1380
+ context "with ssl_enabled => true" do
1381
+ let(:options) { super().merge("ssl_enabled" => true) }
1088
1382
  it_behaves_like 'secure api-key authenticated client'
1089
1383
  end
1090
1384
 
1091
- context "with ssl => false" do
1092
- let(:options) { super().merge("ssl" => "false") }
1385
+ context "with ssl_enabled => false" do
1386
+ let(:options) { super().merge("ssl_enabled" => "false") }
1093
1387
 
1094
1388
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1095
1389
  it "should raise a configuration error" do
@@ -1097,7 +1391,7 @@ describe LogStash::Outputs::ElasticSearch do
1097
1391
  end
1098
1392
  end
1099
1393
 
1100
- context "without ssl specified" do
1394
+ context "without ssl_enabled specified" do
1101
1395
  context "with an https host" do
1102
1396
  let(:options) { super().merge("hosts" => ["https://some.host.com"]) }
1103
1397
  it_behaves_like 'secure api-key authenticated client'
@@ -1121,7 +1415,7 @@ describe LogStash::Outputs::ElasticSearch do
1121
1415
 
1122
1416
  context 'user also set' do
1123
1417
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1124
- let(:options) { { "ssl" => true, "api_key" => api_key, 'user' => 'another' } }
1418
+ let(:options) { { "ssl_enabled" => true, "api_key" => api_key, 'user' => 'another' } }
1125
1419
 
1126
1420
  it "should fail" do
1127
1421
  expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
@@ -1130,7 +1424,7 @@ describe LogStash::Outputs::ElasticSearch do
1130
1424
 
1131
1425
  context 'cloud_auth also set' do
1132
1426
  let(:do_register) { false } # this is what we want to test, so we disable the before(:each) call
1133
- let(:options) { { "ssl" => true, "api_key" => api_key, 'cloud_auth' => 'foobar' } }
1427
+ let(:options) { { "ssl_enabled" => true, "api_key" => api_key, 'cloud_auth' => 'foobar' } }
1134
1428
 
1135
1429
  it "should fail" do
1136
1430
  expect { subject.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
@@ -1225,6 +1519,42 @@ describe LogStash::Outputs::ElasticSearch do
1225
1519
  end
1226
1520
 
1227
1521
  end
1522
+
1523
+ context 'during register/finish_register' do
1524
+
1525
+ let(:options) { { 'hosts' => '127.0.0.1:9999', 'data_stream' => 'true' } }
1526
+ let(:es_version) { '8.7.0' } # DS default on LS 8.x
1527
+
1528
+ before do
1529
+ allow(subject).to receive(:discover_cluster_uuid)
1530
+ allow(subject).to receive(:maybe_create_rollover_alias)
1531
+ allow(subject).to receive(:maybe_create_ilm_policy)
1532
+ allow(subject).to receive(:build_client)
1533
+ end
1534
+
1535
+ # this test could not have been done using latches as the fix to the race
1536
+ # condition alters the order of the instructions in elasticsearch.rb
1537
+ #
1538
+ # the race condition happened when the @index was set to the datastream
1539
+ # after `ilm_in_use?` is called but before `setup_ilm`
1540
+ it 'doesn\'t have a race condition leading to resetting back to ILM' do
1541
+ ilm_in_use = subject.method(:ilm_in_use?)
1542
+ expect(subject).to receive(:ilm_in_use?) do |params|
1543
+ ret = ilm_in_use.call
1544
+ sleep 3
1545
+ ret
1546
+ end
1547
+ setup_mapper_and_target = subject.method(:setup_mapper_and_target)
1548
+ expect(subject).to receive(:setup_mapper_and_target).once do |params|
1549
+ sleep 1
1550
+ setup_mapper_and_target.call(params)
1551
+ end
1552
+ subject.register
1553
+ sleep 6
1554
+ expect(subject.index).to eq("logs-generic-default")
1555
+ end
1556
+
1557
+ end
1228
1558
  end
1229
1559
 
1230
1560
  @private