* quick fix for 7.13 lens migration not being run on by value panels Co-authored-by: Joe Reuter <johannes.reuter@elastic.co> Co-authored-by: Devon Thomson <devon.thomson@elastic.co> Co-authored-by: Joe Reuter <johannes.reuter@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
0a7f567e6a
commit
c18944f156
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EmbeddableRegistryDefinition } from 'src/plugins/embeddable/server';
|
||||
import { SerializableState } from '../../../../../src/plugins/kibana_utils/common';
|
||||
import { DOC_TYPE } from '../../common';
|
||||
import { commonRenameOperationsForFormula } from '../migrations/common_migrations';
|
||||
import { LensDocShapePre712 } from '../migrations/types';
|
||||
|
||||
export const lensEmbeddableFactory = (): EmbeddableRegistryDefinition => {
|
||||
return {
|
||||
id: DOC_TYPE,
|
||||
migrations: {
|
||||
// This migration is run in 7.13.1 for `by value` panels because the 7.13 release window was missed.
|
||||
'7.13.1': (state) => {
|
||||
const lensState = (state as unknown) as { attributes: LensDocShapePre712 };
|
||||
const migratedLensState = commonRenameOperationsForFormula(lensState.attributes);
|
||||
return ({
|
||||
...lensState,
|
||||
attributes: migratedLensState,
|
||||
} as unknown) as SerializableState;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
46
x-pack/plugins/lens/server/migrations/common_migrations.ts
Normal file
46
x-pack/plugins/lens/server/migrations/common_migrations.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { LensDocShapePre712, OperationTypePre712, LensDocShapePost712 } from './types';
|
||||
|
||||
export const commonRenameOperationsForFormula = (
|
||||
attributes: LensDocShapePre712
|
||||
): LensDocShapePost712 => {
|
||||
const renameMapping = {
|
||||
avg: 'average',
|
||||
cardinality: 'unique_count',
|
||||
derivative: 'differences',
|
||||
} as const;
|
||||
function shouldBeRenamed(op: OperationTypePre712): op is keyof typeof renameMapping {
|
||||
return op in renameMapping;
|
||||
}
|
||||
const newAttributes = cloneDeep(attributes);
|
||||
const datasourceLayers = newAttributes.state.datasourceStates.indexpattern.layers || {};
|
||||
(newAttributes as LensDocShapePost712).state.datasourceStates.indexpattern.layers = Object.fromEntries(
|
||||
Object.entries(datasourceLayers).map(([layerId, layer]) => {
|
||||
return [
|
||||
layerId,
|
||||
{
|
||||
...layer,
|
||||
columns: Object.fromEntries(
|
||||
Object.entries(layer.columns).map(([columnId, column]) => {
|
||||
const copy = {
|
||||
...column,
|
||||
operationType: shouldBeRenamed(column.operationType)
|
||||
? renameMapping[column.operationType]
|
||||
: column.operationType,
|
||||
};
|
||||
return [columnId, copy];
|
||||
})
|
||||
),
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
return newAttributes as LensDocShapePost712;
|
||||
};
|
|
@ -5,8 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { migrations, LensDocShape } from './migrations';
|
||||
import { SavedObjectMigrationContext, SavedObjectMigrationFn } from 'src/core/server';
|
||||
import { migrations, LensDocShape } from './saved_object_migrations';
|
||||
import {
|
||||
SavedObjectMigrationContext,
|
||||
SavedObjectMigrationFn,
|
||||
SavedObjectUnsanitizedDoc,
|
||||
} from 'src/core/server';
|
||||
|
||||
describe('Lens migrations', () => {
|
||||
describe('7.7.0 missing dimensions in XY', () => {
|
||||
|
@ -767,10 +771,7 @@ describe('Lens migrations', () => {
|
|||
},
|
||||
};
|
||||
|
||||
it('should rename only specific operation types', () => {
|
||||
const result = migrations['7.13.0'](example, context) as ReturnType<
|
||||
SavedObjectMigrationFn<LensDocShape, LensDocShape>
|
||||
>;
|
||||
const validate = (result: SavedObjectUnsanitizedDoc<LensDocShape<unknown>>) => {
|
||||
const layers = result.attributes.state.datasourceStates.indexpattern.layers;
|
||||
expect(layers).toEqual({
|
||||
'5ab74ddc-93ca-44e2-9857-ecf85c86b53e': {
|
||||
|
@ -832,6 +833,23 @@ describe('Lens migrations', () => {
|
|||
expect(result.attributes.state.query).toEqual(example.attributes.state.query);
|
||||
expect(result.attributes.state.filters).toEqual(example.attributes.state.filters);
|
||||
expect(result.attributes.title).toEqual(example.attributes.title);
|
||||
};
|
||||
|
||||
it('should rename only specific operation types', () => {
|
||||
const result = migrations['7.13.0'](example, context) as ReturnType<
|
||||
SavedObjectMigrationFn<LensDocShape, LensDocShape>
|
||||
>;
|
||||
validate(result);
|
||||
});
|
||||
|
||||
it('can be applied multiple times', () => {
|
||||
const result1 = migrations['7.13.0'](example, context) as ReturnType<
|
||||
SavedObjectMigrationFn<LensDocShape, LensDocShape>
|
||||
>;
|
||||
const result2 = migrations['7.13.1'](result1, context) as ReturnType<
|
||||
SavedObjectMigrationFn<LensDocShape, LensDocShape>
|
||||
>;
|
||||
validate(result2);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -14,7 +14,9 @@ import {
|
|||
SavedObjectUnsanitizedDoc,
|
||||
} from 'src/core/server';
|
||||
import { Query, Filter } from 'src/plugins/data/public';
|
||||
import { PersistableFilter } from '../common';
|
||||
import { PersistableFilter } from '../../common';
|
||||
import { LensDocShapePost712, LensDocShapePre712 } from './types';
|
||||
import { commonRenameOperationsForFormula } from './common_migrations';
|
||||
|
||||
interface LensDocShapePre710<VisualizationState = unknown> {
|
||||
visualizationType: string | null;
|
||||
|
@ -106,86 +108,6 @@ interface DatatableStatePost711 {
|
|||
};
|
||||
}
|
||||
|
||||
type OperationTypePre712 =
|
||||
| 'avg'
|
||||
| 'cardinality'
|
||||
| 'derivative'
|
||||
| 'filters'
|
||||
| 'terms'
|
||||
| 'date_histogram'
|
||||
| 'min'
|
||||
| 'max'
|
||||
| 'sum'
|
||||
| 'median'
|
||||
| 'percentile'
|
||||
| 'last_value'
|
||||
| 'count'
|
||||
| 'range'
|
||||
| 'cumulative_sum'
|
||||
| 'counter_rate'
|
||||
| 'moving_average';
|
||||
type OperationTypePost712 = Exclude<
|
||||
OperationTypePre712 | 'average' | 'unique_count' | 'differences',
|
||||
'avg' | 'cardinality' | 'derivative'
|
||||
>;
|
||||
interface LensDocShapePre712<VisualizationState = unknown> {
|
||||
visualizationType: string | null;
|
||||
title: string;
|
||||
expression: string | null;
|
||||
state: {
|
||||
datasourceStates: {
|
||||
// This is hardcoded as our only datasource
|
||||
indexpattern: {
|
||||
layers: Record<
|
||||
string,
|
||||
{
|
||||
columns: Record<
|
||||
string,
|
||||
{
|
||||
operationType: OperationTypePre712;
|
||||
}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
visualization: VisualizationState;
|
||||
query: Query;
|
||||
filters: Filter[];
|
||||
};
|
||||
}
|
||||
|
||||
interface LensDocShapePost712<VisualizationState = unknown> {
|
||||
visualizationType: string | null;
|
||||
title: string;
|
||||
expression: string | null;
|
||||
state: {
|
||||
datasourceMetaData: {
|
||||
filterableIndexPatterns: Array<{ id: string; title: string }>;
|
||||
};
|
||||
datasourceStates: {
|
||||
// This is hardcoded as our only datasource
|
||||
indexpattern: {
|
||||
currentIndexPatternId: string;
|
||||
layers: Record<
|
||||
string,
|
||||
{
|
||||
columns: Record<
|
||||
string,
|
||||
{
|
||||
operationType: OperationTypePost712;
|
||||
}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
visualization: VisualizationState;
|
||||
query: Query;
|
||||
filters: Filter[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the `lens_auto_date` subexpression from a stored expression
|
||||
* string. For example: aggConfigs={lens_auto_date aggConfigs="JSON string"}
|
||||
|
@ -471,38 +393,11 @@ const renameOperationsForFormula: SavedObjectMigrationFn<
|
|||
LensDocShapePre712,
|
||||
LensDocShapePost712
|
||||
> = (doc) => {
|
||||
const renameMapping = {
|
||||
avg: 'average',
|
||||
cardinality: 'unique_count',
|
||||
derivative: 'differences',
|
||||
} as const;
|
||||
function shouldBeRenamed(op: OperationTypePre712): op is keyof typeof renameMapping {
|
||||
return op in renameMapping;
|
||||
}
|
||||
const newDoc = cloneDeep(doc);
|
||||
const datasourceLayers = newDoc.attributes.state.datasourceStates.indexpattern.layers || {};
|
||||
(newDoc.attributes as LensDocShapePost712).state.datasourceStates.indexpattern.layers = Object.fromEntries(
|
||||
Object.entries(datasourceLayers).map(([layerId, layer]) => {
|
||||
return [
|
||||
layerId,
|
||||
{
|
||||
...layer,
|
||||
columns: Object.fromEntries(
|
||||
Object.entries(layer.columns).map(([columnId, column]) => {
|
||||
const copy = {
|
||||
...column,
|
||||
operationType: shouldBeRenamed(column.operationType)
|
||||
? renameMapping[column.operationType]
|
||||
: column.operationType,
|
||||
};
|
||||
return [columnId, copy];
|
||||
})
|
||||
),
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
return newDoc as SavedObjectUnsanitizedDoc<LensDocShapePost712>;
|
||||
return {
|
||||
...newDoc,
|
||||
attributes: commonRenameOperationsForFormula(newDoc.attributes),
|
||||
};
|
||||
};
|
||||
|
||||
export const migrations: SavedObjectMigrationMap = {
|
||||
|
@ -514,4 +409,5 @@ export const migrations: SavedObjectMigrationMap = {
|
|||
'7.11.0': removeSuggestedPriority,
|
||||
'7.12.0': transformTableState,
|
||||
'7.13.0': renameOperationsForFormula,
|
||||
'7.13.1': renameOperationsForFormula, // duplicate this migration in case a broken by value panel is added to the library
|
||||
};
|
89
x-pack/plugins/lens/server/migrations/types.ts
Normal file
89
x-pack/plugins/lens/server/migrations/types.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Query, Filter } from 'src/plugins/data/public';
|
||||
|
||||
export type OperationTypePre712 =
|
||||
| 'avg'
|
||||
| 'cardinality'
|
||||
| 'derivative'
|
||||
| 'filters'
|
||||
| 'terms'
|
||||
| 'date_histogram'
|
||||
| 'min'
|
||||
| 'max'
|
||||
| 'sum'
|
||||
| 'median'
|
||||
| 'percentile'
|
||||
| 'last_value'
|
||||
| 'count'
|
||||
| 'range'
|
||||
| 'cumulative_sum'
|
||||
| 'counter_rate'
|
||||
| 'moving_average';
|
||||
export type OperationTypePost712 = Exclude<
|
||||
OperationTypePre712 | 'average' | 'unique_count' | 'differences',
|
||||
'avg' | 'cardinality' | 'derivative'
|
||||
>;
|
||||
|
||||
export interface LensDocShapePre712<VisualizationState = unknown> {
|
||||
visualizationType: string | null;
|
||||
title: string;
|
||||
expression: string | null;
|
||||
state: {
|
||||
datasourceStates: {
|
||||
// This is hardcoded as our only datasource
|
||||
indexpattern: {
|
||||
layers: Record<
|
||||
string,
|
||||
{
|
||||
columns: Record<
|
||||
string,
|
||||
{
|
||||
operationType: OperationTypePre712;
|
||||
}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
query: Query;
|
||||
visualization: VisualizationState;
|
||||
filters: Filter[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface LensDocShapePost712<VisualizationState = unknown> {
|
||||
visualizationType: string | null;
|
||||
title: string;
|
||||
expression: string | null;
|
||||
state: {
|
||||
datasourceMetaData: {
|
||||
filterableIndexPatterns: Array<{ id: string; title: string }>;
|
||||
};
|
||||
datasourceStates: {
|
||||
// This is hardcoded as our only datasource
|
||||
indexpattern: {
|
||||
currentIndexPatternId: string;
|
||||
layers: Record<
|
||||
string,
|
||||
{
|
||||
columns: Record<
|
||||
string,
|
||||
{
|
||||
operationType: OperationTypePost712;
|
||||
}
|
||||
>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
};
|
||||
visualization: VisualizationState;
|
||||
query: Query;
|
||||
filters: Filter[];
|
||||
};
|
||||
}
|
|
@ -17,10 +17,13 @@ import {
|
|||
scheduleLensTelemetry,
|
||||
} from './usage';
|
||||
import { setupSavedObjects } from './saved_objects';
|
||||
import { EmbeddableSetup } from '../../../../src/plugins/embeddable/server';
|
||||
import { lensEmbeddableFactory } from './embeddable/lens_embeddable_factory';
|
||||
|
||||
export interface PluginSetupContract {
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
taskManager?: TaskManagerSetupContract;
|
||||
embeddable: EmbeddableSetup;
|
||||
}
|
||||
|
||||
export interface PluginStartContract {
|
||||
|
@ -53,6 +56,7 @@ export class LensServerPlugin implements Plugin<{}, {}, {}, {}> {
|
|||
plugins.taskManager
|
||||
);
|
||||
}
|
||||
plugins.embeddable.registerEmbeddableFactory(lensEmbeddableFactory());
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { CoreSetup } from 'kibana/server';
|
||||
import { getEditPath } from '../common';
|
||||
import { migrations } from './migrations';
|
||||
import { migrations } from './migrations/saved_object_migrations';
|
||||
|
||||
export function setupSavedObjects(core: CoreSetup) {
|
||||
core.savedObjects.registerType({
|
||||
|
|
Loading…
Reference in a new issue