Skip to content

Commit

Permalink
[8.13] [Search] Change endpoint to filter out already attached indices (
Browse files Browse the repository at this point in the history
#178647) (#178743)

# Backport

This will backport the following commits from `main` to `8.13`:
- [[Search] Change endpoint to filter out already attached indices
(#178647)](#178647)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Efe Gürkan
YALAMAN","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-03-14T14:57:31Z","message":"[Search]
Change endpoint to filter out already attached indices (#178647)\n\n##
Summary\r\n\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/1410658/9ab9af95-09eb-4a82-980c-f6df1daa5105\r\n\r\nAttach
box fetch is moved to a simplified copy of the same endpoint
for\r\nfiltering out already attached indices. It helped also
simplifying the\r\nFE code.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [ ] Any text added
follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)","sha":"2cc53695fb862d2f9838323a11ab002cfe938111","branchLabelMapping":{"^v8.14.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:EnterpriseSearch","v8.13.0","v8.14.0"],"title":"[Search]
Change endpoint to filter out already attached
indices","number":178647,"url":"https://github.com/elastic/kibana/pull/178647","mergeCommit":{"message":"[Search]
Change endpoint to filter out already attached indices (#178647)\n\n##
Summary\r\n\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/1410658/9ab9af95-09eb-4a82-980c-f6df1daa5105\r\n\r\nAttach
box fetch is moved to a simplified copy of the same endpoint
for\r\nfiltering out already attached indices. It helped also
simplifying the\r\nFE code.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [ ] Any text added
follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)","sha":"2cc53695fb862d2f9838323a11ab002cfe938111"}},"sourceBranch":"main","suggestedTargetBranches":["8.13"],"targetPullRequestStates":[{"branch":"8.13","label":"v8.13.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.14.0","branchLabelMappingKey":"^v8.14.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/178647","number":178647,"mergeCommit":{"message":"[Search]
Change endpoint to filter out already attached indices (#178647)\n\n##
Summary\r\n\r\n\r\n\r\nhttps://github.com/elastic/kibana/assets/1410658/9ab9af95-09eb-4a82-980c-f6df1daa5105\r\n\r\nAttach
box fetch is moved to a simplified copy of the same endpoint
for\r\nfiltering out already attached indices. It helped also
simplifying the\r\nFE code.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any
items that are not applicable to this PR.\r\n\r\n- [ ] Any text added
follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [ ] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)","sha":"2cc53695fb862d2f9838323a11ab002cfe938111"}}]}]
BACKPORT-->

Co-authored-by: Efe Gürkan YALAMAN <[email protected]>
  • Loading branch information
kibanamachine and efegurkan authored Mar 14, 2024
1 parent 3ec767c commit f4e3f9f
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 42 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { Meta } from '../../../../../common/types/pagination';

import { Actions, createApiLogic } from '../../../shared/api_logic/create_api_logic';
import { INPUT_THROTTLE_DELAY_MS } from '../../../shared/constants/timers';
import { HttpLogic } from '../../../shared/http';

export interface FetchAvailabeIndicesApiParams {
searchQuery?: string;
}
export interface FetchAvailableIndicesApiResponse {
indexNames: string[];
meta: Meta;
}

export const fetchAvailableIndices = async ({
searchQuery,
}: FetchAvailabeIndicesApiParams): Promise<FetchAvailableIndicesApiResponse> => {
const { http } = HttpLogic.values;
const route = '/internal/enterprise_search/connectors/available_indices';
const query = { search_query: searchQuery || null };
const response = await http.get<FetchAvailableIndicesApiResponse>(route, { query });
return response;
};

export const FetchAvailableIndicesAPILogic = createApiLogic(
['content', 'fetch_available_indices_api_logic'],
fetchAvailableIndices,
{
requestBreakpointMS: INPUT_THROTTLE_DELAY_MS,
}
);

export type FetchAvailableIndicesApiActions = Actions<
FetchAvailabeIndicesApiParams,
FetchAvailableIndicesApiResponse
>;
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Connector } from '@kbn/search-connectors';

import { Status } from '../../../../../common/types/api';

import { FetchAllIndicesAPILogic } from '../../api/index/fetch_all_indices_api_logic';
import { FetchAvailableIndicesAPILogic } from '../../api/index/fetch_available_indices_api_logic';

import { AttachIndexLogic } from './attach_index_logic';

Expand Down Expand Up @@ -74,13 +74,12 @@ export const AttachIndexBox: React.FC<AttachIndexBoxProps> = ({ connector }) =>
);
const [selectedLanguage] = useState<string>();
const [query, setQuery] = useState<{
hasMatchingOptions: boolean;
isFullMatch: boolean;
searchValue: string;
}>();

const { makeRequest } = useActions(FetchAllIndicesAPILogic);
const { data, status } = useValues(FetchAllIndicesAPILogic);
const { makeRequest } = useActions(FetchAvailableIndicesAPILogic);
const { data, status } = useValues(FetchAvailableIndicesAPILogic);
const isLoading = [Status.IDLE, Status.LOADING].includes(status);

const onSave = () => {
Expand All @@ -93,14 +92,22 @@ export const AttachIndexBox: React.FC<AttachIndexBoxProps> = ({ connector }) =>

const options: Array<EuiComboBoxOptionOption<string>> = isLoading
? []
: data?.indices.map((index) => {
: data?.indexNames.map((name) => {
return {
label: index.name,
label: name,
};
}) ?? [];

const shouldPrependUserInputAsOption =
!!query?.searchValue && query.hasMatchingOptions && !query.isFullMatch;
const hasMatchingOptions =
data?.indexNames.some((name) =>
name.toLocaleLowerCase().includes(query?.searchValue.toLocaleLowerCase() ?? '')
) ?? false;
const isFullMatch =
data?.indexNames.some(
(name) => name.toLocaleLowerCase() === query?.searchValue.toLocaleLowerCase()
) ?? false;

const shouldPrependUserInputAsOption = !!query?.searchValue && hasMatchingOptions && !isFullMatch;

const groupedOptions: Array<EuiComboBoxOptionOption<string>> = shouldPrependUserInputAsOption
? [
Expand All @@ -127,7 +134,8 @@ export const AttachIndexBox: React.FC<AttachIndexBoxProps> = ({ connector }) =>
}, [connector.id]);

useEffect(() => {
if (query) {
makeRequest({ searchQuery: query?.searchValue || undefined });
if (query?.searchValue) {
checkIndexExists({ indexName: query.searchValue });
}
}, [query]);
Expand Down Expand Up @@ -207,9 +215,8 @@ export const AttachIndexBox: React.FC<AttachIndexBoxProps> = ({ connector }) =>
)}
isLoading={isLoading}
options={groupedOptions}
onSearchChange={(searchValue, hasMatchingOptions) => {
onSearchChange={(searchValue) => {
setQuery({
hasMatchingOptions: !!hasMatchingOptions,
isFullMatch: options.some((option) => option.label === searchValue),
searchValue,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { IScopedClusterClient } from '@kbn/core/server';
import { fetchConnectors } from '@kbn/search-connectors';

import { isNotNullish } from '../../../common/utils/is_not_nullish';
import { fetchCrawlers } from '../crawler/fetch_crawlers';

import { getUnattachedIndexData } from './utils/get_index_data';

export const fetchUnattachedIndices = async (
client: IScopedClusterClient,
searchQuery: string | undefined,
from: number,
size: number
): Promise<{
indexNames: string[];
totalResults: number;
}> => {
const { indexNames } = await getUnattachedIndexData(client, searchQuery);
const connectors = await fetchConnectors(client.asCurrentUser, indexNames);
const crawlers = await fetchCrawlers(client, indexNames);

const connectedIndexNames = [
...connectors.map((con) => con.index_name).filter(isNotNullish),
...crawlers.map((crawler) => crawler.index_name).filter(isNotNullish),
];

const indexNameSlice = indexNames
.filter((indexName) => !connectedIndexNames.includes(indexName))
.filter(isNotNullish)
.slice(from, from + size);

if (indexNameSlice.length === 0) {
return {
indexNames: [],
totalResults: indexNames.length,
};
}

return {
indexNames: indexNameSlice,
totalResults: indexNames.length,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,33 @@ export const getIndexData = async (
indexNames,
};
};

export const getUnattachedIndexData = async (
client: IScopedClusterClient,
searchQuery?: string
): Promise<{ indexData: IndicesGetResponse; indexNames: string[] }> => {
const expandWildcards: ExpandWildcard[] = ['open'];
const indexPattern = searchQuery ? `*${searchQuery}*` : '*';
const allIndexMatches = await client.asCurrentUser.indices.get({
expand_wildcards: expandWildcards,
// for better performance only compute aliases and settings of indices but not mappings
features: ['aliases', 'settings'],
// only get specified index properties from ES to keep the response under 536MB
// node.js string length limit: https://github.com/nodejs/node/issues/33960
filter_path: ['*.aliases', '*.settings.index.hidden', '*.settings.index.verified_before_close'],
index: indexPattern,
});

const allIndexNames = Object.keys(allIndexMatches).filter(
(indexName) =>
allIndexMatches[indexName] &&
!isHidden(allIndexMatches[indexName]) &&
!isClosed(allIndexMatches[indexName])
);
const indexNames = allIndexNames;

return {
indexData: allIndexMatches,
indexNames,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { addConnector } from '../../lib/connectors/add_connector';
import { startSync } from '../../lib/connectors/start_sync';
import { deleteAccessControlIndex } from '../../lib/indices/delete_access_control_index';
import { fetchIndexCounts } from '../../lib/indices/fetch_index_counts';
import { fetchUnattachedIndices } from '../../lib/indices/fetch_unattached_indices';
import { generateApiKey } from '../../lib/indices/generate_api_key';
import { deleteIndexPipelines } from '../../lib/pipelines/delete_pipelines';
import { getDefaultPipeline } from '../../lib/pipelines/get_default_pipeline';
Expand Down Expand Up @@ -696,4 +697,42 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) {
return response.ok();
})
);

router.get(
{
path: '/internal/enterprise_search/connectors/available_indices',
validate: {
query: schema.object({
from: schema.number({ defaultValue: 0, min: 0 }),
search_query: schema.maybe(schema.string()),
size: schema.number({ defaultValue: 40, min: 0 }),
}),
},
},
elasticsearchErrorHandler(log, async (context, request, response) => {
const { from, size, search_query: searchQuery } = request.query;
const { client } = (await context.core).elasticsearch;

const { indexNames, totalResults } = await fetchUnattachedIndices(
client,
searchQuery,
from,
size
);

return response.ok({
body: {
indexNames,
meta: {
page: {
from,
size,
total: totalResults,
},
},
},
headers: { 'content-type': 'application/json' },
});
})
);
}

0 comments on commit f4e3f9f

Please sign in to comment.