Migrate graph_workspace saved object registration to Kibana platform (#64157)

* Migrate graph_workspace saved object registration to Kibana platform
* Remove legacy plugin 🎉
This commit is contained in:
Matthias Wilhelm 2020-04-24 14:55:43 +02:00 committed by GitHub
parent 66074f9042
commit 6d099d0a4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 203 additions and 211 deletions

View file

@ -159,8 +159,6 @@ export const TEMPORARILY_IGNORED_PATHS = [
'webpackShims/elasticsearch-browser.js',
'webpackShims/moment-timezone.js',
'webpackShims/ui-bootstrap.js',
'x-pack/legacy/plugins/graph/public/graphClientWorkspace.js',
'x-pack/legacy/plugins/graph/public/angular-venn-simple.js',
'x-pack/legacy/plugins/index_management/public/lib/editSettings.js',
'x-pack/legacy/plugins/license_management/public/store/reducers/licenseManagement.js',
'x-pack/legacy/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js',

View file

@ -15,7 +15,7 @@
"xpack.endpoint": "plugins/endpoint",
"xpack.features": "plugins/features",
"xpack.fileUpload": "plugins/file_upload",
"xpack.graph": ["legacy/plugins/graph", "plugins/graph"],
"xpack.graph": ["plugins/graph"],
"xpack.grokDebugger": "plugins/grokdebugger",
"xpack.idxMgmt": "plugins/index_management",
"xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management",

View file

@ -5,7 +5,6 @@
*/
import { xpackMain } from './legacy/plugins/xpack_main';
import { graph } from './legacy/plugins/graph';
import { monitoring } from './legacy/plugins/monitoring';
import { reporting } from './legacy/plugins/reporting';
import { security } from './legacy/plugins/security';
@ -32,7 +31,6 @@ import { triggersActionsUI } from './legacy/plugins/triggers_actions_ui';
module.exports = function(kibana) {
return [
xpackMain(kibana),
graph(kibana),
monitoring(kibana),
reporting(kibana),
spaces(kibana),

View file

@ -1,32 +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;
* you may not use this file except in compliance with the Elastic License.
*/
// @ts-ignore
import migrations from './migrations';
import mappings from './mappings.json';
import { LegacyPluginInitializer } from '../../../../src/legacy/plugin_discovery/types';
export const graph: LegacyPluginInitializer = kibana => {
return new kibana.Plugin({
id: 'graph',
configPrefix: 'xpack.graph',
require: ['kibana', 'elasticsearch', 'xpack_main'],
uiExports: {
mappings,
migrations,
},
config(Joi: any) {
return Joi.object({
enabled: Joi.boolean().default(true),
canEditDrillDownUrls: Joi.boolean().default(true),
savePolicy: Joi.string()
.valid(['config', 'configAndDataWithConsent', 'configAndData', 'none'])
.default('configAndData'),
}).default();
},
});
};

View file

@ -1,31 +0,0 @@
{
"graph-workspace": {
"properties": {
"description": {
"type": "text"
},
"kibanaSavedObjectMeta": {
"properties": {
"searchSourceJSON": {
"type": "text"
}
}
},
"numLinks": {
"type": "integer"
},
"numVertices": {
"type": "integer"
},
"title": {
"type": "text"
},
"version": {
"type": "integer"
},
"wsState": {
"type": "text"
}
}
}
}

View file

@ -1,41 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { get } from 'lodash';
export default {
'graph-workspace': {
'7.0.0': doc => {
// Set new "references" attribute
doc.references = doc.references || [];
// Migrate index pattern
const wsState = get(doc, 'attributes.wsState');
if (typeof wsState !== 'string') {
return doc;
}
let state;
try {
state = JSON.parse(JSON.parse(wsState));
} catch (e) {
// Let it go, the data is invalid and we'll leave it as is
return doc;
}
const { indexPattern } = state;
if (!indexPattern) {
return doc;
}
state.indexPatternRefName = 'indexPattern_0';
delete state.indexPattern;
doc.attributes.wsState = JSON.stringify(JSON.stringify(state));
doc.references.push({
name: 'indexPattern_0',
type: 'index-pattern',
id: indexPattern,
});
return doc;
},
},
};

View file

@ -1,102 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import migrations from './migrations';
describe('graph-workspace', () => {
describe('7.0.0', () => {
const migration = migrations['graph-workspace']['7.0.0'];
test('returns doc on empty object', () => {
expect(migration({})).toMatchInlineSnapshot(`
Object {
"references": Array [],
}
`);
});
test('returns doc when wsState is not a string', () => {
const doc = {
id: '1',
attributes: {
wsState: true,
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": true,
},
"id": "1",
"references": Array [],
}
`);
});
test('returns doc when wsState is not valid JSON', () => {
const doc = {
id: '1',
attributes: {
wsState: '123abc',
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": "123abc",
},
"id": "1",
"references": Array [],
}
`);
});
test('returns doc when "indexPattern" is missing from wsState', () => {
const doc = {
id: '1',
attributes: {
wsState: JSON.stringify(JSON.stringify({ foo: true })),
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": "\\"{\\\\\\"foo\\\\\\":true}\\"",
},
"id": "1",
"references": Array [],
}
`);
});
test('extract "indexPattern" attribute from doc', () => {
const doc = {
id: '1',
attributes: {
wsState: JSON.stringify(JSON.stringify({ foo: true, indexPattern: 'pattern*' })),
bar: true,
},
};
const migratedDoc = migration(doc);
expect(migratedDoc).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"bar": true,
"wsState": "\\"{\\\\\\"foo\\\\\\":true,\\\\\\"indexPatternRefName\\\\\\":\\\\\\"indexPattern_0\\\\\\"}\\"",
},
"id": "1",
"references": Array [
Object {
"id": "pattern*",
"name": "indexPattern_0",
"type": "index-pattern",
},
],
}
`);
});
});
});

View file

@ -13,6 +13,7 @@ import { registerExploreRoute } from './routes/explore';
import { HomeServerPluginSetup } from '../../../../src/plugins/home/server';
import { registerSampleData } from './sample_data';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
import { graphWorkspace } from './saved_objects';
export class GraphPlugin implements Plugin {
private licenseState: LicenseState | null = null;
@ -32,6 +33,7 @@ export class GraphPlugin implements Plugin {
const licenseState = new LicenseState();
licenseState.start(licensing.license$);
this.licenseState = licenseState;
core.savedObjects.registerType(graphWorkspace);
if (home) {
registerSampleData(home.sampleData, licenseState);

View file

@ -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;
* you may not use this file except in compliance with the Elastic License.
*/
import { SavedObjectsType } from 'kibana/server';
import { graphMigrations } from './migrations';
export const graphWorkspace: SavedObjectsType = {
name: 'graph-workspace',
namespaceType: 'single',
hidden: false,
migrations: graphMigrations,
mappings: {
properties: {
description: {
type: 'text',
},
kibanaSavedObjectMeta: {
properties: {
searchSourceJSON: {
type: 'text',
},
},
},
numLinks: {
type: 'integer',
},
numVertices: {
type: 'integer',
},
title: {
type: 'text',
},
version: {
type: 'integer',
},
wsState: {
type: 'text',
},
},
},
};

View file

@ -0,0 +1,6 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { graphWorkspace } from './graph_workspace';

View file

@ -0,0 +1,111 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { graphMigrations } from './migrations';
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
describe('graph-workspace', () => {
describe('7.0.0', () => {
const migration = graphMigrations['7.0.0'];
test('returns doc on empty object', () => {
expect(migration({} as SavedObjectUnsanitizedDoc)).toMatchInlineSnapshot(`
Object {
"references": Array [],
}
`);
});
test('returns doc when wsState is not a string', () => {
const doc = {
id: '1',
type: 'graph-workspace',
attributes: {
wsState: true,
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": true,
},
"id": "1",
"references": Array [],
"type": "graph-workspace",
}
`);
});
test('returns doc when wsState is not valid JSON', () => {
const doc = {
id: '1',
type: 'graph-workspace',
attributes: {
wsState: '123abc',
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": "123abc",
},
"id": "1",
"references": Array [],
"type": "graph-workspace",
}
`);
});
test('returns doc when "indexPattern" is missing from wsState', () => {
const doc = {
id: '1',
type: 'graph-workspace',
attributes: {
wsState: JSON.stringify(JSON.stringify({ foo: true })),
},
};
expect(migration(doc)).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"wsState": "\\"{\\\\\\"foo\\\\\\":true}\\"",
},
"id": "1",
"references": Array [],
"type": "graph-workspace",
}
`);
});
test('extract "indexPattern" attribute from doc', () => {
const doc = {
id: '1',
type: 'graph-workspace',
attributes: {
wsState: JSON.stringify(JSON.stringify({ foo: true, indexPattern: 'pattern*' })),
bar: true,
},
};
const migratedDoc = migration(doc);
expect(migratedDoc).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"bar": true,
"wsState": "\\"{\\\\\\"foo\\\\\\":true,\\\\\\"indexPatternRefName\\\\\\":\\\\\\"indexPattern_0\\\\\\"}\\"",
},
"id": "1",
"references": Array [
Object {
"id": "pattern*",
"name": "indexPattern_0",
"type": "index-pattern",
},
],
"type": "graph-workspace",
}
`);
});
});
});

View file

@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { get } from 'lodash';
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
export const graphMigrations = {
'7.0.0': (doc: SavedObjectUnsanitizedDoc) => {
// Set new "references" attribute
doc.references = doc.references || [];
// Migrate index pattern
const wsState = get(doc, 'attributes.wsState');
if (typeof wsState !== 'string') {
return doc;
}
let state;
try {
state = JSON.parse(JSON.parse(wsState));
} catch (e) {
// Let it go, the data is invalid and we'll leave it as is
return doc;
}
const { indexPattern } = state;
if (!indexPattern) {
return doc;
}
state.indexPatternRefName = 'indexPattern_0';
delete state.indexPattern;
doc.attributes.wsState = JSON.stringify(JSON.stringify(state));
doc.references.push({
name: 'indexPattern_0',
type: 'index-pattern',
id: indexPattern,
});
return doc;
},
};