mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[UA] Remove enterprise search related code (#217439)
This commit is contained in:
parent
6190ca8c14
commit
95f80dac20
12 changed files with 3 additions and 891 deletions
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* 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 { DeprecationDetailsMessage, DeprecationsDetails } from '@kbn/core-deprecations-common';
|
||||
import { GetDeprecationsContext } from '@kbn/core-deprecations-server';
|
||||
|
||||
import { getEnterpriseSearchPre8IndexDeprecations } from './enterprise_search_deprecations';
|
||||
import indexDeprecatorFxns = require('./pre_eight_index_deprecator');
|
||||
|
||||
const ctx = {
|
||||
esClient: {
|
||||
asInternalUser: {},
|
||||
},
|
||||
} as GetDeprecationsContext;
|
||||
|
||||
function getMessageFromDeprecation(details: DeprecationsDetails): string {
|
||||
const message = details.message as DeprecationDetailsMessage;
|
||||
return message.content;
|
||||
}
|
||||
|
||||
describe('getEnterpriseSearchPre8IndexDeprecations', () => {
|
||||
it('can register index and data stream deprecations that need to be set to read only', async () => {
|
||||
const getIndicesMock = jest.fn(() =>
|
||||
Promise.resolve([
|
||||
{
|
||||
name: '.ent-search-index_without_datastream',
|
||||
hasDatastream: false,
|
||||
datastreams: [],
|
||||
},
|
||||
{
|
||||
name: '.ent-search-with_data_stream',
|
||||
hasDatastream: true,
|
||||
datastreams: ['datastream-testing'],
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
jest
|
||||
.spyOn(indexDeprecatorFxns, 'getPreEightEnterpriseSearchIndices')
|
||||
.mockImplementation(getIndicesMock);
|
||||
|
||||
const deprecations = await getEnterpriseSearchPre8IndexDeprecations(ctx, 'docsurl');
|
||||
expect(deprecations).toHaveLength(1);
|
||||
expect(deprecations[0].correctiveActions.api?.path).toStrictEqual(
|
||||
'/internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only'
|
||||
);
|
||||
expect(deprecations[0].title).toMatch('Pre 8.x Enterprise Search indices compatibility');
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain(
|
||||
'The following indices are found to be incompatible for upgrade'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain(
|
||||
'.ent-search-index_without_datastream'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain(
|
||||
'The following data streams are found to be incompatible for upgrade'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain('.ent-search-with_data_stream');
|
||||
});
|
||||
|
||||
it('can register an index without data stream deprecations that need to be set to read only', async () => {
|
||||
const getIndicesMock = jest.fn(() =>
|
||||
Promise.resolve([
|
||||
{
|
||||
name: '.ent-search-index_without_datastream',
|
||||
hasDatastream: false,
|
||||
datastreams: [''],
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
jest
|
||||
.spyOn(indexDeprecatorFxns, 'getPreEightEnterpriseSearchIndices')
|
||||
.mockImplementation(getIndicesMock);
|
||||
|
||||
const deprecations = await getEnterpriseSearchPre8IndexDeprecations(ctx, 'docsurl');
|
||||
expect(deprecations).toHaveLength(1);
|
||||
expect(deprecations[0].correctiveActions.api?.path).toStrictEqual(
|
||||
'/internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only'
|
||||
);
|
||||
expect(deprecations[0].title).toMatch('Pre 8.x Enterprise Search indices compatibility');
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain(
|
||||
'The following indices are found to be incompatible for upgrade'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).toContain(
|
||||
'.ent-search-index_without_datastream'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).not.toContain(
|
||||
'The following data streams are found to be incompatible for upgrade'
|
||||
);
|
||||
expect(getMessageFromDeprecation(deprecations[0])).not.toContain(
|
||||
'.ent-search-with_data_stream'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* 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 { DeprecationsDetails } from '@kbn/core-deprecations-common';
|
||||
import { GetDeprecationsContext, RegisterDeprecationsConfig } from '@kbn/core-deprecations-server';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getPreEightEnterpriseSearchIndices } from './pre_eight_index_deprecator';
|
||||
|
||||
export const getEntepriseSearchRegisteredDeprecations = (
|
||||
docsUrl: string
|
||||
): RegisterDeprecationsConfig => {
|
||||
return {
|
||||
getDeprecations: async (ctx: GetDeprecationsContext) => {
|
||||
const [entSearchIndexIncompatibility] = await Promise.all([
|
||||
getEnterpriseSearchPre8IndexDeprecations(ctx, docsUrl),
|
||||
]);
|
||||
return [...entSearchIndexIncompatibility];
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* If there are any Enterprise Search indices that were created with Elasticsearch 7.x, they must be removed
|
||||
* or set to read-only
|
||||
*/
|
||||
export async function getEnterpriseSearchPre8IndexDeprecations(
|
||||
ctx: GetDeprecationsContext,
|
||||
docsUrl: string
|
||||
): Promise<DeprecationsDetails[]> {
|
||||
const deprecations: DeprecationsDetails[] = [];
|
||||
|
||||
const entSearchIndices = await getPreEightEnterpriseSearchIndices(ctx.esClient.asInternalUser);
|
||||
if (!entSearchIndices || entSearchIndices.length === 0) {
|
||||
return deprecations;
|
||||
}
|
||||
|
||||
let indicesList = '';
|
||||
let datastreamsList = '';
|
||||
for (const index of entSearchIndices) {
|
||||
if (index.hasDatastream) {
|
||||
indicesList += `${index.name}\n`;
|
||||
for (const datastream of index.datastreams) {
|
||||
if (datastream === '') continue;
|
||||
datastreamsList += `${datastream}\n`;
|
||||
}
|
||||
} else {
|
||||
indicesList += `${index.name}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
let message = `There are ${entSearchIndices.length} incompatible Enterprise Search indices.\n\n`;
|
||||
|
||||
if (indicesList.length > 0) {
|
||||
message +=
|
||||
'The following indices are found to be incompatible for upgrade:\n\n' +
|
||||
'```\n' +
|
||||
`${indicesList}` +
|
||||
'\n```\n' +
|
||||
'These indices must be either set to read-only or deleted before upgrading.\n';
|
||||
}
|
||||
|
||||
if (datastreamsList.length > 0) {
|
||||
message +=
|
||||
'\nThe following data streams are found to be incompatible for upgrade:\n\n' +
|
||||
'```\n' +
|
||||
`${datastreamsList}` +
|
||||
'\n```\n' +
|
||||
'Using the "quick resolve" button below will roll over any datastreams and set all incompatible indices to read-only.\n\n' +
|
||||
'Alternatively, manually deleting these indices and data streams will also unblock your upgrade.';
|
||||
} else {
|
||||
message +=
|
||||
'Setting these indices to read-only can be attempted with the "quick resolve" button below.\n\n' +
|
||||
'Alternatively, manually deleting these indices will also unblock your upgrade.';
|
||||
}
|
||||
|
||||
deprecations.push({
|
||||
level: 'critical',
|
||||
deprecationType: 'feature',
|
||||
title: i18n.translate(
|
||||
'xpack.upgradeAssistant.deprecations.incompatibleEnterpriseSearchIndexes.title',
|
||||
{
|
||||
defaultMessage: 'Pre 8.x Enterprise Search indices compatibility',
|
||||
}
|
||||
),
|
||||
message: {
|
||||
type: 'markdown',
|
||||
content: i18n.translate(
|
||||
'xpack.upgradeAssistant.deprecations.incompatibleEnterpriseSearchIndexes.message',
|
||||
{
|
||||
defaultMessage: message,
|
||||
}
|
||||
),
|
||||
},
|
||||
documentationUrl: docsUrl,
|
||||
correctiveActions: {
|
||||
manualSteps: [
|
||||
i18n.translate(
|
||||
'xpack.upgradeAssistant.deprecations.incompatibleEnterpriseSearchIndexes.deleteIndices',
|
||||
{
|
||||
defaultMessage: 'Set all incompatible indices and data streams to read only, or',
|
||||
}
|
||||
),
|
||||
i18n.translate(
|
||||
'xpack.upgradeAssistant.deprecations.incompatibleEnterpriseSearchIndexes.deleteIndices',
|
||||
{
|
||||
defaultMessage: 'Delete all incompatible indices and data streams',
|
||||
}
|
||||
),
|
||||
],
|
||||
api: {
|
||||
method: 'POST',
|
||||
path: '/internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only',
|
||||
body: {
|
||||
deprecationDetails: { domainId: 'enterpriseSearch' },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return deprecations;
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* 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 { kibanaResponseFactory } from '@kbn/core/server';
|
||||
|
||||
import { handleEsError } from '../../shared_imports';
|
||||
import {
|
||||
createMockRouter,
|
||||
MockRouter,
|
||||
routeHandlerContextMock,
|
||||
} from '../../routes/__mocks__/routes.mock';
|
||||
import { createRequestMock } from '../../routes/__mocks__/request.mock';
|
||||
|
||||
jest.mock('../es_version_precheck', () => ({
|
||||
versionCheckHandlerWrapper: (a: any) => a,
|
||||
}));
|
||||
|
||||
import indexDeprecatorFxns = require('./pre_eight_index_deprecator');
|
||||
|
||||
import { registerEnterpriseSearchDeprecationRoutes } from './enterprise_search_deprecations_routes';
|
||||
|
||||
describe('deprecation routes', () => {
|
||||
let routeDependencies: any;
|
||||
|
||||
describe('POST /internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only', () => {
|
||||
let mockRouter: MockRouter;
|
||||
|
||||
function registerMockRouter({ mlSnapshots } = { mlSnapshots: true }) {
|
||||
mockRouter = createMockRouter();
|
||||
routeDependencies = {
|
||||
config: {
|
||||
featureSet: { mlSnapshots, migrateSystemIndices: true, reindexCorrectiveActions: true },
|
||||
},
|
||||
router: mockRouter,
|
||||
lib: { handleEsError },
|
||||
};
|
||||
registerEnterpriseSearchDeprecationRoutes(routeDependencies);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
registerMockRouter();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('sets read-only and 200s correctly in happy path', async () => {
|
||||
const setIndicesReadOnlyMock = jest.spyOn(
|
||||
indexDeprecatorFxns,
|
||||
'setPreEightEnterpriseSearchIndicesReadOnly'
|
||||
);
|
||||
|
||||
setIndicesReadOnlyMock.mockResolvedValue('');
|
||||
|
||||
const resp = await routeDependencies.router.getHandler({
|
||||
method: 'post',
|
||||
pathPattern:
|
||||
'/internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only',
|
||||
})(
|
||||
routeHandlerContextMock,
|
||||
createRequestMock({
|
||||
body: { deprecationDetails: { domainId: 'enterpriseSearch' } },
|
||||
}),
|
||||
kibanaResponseFactory
|
||||
);
|
||||
|
||||
expect(resp.status).toEqual(200);
|
||||
expect(resp.payload).toEqual({
|
||||
acknowedged: true,
|
||||
});
|
||||
|
||||
expect(setIndicesReadOnlyMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* 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 { setPreEightEnterpriseSearchIndicesReadOnly } from './pre_eight_index_deprecator';
|
||||
import { versionCheckHandlerWrapper } from '../es_version_precheck';
|
||||
import { RouteDependencies } from '../../types';
|
||||
|
||||
export function registerEnterpriseSearchDeprecationRoutes({ router }: RouteDependencies) {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/enterprise_search/deprecations/set_enterprise_search_indices_read_only',
|
||||
security: {
|
||||
authz: {
|
||||
enabled: false,
|
||||
reason: 'Relies on elasticsearch for authorization',
|
||||
},
|
||||
},
|
||||
validate: {},
|
||||
},
|
||||
versionCheckHandlerWrapper(async ({ core }, request, response) => {
|
||||
const { client } = (await core).elasticsearch;
|
||||
const setResponse = await setPreEightEnterpriseSearchIndicesReadOnly(client.asCurrentUser);
|
||||
if (setResponse.length > 0) {
|
||||
return response.badRequest({
|
||||
body: { message: setResponse },
|
||||
headers: { 'content-type': 'application/json' },
|
||||
});
|
||||
}
|
||||
return response.ok({
|
||||
body: { acknowedged: true },
|
||||
headers: { 'content-type': 'application/json' },
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
ENT_SEARCH_DATASTREAM_PATTERN,
|
||||
ENT_SEARCH_DATASTREAM_PREFIXES,
|
||||
ENT_SEARCH_INDEX_PREFIX,
|
||||
} from './pre_eight_index_deprecator';
|
|
@ -1,276 +0,0 @@
|
|||
/*
|
||||
* 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 { ElasticsearchClient } from '@kbn/core/server';
|
||||
|
||||
import {
|
||||
getPreEightEnterpriseSearchIndices,
|
||||
setPreEightEnterpriseSearchIndicesReadOnly,
|
||||
} from './pre_eight_index_deprecator';
|
||||
import type {
|
||||
IndicesDataStream,
|
||||
IndicesGetDataStreamResponse,
|
||||
IndicesGetResponse,
|
||||
IndicesIndexState,
|
||||
} from '@elastic/elasticsearch/lib/api/types';
|
||||
|
||||
const testIndices = {
|
||||
'.ent-search-already_read_only': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
blocks: {
|
||||
write: 'true',
|
||||
},
|
||||
verified_read_only: 'true',
|
||||
},
|
||||
},
|
||||
data_stream: 'datastream-123',
|
||||
},
|
||||
'.ent-search-post_7_index': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '8.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'.ent-search-index_without_datastream': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'.ent-search-with_data_stream': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
data_stream: 'datastream-testing',
|
||||
},
|
||||
'.ent-search-with_another_data_stream': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
data_stream: 'datastream-testing-another',
|
||||
},
|
||||
'.ent-search-with_same_data_stream': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
data_stream: 'datastream-testing',
|
||||
},
|
||||
};
|
||||
|
||||
const testBackingIndex = {
|
||||
'.ds-some-other-backing-index': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
data_stream: 'logs-app_search.testdatastream',
|
||||
},
|
||||
};
|
||||
|
||||
const additionalDatastreams: Record<string, IndicesDataStream> = {
|
||||
'logs-app_search.testdatastream': {
|
||||
name: 'logs-app_search.testdatastream',
|
||||
indices: [
|
||||
{ index_name: '.ds-some-other-backing-index', index_uuid: '1' },
|
||||
{ index_name: '.ent-search-with_same_data_stream', index_uuid: '2' },
|
||||
],
|
||||
} as IndicesDataStream,
|
||||
};
|
||||
|
||||
const testIndicesWithoutDatastream: Record<string, IndicesIndexState> = {
|
||||
'.ent-search-already_read_only': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
blocks: {
|
||||
write: 'true',
|
||||
},
|
||||
verified_read_only: 'true',
|
||||
},
|
||||
},
|
||||
},
|
||||
'.ent-search-post_7_index': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '8.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'.ent-search-index_without_datastream': {
|
||||
settings: {
|
||||
index: {
|
||||
version: {
|
||||
created: '7.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function getMockIndicesFxn(values: Record<string, IndicesIndexState>) {
|
||||
return () => {
|
||||
const ret: IndicesGetResponse = {};
|
||||
for (const [index, indexData] of Object.entries(values)) {
|
||||
ret[index] = indexData;
|
||||
}
|
||||
return Promise.resolve(ret);
|
||||
};
|
||||
}
|
||||
|
||||
function getMockDatastreamsFxn(values: Record<string, IndicesDataStream>) {
|
||||
return () => {
|
||||
const ret: IndicesGetDataStreamResponse = { data_streams: [] };
|
||||
for (const [, datastreamData] of Object.entries(values)) {
|
||||
ret.data_streams.push(datastreamData);
|
||||
}
|
||||
return Promise.resolve(ret);
|
||||
};
|
||||
}
|
||||
|
||||
describe('getPreEightEnterpriseSearchIndices', () => {
|
||||
let esClientMock: ElasticsearchClient;
|
||||
let getIndicesMock: jest.Mock;
|
||||
let getDatastreamsMock: jest.Mock;
|
||||
beforeEach(() => {
|
||||
getIndicesMock = jest.fn();
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testIndices));
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testBackingIndex));
|
||||
|
||||
getDatastreamsMock = jest.fn(getMockDatastreamsFxn(additionalDatastreams));
|
||||
esClientMock = {
|
||||
indices: {
|
||||
get: getIndicesMock,
|
||||
getDataStream: getDatastreamsMock,
|
||||
},
|
||||
} as unknown as ElasticsearchClient;
|
||||
});
|
||||
|
||||
it('returns the correct indices', async () => {
|
||||
const indices = await getPreEightEnterpriseSearchIndices(esClientMock);
|
||||
expect(indices).toEqual([
|
||||
{
|
||||
name: '.ent-search-index_without_datastream',
|
||||
hasDatastream: false,
|
||||
datastreams: [''],
|
||||
},
|
||||
{
|
||||
name: '.ent-search-with_data_stream',
|
||||
hasDatastream: true,
|
||||
datastreams: ['datastream-testing'],
|
||||
},
|
||||
{
|
||||
name: '.ent-search-with_another_data_stream',
|
||||
hasDatastream: true,
|
||||
datastreams: ['datastream-testing-another'],
|
||||
},
|
||||
{
|
||||
name: '.ent-search-with_same_data_stream',
|
||||
hasDatastream: true,
|
||||
datastreams: ['datastream-testing'],
|
||||
},
|
||||
{
|
||||
name: '.ds-some-other-backing-index',
|
||||
hasDatastream: true,
|
||||
datastreams: ['logs-app_search.testdatastream'],
|
||||
},
|
||||
]);
|
||||
expect(getIndicesMock).toHaveBeenCalledTimes(2);
|
||||
expect(getIndicesMock).toHaveBeenNthCalledWith(1, {
|
||||
expand_wildcards: ['all', 'hidden'],
|
||||
ignore_unavailable: true,
|
||||
index: '.ent-search-*',
|
||||
});
|
||||
expect(getIndicesMock).toHaveBeenNthCalledWith(2, {
|
||||
ignore_unavailable: true,
|
||||
index: ['.ds-some-other-backing-index'],
|
||||
});
|
||||
|
||||
expect(getDatastreamsMock).toHaveBeenCalledTimes(1);
|
||||
expect(getDatastreamsMock).toHaveBeenCalledWith({
|
||||
expand_wildcards: ['all', 'hidden'],
|
||||
name: 'logs-enterprise_search.*,logs-app_search.*,logs-workplace_search.*',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setPreEightEnterpriseSearchIndicesReadOnly', () => {
|
||||
it('does not rollover datastreams if there are none', async () => {
|
||||
const getIndicesMock = jest.fn(getMockIndicesFxn(testIndicesWithoutDatastream));
|
||||
const getDatastreamsMock = jest.fn(() => Promise.resolve({ data_streams: [] }));
|
||||
const rolloverMock = jest.fn(() => Promise.resolve(true));
|
||||
const addBlockMock = jest.fn(() => Promise.resolve({ acknowledged: true }));
|
||||
const esClientMock = {
|
||||
indices: {
|
||||
get: getIndicesMock,
|
||||
getDataStream: getDatastreamsMock,
|
||||
rollover: rolloverMock,
|
||||
addBlock: addBlockMock,
|
||||
},
|
||||
} as unknown as ElasticsearchClient;
|
||||
|
||||
const result = await setPreEightEnterpriseSearchIndicesReadOnly(esClientMock);
|
||||
expect(result).toEqual('');
|
||||
expect(getIndicesMock).toHaveBeenCalledTimes(1);
|
||||
expect(rolloverMock).not.toHaveBeenCalled();
|
||||
expect(addBlockMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does rollover datastreams if there are any', async () => {
|
||||
const getIndicesMock = jest.fn();
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testIndices));
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testBackingIndex));
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testIndices));
|
||||
getIndicesMock.mockImplementationOnce(getMockIndicesFxn(testBackingIndex));
|
||||
|
||||
const getDatastreamsMock = getMockDatastreamsFxn(additionalDatastreams);
|
||||
const rolloverMock = jest.fn(() => Promise.resolve(true));
|
||||
const addBlockMock = jest.fn(() => Promise.resolve({ acknowledged: true }));
|
||||
const esClientMock = {
|
||||
indices: {
|
||||
get: getIndicesMock,
|
||||
getDataStream: getDatastreamsMock,
|
||||
rollover: rolloverMock,
|
||||
addBlock: addBlockMock,
|
||||
},
|
||||
} as unknown as ElasticsearchClient;
|
||||
|
||||
const result = await setPreEightEnterpriseSearchIndicesReadOnly(esClientMock);
|
||||
expect(result).toEqual('');
|
||||
expect(getIndicesMock).toHaveBeenCalledTimes(4);
|
||||
expect(rolloverMock).toHaveBeenCalledTimes(3);
|
||||
expect(addBlockMock).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
});
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* 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 { IndicesIndexState } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
|
||||
export const ENT_SEARCH_INDEX_PREFIX = '.ent-search-';
|
||||
export const ENT_SEARCH_DATASTREAM_PREFIXES = [
|
||||
'logs-enterprise_search.',
|
||||
'logs-app_search.',
|
||||
'logs-workplace_search.',
|
||||
];
|
||||
export const ENT_SEARCH_DATASTREAM_PATTERN = [
|
||||
'logs-enterprise_search.*',
|
||||
'logs-app_search.*',
|
||||
'logs-workplace_search.*',
|
||||
];
|
||||
|
||||
export interface EnterpriseSearchIndexMapping {
|
||||
name: string;
|
||||
hasDatastream: boolean;
|
||||
datastreams: string[];
|
||||
}
|
||||
|
||||
function is7xIncompatibleIndex(indexData: IndicesIndexState): boolean {
|
||||
const isReadOnly = indexData.settings?.index?.verified_read_only ?? 'false';
|
||||
return Boolean(
|
||||
indexData.settings?.index?.version?.created?.startsWith('7') && isReadOnly !== 'true'
|
||||
);
|
||||
}
|
||||
|
||||
export async function getPreEightEnterpriseSearchIndices(
|
||||
esClient: ElasticsearchClient
|
||||
): Promise<EnterpriseSearchIndexMapping[]> {
|
||||
const entSearchIndices = await esClient.indices.get({
|
||||
index: `${ENT_SEARCH_INDEX_PREFIX}*`,
|
||||
ignore_unavailable: true,
|
||||
expand_wildcards: ['all', 'hidden'],
|
||||
});
|
||||
|
||||
const returnIndices: EnterpriseSearchIndexMapping[] = [];
|
||||
|
||||
for (const [index, indexData] of Object.entries(entSearchIndices)) {
|
||||
if (is7xIncompatibleIndex(indexData)) {
|
||||
const dataStreamName = indexData.data_stream;
|
||||
returnIndices.push({
|
||||
name: index,
|
||||
hasDatastream: dataStreamName ? true : false,
|
||||
datastreams: [dataStreamName ?? ''],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const { data_streams: entSearchDatastreams } = await esClient.indices.getDataStream({
|
||||
name: ENT_SEARCH_DATASTREAM_PATTERN.join(','),
|
||||
expand_wildcards: ['all', 'hidden'],
|
||||
});
|
||||
|
||||
const dsIndices = new Set<string>();
|
||||
entSearchDatastreams.forEach(({ indices: dsi }) => {
|
||||
dsi.forEach(({ index_name: indexName }) => {
|
||||
dsIndices.add(indexName);
|
||||
});
|
||||
});
|
||||
|
||||
if (!dsIndices.size) return returnIndices;
|
||||
|
||||
for (const returnIndex of returnIndices) {
|
||||
if (dsIndices.has(returnIndex.name)) {
|
||||
dsIndices.delete(returnIndex.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dsIndices.size) return returnIndices;
|
||||
|
||||
const entSearchDsIndices = await esClient.indices.get({
|
||||
index: Array.from(dsIndices.values()),
|
||||
ignore_unavailable: true,
|
||||
});
|
||||
|
||||
for (const [index, indexData] of Object.entries(entSearchDsIndices)) {
|
||||
if (is7xIncompatibleIndex(indexData)) {
|
||||
const dataStreamName = indexData.data_stream;
|
||||
returnIndices.push({
|
||||
name: index,
|
||||
hasDatastream: dataStreamName ? true : false,
|
||||
datastreams: [dataStreamName ?? ''],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return returnIndices;
|
||||
}
|
||||
|
||||
export async function setPreEightEnterpriseSearchIndicesReadOnly(
|
||||
esClient: ElasticsearchClient
|
||||
): Promise<string> {
|
||||
// get the indices again to ensure nothing's changed since the last check
|
||||
let indices = await getPreEightEnterpriseSearchIndices(esClient);
|
||||
|
||||
// rollover any datastreams first
|
||||
const rolledOverDatastreams: { [id: string]: boolean } = {};
|
||||
for (const index of indices) {
|
||||
if (index.hasDatastream) {
|
||||
for (const datastream of index.datastreams) {
|
||||
if (datastream.length === 0 || rolledOverDatastreams[datastream]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const indexResponse = await esClient.indices.rollover({ alias: datastream });
|
||||
|
||||
if (!indexResponse) {
|
||||
return `Could not roll over datastream: ${index.name}`;
|
||||
}
|
||||
|
||||
rolledOverDatastreams[datastream] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(rolledOverDatastreams).length > 0) {
|
||||
// we rolled over at least one datastream,
|
||||
// get the indices again
|
||||
indices = await getPreEightEnterpriseSearchIndices(esClient);
|
||||
}
|
||||
|
||||
for (const index of indices) {
|
||||
const indexName = index.name;
|
||||
const indexResponse = await esClient.indices.addBlock({ index: indexName, block: 'write' });
|
||||
|
||||
if (!indexResponse || indexResponse.acknowledged !== true) {
|
||||
return `Could not set index read-only: ${indexName}`;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
|
@ -78,24 +78,6 @@ Object {
|
|||
"type": "index_settings",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"excludedActions": Array [],
|
||||
"metadata": Object {
|
||||
"isClosedIndex": false,
|
||||
"isFrozenIndex": false,
|
||||
"isInDataStream": false,
|
||||
},
|
||||
"type": "reindex",
|
||||
},
|
||||
"details": "This index was created using version: 6.8.13",
|
||||
"index": "old_index",
|
||||
"isCritical": true,
|
||||
"message": "Index created before 7.0",
|
||||
"resolveDuringUpgrade": false,
|
||||
"type": "index_settings",
|
||||
"url": "https: //www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"metadata": Object {
|
||||
|
@ -113,24 +95,6 @@ Object {
|
|||
"type": "index_settings",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/frozen-indices.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"excludedActions": Array [],
|
||||
"metadata": Object {
|
||||
"isClosedIndex": true,
|
||||
"isFrozenIndex": false,
|
||||
"isInDataStream": false,
|
||||
},
|
||||
"type": "reindex",
|
||||
},
|
||||
"details": "This index was created using version: 6.8.13",
|
||||
"index": "closed_index",
|
||||
"isCritical": true,
|
||||
"message": "Index created before 7.0",
|
||||
"resolveDuringUpgrade": false,
|
||||
"type": "index_settings",
|
||||
"url": "https: //www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"deprecatedSettings": Array [
|
||||
|
@ -186,68 +150,6 @@ Object {
|
|||
"type": "index_settings",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"excludedActions": Array [],
|
||||
"metadata": Object {
|
||||
"isClosedIndex": false,
|
||||
"isFrozenIndex": false,
|
||||
"isInDataStream": false,
|
||||
},
|
||||
"transformIds": Array [
|
||||
"abc",
|
||||
],
|
||||
"type": "reindex",
|
||||
},
|
||||
"details": "This index has version: 7.17.25",
|
||||
"index": "transforms_index",
|
||||
"isCritical": true,
|
||||
"message": "Old index with a compatibility version < 8.0",
|
||||
"resolveDuringUpgrade": false,
|
||||
"type": "index_settings",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-9.0.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"excludedActions": Array [],
|
||||
"metadata": Object {
|
||||
"isClosedIndex": false,
|
||||
"isFrozenIndex": false,
|
||||
"isInDataStream": false,
|
||||
},
|
||||
"type": "reindex",
|
||||
},
|
||||
"details": "This index has version: 7.17.25",
|
||||
"index": "myindex",
|
||||
"isCritical": true,
|
||||
"message": "Old index with a compatibility version < 8.0",
|
||||
"resolveDuringUpgrade": false,
|
||||
"type": "index_settings",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-9.0.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": Object {
|
||||
"metadata": Object {
|
||||
"excludedActions": Array [],
|
||||
"ignoredIndicesRequiringUpgrade": Array [],
|
||||
"ignoredIndicesRequiringUpgradeCount": 0,
|
||||
"indicesRequiringUpgrade": Array [
|
||||
".ds-some-backing-index-5-2024.11.07-000001",
|
||||
],
|
||||
"indicesRequiringUpgradeCount": 1,
|
||||
"reindexRequired": true,
|
||||
"totalBackingIndices": 2,
|
||||
},
|
||||
"type": "dataStream",
|
||||
},
|
||||
"details": "This data stream has backing indices that were created before Elasticsearch 8.0.0",
|
||||
"index": "my-v7-data-stream",
|
||||
"isCritical": true,
|
||||
"message": "Old data stream with a compatibility version < 8.0",
|
||||
"resolveDuringUpgrade": false,
|
||||
"type": "data_streams",
|
||||
"url": "https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-9.0.html",
|
||||
},
|
||||
Object {
|
||||
"correctiveAction": undefined,
|
||||
"details": "This action is already a noop so it can be safely removed, because frozen indices no longer offer any advantages. Consider cold or frozen tiers in place of frozen indices.",
|
||||
|
@ -269,7 +171,7 @@ Object {
|
|||
"url": "https://github.com/elastic/elasticsearch/pull/117172",
|
||||
},
|
||||
],
|
||||
"totalCriticalDeprecations": 9,
|
||||
"totalCriticalDeprecations": 4,
|
||||
"totalCriticalHealthIssues": 0,
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -22,7 +22,6 @@ import {
|
|||
isFrozenDeprecation,
|
||||
} from './get_corrective_actions';
|
||||
import { esIndicesStateCheck } from '../es_indices_state_check';
|
||||
import { ENT_SEARCH_DATASTREAM_PREFIXES, ENT_SEARCH_INDEX_PREFIX } from '../enterprise_search';
|
||||
|
||||
/**
|
||||
* Remove once the these keys are added to the `MigrationDeprecationsResponse` type
|
||||
|
@ -195,17 +194,12 @@ const excludeDeprecation = (
|
|||
deprecation: BaseDeprecation,
|
||||
correctiveAction?: CorrectiveAction
|
||||
): boolean => {
|
||||
if (
|
||||
deprecation.type === 'index_settings' &&
|
||||
correctiveAction?.type === 'reindex' &&
|
||||
deprecation.index?.startsWith(ENT_SEARCH_INDEX_PREFIX)
|
||||
) {
|
||||
if (deprecation.type === 'index_settings' && correctiveAction?.type === 'reindex') {
|
||||
return true;
|
||||
} else if (
|
||||
deprecation.type === 'data_streams' &&
|
||||
correctiveAction?.type === 'dataStream' &&
|
||||
correctiveAction.metadata.reindexRequired &&
|
||||
ENT_SEARCH_DATASTREAM_PREFIXES.some((prefix) => deprecation.index?.startsWith(prefix))
|
||||
correctiveAction.metadata.reindexRequired
|
||||
) {
|
||||
return true;
|
||||
} else if (
|
||||
|
|
|
@ -38,7 +38,6 @@ import { handleEsError } from './shared_imports';
|
|||
import { RouteDependencies } from './types';
|
||||
import type { UpgradeAssistantConfig } from './config';
|
||||
import type { DataSourceExclusions, FeatureSet } from '../common/types';
|
||||
import { getEntepriseSearchRegisteredDeprecations } from './lib/enterprise_search/enterprise_search_deprecations';
|
||||
import { defaultExclusions } from './lib/data_source_exclusions';
|
||||
|
||||
interface PluginsSetup {
|
||||
|
@ -152,11 +151,6 @@ export class UpgradeAssistantServerPlugin implements Plugin {
|
|||
|
||||
registerRoutes(dependencies, this.getWorker.bind(this));
|
||||
|
||||
// Register deprecations for Enterprise Search pre-8 indices
|
||||
deprecations.registerDeprecations({
|
||||
...getEntepriseSearchRegisteredDeprecations(docLinks.links.enterpriseSearch.upgrade9x),
|
||||
});
|
||||
|
||||
if (usageCollection) {
|
||||
void getStartServices().then(([{ elasticsearch }]) => {
|
||||
registerUpgradeAssistantUsageCollector({
|
||||
|
|
|
@ -23,7 +23,6 @@ import { registerNodeDiskSpaceRoute } from './node_disk_space';
|
|||
import { registerClusterSettingsRoute } from './cluster_settings';
|
||||
import { registerMigrateDataStreamRoutes } from './migrate_data_streams';
|
||||
import { registerUpdateIndexRoute } from './update_index';
|
||||
import { registerEnterpriseSearchDeprecationRoutes } from '../lib/enterprise_search/enterprise_search_deprecations_routes';
|
||||
|
||||
export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) {
|
||||
registerAppRoutes(dependencies);
|
||||
|
@ -48,7 +47,4 @@ export function registerRoutes(dependencies: RouteDependencies, getWorker: () =>
|
|||
|
||||
// Mark index as read-only and unfreeze it
|
||||
registerUpdateIndexRoute(dependencies);
|
||||
|
||||
// Enterprise Search deprecations
|
||||
registerEnterpriseSearchDeprecationRoutes(dependencies);
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
"@kbn/core-http-server-mocks",
|
||||
"@kbn/core-http-server-utils",
|
||||
"@kbn/core-elasticsearch-server",
|
||||
"@kbn/core-deprecations-common",
|
||||
"@kbn/core-deprecations-server"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue