From 482909a91d0dfc786f58d999699092bdae3d97a2 Mon Sep 17 00:00:00 2001 From: Court Ewing Date: Wed, 25 May 2016 12:23:27 -0400 Subject: [PATCH] Query no matches on .kibana instead of .kibana-devnull The devnull query was always a big hack to try to force Elasticsearch into giving us an empty search response when we know there are no indices that match the current search in the current timeframe. That hack does not work in all situations, for example if someone creates an index called .kibana-devnull or doesn't enable access to that index pattern in shield. We know users must have access to the kibana index, so it should be safe to query it, and we know we can force an empty response by doing a must_not match_all boolean query, so that's what we do here. Performance shouldn't be an issue since the kibana index is just storing kibana meta data, configurations, and saved objects. --- .../fetch/strategy/__tests__/search.js | 14 +++++++++++-- .../public/courier/fetch/strategy/search.js | 20 ++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/ui/public/courier/fetch/strategy/__tests__/search.js b/src/ui/public/courier/fetch/strategy/__tests__/search.js index ac73fe8e1a18b..6cad183f05785 100644 --- a/src/ui/public/courier/fetch/strategy/__tests__/search.js +++ b/src/ui/public/courier/fetch/strategy/__tests__/search.js @@ -55,11 +55,21 @@ describe('ui/courier/fetch/strategy/search', () => { context('when indexList is empty', () => { beforeEach(() => reqsFetchParams[0].index = []); - it('queries .kibana-devnull instead', () => { + it('queries the kibana index (.kibana) with a must_not match_all boolean', () => { + const query = JSON.stringify({ + query: { + bool: { + must_not: [ + { match_all: {} } + ] + } + } + }); let value; search.reqsFetchParamsToBody(reqsFetchParams).then(val => value = val); $rootScope.$apply(); - expect(_.includes(value, '"index":[".kibana-devnull"]')).to.be(true); + expect(_.includes(value, '"index":[".kibana"]')).to.be(true); + expect(_.includes(value, query)).to.be(true); }); }); }); diff --git a/src/ui/public/courier/fetch/strategy/search.js b/src/ui/public/courier/fetch/strategy/search.js index 2abda799343b6..5b92a7cbf12a5 100644 --- a/src/ui/public/courier/fetch/strategy/search.js +++ b/src/ui/public/courier/fetch/strategy/search.js @@ -3,7 +3,7 @@ import angular from 'angular'; import { toJson } from 'ui/utils/aggressive_parse'; -export default function FetchStrategyForSearch(Private, Promise, timefilter) { +export default function FetchStrategyForSearch(Private, Promise, timefilter, kbnIndex) { return { clientMethod: 'msearch', @@ -26,6 +26,7 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter) { return indexList.toIndexList(timeBounds.min, timeBounds.max); }) .then(function (indexList) { + let body = fetchParams.body || {}; // If we've reached this point and there are no indexes in the // index list at all, it means that we shouldn't expect any indexes // to contain the documents we're looking for, so we instead @@ -35,7 +36,8 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter) { // handle that request by querying *all* indexes, which is the // opposite of what we want in this case. if (_.isArray(indexList) && indexList.length === 0) { - indexList.push('.kibana-devnull'); + indexList.push(kbnIndex); + body = emptySearch(); } return angular.toJson({ index: indexList, @@ -44,7 +46,7 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter) { ignore_unavailable: true }) + '\n' - + toJson(fetchParams.body || {}, angular.toJson); + + toJson(body, angular.toJson); }); }) .then(function (requests) { @@ -62,3 +64,15 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter) { } }; }; + +function emptySearch() { + return { + query: { + bool: { + must_not: [ + { match_all: {} } + ] + } + } + }; +}