Commit e3b2cb16 authored by Robert Speicher's avatar Robert Speicher

Merge branch '11795-fix-searching-with-search-disabled' into 'master'

Only use elasticsearch when it is enabled

Closes #11795

See merge request gitlab-org/gitlab-ee!13495
parents a67c2702 0ab515d9
...@@ -167,6 +167,22 @@ module EE ...@@ -167,6 +167,22 @@ module EE
end end
alias_method :elasticsearch_search?, :elasticsearch_search alias_method :elasticsearch_search?, :elasticsearch_search
# Determines whether a search should use elasticsearch, taking the scope
# (nil for global search, otherwise a namespace or project) into account
def search_using_elasticsearch?(scope: nil)
return false unless elasticsearch_indexing? && elasticsearch_search?
return true unless elasticsearch_limit_indexing?
case scope
when Namespace
elasticsearch_indexes_namespace?(scope)
when Project
elasticsearch_indexes_project?(scope)
else
false # Never use elasticsearch for the global scope when limiting is on
end
end
def elasticsearch_url def elasticsearch_url
read_attribute(:elasticsearch_url).split(',').map(&:strip) read_attribute(:elasticsearch_url).split(',').map(&:strip)
end end
......
...@@ -8,18 +8,19 @@ module EE ...@@ -8,18 +8,19 @@ module EE
override :execute override :execute
def execute def execute
if use_elasticsearch? return super unless use_elasticsearch?
::Gitlab::Elastic::SearchResults.new(current_user, params[:search],
elastic_projects, projects, ::Gitlab::Elastic::SearchResults.new(
elastic_global) current_user,
else params[:search],
super elastic_projects,
end projects,
elastic_global
)
end end
def use_elasticsearch? def use_elasticsearch?
::Gitlab::CurrentSettings.elasticsearch_search? && ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: nil)
!::Gitlab::CurrentSettings.elasticsearch_limit_indexing?
end end
def elastic_projects def elastic_projects
......
...@@ -7,7 +7,7 @@ module EE ...@@ -7,7 +7,7 @@ module EE
override :use_elasticsearch? override :use_elasticsearch?
def use_elasticsearch? def use_elasticsearch?
group&.use_elasticsearch? ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: group)
end end
override :elastic_projects override :elastic_projects
...@@ -22,11 +22,17 @@ module EE ...@@ -22,11 +22,17 @@ module EE
override :execute override :execute
def execute def execute
return super unless ::Gitlab::CurrentSettings.elasticsearch_search? return super unless use_elasticsearch?
::Gitlab::Elastic::GroupSearchResults.new( ::Gitlab::Elastic::GroupSearchResults.new(
current_user, elastic_projects, projects, group, params[:search], current_user,
elastic_global, default_project_filter: default_project_filter) elastic_projects,
projects,
group,
params[:search],
elastic_global,
default_project_filter: default_project_filter
)
end end
end end
end end
......
...@@ -7,19 +7,19 @@ module EE ...@@ -7,19 +7,19 @@ module EE
override :execute override :execute
def execute def execute
if use_elasticsearch? return super unless use_elasticsearch?
::Gitlab::Elastic::ProjectSearchResults.new(current_user,
params[:search], ::Gitlab::Elastic::ProjectSearchResults.new(
project.id, current_user,
params[:repository_ref]) params[:search],
else project.id,
super params[:repository_ref]
end )
end end
# This method is used in the top-level SearchService, so cannot be in-lined into #execute # This method is used in the top-level SearchService, so cannot be in-lined into #execute
def use_elasticsearch? def use_elasticsearch?
project.use_elasticsearch? ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: project)
end end
end end
end end
......
...@@ -6,18 +6,15 @@ module EE ...@@ -6,18 +6,15 @@ module EE
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
override :execute override :execute
def execute def execute
if use_elasticsearch? return super unless use_elasticsearch?
::Gitlab::Elastic::SnippetSearchResults.new(current_user, params[:search])
else ::Gitlab::Elastic::SnippetSearchResults.new(current_user, params[:search])
super
end
end end
# This method is used in the top-level SearchService, so cannot be in-lined into #execute # This method is used in the top-level SearchService, so cannot be in-lined into #execute
def use_elasticsearch? def use_elasticsearch?
::Gitlab::CurrentSettings.elasticsearch_search? ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: nil)
end end
end end
end end
......
---
title: Only use elasticsearch when it is enabled
merge_request: 13495
author:
type: fixed
...@@ -238,6 +238,64 @@ describe ApplicationSetting do ...@@ -238,6 +238,64 @@ describe ApplicationSetting do
end end
end end
describe '#search_using_elasticsearch?' do
# Constructs a truth table with 16 entries to run the specs against
where(indexing: [true, false], searching: [true, false], limiting: [true, false])
with_them do
set(:included_project_container) { create(:elasticsearch_indexed_project) }
set(:included_namespace_container) { create(:elasticsearch_indexed_namespace) }
set(:included_project) { included_project_container.project }
set(:included_namespace) { included_namespace_container.namespace }
set(:excluded_project) { create(:project) }
set(:excluded_namespace) { create(:namespace) }
let(:only_when_enabled_globally) { indexing && searching && !limiting }
subject { setting.search_using_elasticsearch?(scope: scope) }
before do
setting.update!(
elasticsearch_indexing: indexing,
elasticsearch_search: searching,
elasticsearch_limit_indexing: limiting
)
end
context 'global scope' do
let(:scope) { nil }
it { is_expected.to eq(only_when_enabled_globally) }
end
context 'namespace (in scope)' do
let(:scope) { included_namespace }
it { is_expected.to eq(indexing && searching) }
end
context 'namespace (not in scope)' do
let(:scope) { excluded_namespace }
it { is_expected.to eq(only_when_enabled_globally) }
end
context 'project (in scope)' do
let(:scope) { included_project }
it { is_expected.to eq(indexing && searching) }
end
context 'project (not in scope)' do
let(:scope) { excluded_project }
it { is_expected.to eq(only_when_enabled_globally) }
end
end
end
describe 'custom project templates' do describe 'custom project templates' do
let(:group) { create(:group) } let(:group) { create(:group) }
let(:projects) { create_list(:project, 3, namespace: group) } let(:projects) { create_list(:project, 3, namespace: group) }
......
...@@ -3,13 +3,8 @@ require 'spec_helper' ...@@ -3,13 +3,8 @@ require 'spec_helper'
describe Search::GlobalService do describe Search::GlobalService do
let(:user) { create(:user) } let(:user) { create(:user) }
describe 'elasticsearch' do it_behaves_like 'EE search service shared examples', ::Gitlab::SearchResults, ::Gitlab::Elastic::SearchResults do
before do let(:scope) { nil }
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true) let(:service) { described_class.new(user, search: '*') }
end
subject(:results) { described_class.new(user, search: '*').execute }
it { is_expected.to be_a(::Gitlab::Elastic::SearchResults) }
end end
end end
require 'spec_helper' require 'spec_helper'
describe Search::GroupService do describe Search::GroupService, :elastic do
shared_examples_for 'group search' do let(:user) { create(:user) }
context 'finding projects by name' do
let(:user) { create(:user) }
let(:term) { "Project Name" }
let(:nested_group) { create(:group, :nested) }
# These projects shouldn't be found
let!(:outside_project) { create(:project, :public, name: "Outside #{term}") }
let!(:private_project) { create(:project, :private, namespace: nested_group, name: "Private #{term}" )}
let!(:other_project) { create(:project, :public, namespace: nested_group, name: term.reverse) }
# These projects should be found it_behaves_like 'EE search service shared examples', ::Gitlab::GroupSearchResults, ::Gitlab::Elastic::GroupSearchResults do
let!(:project1) { create(:project, :internal, namespace: nested_group, name: "Inner #{term} 1") } let(:scope) { create(:group) }
let!(:project2) { create(:project, :internal, namespace: nested_group, name: "Inner #{term} 2") } let(:service) { described_class.new(user, scope, search: '*') }
let!(:project3) { create(:project, :internal, namespace: nested_group.parent, name: "Outer #{term}") } end
let(:results) { described_class.new(user, search_group, search: term).execute }
subject { results.objects('projects') }
context 'in parent group' do describe 'group search' do
let(:search_group) { nested_group.parent } let(:term) { "Project Name" }
let(:nested_group) { create(:group, :nested) }
it { is_expected.to match_array([project1, project2, project3]) } # These projects shouldn't be found
end let(:outside_project) { create(:project, :public, name: "Outside #{term}") }
let(:private_project) { create(:project, :private, namespace: nested_group, name: "Private #{term}" )}
let(:other_project) { create(:project, :public, namespace: nested_group, name: term.reverse) }
context 'in subgroup' do # These projects should be found
let(:search_group) { nested_group } let(:project1) { create(:project, :internal, namespace: nested_group, name: "Inner #{term} 1") }
let(:project2) { create(:project, :internal, namespace: nested_group, name: "Inner #{term} 2") }
let(:project3) { create(:project, :internal, namespace: nested_group.parent, name: "Outer #{term}") }
it { is_expected.to match_array([project1, project2]) } let(:results) { described_class.new(user, search_group, search: term).execute }
end
end
end
describe 'elasticsearch' do
before do before do
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true) stub_ee_application_setting(
Gitlab::Elastic::Helper.create_empty_index elasticsearch_search: true,
elasticsearch_indexing: true
)
# Ensure these are present when the index is refreshed # Ensure these are present when the index is refreshed
_ = [ _ = [
...@@ -48,23 +39,20 @@ describe Search::GroupService do ...@@ -48,23 +39,20 @@ describe Search::GroupService do
Gitlab::Elastic::Helper.refresh_index Gitlab::Elastic::Helper.refresh_index
end end
after do context 'finding projects by name' do
Gitlab::Elastic::Helper.delete_index subject { results.objects('projects') }
end
include_examples 'group search'
end
describe 'elasticsearch result' do context 'in parent group' do
let(:user) { create(:user) } let(:search_group) { nested_group.parent }
let(:group) { create(:group) }
before do it { is_expected.to match_array([project1, project2, project3]) }
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true) end
end
subject(:results) { described_class.new(user, group, search: '*').execute } context 'in subgroup' do
let(:search_group) { nested_group }
it { is_expected.to be_a(::Gitlab::Elastic::GroupSearchResults) } it { is_expected.to match_array([project1, project2]) }
end
end
end end
end end
require 'spec_helper' require 'spec_helper'
describe Search::ProjectService do describe Search::ProjectService do
let(:project) { create(:project) } it_behaves_like 'EE search service shared examples', ::Gitlab::ProjectSearchResults, ::Gitlab::Elastic::ProjectSearchResults do
let(:user) { project.owner } let(:user) { scope.owner }
let(:scope) { create(:project) }
describe 'elasticsearch' do let(:service) { described_class.new(scope, user, search: '*') }
before do
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
end
subject(:results) { described_class.new(project, user, search: '*').execute }
it { is_expected.to be_a(::Gitlab::Elastic::ProjectSearchResults) }
end end
end end
require 'spec_helper' require 'spec_helper'
describe Search::SnippetService do describe Search::SnippetService do
let(:user) { create(:user) } it_behaves_like 'EE search service shared examples', ::Gitlab::SnippetSearchResults, ::Gitlab::Elastic::SnippetSearchResults do
let(:user) { create(:user) }
describe 'elasticsearch' do let(:scope) { nil }
before do let(:service) { described_class.new(user, search: '*') }
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
end
subject(:results) { described_class.new(user, search: '*').execute }
it { is_expected.to be_a(::Gitlab::Elastic::SnippetSearchResults) }
end end
end end
# frozen_string_literal: true
RSpec.shared_examples 'EE search service shared examples' do |normal_results, elasticsearch_results|
describe '#use_elasticsearch?' do
it 'delegates to Gitlab::CurrentSettings.search_using_elasticsearch?' do
expect(Gitlab::CurrentSettings)
.to receive(:search_using_elasticsearch?)
.with(scope: scope)
.and_return(:value)
expect(service.use_elasticsearch?).to eq(:value)
end
end
describe '#execute' do
subject { service.execute }
it 'returns an Elastic result object when elasticsearch is enabled' do
expect(Gitlab::CurrentSettings)
.to receive(:search_using_elasticsearch?)
.with(scope: scope)
.and_return(true)
is_expected.to be_a(elasticsearch_results)
end
it 'returns an ordinary result object when elasticsearch is disabled' do
expect(Gitlab::CurrentSettings)
.to receive(:search_using_elasticsearch?)
.with(scope: scope)
.and_return(false)
is_expected.to be_a(normal_results)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment