Dashboards: Unify angular auto-migration code (#63915)

This commit is contained in:
Ryan McKinley
2023-03-27 08:11:45 -07:00
committed by GitHub
parent f948482386
commit 36e8ca7f13
9 changed files with 68 additions and 81 deletions

View File

@@ -85,7 +85,9 @@ it('handles a default datasource in a template variable', async () => {
],
},
};
const dashboardModel = new DashboardModel(dashboard, {}, () => dashboard.templating.list);
const dashboardModel = new DashboardModel(dashboard, undefined, {
getVariablesFromState: () => dashboard.templating.list,
});
const exporter = new DashboardExporter();
const exported: any = await exporter.makeExportable(dashboardModel);
expect(exported.templating.list[0].datasource.uid).toBe('${DS_GFDB}');
@@ -105,7 +107,9 @@ it('If a panel queries has no datasource prop ignore it', async () => {
},
],
};
const dashboardModel = new DashboardModel(dashboard, {}, () => []);
const dashboardModel = new DashboardModel(dashboard, undefined, {
getVariablesFromState: () => [],
});
const exporter = new DashboardExporter();
const exported: any = await exporter.makeExportable(dashboardModel);
expect(exported.panels[0].datasource).toEqual({ uid: '${DS_OTHER}', type: 'other' });
@@ -230,7 +234,13 @@ describe('given dashboard with repeated panels', () => {
info: { version: '1.1.2' },
} as PanelPluginMeta;
dash = new DashboardModel(dash, {}, () => dash.templating.list);
dash = new DashboardModel(
dash,
{},
{
getVariablesFromState: () => dash.templating.list,
}
);
// init library panels
dash.getPanelById(17).initLibraryPanel({

View File

@@ -16,7 +16,7 @@ import {
TimeZone,
UrlQueryValue,
} from '@grafana/data';
import { RefreshEvent, TimeRangeUpdatedEvent } from '@grafana/runtime';
import { RefreshEvent, TimeRangeUpdatedEvent, config } from '@grafana/runtime';
import { Dashboard } from '@grafana/schema';
import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants';
@@ -41,7 +41,7 @@ import { getTimeSrv } from '../services/TimeSrv';
import { mergePanels, PanelMergeInfo } from '../utils/panelMerge';
import { DashboardMigrator } from './DashboardMigrator';
import { GridPos, PanelModel } from './PanelModel';
import { GridPos, PanelModel, autoMigrateAngular } from './PanelModel';
import { TimeModel } from './TimeModel';
import { deleteScopeVars, isOnTheSameGridRow } from './utils';
@@ -108,6 +108,7 @@ export class DashboardModel implements TimeModel {
// repeat process cycles
declare meta: DashboardMeta;
events: EventBusExtended;
private getVariablesFromState: GetVariables;
static nonPersistedProperties: { [str: string]: boolean } = {
events: true,
@@ -126,7 +127,18 @@ export class DashboardModel implements TimeModel {
lastRefresh: true,
};
constructor(data: Dashboard, meta?: DashboardMeta, private getVariablesFromState: GetVariables = getVariablesByKey) {
constructor(
data: Dashboard,
meta?: DashboardMeta,
options?: {
// By default this uses variables from redux state
getVariablesFromState?: GetVariables;
// Force the loader to migrate panels
autoMigrateOldPanels?: boolean;
}
) {
this.getVariablesFromState = options?.getVariablesFromState ?? getVariablesByKey;
this.events = new EventBusSrv();
this.id = data.id || null;
// UID is not there for newly created dashboards
@@ -162,6 +174,17 @@ export class DashboardModel implements TimeModel {
this.initMeta(meta);
this.updateSchema(data);
// Auto-migrate old angular panels
if (options?.autoMigrateOldPanels || !config.angularSupportEnabled || config.featureToggles.autoMigrateOldPanels) {
this.panels.forEach((p) => {
const newType = autoMigrateAngular[p.type];
if (!p.autoMigrateFrom && newType) {
p.autoMigrateFrom = p.type;
p.type = newType;
}
});
}
this.addBuiltInAnnotationQuery();
this.sortPanelsByGridPos();
this.panelsAffectedByVariableChange = null;

View File

@@ -132,6 +132,19 @@ const defaults: any = {
title: '',
};
export const autoMigrateAngular: Record<string, string> = {
graph: 'timeseries',
'table-old': 'table',
singlestat: 'stat', // also automigrated if dashboard schemaVerion < 27
'grafana-singlestat-panel': 'stat',
'grafana-piechart-panel': 'piechart',
'grafana-worldmap-panel': 'geomap',
};
const autoMigratePanelType: Record<string, string> = {
'heatmap-new': 'heatmap', // this was a temporary development panel that is now standard
};
export class PanelModel implements DataConfigSource, IPanelModel {
/* persisted id, used in URL to identify a panel */
id!: number;
@@ -235,23 +248,10 @@ export class PanelModel implements DataConfigSource, IPanelModel {
(this as any)[property] = model[property];
}
switch (this.type) {
case 'graph':
if (config.featureToggles?.autoMigrateOldPanels || !config.angularSupportEnabled) {
this.autoMigrateFrom = this.type;
this.type = 'timeseries';
}
break;
case 'table-old':
if (config.featureToggles?.autoMigrateOldPanels || !config.angularSupportEnabled) {
this.autoMigrateFrom = this.type;
this.type = 'table';
}
break;
case 'heatmap-new':
this.autoMigrateFrom = this.type;
this.type = 'heatmap';
break;
const newType = autoMigratePanelType[this.type];
if (newType) {
this.autoMigrateFrom = this.type;
this.type = newType;
}
// defaults
@@ -427,7 +427,7 @@ export class PanelModel implements DataConfigSource, IPanelModel {
const version = getPluginVersion(plugin);
if (this.autoMigrateFrom) {
const wasAngular = this.autoMigrateFrom === 'graph' || this.autoMigrateFrom === 'table-old';
const wasAngular = autoMigrateAngular[this.autoMigrateFrom] != null;
this.callPanelTypeChangeHandler(
plugin,
this.autoMigrateFrom,

View File

@@ -27,7 +27,7 @@ export function createDashboardModelFixture(
...dashboardInput,
};
return new DashboardModel(dashboardJson, meta, getVariablesFromState);
return new DashboardModel(dashboardJson, meta, { getVariablesFromState });
}
export function createPanelJSONFixture(panelInput: Partial<Panel | GraphPanel | RowPanel> = {}): Panel {

View File

@@ -25,7 +25,6 @@ import {
import { StateManagerBase } from 'app/core/services/StateManagerBase';
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { graphToTimeseriesOptions } from 'app/plugins/panel/timeseries/migrations';
import { DashboardDTO } from 'app/types';
import { DashboardScene } from './DashboardScene';
@@ -63,7 +62,9 @@ export class DashboardLoader extends StateManagerBase<DashboardLoaderState> {
private initDashboard(rsp: DashboardDTO) {
// Just to have migrations run
const oldModel = new DashboardModel(rsp.dashboard, rsp.meta);
const oldModel = new DashboardModel(rsp.dashboard, rsp.meta, {
autoMigrateOldPanels: true,
});
const dashboard = createDashboardSceneFromDashboardModel(oldModel);
@@ -262,14 +263,6 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
maxDataPoints: panel.maxDataPoints ?? undefined,
});
// Migrate graph to timeseries
if (panel.type === 'graph') {
const { fieldConfig, options } = graphToTimeseriesOptions(panel);
panel.fieldConfig = fieldConfig;
panel.options = options;
panel.type = 'timeseries';
}
return new VizPanel({
title: panel.title,
pluginId: panel.type,