From c6183394820cf02dc0410a465bcceaf0be24a0fb Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Mon, 17 Jan 2022 10:21:13 +0000 Subject: [PATCH] Export: Fix error being thrown when exporting dashboards using query variables that reference the default datasource (#44034) * handle undefined datasources, add unit test * slightly nicer --- .../DashExportModal/DashboardExporter.test.ts | 142 ++++++++++++++++++ .../DashExportModal/DashboardExporter.ts | 2 +- 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts index 7a9f8d2fc4d..dc928b935eb 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts @@ -41,6 +41,148 @@ variableAdapters.register(createQueryVariableAdapter()); variableAdapters.register(createConstantVariableAdapter()); variableAdapters.register(createDataSourceVariableAdapter()); +it('handles a default datasource in a template variable', async () => { + const dashboard: any = { + annotations: { + list: [ + { + builtIn: 1, + datasource: '-- Grafana --', + enable: true, + hide: true, + iconColor: 'rgba(0, 211, 255, 1)', + name: 'Annotations & Alerts', + target: { + limit: 100, + matchAny: false, + tags: [], + type: 'dashboard', + }, + type: 'dashboard', + }, + ], + }, + editable: true, + fiscalYearStartMonth: 0, + graphTooltip: 0, + id: 331, + iteration: 1642157860116, + links: [], + liveNow: false, + panels: [ + { + fieldConfig: { + defaults: { + color: { + mode: 'palette-classic', + }, + custom: { + axisLabel: '', + axisPlacement: 'auto', + barAlignment: 0, + drawStyle: 'line', + fillOpacity: 0, + gradientMode: 'none', + hideFrom: { + legend: false, + tooltip: false, + viz: false, + }, + lineInterpolation: 'linear', + lineWidth: 1, + pointSize: 5, + scaleDistribution: { + type: 'linear', + }, + showPoints: 'auto', + spanNulls: false, + stacking: { + group: 'A', + mode: 'none', + }, + thresholdsStyle: { + mode: 'off', + }, + }, + mappings: [], + thresholds: { + mode: 'absolute', + steps: [ + { + color: 'green', + value: null, + }, + { + color: 'red', + value: 80, + }, + ], + }, + }, + overrides: [], + }, + gridPos: { + h: 9, + w: 12, + x: 0, + y: 0, + }, + id: 2, + options: { + legend: { + calcs: [], + displayMode: 'list', + placement: 'bottom', + }, + tooltip: { + mode: 'single', + sort: 'none', + }, + }, + targets: [ + { + datasource: { + type: 'testdata', + uid: 'PD8C576611E62080A', + }, + expr: '{filename="/var/log/system.log"}', + refId: 'A', + }, + ], + title: 'Panel Title', + type: 'timeseries', + }, + ], + templating: { + list: [ + { + current: {}, + definition: 'test', + error: {}, + hide: 0, + includeAll: false, + multi: false, + name: 'query0', + options: [], + query: { + query: 'test', + refId: 'StandardVariableQuery', + }, + refresh: 1, + regex: '', + skipUrlSync: false, + sort: 0, + type: 'query', + }, + ], + }, + }; + const dashboardModel = new DashboardModel(dashboard, {}, () => dashboard.templating.list); + const exporter = new DashboardExporter(); + const exported: any = await exporter.makeExportable(dashboardModel); + expect(exported.templating.list[0].datasource).toBe('${DS_GFDB}'); +}); + describe('given dashboard with repeated panels', () => { let dash: any, exported: any; diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts index ff29ddb6e58..74f321e675c 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts @@ -116,7 +116,7 @@ export class DashboardExporter { pluginName: ds.meta?.name, }; - if (obj.datasource === null || typeof obj.datasource === 'string') { + if (!obj.datasource || typeof obj.datasource === 'string') { obj.datasource = '${' + refName + '}'; } else { obj.datasource.uid = '${' + refName + '}';