spec/app/preflight_check_spec.rb (146 lines of code) (raw):

# # Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one # or more contributor license agreements. Licensed under the Elastic License; # you may not use this file except in compliance with the Elastic License. # # frozen_string_literal: true require 'app/preflight_check' describe App::PreflightCheck do describe '.run!' do let(:client) { double } let(:native_mode) { true } before(:each) do allow(described_class).to receive(:client).and_return(client) allow(App::Config).to receive(:native_mode).and_return(native_mode) end context 'when Elasticsearch is not running' do let(:cluster) { double } before(:each) do stub_const('App::PreflightCheck::STARTUP_RETRY_INTERVAL', 1) stub_const('App::PreflightCheck::STARTUP_RETRY_TIMEOUT', 3) allow(client).to receive(:cluster).and_return(cluster) allow(cluster).to receive(:health).and_raise(Faraday::ConnectionFailed, 'nope') end it 'should retry multiple times and fail the check' do expect(cluster).to receive(:health).at_least(2).times expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when Elasticsearch is running' do before(:each) do stub_const('App::PreflightCheck::STARTUP_RETRY_INTERVAL', 0) stub_const('App::PreflightCheck::STARTUP_RETRY_TIMEOUT', 0) allow(client).to receive_message_chain(:cluster, :health).and_return({ 'status' => status }) end context 'when Elasticsearch status is red' do let(:status) { 'red' } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when Elasticsearch status is yellow' do let(:status) { 'yellow' } before(:each) do allow(described_class).to receive(:check_es_version!) allow(described_class).to receive(:check_system_indices!) end it 'should log warn message' do expect(Utility::Logger).to receive(:warn) described_class.run! end end context 'when Elasticsearch status is invalid status' do let(:status) { 'garbage' } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when Elasticsearch status is green' do let(:status) { 'green' } let(:es_version) { '8.4.0-SNAPSHOT' } before(:each) do allow(client).to receive(:info).and_return({ 'version' => { 'number' => es_version } }) end context 'when Elasticsearch version doesn\'t match connector service version' do it 'should fail the check' do stub_const('App::VERSION', '8.5.0.0-foobar') expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when Elasticsearch version matches connector service version' do let(:indices) { double } before(:each) do stub_const('App::VERSION', '8.4.0.0-foobar') allow(client).to receive(:indices).and_return(indices) allow(indices).to receive(:exists?).with(:index => Utility::Constants::CONNECTORS_INDEX).and_return(connector_index_exist) allow(indices).to receive(:exists?).with(:index => Utility::Constants::JOB_INDEX).and_return(job_index_exist) end context 'with retries' do let(:connector_index_exist) { true } let(:job_index_exist) { false } before(:each) do stub_const('App::PreflightCheck::STARTUP_RETRY_INTERVAL', 1) stub_const('App::PreflightCheck::STARTUP_RETRY_TIMEOUT', 3) end it 'should retry multiple times and fail the check' do expect(indices).to receive(:exists?).with(:index => Utility::Constants::CONNECTORS_INDEX).at_least(2).times expect(indices).to receive(:exists?).with(:index => Utility::Constants::JOB_INDEX).at_least(2).times expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when both indices exist' do let(:connector_index_exist) { true } let(:job_index_exist) { true } it 'should pass the check' do expect { described_class.run! }.to_not raise_error(described_class::CheckFailure) end context 'when in single mode' do let(:native_mode) { false } before(:each) do allow(App::Config).to receive(:service_type).and_return('mongodb') allow(Connectors::REGISTRY).to receive(:registered?).and_return(supported?) end context 'when service type is not supported' do let(:supported?) { false } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when service type is supported' do let(:supported?) { true } it 'should fail the check' do expect { described_class.run! }.to_not raise_error(described_class::CheckFailure) end end end end context 'when connector index does not exist' do let(:connector_index_exist) { false } let(:job_index_exist) { true } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when job index does not exist' do let(:connector_index_exist) { true } let(:job_index_exist) { false } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when both indices do not exist' do let(:connector_index_exist) { false } let(:job_index_exist) { false } it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end context 'when authorization error appears' do let(:connector_index_exist) { true } let(:job_index_exist) { true } before(:each) do allow(client).to receive_message_chain(:cluster, :health).and_raise(Elastic::Transport::Transport::Errors::Unauthorized) end it 'should fail the check' do expect { described_class.run! }.to raise_error(described_class::CheckFailure) end end end end end end end