|
50 | 50 |
|
51 | 51 | describe "healthcheck url handling" do
|
52 | 52 | let(:initial_urls) { [::LogStash::Util::SafeURI.new("http://localhost:9200")] }
|
| 53 | + before(:example) do |
| 54 | + expect(adapter).to receive(:perform_request).with(anything, :get, "/", anything, anything) do |url, _, _, _, _| |
| 55 | + expect(url.path).to be_empty |
| 56 | + end |
| 57 | + end |
53 | 58 |
|
54 | 59 | context "and not setting healthcheck_path" do
|
55 | 60 | it "performs the healthcheck to the root" do
|
56 |
| - expect(adapter).to receive(:perform_request) do |url, method, req_path, _, _| |
57 |
| - expect(method).to eq(:head) |
| 61 | + expect(adapter).to receive(:perform_request).with(anything, :head, "/", anything, anything) do |url, _, _, _, _| |
58 | 62 | expect(url.path).to be_empty
|
59 |
| - expect(req_path).to eq("/") |
60 | 63 | end
|
61 |
| - subject.healthcheck! |
| 64 | + expect { subject.healthcheck! }.to raise_error(LogStash::ConfigurationError, "Could not connect to a compatible version of Elasticsearch") |
62 | 65 | end
|
63 | 66 | end
|
64 | 67 |
|
65 | 68 | context "and setting healthcheck_path" do
|
66 | 69 | let(:healthcheck_path) { "/my/health" }
|
67 | 70 | let(:options) { super().merge(:healthcheck_path => healthcheck_path) }
|
68 | 71 | it "performs the healthcheck to the healthcheck_path" do
|
69 |
| - expect(adapter).to receive(:perform_request) do |url, method, req_path, _, _| |
70 |
| - expect(method).to eq(:head) |
| 72 | + expect(adapter).to receive(:perform_request).with(anything, :head, eq(healthcheck_path), anything, anything) do |url, _, _, _, _| |
71 | 73 | expect(url.path).to be_empty
|
72 |
| - expect(req_path).to eq(healthcheck_path) |
73 | 74 | end
|
74 |
| - subject.healthcheck! |
| 75 | + expect { subject.healthcheck! }.to raise_error(LogStash::ConfigurationError, "Could not connect to a compatible version of Elasticsearch") |
75 | 76 | end
|
76 | 77 | end
|
77 | 78 | end
|
|
164 | 165 | end
|
165 | 166 | end
|
166 | 167 |
|
| 168 | + class MockResponse |
| 169 | + attr_reader :code, :headers |
| 170 | + |
| 171 | + def initialize(code = 200, body = nil, headers = {}) |
| 172 | + @code = code |
| 173 | + @body = body |
| 174 | + @headers = headers |
| 175 | + end |
| 176 | + |
| 177 | + def body |
| 178 | + @body.to_json |
| 179 | + end |
| 180 | + end |
| 181 | + |
167 | 182 | describe "connection management" do
|
168 | 183 | before(:each) { subject.start }
|
169 | 184 | context "with only one URL in the list" do
|
|
175 | 190 | end
|
176 | 191 |
|
177 | 192 | context "with multiple URLs in the list" do
|
| 193 | + let(:version_ok) do |
| 194 | + MockResponse.new(200, {"tagline" => "You Know, for Search", |
| 195 | + "version" => { |
| 196 | + "number" => '7.13.0', |
| 197 | + "build_flavor" => 'default'} |
| 198 | + }) |
| 199 | + end |
| 200 | + |
178 | 201 | before :each do
|
179 | 202 | allow(adapter).to receive(:perform_request).with(anything, :head, subject.healthcheck_path, {}, nil)
|
| 203 | + allow(adapter).to receive(:perform_request).with(anything, :get, subject.healthcheck_path, {}, nil).and_return(version_ok) |
180 | 204 | end
|
181 | 205 | let(:initial_urls) { [ ::LogStash::Util::SafeURI.new("http://localhost:9200"), ::LogStash::Util::SafeURI.new("http://localhost:9201"), ::LogStash::Util::SafeURI.new("http://localhost:9202") ] }
|
182 | 206 |
|
|
220 | 244 | ::LogStash::Util::SafeURI.new("http://otherhost:9201")
|
221 | 245 | ] }
|
222 | 246 |
|
| 247 | + let(:valid_response) { MockResponse.new(200, {"tagline" => "You Know, for Search", |
| 248 | + "version" => { |
| 249 | + "number" => '7.13.0', |
| 250 | + "build_flavor" => 'default'} |
| 251 | + }) } |
| 252 | + |
223 | 253 | before(:each) do
|
224 |
| - allow(subject).to receive(:perform_request_to_url).and_return(nil) |
| 254 | + allow(subject).to receive(:perform_request_to_url).and_return(valid_response) |
225 | 255 | subject.start
|
226 | 256 | end
|
227 | 257 |
|
|
240 | 270 | describe "license checking" do
|
241 | 271 | before(:each) do
|
242 | 272 | allow(subject).to receive(:health_check_request)
|
| 273 | + allow(subject).to receive(:elasticsearch?).and_return(true) |
243 | 274 | end
|
244 | 275 |
|
245 | 276 | let(:options) do
|
|
273 | 304 |
|
274 | 305 | before(:each) do
|
275 | 306 | allow(subject).to receive(:health_check_request)
|
| 307 | + allow(subject).to receive(:elasticsearch?).and_return(true) |
276 | 308 | end
|
277 | 309 |
|
278 | 310 | context "if ES doesn't return a valid license" do
|
|
319 | 351 | end
|
320 | 352 | end
|
321 | 353 | end
|
| 354 | + |
| 355 | +describe "#elasticsearch?" do |
| 356 | + let(:logger) { Cabin::Channel.get } |
| 357 | + let(:adapter) { double("Manticore Adapter") } |
| 358 | + let(:initial_urls) { [::LogStash::Util::SafeURI.new("http://localhost:9200")] } |
| 359 | + let(:options) { {:resurrect_delay => 2, :url_normalizer => proc {|u| u}} } # Shorten the delay a bit to speed up tests |
| 360 | + let(:es_node_versions) { [ "0.0.0" ] } |
| 361 | + let(:license_status) { 'active' } |
| 362 | + |
| 363 | + subject { LogStash::Outputs::ElasticSearch::HttpClient::Pool.new(logger, adapter, initial_urls, options) } |
| 364 | + |
| 365 | + let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200") } |
| 366 | + |
| 367 | + context "in case HTTP error code" do |
| 368 | + it "should fail for 401" do |
| 369 | + allow(adapter).to receive(:perform_request) |
| 370 | + .with(anything, :get, "/", anything, anything) |
| 371 | + .and_return(MockResponse.new(401)) |
| 372 | + |
| 373 | + expect(subject.elasticsearch?(url)).to be false |
| 374 | + end |
| 375 | + |
| 376 | + it "should fail for 403" do |
| 377 | + allow(adapter).to receive(:perform_request) |
| 378 | + .with(anything, :get, "/", anything, anything) |
| 379 | + .and_return(status: 403) |
| 380 | + expect(subject.elasticsearch?(url)).to be false |
| 381 | + end |
| 382 | + end |
| 383 | + |
| 384 | + context "when connecting to a cluster which reply without 'version' field" do |
| 385 | + it "should fail" do |
| 386 | + allow(adapter).to receive(:perform_request) |
| 387 | + .with(anything, :get, "/", anything, anything) |
| 388 | + .and_return(body: {"field" => "funky.com"}.to_json) |
| 389 | + expect(subject.elasticsearch?(url)).to be false |
| 390 | + end |
| 391 | + end |
| 392 | + |
| 393 | + context "when connecting to a cluster with version < 6.0.0" do |
| 394 | + it "should fail" do |
| 395 | + allow(adapter).to receive(:perform_request) |
| 396 | + .with(anything, :get, "/", anything, anything) |
| 397 | + .and_return(200, {"version" => { "number" => "5.0.0"}}.to_json) |
| 398 | + expect(subject.elasticsearch?(url)).to be false |
| 399 | + end |
| 400 | + end |
| 401 | + |
| 402 | + context "when connecting to a cluster with version in [6.0.0..7.0.0)" do |
| 403 | + it "must be successful with valid 'tagline'" do |
| 404 | + allow(adapter).to receive(:perform_request) |
| 405 | + .with(anything, :get, "/", anything, anything) |
| 406 | + .and_return(MockResponse.new(200, {"version" => {"number" => "6.5.0"}, "tagline" => "You Know, for Search"})) |
| 407 | + expect(subject.elasticsearch?(url)).to be true |
| 408 | + end |
| 409 | + |
| 410 | + it "should fail if invalid 'tagline'" do |
| 411 | + allow(adapter).to receive(:perform_request) |
| 412 | + .with(anything, :get, "/", anything, anything) |
| 413 | + .and_return(MockResponse.new(200, {"version" => {"number" => "6.5.0"}, "tagline" => "You don't know"})) |
| 414 | + expect(subject.elasticsearch?(url)).to be false |
| 415 | + end |
| 416 | + |
| 417 | + it "should fail if 'tagline' is not present" do |
| 418 | + allow(adapter).to receive(:perform_request) |
| 419 | + .with(anything, :get, "/", anything, anything) |
| 420 | + .and_return(MockResponse.new(200, {"version" => {"number" => "6.5.0"}})) |
| 421 | + expect(subject.elasticsearch?(url)).to be false |
| 422 | + end |
| 423 | + end |
| 424 | + |
| 425 | + context "when connecting to a cluster with version in [7.0.0..7.14.0)" do |
| 426 | + it "must be successful is 'build_flavor' is 'default' and tagline is correct" do |
| 427 | + allow(adapter).to receive(:perform_request) |
| 428 | + .with(anything, :get, "/", anything, anything) |
| 429 | + .and_return(MockResponse.new(200, {"version": {"number": "7.5.0", "build_flavor": "default"}, "tagline": "You Know, for Search"})) |
| 430 | + expect(subject.elasticsearch?(url)).to be true |
| 431 | + end |
| 432 | + |
| 433 | + it "should fail if 'build_flavor' is not 'default' and tagline is correct" do |
| 434 | + allow(adapter).to receive(:perform_request) |
| 435 | + .with(anything, :get, "/", anything, anything) |
| 436 | + .and_return(MockResponse.new(200, {"version": {"number": "7.5.0", "build_flavor": "oss"}, "tagline": "You Know, for Search"})) |
| 437 | + expect(subject.elasticsearch?(url)).to be false |
| 438 | + end |
| 439 | + |
| 440 | + it "should fail if 'build_flavor' is not present and tagline is correct" do |
| 441 | + allow(adapter).to receive(:perform_request) |
| 442 | + .with(anything, :get, "/", anything, anything) |
| 443 | + .and_return(MockResponse.new(200, {"version": {"number": "7.5.0"}, "tagline": "You Know, for Search"})) |
| 444 | + expect(subject.elasticsearch?(url)).to be false |
| 445 | + end |
| 446 | + end |
| 447 | + |
| 448 | + context "when connecting to a cluster with version >= 7.14.0" do |
| 449 | + it "should fail if 'X-elastic-product' header is not present" do |
| 450 | + allow(adapter).to receive(:perform_request) |
| 451 | + .with(anything, :get, "/", anything, anything) |
| 452 | + .and_return(MockResponse.new(200, {"version": {"number": "7.14.0"}})) |
| 453 | + expect(subject.elasticsearch?(url)).to be false |
| 454 | + end |
| 455 | + |
| 456 | + it "should fail if 'X-elastic-product' header is present but with bad value" do |
| 457 | + allow(adapter).to receive(:perform_request) |
| 458 | + .with(anything, :get, "/", anything, anything) |
| 459 | + .and_return(MockResponse.new(200, {"version": {"number": "7.14.0"}}, {'X-elastic-product' => 'not good'})) |
| 460 | + expect(subject.elasticsearch?(url)).to be false |
| 461 | + end |
| 462 | + |
| 463 | + it "must be successful when 'X-elastic-product' header is present with 'Elasticsearch' value" do |
| 464 | + allow(adapter).to receive(:perform_request) |
| 465 | + .with(anything, :get, "/", anything, anything) |
| 466 | + .and_return(MockResponse.new(200, {"version": {"number": "7.14.0"}}, {'X-elastic-product' => 'Elasticsearch'})) |
| 467 | + expect(subject.elasticsearch?(url)).to be true |
| 468 | + end |
| 469 | + end |
| 470 | +end |
0 commit comments