[Discover] Implement search source migration (#128609)

This commit is contained in:
Matthias Wilhelm 2022-03-30 09:40:17 +02:00 committed by GitHub
parent d0c06b0112
commit 4f54124b77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 140 additions and 49 deletions

View file

@ -9,13 +9,22 @@
import { CoreSetup, CoreStart, Plugin } from 'kibana/server'; import { CoreSetup, CoreStart, Plugin } from 'kibana/server';
import { getUiSettings } from './ui_settings'; import { getUiSettings } from './ui_settings';
import { capabilitiesProvider } from './capabilities_provider'; import { capabilitiesProvider } from './capabilities_provider';
import { searchSavedObjectType } from './saved_objects'; import { getSavedSearchObjectType } from './saved_objects';
import type { PluginSetup as DataPluginSetup } from '../../data/server';
export class DiscoverServerPlugin implements Plugin<object, object> { export class DiscoverServerPlugin implements Plugin<object, object> {
public setup(core: CoreSetup) { public setup(
core: CoreSetup,
plugins: {
data: DataPluginSetup;
}
) {
const getSearchSourceMigrations = plugins.data.search.searchSource.getAllMigrations.bind(
plugins.data.search.searchSource
);
core.capabilities.registerProvider(capabilitiesProvider); core.capabilities.registerProvider(capabilitiesProvider);
core.uiSettings.register(getUiSettings(core.docLinks)); core.uiSettings.register(getUiSettings(core.docLinks));
core.savedObjects.registerType(searchSavedObjectType); core.savedObjects.registerType(getSavedSearchObjectType(getSearchSourceMigrations));
return {}; return {};
} }

View file

@ -6,4 +6,4 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
export { searchSavedObjectType } from './search'; export { getSavedSearchObjectType } from './search';

View file

@ -7,46 +7,51 @@
*/ */
import { SavedObjectsType } from 'kibana/server'; import { SavedObjectsType } from 'kibana/server';
import { searchMigrations } from './search_migrations'; import { MigrateFunctionsObject } from 'src/plugins/kibana_utils/common';
import { getAllMigrations } from './search_migrations';
export const searchSavedObjectType: SavedObjectsType = { export function getSavedSearchObjectType(
name: 'search', getSearchSourceMigrations: () => MigrateFunctionsObject
hidden: false, ): SavedObjectsType {
namespaceType: 'multiple-isolated', return {
convertToMultiNamespaceTypeVersion: '8.0.0', name: 'search',
management: { hidden: false,
icon: 'discoverApp', namespaceType: 'multiple-isolated',
defaultSearchField: 'title', convertToMultiNamespaceTypeVersion: '8.0.0',
importableAndExportable: true, management: {
getTitle(obj) { icon: 'discoverApp',
return obj.attributes.title; defaultSearchField: 'title',
}, importableAndExportable: true,
getInAppUrl(obj) { getTitle(obj) {
return { return obj.attributes.title;
path: `/app/discover#/view/${encodeURIComponent(obj.id)}`, },
uiCapabilitiesPath: 'discover.show', getInAppUrl(obj) {
}; return {
}, path: `/app/discover#/view/${encodeURIComponent(obj.id)}`,
}, uiCapabilitiesPath: 'discover.show',
mappings: { };
properties: {
columns: { type: 'keyword', index: false, doc_values: false },
description: { type: 'text' },
viewMode: { type: 'keyword', index: false, doc_values: false },
hideChart: { type: 'boolean', index: false, doc_values: false },
hideAggregatedPreview: { type: 'boolean', index: false, doc_values: false },
hits: { type: 'integer', index: false, doc_values: false },
kibanaSavedObjectMeta: {
properties: {
searchSourceJSON: { type: 'text', index: false },
},
}, },
sort: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
grid: { type: 'object', enabled: false },
version: { type: 'integer' },
rowHeight: { type: 'text' },
}, },
}, mappings: {
migrations: searchMigrations, properties: {
}; columns: { type: 'keyword', index: false, doc_values: false },
description: { type: 'text' },
viewMode: { type: 'keyword', index: false, doc_values: false },
hideChart: { type: 'boolean', index: false, doc_values: false },
hideAggregatedPreview: { type: 'boolean', index: false, doc_values: false },
hits: { type: 'integer', index: false, doc_values: false },
kibanaSavedObjectMeta: {
properties: {
searchSourceJSON: { type: 'text', index: false },
},
},
sort: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
grid: { type: 'object', enabled: false },
version: { type: 'integer' },
rowHeight: { type: 'text' },
},
},
migrations: () => getAllMigrations(getSearchSourceMigrations()),
};
}

View file

@ -6,8 +6,8 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { SavedObjectMigrationContext } from 'kibana/server'; import { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from 'kibana/server';
import { searchMigrations } from './search_migrations'; import { getAllMigrations, searchMigrations } from './search_migrations';
const savedObjectMigrationContext = null as unknown as SavedObjectMigrationContext; const savedObjectMigrationContext = null as unknown as SavedObjectMigrationContext;
@ -350,4 +350,33 @@ Object {
testMigrateMatchAllQuery(migrationFn); testMigrateMatchAllQuery(migrationFn);
}); });
}); });
it('should apply search source migrations within saved search', () => {
const savedSearch = {
attributes: {
kibanaSavedObjectMeta: {
searchSourceJSON: JSON.stringify({
some: 'prop',
migrated: false,
}),
},
},
} as SavedObjectUnsanitizedDoc;
const versionToTest = '9.1.1';
const migrations = getAllMigrations({
// providing a function for search source migration that's just setting `migrated` to true
[versionToTest]: (state) => ({ ...state, migrated: true }),
});
expect(migrations[versionToTest](savedSearch, {} as SavedObjectMigrationContext)).toEqual({
attributes: {
kibanaSavedObjectMeta: {
searchSourceJSON: JSON.stringify({
some: 'prop',
migrated: true,
}),
},
},
});
});
}); });

View file

@ -8,10 +8,22 @@
// TODO: This needs to be removed and properly typed // TODO: This needs to be removed and properly typed
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { flow, get, mapValues } from 'lodash';
import { flow, get } from 'lodash'; import type {
import { SavedObjectMigrationFn } from 'kibana/server'; SavedObjectAttributes,
SavedObjectMigrationFn,
SavedObjectMigrationMap,
} from 'kibana/server';
import { mergeSavedObjectMigrationMaps } from '../../../../core/server';
import { DEFAULT_QUERY_LANGUAGE } from '../../../data/server'; import { DEFAULT_QUERY_LANGUAGE } from '../../../data/server';
import { MigrateFunctionsObject, MigrateFunction } from '../../../kibana_utils/common';
import type { SerializedSearchSourceFields } from '../../../data/common';
export interface SavedSearchMigrationAttributes extends SavedObjectAttributes {
kibanaSavedObjectMeta: {
searchSourceJSON: string;
};
}
/** /**
* This migration script is related to: * This migration script is related to:
@ -120,9 +132,45 @@ const migrateSearchSortToNestedArray: SavedObjectMigrationFn<any, any> = (doc) =
}; };
}; };
/**
* This creates a migration map that applies search source migrations
*/
const getSearchSourceMigrations = (searchSourceMigrations: MigrateFunctionsObject) =>
mapValues<MigrateFunctionsObject, MigrateFunction>(
searchSourceMigrations,
(migrate: MigrateFunction<SerializedSearchSourceFields>): MigrateFunction =>
(state) => {
const _state = state as unknown as { attributes: SavedSearchMigrationAttributes };
const parsedSearchSourceJSON = _state.attributes.kibanaSavedObjectMeta.searchSourceJSON;
if (!parsedSearchSourceJSON) return _state;
return {
..._state,
attributes: {
..._state.attributes,
kibanaSavedObjectMeta: {
..._state.attributes.kibanaSavedObjectMeta,
searchSourceJSON: JSON.stringify(migrate(JSON.parse(parsedSearchSourceJSON))),
},
},
};
}
);
export const searchMigrations = { export const searchMigrations = {
'6.7.2': flow(migrateMatchAllQuery), '6.7.2': flow(migrateMatchAllQuery),
'7.0.0': flow(setNewReferences), '7.0.0': flow(setNewReferences),
'7.4.0': flow(migrateSearchSortToNestedArray), '7.4.0': flow(migrateSearchSortToNestedArray),
'7.9.3': flow(migrateMatchAllQuery), '7.9.3': flow(migrateMatchAllQuery),
}; };
export const getAllMigrations = (
searchSourceMigrations: MigrateFunctionsObject
): SavedObjectMigrationMap => {
return mergeSavedObjectMigrationMaps(
searchMigrations,
getSearchSourceMigrations(searchSourceMigrations) as unknown as SavedObjectMigrationMap
);
};