[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 { getUiSettings } from './ui_settings';
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> {
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.uiSettings.register(getUiSettings(core.docLinks));
core.savedObjects.registerType(searchSavedObjectType);
core.savedObjects.registerType(getSavedSearchObjectType(getSearchSourceMigrations));
return {};
}

View file

@ -6,4 +6,4 @@
* 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 { searchMigrations } from './search_migrations';
import { MigrateFunctionsObject } from 'src/plugins/kibana_utils/common';
import { getAllMigrations } from './search_migrations';
export const searchSavedObjectType: SavedObjectsType = {
name: 'search',
hidden: false,
namespaceType: 'multiple-isolated',
convertToMultiNamespaceTypeVersion: '8.0.0',
management: {
icon: 'discoverApp',
defaultSearchField: 'title',
importableAndExportable: true,
getTitle(obj) {
return obj.attributes.title;
},
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 },
},
export function getSavedSearchObjectType(
getSearchSourceMigrations: () => MigrateFunctionsObject
): SavedObjectsType {
return {
name: 'search',
hidden: false,
namespaceType: 'multiple-isolated',
convertToMultiNamespaceTypeVersion: '8.0.0',
management: {
icon: 'discoverApp',
defaultSearchField: 'title',
importableAndExportable: true,
getTitle(obj) {
return obj.attributes.title;
},
getInAppUrl(obj) {
return {
path: `/app/discover#/view/${encodeURIComponent(obj.id)}`,
uiCapabilitiesPath: 'discover.show',
};
},
sort: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
grid: { type: 'object', enabled: false },
version: { type: 'integer' },
rowHeight: { type: 'text' },
},
},
migrations: searchMigrations,
};
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' },
},
},
migrations: () => getAllMigrations(getSearchSourceMigrations()),
};
}

View file

@ -6,8 +6,8 @@
* Side Public License, v 1.
*/
import { SavedObjectMigrationContext } from 'kibana/server';
import { searchMigrations } from './search_migrations';
import { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from 'kibana/server';
import { getAllMigrations, searchMigrations } from './search_migrations';
const savedObjectMigrationContext = null as unknown as SavedObjectMigrationContext;
@ -350,4 +350,33 @@ Object {
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
/* eslint-disable @typescript-eslint/no-explicit-any */
import { flow, get } from 'lodash';
import { SavedObjectMigrationFn } from 'kibana/server';
import { flow, get, mapValues } from 'lodash';
import type {
SavedObjectAttributes,
SavedObjectMigrationFn,
SavedObjectMigrationMap,
} from 'kibana/server';
import { mergeSavedObjectMigrationMaps } from '../../../../core/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:
@ -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 = {
'6.7.2': flow(migrateMatchAllQuery),
'7.0.0': flow(setNewReferences),
'7.4.0': flow(migrateSearchSortToNestedArray),
'7.9.3': flow(migrateMatchAllQuery),
};
export const getAllMigrations = (
searchSourceMigrations: MigrateFunctionsObject
): SavedObjectMigrationMap => {
return mergeSavedObjectMigrationMaps(
searchMigrations,
getSearchSourceMigrations(searchSourceMigrations) as unknown as SavedObjectMigrationMap
);
};