|
14 | 14 | describe LogStash::ConfigManagement::ElasticsearchSource do |
15 | 15 | let(:system_indices_api) { LogStash::ConfigManagement::SystemIndicesFetcher::SYSTEM_INDICES_API_PATH } |
16 | 16 | let(:system_indices_url_regex) { Regexp.new("^#{system_indices_api}") } |
| 17 | + let(:system_indices_url_search_regex) { Regexp.new("^#{Regexp.escape(system_indices_api)}[?]id=([^=&]+)$") } |
| 18 | + let(:system_indices_url_all_regex) { Regexp.new("^#{Regexp.escape(system_indices_api)}/?$") } |
17 | 19 | let(:elasticsearch_url) { ["https://localhost:9898"] } |
18 | 20 | let(:elasticsearch_username) { "elastictest" } |
19 | 21 | let(:elasticsearch_password) { "testchangeme" } |
|
91 | 93 |
|
92 | 94 | let(:es_version_response) { es_version_8_response } |
93 | 95 | let(:es_version_8_response) { cluster_info("8.0.0-SNAPSHOT") } |
| 96 | + let(:es_version_8_3_response) { cluster_info("8.3.0") } |
94 | 97 | let(:es_version_7_9_response) { cluster_info("7.9.1") } |
95 | 98 |
|
96 | 99 | let(:elasticsearch_7_9_err_response) { |
|
230 | 233 | let(:pipeline_id) { "super_generator" } |
231 | 234 | let(:elasticsearch_response) { {"#{pipeline_id}" => {"pipeline" => "#{config}"}} } |
232 | 235 | let(:all_pipelines) { JSON.parse(::File.read(::File.join(::File.dirname(__FILE__), "fixtures", "pipelines.json"))) } |
233 | | - let(:mock_logger) { double("fetcher's logger") } |
| 236 | + let(:mock_logger) { double("fetcher's logger").as_null_object } |
| 237 | + |
| 238 | + let(:bad_response_code_error) { LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError } |
234 | 239 |
|
235 | 240 | before(:each) { |
236 | 241 | allow(subject).to receive(:logger).and_return(mock_logger) |
|
242 | 247 | expect(subject.get_single_pipeline_setting(pipeline_id)).to eq({"pipeline" => "#{config}"}) |
243 | 248 | end |
244 | 249 |
|
245 | | - it "#fetch_config from ES v8.3" do |
246 | | - expect(mock_client).to receive(:get).with("#{described_class::SYSTEM_INDICES_API_PATH}?id=#{pipeline_id}").and_return(elasticsearch_response.clone) |
247 | | - expect(subject.fetch_config(es_version_8_3, [pipeline_id], mock_client)).to eq(elasticsearch_response) |
248 | | - expect(subject.get_single_pipeline_setting(pipeline_id)).to eq({"pipeline" => "#{config}"}) |
249 | | - end |
| 250 | + { |
| 251 | + 'v8.3' => { major: 8, minor: 3}, |
| 252 | + 'v9.0' => { major: 9, minor: 0} |
| 253 | + }.each do |desc, es_version| |
| 254 | + context "ES #{desc}" do |
| 255 | + it "#fetch_config works" do |
| 256 | + expect(mock_client).to receive(:get).with("#{described_class::SYSTEM_INDICES_API_PATH}?id=#{pipeline_id}").and_return(elasticsearch_response.clone) |
| 257 | + expect(subject.fetch_config(es_version, [pipeline_id], mock_client)).to eq(elasticsearch_response) |
| 258 | + expect(subject.get_single_pipeline_setting(pipeline_id)).to eq({"pipeline" => "#{config}"}) |
| 259 | + end |
250 | 260 |
|
251 | | - it "#fetch_config from ES v9.0" do |
252 | | - expect(mock_client).to receive(:get).with("#{described_class::SYSTEM_INDICES_API_PATH}?id=#{pipeline_id}").and_return(elasticsearch_response.clone) |
253 | | - expect(subject.fetch_config(es_version_9_0, [pipeline_id], mock_client)).to eq(elasticsearch_response) |
254 | | - expect(subject.get_single_pipeline_setting(pipeline_id)).to eq({"pipeline" => "#{config}"}) |
| 261 | + it "#fetch_config from ES v8.3 with 404->200 is empty list" do |
| 262 | + wildcard_search_path = "#{described_class::SYSTEM_INDICES_API_PATH}?id=#{pipeline_id}" |
| 263 | + expect(mock_client).to receive(:get).with(wildcard_search_path) |
| 264 | + .and_raise(bad_response_code_error.new(404, wildcard_search_path, nil, '{}')) |
| 265 | + expect(mock_client).to receive(:get).with("#{described_class::SYSTEM_INDICES_API_PATH}/").and_return({}) |
| 266 | + expect(subject.fetch_config(es_version, [pipeline_id], mock_client)).to eq({}) |
| 267 | + end |
| 268 | + |
| 269 | + it "#fetch_config from ES v8.3 with 404->404 is error" do |
| 270 | + # 404's on Wildcard search need to be confirmed with a 404 from the get-all endpoint |
| 271 | + wildcard_search_path = "#{described_class::SYSTEM_INDICES_API_PATH}?id=#{pipeline_id}" |
| 272 | + expect(mock_client).to receive(:get).with(wildcard_search_path) |
| 273 | + .and_raise(bad_response_code_error.new(404, wildcard_search_path, nil, '{}')) |
| 274 | + get_all_path = "#{described_class::SYSTEM_INDICES_API_PATH}/" |
| 275 | + expect(mock_client).to receive(:get).with(get_all_path) |
| 276 | + .and_raise(bad_response_code_error.new(404, get_all_path, nil, '{}')) |
| 277 | + expect { subject.fetch_config(es_version, [pipeline_id], mock_client) }.to raise_error(LogStash::ConfigManagement::ElasticsearchSource::RemoteConfigError) |
| 278 | + end |
| 279 | + end |
255 | 280 | end |
256 | 281 |
|
257 | 282 | it "#fetch_config should raise error" do |
|
359 | 384 | expect { subject.fetch_config(empty_es_version, [pipeline_id, another_pipeline_id], mock_client) }.to raise_error(LogStash::ConfigManagement::ElasticsearchSource::RemoteConfigError) |
360 | 385 | end |
361 | 386 |
|
362 | | - it "#fetch_config should raise error when response is empty" do |
| 387 | + it "#fetch_config should raise error when response is malformed" do |
363 | 388 | expect(mock_client).to receive(:post).with("#{described_class::PIPELINE_INDEX}/_mget", {}, "{\"docs\":[{\"_id\":\"#{pipeline_id}\"},{\"_id\":\"#{another_pipeline_id}\"}]}").and_return(LogStash::Json.load("{}")) |
364 | 389 | expect { subject.fetch_config(empty_es_version, [pipeline_id, another_pipeline_id], mock_client) }.to raise_error(LogStash::ConfigManagement::ElasticsearchSource::RemoteConfigError) |
365 | 390 | end |
|
760 | 785 | expect { subject.pipeline_configs }.to raise_error /Something bad/ |
761 | 786 | end |
762 | 787 |
|
763 | | - it "returns empty pipeline when ES client raise BadResponseCodeError in [8]" do |
764 | | - allow(mock_client).to receive(:get).with("/").and_return(es_version_response) |
765 | | - expect(mock_client).to receive(:get).with(system_indices_url_regex).and_raise(bad_response_404) |
766 | | - expect(subject.pipeline_configs).to be_empty |
| 788 | + context "8.0" do |
| 789 | + it "returns empty pipeline when ES client raise BadResponseCodeError in [8]" do |
| 790 | + allow(mock_client).to receive(:get).with("/").and_return(es_version_response) |
| 791 | + expect(mock_client).to receive(:get).with(system_indices_url_regex).and_raise(bad_response_404) |
| 792 | + expect { subject.pipeline_configs }.to raise_error /response code '404'/ |
| 793 | + end |
| 794 | + end |
| 795 | + |
| 796 | + context "8.3+" do |
| 797 | + it "returns empty pipeline when ES search 404's but client-side 200's and includes no matching pipelines" do |
| 798 | + expect(mock_client).to receive(:get).with("/").and_return(es_version_8_3_response) |
| 799 | + expect(mock_client).to receive(:get).with(system_indices_url_search_regex).and_raise(bad_response_404) |
| 800 | + expect(mock_client).to receive(:get).with(system_indices_url_all_regex).and_return({}) |
| 801 | + expect(subject.pipeline_configs).to be_empty |
| 802 | + end |
| 803 | + |
| 804 | + it "raises the 404 when ES search 404's and client-side query 404's too" do |
| 805 | + expect(mock_client).to receive(:get).with("/").and_return(es_version_8_3_response) |
| 806 | + expect(mock_client).to receive(:get).with(system_indices_url_search_regex).and_raise(bad_response_404) |
| 807 | + expect(mock_client).to receive(:get).with(system_indices_url_all_regex).and_raise(bad_response_404) |
| 808 | + expect { subject.pipeline_configs }.to raise_error /response code '404'/ |
| 809 | + end |
767 | 810 | end |
768 | 811 |
|
769 | 812 | it "returns empty pipeline when ES client raise BadResponseCodeError in [7.9]" do |
|
0 commit comments