Skip to content

Commit

Permalink
[Lens] [7.7] Migration for 7.7 (#62877)
Browse files Browse the repository at this point in the history
* [Lens] [7.7] Migration for 7.7

* Fix type issues
  • Loading branch information
Wylie Conlon authored Apr 8, 2020
1 parent 8159b20 commit 6449d95
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 0 deletions.
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/lens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
getEditPath,
NOT_INTERNATIONALIZED_PRODUCT_NAME,
} from '../../../plugins/lens/common';
import { migrations } from './migrations';

export const lens: LegacyPluginInitializer = kibana => {
return new kibana.Plugin({
Expand All @@ -33,6 +34,7 @@ export const lens: LegacyPluginInitializer = kibana => {
embeddableFactories: [`plugins/${PLUGIN_ID}/legacy`],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
mappings,
migrations: { lens: migrations },
savedObjectsManagement: {
lens: {
defaultSearchField: 'title',
Expand Down
158 changes: 158 additions & 0 deletions x-pack/legacy/plugins/lens/migrations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* 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, RawLensSavedXYObject770 } from './migrations';
import { SimpleSavedObject } from 'src/core/public';

describe('Lens migrations', () => {
describe('7.7.0 missing dimensions in XY', () => {
const migrate = (doc: SimpleSavedObject | RawLensSavedXYObject770) => migrations['7.7.0'](doc);

const example: RawLensSavedXYObject770 = {
type: 'lens',
attributes: {
expression:
'kibana\n| kibana_context query="{\\"language\\":\\"kuery\\",\\"query\\":\\"\\"}" \n| lens_merge_tables layerIds="c61a8afb-a185-4fae-a064-fb3846f6c451" \n tables={esaggs index="logstash-*" metricsAtAllLevels=false partialRows=false includeFormatHints=true aggConfigs="[{\\"id\\":\\"2cd09808-3915-49f4-b3b0-82767eba23f7\\",\\"enabled\\":true,\\"type\\":\\"max\\",\\"schema\\":\\"metric\\",\\"params\\":{\\"field\\":\\"bytes\\"}}]" | lens_rename_columns idMap="{\\"col-0-2cd09808-3915-49f4-b3b0-82767eba23f7\\":\\"2cd09808-3915-49f4-b3b0-82767eba23f7\\"}"}\n| lens_metric_chart title="Maximum of bytes" accessor="2cd09808-3915-49f4-b3b0-82767eba23f7"',
state: {
datasourceMetaData: {
filterableIndexPatterns: [
{
id: 'logstash-*',
title: 'logstash-*',
},
],
},
datasourceStates: {
indexpattern: {
currentIndexPatternId: 'logstash-*',
layers: {
'c61a8afb-a185-4fae-a064-fb3846f6c451': {
columnOrder: ['2cd09808-3915-49f4-b3b0-82767eba23f7'],
columns: {
'2cd09808-3915-49f4-b3b0-82767eba23f7': {
dataType: 'number',
isBucketed: false,
label: 'Maximum of bytes',
operationType: 'max',
scale: 'ratio',
sourceField: 'bytes',
},
'd3e62a7a-c259-4fff-a2fc-eebf20b7008a': {
dataType: 'number',
isBucketed: false,
label: 'Minimum of bytes',
operationType: 'min',
scale: 'ratio',
sourceField: 'bytes',
},
'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8': {
dataType: 'date',
isBucketed: true,
label: 'Date Histogram of @timestamp',
operationType: 'date_histogram',
params: {
interval: 'auto',
},
scale: 'interval',
sourceField: '@timestamp',
},
},
indexPatternId: 'logstash-*',
},
},
},
},
filters: [],
query: {
language: 'kuery',
query: '',
},
visualization: {
accessor: '2cd09808-3915-49f4-b3b0-82767eba23f7',
isHorizontal: false,
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
layers: [
{
accessors: [
'd3e62a7a-c259-4fff-a2fc-eebf20b7008a',
'26ef70a9-c837-444c-886e-6bd905ee7335',
],
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
seriesType: 'area',
splitAccessor: '54cd64ed-2a44-4591-af84-b2624504569a',
xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8',
},
],
legend: {
isVisible: true,
position: 'right',
},
preferredSeriesType: 'area',
},
},
title: 'Artistpreviouslyknownaslens',
visualizationType: 'lnsXY',
},
};

it('should not change anything by XY visualizations', () => {
const target = {
...example,
attributes: {
...example.attributes,
visualizationType: 'lnsMetric',
},
};
const result = migrate(target as SimpleSavedObject);
expect(result).toEqual(target);
});

it('should handle missing layers', () => {
const result = migrate({
...example,
attributes: {
...example.attributes,
state: {
...example.attributes.state,
datasourceStates: {
indexpattern: {
layers: [],
},
},
},
},
} as SimpleSavedObject) as RawLensSavedXYObject770;

expect(result.attributes.state.visualization.layers).toEqual([
{
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
seriesType: 'area',
// Removed split accessor
splitAccessor: undefined,
xAccessor: undefined,
// Removed a yAcccessor
accessors: [],
},
]);
});

it('should remove only missing accessors', () => {
const result = migrate(example) as RawLensSavedXYObject770;

expect(result.attributes.state.visualization.layers).toEqual([
{
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
seriesType: 'area',
xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8',
// Removed split accessor
splitAccessor: undefined,
// Removed a yAcccessor
accessors: ['d3e62a7a-c259-4fff-a2fc-eebf20b7008a'],
},
]);
});
});
});
69 changes: 69 additions & 0 deletions x-pack/legacy/plugins/lens/migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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 { cloneDeep } from 'lodash';
import { SimpleSavedObject } from 'src/core/public';

export interface RawLensSavedXYObject770 {
type: 'lens';
attributes: Record<string, unknown> & {
visualizationType: string;
state: Record<string, unknown> & {
datasourceStates?: Record<string, unknown> & {
indexpattern?: Record<string, unknown> & {
layers: Record<string, Record<string, unknown> & { columns: Record<string, unknown> }>;
};
};
visualization: Record<string, unknown> & {
layers: Array<
Record<string, unknown> & {
layerId: string;
accessors: string[];
xAccessor: string;
splitAccessor: string;
}
>;
};
};
};
}

type LensSavedXYObjectPost770 = RawLensSavedXYObject770;

function isLensSavedXY770(
doc: SimpleSavedObject | RawLensSavedXYObject770
): doc is RawLensSavedXYObject770 {
return (
doc.type === 'lens' &&
doc.attributes &&
(doc.attributes as Record<string, string>).visualizationType === 'lnsXY'
);
}

export const migrations = {
'7.7.0': (
doc: SimpleSavedObject | RawLensSavedXYObject770
): SimpleSavedObject | LensSavedXYObjectPost770 => {
const newDoc = cloneDeep(doc);
if (!isLensSavedXY770(newDoc)) {
return newDoc;
}
const datasourceState = newDoc.attributes.state?.datasourceStates?.indexpattern;
const datasourceLayers = datasourceState?.layers ?? {};
const xyState = newDoc.attributes.state?.visualization;
newDoc.attributes.state.visualization.layers = xyState.layers.map(layer => {
const layerId = layer.layerId;
const datasource = datasourceLayers[layerId];
return {
...layer,
xAccessor: datasource?.columns[layer.xAccessor] ? layer.xAccessor : undefined,
splitAccessor: datasource?.columns[layer.splitAccessor] ? layer.splitAccessor : undefined,
accessors: layer.accessors.filter(accessor => !!datasource?.columns[accessor]),
};
}) as typeof xyState.layers;
return newDoc;
},
};

0 comments on commit 6449d95

Please sign in to comment.