Skip to content

Commit 7420742

Browse files
Wylie Conlonelasticmachine
andauthored
[Lens] Migration from 7.7 (elastic#62879) (elastic#63469)
* [Lens] Migration from 7.7 * Fix types * Fix types in test * Add docs * Commit forgotten file * Remove extra types Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent e6c5ce6 commit 7420742

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { migrations } from './migrations';
8+
import { SavedObjectMigrationContext } from 'src/core/server';
9+
10+
describe('Lens migrations', () => {
11+
describe('7.7.0 missing dimensions in XY', () => {
12+
const context = {} as SavedObjectMigrationContext;
13+
14+
const example = {
15+
type: 'lens',
16+
attributes: {
17+
expression:
18+
'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"',
19+
state: {
20+
datasourceMetaData: {
21+
filterableIndexPatterns: [
22+
{
23+
id: 'logstash-*',
24+
title: 'logstash-*',
25+
},
26+
],
27+
},
28+
datasourceStates: {
29+
indexpattern: {
30+
currentIndexPatternId: 'logstash-*',
31+
layers: {
32+
'c61a8afb-a185-4fae-a064-fb3846f6c451': {
33+
columnOrder: ['2cd09808-3915-49f4-b3b0-82767eba23f7'],
34+
columns: {
35+
'2cd09808-3915-49f4-b3b0-82767eba23f7': {
36+
dataType: 'number',
37+
isBucketed: false,
38+
label: 'Maximum of bytes',
39+
operationType: 'max',
40+
scale: 'ratio',
41+
sourceField: 'bytes',
42+
},
43+
'd3e62a7a-c259-4fff-a2fc-eebf20b7008a': {
44+
dataType: 'number',
45+
isBucketed: false,
46+
label: 'Minimum of bytes',
47+
operationType: 'min',
48+
scale: 'ratio',
49+
sourceField: 'bytes',
50+
},
51+
'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8': {
52+
dataType: 'date',
53+
isBucketed: true,
54+
label: 'Date Histogram of @timestamp',
55+
operationType: 'date_histogram',
56+
params: {
57+
interval: 'auto',
58+
},
59+
scale: 'interval',
60+
sourceField: '@timestamp',
61+
},
62+
},
63+
indexPatternId: 'logstash-*',
64+
},
65+
},
66+
},
67+
},
68+
filters: [],
69+
query: {
70+
language: 'kuery',
71+
query: '',
72+
},
73+
visualization: {
74+
accessor: '2cd09808-3915-49f4-b3b0-82767eba23f7',
75+
isHorizontal: false,
76+
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
77+
layers: [
78+
{
79+
accessors: [
80+
'd3e62a7a-c259-4fff-a2fc-eebf20b7008a',
81+
'26ef70a9-c837-444c-886e-6bd905ee7335',
82+
],
83+
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
84+
seriesType: 'area',
85+
splitAccessor: '54cd64ed-2a44-4591-af84-b2624504569a',
86+
xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8',
87+
},
88+
],
89+
legend: {
90+
isVisible: true,
91+
position: 'right',
92+
},
93+
preferredSeriesType: 'area',
94+
},
95+
},
96+
title: 'Artistpreviouslyknownaslens',
97+
visualizationType: 'lnsXY',
98+
},
99+
};
100+
101+
it('should not change anything by XY visualizations', () => {
102+
const target = {
103+
...example,
104+
attributes: {
105+
...example.attributes,
106+
visualizationType: 'lnsMetric',
107+
},
108+
};
109+
const result = migrations['7.7.0'](target, context);
110+
expect(result).toEqual(target);
111+
});
112+
113+
it('should handle missing layers', () => {
114+
const result = migrations['7.7.0'](
115+
{
116+
...example,
117+
attributes: {
118+
...example.attributes,
119+
state: {
120+
...example.attributes.state,
121+
datasourceStates: {
122+
indexpattern: {
123+
layers: [],
124+
},
125+
},
126+
},
127+
},
128+
},
129+
context
130+
);
131+
132+
expect(result.attributes.state.visualization.layers).toEqual([
133+
{
134+
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
135+
seriesType: 'area',
136+
// Removed split accessor
137+
splitAccessor: undefined,
138+
xAccessor: undefined,
139+
// Removed a yAcccessor
140+
accessors: [],
141+
},
142+
]);
143+
});
144+
145+
it('should remove only missing accessors', () => {
146+
const result = migrations['7.7.0'](example, context);
147+
148+
expect(result.attributes.state.visualization.layers).toEqual([
149+
{
150+
layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451',
151+
seriesType: 'area',
152+
xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8',
153+
// Removed split accessor
154+
splitAccessor: undefined,
155+
// Removed a yAcccessor
156+
accessors: ['d3e62a7a-c259-4fff-a2fc-eebf20b7008a'],
157+
},
158+
]);
159+
});
160+
});
161+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { cloneDeep } from 'lodash';
8+
import { SavedObjectMigrationFn } from 'src/core/server';
9+
10+
interface XYLayerPre77 {
11+
layerId: string;
12+
xAccessor: string;
13+
splitAccessor: string;
14+
accessors: string[];
15+
}
16+
17+
export const migrations: Record<string, SavedObjectMigrationFn> = {
18+
'7.7.0': doc => {
19+
const newDoc = cloneDeep(doc);
20+
if (newDoc.attributes?.visualizationType === 'lnsXY') {
21+
const datasourceState = newDoc.attributes.state?.datasourceStates?.indexpattern;
22+
const datasourceLayers = datasourceState?.layers ?? {};
23+
const xyState = newDoc.attributes.state?.visualization;
24+
newDoc.attributes.state.visualization.layers = xyState.layers.map((layer: XYLayerPre77) => {
25+
const layerId = layer.layerId;
26+
const datasource = datasourceLayers[layerId];
27+
return {
28+
...layer,
29+
xAccessor: datasource?.columns[layer.xAccessor] ? layer.xAccessor : undefined,
30+
splitAccessor: datasource?.columns[layer.splitAccessor] ? layer.splitAccessor : undefined,
31+
accessors: layer.accessors.filter(accessor => !!datasource?.columns[accessor]),
32+
};
33+
}) as typeof xyState.layers;
34+
}
35+
return newDoc;
36+
},
37+
};

x-pack/plugins/lens/server/saved_objects.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { CoreSetup } from 'kibana/server';
88
import { getEditPath } from '../common';
9+
import { migrations } from './migrations';
910

1011
export function setupSavedObjects(core: CoreSetup) {
1112
core.savedObjects.registerType({
@@ -22,6 +23,7 @@ export function setupSavedObjects(core: CoreSetup) {
2223
uiCapabilitiesPath: 'visualize.show',
2324
}),
2425
},
26+
migrations,
2527
mappings: {
2628
properties: {
2729
title: {

0 commit comments

Comments
 (0)