[v8.4.x] Datasource: Fixes changing default data source causes inconsistency between panel data source and query data source (#46221)

* Datasource: Fixes changing default data source causes inconsistency between panel data source and query data source (#46167)

* Datasource: Fixes changing default data source causes inconsistency between panel data source and query data source

* Fix unit tests

(cherry picked from commit a404dba29d)

* updated test

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
Grot (@grafanabot)
2022-03-31 10:46:56 +02:00
committed by GitHub
co-authored by Torkel Ödegaard
parent 3af9f2fa2e
commit 90a99a4719
4 changed files with 71 additions and 1 deletions
@@ -17,6 +17,13 @@ const dataSources = {
prom: mockDataSource({
name: 'prom',
type: 'prometheus',
isDefault: true,
}),
notDefault: mockDataSource({
name: 'prom-not-default',
uid: 'prom-not-default-uid',
type: 'prometheus',
isDefault: false,
}),
[MIXED_DATASOURCE_NAME]: mockDataSource({
name: MIXED_DATASOURCE_NAME,
@@ -1840,6 +1847,33 @@ describe('DashboardModel', () => {
});
});
describe('when fixing query and panel data source refs out of sync due to default data source change', () => {
let model: DashboardModel;
beforeEach(() => {
model = new DashboardModel({
templating: {
list: [],
},
panels: [
{
id: 2,
datasource: null,
targets: [
{
datasource: 'prom-not-default',
},
],
},
],
});
});
it('should not update panel datasource to that of query level ds', () => {
expect(model.panels[0].datasource?.uid).toEqual('prom-not-default-uid');
});
});
describe('when migrating time series axis visibility', () => {
test('preserves x axis visibility', () => {
const model = new DashboardModel({
@@ -67,6 +67,40 @@ export class DashboardMigrator {
this.dashboard = dashboardModel;
}
/**
* When changing default datasource which is stored as null Grafana get's into a mixed state where queries have
* data source uid & type set that is different from the now new default
*/
syncQueryDataSources() {
const dataSourceSrv = getDataSourceSrv();
// This only happens in some unit tests that does not set a DataSourceSrv
if (!dataSourceSrv) {
return;
}
const defaultDS = getDataSourceSrv().getInstanceSettings(null);
// if default ds is mixed then skip this
if (!defaultDS || defaultDS.meta.mixed) {
return;
}
for (const panel of this.dashboard.panels) {
// only interested in panels that use default (null) data source
if (panel.datasource) {
continue;
}
for (const target of panel.targets) {
// If query level data source is different from panel
if (target.datasource && target.datasource.uid !== defaultDS?.uid) {
// set panel level data source to data source on the query as this is more likely the correct one
// But impossible to say, and this changes the behavior of of what default means ahead of the big change to default
panel.datasource = target.datasource;
}
}
}
}
updateSchema(old: any) {
let i, j, k, n;
const oldVersion = this.dashboard.schemaVersion;
@@ -1067,6 +1067,7 @@ export class DashboardModel {
private updateSchema(old: any) {
const migrator = new DashboardMigrator(this);
migrator.updateSchema(old);
migrator.syncQueryDataSources();
}
resetOriginalTime() {
@@ -80,7 +80,7 @@ function setup(state?: any) {
return Object.values(datasources).map((d) => ({ name: d.name }));
},
getInstanceSettings(name: string) {
return { name, getRef: () => ({ uid: name }) };
return { name, getRef: () => ({ uid: name }), meta: { name } };
},
get(name?: string) {
return Promise.resolve(
@@ -90,6 +90,7 @@ function setup(state?: any) {
testDatasource: jest.fn(),
init: jest.fn(),
name: 'default',
meta: {},
}
);
},