Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions x-pack/plugins/lens/server/migrations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* 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';
import { SavedObjectMigrationContext } from 'src/core/server';

describe('Lens migrations', () => {
describe('7.7.0 missing dimensions in XY', () => {
const context = {} as SavedObjectMigrationContext;

const example = {
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 = migrations['7.7.0'](target, context);
expect(result).toEqual(target);
});

it('should handle missing layers', () => {
const result = migrations['7.7.0'](
{
...example,
attributes: {
...example.attributes,
state: {
...example.attributes.state,
datasourceStates: {
indexpattern: {
layers: [],
},
},
},
},
},
context
);

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 = migrations['7.7.0'](example, context);

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'],
},
]);
});
});
});
37 changes: 37 additions & 0 deletions x-pack/plugins/lens/server/migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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 { SavedObjectMigrationFn } from 'src/core/server';

interface XYLayerPre77 {
layerId: string;
xAccessor: string;
splitAccessor: string;
accessors: string[];
}

export const migrations: Record<string, SavedObjectMigrationFn> = {
'7.7.0': doc => {
const newDoc = cloneDeep(doc);
if (newDoc.attributes?.visualizationType === 'lnsXY') {
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: XYLayerPre77) => {
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;
},
};
2 changes: 2 additions & 0 deletions x-pack/plugins/lens/server/saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { CoreSetup } from 'kibana/server';
import { getEditPath } from '../common';
import { migrations } from './migrations';

export function setupSavedObjects(core: CoreSetup) {
core.savedObjects.registerType({
Expand All @@ -22,6 +23,7 @@ export function setupSavedObjects(core: CoreSetup) {
uiCapabilitiesPath: 'visualize.show',
}),
},
migrations,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is slightly different from 7.7 because migrations are now registered to specific types

mappings: {
properties: {
title: {
Expand Down