diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap index aa978d27f9e23..4fea46169cc5b 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap +++ b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap @@ -103,6 +103,7 @@ exports[`extend index management ilm summary extension should return extension w "documents": "2", "documents_deleted": "0", "health": "yellow", + "hidden": false, "ilm": Object { "action": "rollover", "action_time_millis": 1544187775891, @@ -650,6 +651,7 @@ exports[`extend index management ilm summary extension should return extension w "documents": "2", "documents_deleted": "0", "health": "yellow", + "hidden": false, "ilm": Object { "action": "complete", "action_time_millis": 1544187775867, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx index 9e315f118fd8d..31b43cb67d934 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx @@ -49,6 +49,7 @@ const indexWithoutLifecyclePolicy: Index = { primary_size: '3.4kb', aliases: 'none', isFrozen: false, + hidden: false, ilm: { index: 'testy1', managed: false, @@ -68,6 +69,7 @@ const indexWithLifecyclePolicy: Index = { primary_size: '6.5kb', aliases: 'none', isFrozen: false, + hidden: false, ilm: { index: 'testy3', managed: true, @@ -95,6 +97,7 @@ const indexWithLifecycleError = { primary_size: '6.5kb', aliases: 'none', isFrozen: false, + hidden: false, ilm: { index: 'testy3', managed: true, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/constants.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/constants.ts index e0f26f1d724dc..e2a60dde00ec6 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/constants.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/constants.ts @@ -5,4 +5,4 @@ * 2.0. */ -export const BRANCH = '8.x'; +export const MAJOR_VERSION = '8.0.0'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts index 05cf987238bd1..997f234cf3090 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts @@ -9,8 +9,11 @@ import './mocks'; export { nextTick, getRandomString, findTestSubject, TestBed } from '@kbn/test/jest'; -export { setupEnvironment, WithAppDependencies, services } from './setup_environment'; +export { + setupEnvironment, + WithAppDependencies, + services, + kibanaVersion, +} from './setup_environment'; export { TestSubjects } from './test_subjects'; - -export { BRANCH } from './constants'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx index 7ce81fa47df97..3066742d4c0e0 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -9,6 +9,7 @@ import React from 'react'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { merge } from 'lodash'; +import { SemVer } from 'semver'; import { notificationServiceMock, @@ -31,10 +32,13 @@ import { } from '../../../public/application/components'; import { componentTemplatesMockDependencies } from '../../../public/application/components/component_templates/__jest__'; import { init as initHttpRequests } from './http_requests'; +import { MAJOR_VERSION } from './constants'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); const { GlobalFlyoutProvider } = GlobalFlyout; +export const kibanaVersion = new SemVer(MAJOR_VERSION); + export const services = { extensionsService: new ExtensionsService(), uiMetricService: new UiMetricService('index_management'), diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx index 98d361f0b9723..d4680e7663322 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx @@ -10,7 +10,7 @@ import { act } from 'react-dom/test-utils'; import '../../../test/global_mocks'; import * as fixtures from '../../../test/fixtures'; -import { setupEnvironment, BRANCH } from '../helpers'; +import { setupEnvironment, kibanaVersion } from '../helpers'; import { TEMPLATE_NAME, SETTINGS, ALIASES, MAPPINGS as DEFAULT_MAPPING } from './constants'; import { setup } from './template_edit.helpers'; @@ -263,8 +263,7 @@ describe('', () => { }); }); - // @ts-expect-error - if (BRANCH === '7.x') { + if (kibanaVersion.major < 8) { describe('legacy index templates', () => { const legacyTemplateToEdit = fixtures.getTemplate({ name: 'legacy_index_template', diff --git a/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap b/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap index 38d97fbe08101..b35f3515a9af0 100644 --- a/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap +++ b/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap @@ -22,7 +22,7 @@ exports[`index table force merge button works from context menu 3`] = `"open"`; exports[`index table open index button works from context menu 1`] = `"opening..."`; -exports[`index table open index button works from context menu 2`] = `"open"`; +exports[`index table open index button works from context menu 2`] = `"opening..."`; exports[`index table refresh button works from context menu 1`] = `"refreshing..."`; @@ -31,30 +31,30 @@ exports[`index table refresh button works from context menu 2`] = `"open"`; exports[`index table should change pages when a pagination link is clicked on 1`] = ` Array [ "testy0", + ".admin0", "testy1", "testy2", + ".admin2", "testy3", "testy4", + ".admin4", "testy5", - "testy6", - "testy7", - "testy8", - "testy9", + ".admin5", ] `; exports[`index table should change pages when a pagination link is clicked on 2`] = ` Array [ + "testy6", + ".admin6", + "testy7", + ".admin7", + "testy8", + ".admin8", + "testy9", + ".admin9", "testy10", - "testy11", - "testy12", - "testy13", - "testy14", - "testy15", - "testy16", - "testy17", - "testy18", - "testy19", + ".admin10", ] `; @@ -64,27 +64,33 @@ Array [ ] `; -exports[`index table should show system indices only when the switch is turned on 1`] = ` +exports[`index table should show hidden indices only when the switch is turned on 1`] = ` Array [ - "1", - "2", - "3", - "4", - "5", - "…", - "11", + "testy0", + ".admin0", + "testy1", + "testy2", + ".admin2", + "testy3", + "testy4", + ".admin4", + "testy5", + ".admin5", ] `; -exports[`index table should show system indices only when the switch is turned on 2`] = ` +exports[`index table should show hidden indices only when the switch is turned on 2`] = ` Array [ - "1", - "2", - "3", - "4", - "5", - "…", - "21", + "testy0", + ".admin0", + "testy1", + ".admin1", + "testy2", + ".admin2", + "testy3", + ".admin3", + "testy4", + ".admin4", ] `; @@ -142,16 +148,16 @@ Array [ exports[`index table should sort when header is clicked 1`] = ` Array [ - "testy0", - "testy1", - "testy10", - "testy100", - "testy101", - "testy102", - "testy103", - "testy104", - "testy11", - "testy12", + ".admin0", + ".admin10", + ".admin100", + ".admin101", + ".admin102", + ".admin103", + ".admin104", + ".admin11", + ".admin12", + ".admin13", ] `; diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js index 463d0b30cad08..ba07db10d22d8 100644 --- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js @@ -33,6 +33,7 @@ import { setUiMetricService } from '../../public/application/services/api'; import { indexManagementStore } from '../../public/application/store'; import { setExtensionsService } from '../../public/application/store/selectors/extension_service'; import { ExtensionsService } from '../../public/services'; +import { kibanaVersion } from '../client_integration/helpers'; /* eslint-disable @kbn/eslint/no-restricted-paths */ import { notificationServiceMock } from '../../../../../src/core/public/notifications/notifications_service.mock'; @@ -43,10 +44,10 @@ let server = null; let store = null; const indices = []; -for (let i = 0; i < 105; i++) { - const baseFake = { - health: i % 2 === 0 ? 'green' : 'yellow', - status: i % 2 === 0 ? 'open' : 'closed', +const getBaseFakeIndex = (isOpen) => { + return { + health: isOpen ? 'green' : 'yellow', + status: isOpen ? 'open' : 'closed', primary: 1, replica: 1, documents: 10000, @@ -54,13 +55,19 @@ for (let i = 0; i < 105; i++) { size: '156kb', primary_size: '156kb', }; +}; + +for (let i = 0; i < 105; i++) { indices.push({ - ...baseFake, + ...getBaseFakeIndex(true), name: `testy${i}`, }); indices.push({ - ...baseFake, + ...getBaseFakeIndex(false), name: `.admin${i}`, + // Add 2 hidden indices in the list in position 3 & 7 + // note: for each loop iteration we add 2 indices + hidden: i === 1 || i === 3 ? true : false, // ".admin1" and ".admin3" are the only hidden in 8.x }); } @@ -110,6 +117,7 @@ const testAction = (rendered, buttonIndex, rowIndex = 0) => { // so we "time" our assertion based on how many Redux actions we observe. This is brittle because it // depends upon how our UI is architected, which will affect how many actions are dispatched. // Expect this to break when we rearchitect the UI. + // Update: Expect this to be removed when we rearchitect the UI :) let dispatchedActionsCount = 0; store.subscribe(() => { if (dispatchedActionsCount === 1) { @@ -254,15 +262,44 @@ describe('index table', () => { expect(button.text()).toEqual('Manage 2 indices'); }); - test('should show system indices only when the switch is turned on', async () => { + test('should show hidden indices only when the switch is turned on', async () => { const rendered = mountWithIntl(component); await runAllPromises(); rendered.update(); - snapshot(rendered.find('.euiPagination li').map((item) => item.text())); - const switchControl = rendered.find('.euiSwitch__button'); + // We have manually set `.admin1` and `.admin3` as hidden indices + // We **don't** expect them to be in this list as by default we don't show hidden indices + let indicesInTable = namesText(rendered); + expect(indicesInTable).not.toContain('.admin1'); + expect(indicesInTable).not.toContain('.admin3'); + + if (kibanaVersion.major >= 8) { + // From 8.x indices starting with a period are treated as normal indices + expect(indicesInTable).toContain('.admin0'); + expect(indicesInTable).toContain('.admin2'); + } else if (kibanaVersion.major < 8) { + // In 7.x those are treated as system and are thus hidden + expect(indicesInTable).not.toContain('.admin0'); + expect(indicesInTable).not.toContain('.admin2'); + } + + snapshot(indicesInTable); + + // Enable "Show hidden indices" + const switchControl = findTestSubject(rendered, 'indexTableIncludeHiddenIndicesToggle'); switchControl.simulate('click'); - snapshot(rendered.find('.euiPagination li').map((item) => item.text())); + + // We do expect now the `.admin1` and `.admin3` indices to be in the list + indicesInTable = namesText(rendered); + expect(indicesInTable).toContain('.admin1'); + expect(indicesInTable).toContain('.admin3'); + + if (kibanaVersion.major < 8) { + expect(indicesInTable).toContain('.admin0'); + expect(indicesInTable).toContain('.admin2'); + } + + snapshot(indicesInTable); }); test('should filter based on content of search input', async () => { diff --git a/x-pack/plugins/index_management/common/types/indices.ts b/x-pack/plugins/index_management/common/types/indices.ts index 82184e373d400..375632942b3dd 100644 --- a/x-pack/plugins/index_management/common/types/indices.ts +++ b/x-pack/plugins/index_management/common/types/indices.ts @@ -58,9 +58,10 @@ export interface Index { uuid: string; primary: string; replica: string; - documents: any; + documents?: string; size: any; isFrozen: boolean; + hidden: boolean; aliases: string | string[]; data_stream?: string; [key: string]: any; diff --git a/x-pack/plugins/index_management/public/application/lib/indices.ts b/x-pack/plugins/index_management/public/application/lib/indices.ts new file mode 100644 index 0000000000000..1378dc64b8d5b --- /dev/null +++ b/x-pack/plugins/index_management/public/application/lib/indices.ts @@ -0,0 +1,27 @@ +/* + * 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 SemVer from 'semver/classes/semver'; +import { Index } from '../../../common'; + +const version = '8.0.0'; +const kibanaVersion = new SemVer(version); + +export const isHiddenIndex = (index: Index): boolean => { + if (kibanaVersion.major < 8) { + // In 7.x we consider hidden index all indices whose name start with a dot + return (index.name ?? '').startsWith('.') || index.hidden === true; + } + return index.hidden === true; +}; + +export const isSystemIndex = (index: Index): boolean => { + if (kibanaVersion.major < 8) { + return (index.name ?? '').startsWith('.'); + } + // From 8.0 we won't surface system indices in Index management + return false; +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js index c01235bfd99c5..4470d7ba152cc 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js @@ -34,6 +34,7 @@ import { const mapStateToProps = (state, ownProps) => { const indexStatusByName = {}; const { indexNames } = ownProps; + const allIndices = state.indices.byId; indexNames.forEach((indexName) => { indexStatusByName[indexName] = getIndexStatusByIndexName(state, indexName); @@ -42,8 +43,8 @@ const mapStateToProps = (state, ownProps) => { return { indexStatusByName, indices: getIndicesByName(state, indexNames), - isSystemIndexByName: getIsSystemIndexByName(indexNames), - hasSystemIndex: hasSystemIndex(indexNames), + isSystemIndexByName: getIsSystemIndexByName(indexNames, allIndices), + hasSystemIndex: hasSystemIndex(indexNames, allIndices), }; }; diff --git a/x-pack/plugins/index_management/public/application/store/selectors/index.js b/x-pack/plugins/index_management/public/application/store/selectors/index.js index c05d34c07d7d4..b19e9b973cd79 100644 --- a/x-pack/plugins/index_management/public/application/store/selectors/index.js +++ b/x-pack/plugins/index_management/public/application/store/selectors/index.js @@ -10,6 +10,7 @@ import { Pager, EuiSearchBar } from '@elastic/eui'; import { createSelector } from 'reselect'; import * as qs from 'query-string'; import { indexStatusLabels } from '../../lib/index_status_labels'; +import { isHiddenIndex, isSystemIndex } from '../../lib/indices'; import { sortTable } from '../../services'; import { extensionsService } from './extension_service'; @@ -39,14 +40,14 @@ export const getIndexStatusByIndexName = (state, indexName) => { const { status } = indices[indexName] || {}; return status; }; -export const getIsSystemIndexByName = (indexNames) => { +export const getIsSystemIndexByName = (indexNames, allIndices) => { return indexNames.reduce((obj, indexName) => { - obj[indexName] = indexName.startsWith('.'); + obj[indexName] = isSystemIndex(allIndices[indexName]); return obj; }, {}); }; -export const hasSystemIndex = (indexNames) => { - return Boolean(indexNames.find((indexName) => indexName.startsWith('.'))); +export const hasSystemIndex = (indexNames, allIndices) => { + return indexNames.some((indexName) => isSystemIndex(allIndices[indexName])); }; const defaultFilterFields = ['name']; @@ -90,9 +91,7 @@ export const getFilteredIndices = createSelector( const includeHidden = includeHiddenParam === 'true'; const filteredIndices = includeHidden ? indexArray - : indexArray.filter((index) => { - return !(index.name + '').startsWith('.') && !index.hidden; - }); + : indexArray.filter((index) => !isHiddenIndex(index)); const filter = tableState.filter || EuiSearchBar.Query.MATCH_ALL; return EuiSearchBar.Query.execute(filter, filteredIndices, { defaultFields: defaultFilterFields, diff --git a/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts b/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts index de952cadc8173..e55566b8356d1 100644 --- a/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts +++ b/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts @@ -4,13 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import SemVer from 'semver/classes/semver'; import { ExtensionsService } from '../../../services'; import { getFilteredIndices } from '.'; // @ts-ignore import { defaultTableState } from '../reducers/table_state'; import { setExtensionsService } from './extension_service'; +const version = '8.0.0'; +const kibanaVersion = new SemVer(version); + describe('getFilteredIndices selector', () => { let extensionService: ExtensionsService; beforeAll(() => { @@ -33,10 +36,14 @@ describe('getFilteredIndices selector', () => { }; it('filters out hidden indices', () => { - expect(getFilteredIndices(state, { location: { search: '' } })).toEqual([ - { name: 'index2', hidden: false }, - { name: 'index3' }, - ]); + let expected = [{ name: 'index2', hidden: false }, { name: 'index3' }, { name: '.index4' }]; + + if (kibanaVersion.major < 8) { + // In 7.x index name starting with a dot are considered hidden indices + expected = [{ name: 'index2', hidden: false }, { name: 'index3' }]; + } + + expect(getFilteredIndices(state, { location: { search: '' } })).toEqual(expected); }); it('includes hidden indices', () => {