mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
PublicDashboards: Modal warns when using unsupported datasources (#58926)
Adds warning to pubdash modal when dashboard uses datasources not supported by pubdash
This commit is contained in:
parent
d2c129fbac
commit
97e81ecbde
@ -193,6 +193,7 @@ export const Pages = {
|
||||
CopyUrlInput: 'data-testid public dashboard copy url input',
|
||||
CopyUrlButton: 'data-testid public dashboard copy url button',
|
||||
TemplateVariablesWarningAlert: 'data-testid public dashboard disabled template variables alert',
|
||||
UnsupportedDatasourcesWarningAlert: 'data-testid public dashboard unsupported datasources',
|
||||
},
|
||||
},
|
||||
Explore: {
|
||||
|
@ -10,30 +10,27 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/commands/generate_datasources"
|
||||
)
|
||||
|
||||
var goTemplate = `
|
||||
var tsDatasourcesTemplate = `
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
|
||||
package publicdashboards
|
||||
|
||||
var SupportedDatasources = map[string]bool{
|
||||
export const supportedDatasources = new Set<string>([
|
||||
{{- range . }}
|
||||
"{{ printf "%s" . }}": true,
|
||||
'{{ printf "%s" . }}',
|
||||
{{- end }}
|
||||
}
|
||||
])
|
||||
`
|
||||
|
||||
func main() {
|
||||
baseUrl := "https://grafana.com"
|
||||
slugs, err := generate_datasources.GetCompatibleDatasources(baseUrl)
|
||||
tsTemplate := template.Must(template.New("").Parse(tsDatasourcesTemplate))
|
||||
|
||||
myTemplate := template.Must(template.New("").Parse(goTemplate))
|
||||
|
||||
file, err := os.Create("supported_datasources_gen.go")
|
||||
// Generate supported datasources for Typescript
|
||||
tsFile, err := os.Create("./../../../public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SupportedPubdashDatasources.ts")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
err = myTemplate.Execute(file, slugs)
|
||||
err = tsTemplate.Execute(tsFile, slugs)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
|
||||
package publicdashboards
|
||||
|
||||
var SupportedDatasources = map[string]bool{
|
||||
"aquaqanalytics-kdbbackend-datasource": true,
|
||||
"cloudwatch": true,
|
||||
"dlopes7-appdynamics-datasource": true,
|
||||
"doitintl-bigquery-datasource": true,
|
||||
"elasticsearch": true,
|
||||
"frser-sqlite-datasource": true,
|
||||
"grafadruid-druid-datasource": true,
|
||||
"grafana-athena-datasource": true,
|
||||
"grafana-azure-data-explorer-datasource": true,
|
||||
"grafana-azure-monitor-datasource": true,
|
||||
"grafana-bigquery-datasource": true,
|
||||
"grafana-clickhouse-datasource": true,
|
||||
"grafana-databricks-datasource": true,
|
||||
"grafana-datadog-datasource": true,
|
||||
"grafana-db2-datasource": true,
|
||||
"grafana-dynatrace-datasource": true,
|
||||
"grafana-es-open-distro-datasource": true,
|
||||
"grafana-github-datasource": true,
|
||||
"grafana-honeycomb-datasource": true,
|
||||
"grafana-iot-sitewise-datasource": true,
|
||||
"grafana-jira-datasource": true,
|
||||
"grafana-mock-datasource": true,
|
||||
"grafana-mongodb-datasource": true,
|
||||
"grafana-newrelic-datasource": true,
|
||||
"grafana-odbc-datasource": true,
|
||||
"grafana-opcua-datasource": true,
|
||||
"grafana-opensearch-datasource": true,
|
||||
"grafana-oracle-datasource": true,
|
||||
"grafana-orbit-datasource": true,
|
||||
"grafana-redshift-datasource": true,
|
||||
"grafana-salesforce-datasource": true,
|
||||
"grafana-saphana-datasource": true,
|
||||
"grafana-sentry-datasource": true,
|
||||
"grafana-servicenow-datasource": true,
|
||||
"grafana-snowflake-datasource": true,
|
||||
"grafana-splunk-datasource": true,
|
||||
"grafana-splunk-monitoring-datasource": true,
|
||||
"grafana-timestream-datasource": true,
|
||||
"grafana-wavefront-datasource": true,
|
||||
"grafana-x-ray-datasource": true,
|
||||
"graphite": true,
|
||||
"hadesarchitect-cassandra-datasource": true,
|
||||
"influxdb": true,
|
||||
"innius-grpc-datasource": true,
|
||||
"kniepdennis-neo4j-datasource": true,
|
||||
"loki": true,
|
||||
"marcusolsson-csv-datasource": true,
|
||||
"marcusolsson-ynab-datasource": true,
|
||||
"mssql": true,
|
||||
"mysql": true,
|
||||
"opentsdb": true,
|
||||
"postgres": true,
|
||||
"prometheus": true,
|
||||
"redis-datasource": true,
|
||||
"sentinelone-dataset-datasource": true,
|
||||
"tdengine-datasource": true,
|
||||
"vertamedia-clickhouse-datasource": true,
|
||||
"vertica-grafana-datasource": true,
|
||||
"yesoreyeram-infinity-datasource": true,
|
||||
}
|
@ -5,7 +5,7 @@ import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import 'whatwg-fetch';
|
||||
import { BootData } from '@grafana/data/src';
|
||||
import { BootData, DataQuery } from '@grafana/data/src';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
|
||||
import { setEchoSrv } from '@grafana/runtime/src';
|
||||
import config from 'app/core/config';
|
||||
@ -192,6 +192,23 @@ describe('SharePublic - New config setup', () => {
|
||||
await renderSharePublicDashboard({ panel: mockPanel, dashboard: mockDashboard, onDismiss: () => {} });
|
||||
expect(screen.getByTestId(selectors.SaveConfigButton)).toBeDisabled();
|
||||
});
|
||||
it('when dashboard has unsupported datasources, warning is shown', async () => {
|
||||
const panelModel = {
|
||||
targets: [
|
||||
{
|
||||
datasource: { type: 'notSupportedDatasource', uid: 'abc123' },
|
||||
} as DataQuery,
|
||||
] as DataQuery[],
|
||||
} as PanelModel;
|
||||
const dashboard = new DashboardModel({
|
||||
id: 1,
|
||||
panels: [panelModel],
|
||||
});
|
||||
|
||||
await renderSharePublicDashboard({ panel: mockPanel, dashboard, onDismiss: () => {} });
|
||||
|
||||
expect(screen.queryByTestId(selectors.UnsupportedDatasourcesWarningAlert)).toBeInTheDocument();
|
||||
});
|
||||
it('when fetch is done, then no loader spinner appears, inputs are enabled and save button is disabled', async () => {
|
||||
await renderSharePublicDashboard({ panel: mockPanel, dashboard: mockDashboard, onDismiss: () => {} });
|
||||
expect(screen.queryByTestId('Spinner')).not.toBeInTheDocument();
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
Acknowledgements,
|
||||
dashboardHasTemplateVariables,
|
||||
generatePublicDashboardUrl,
|
||||
getUnsupportedDashboardDatasources,
|
||||
publicDashboardPersisted,
|
||||
} from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
import { ShareModalTabProps } from 'app/features/dashboard/components/ShareModal/types';
|
||||
@ -161,6 +162,23 @@ export const SharePublicDashboard = (props: Props) => {
|
||||
{(isGetLoading || isFetching) && <Spinner />}
|
||||
</HorizontalGroup>
|
||||
<div className={styles.content}>
|
||||
{getUnsupportedDashboardDatasources(props.dashboard.panels).length > 0 ? (
|
||||
<Alert
|
||||
severity="warning"
|
||||
title="Unsupported Datasources"
|
||||
data-testid={selectors.UnsupportedDatasourcesWarningAlert}
|
||||
>
|
||||
<div>
|
||||
{`There are datasources in this dashboard that are unsupported for public dashboards. Panels that use these datasources may not function properly: ${getUnsupportedDashboardDatasources(
|
||||
props.dashboard.panels
|
||||
).join(', ')}. See the `}
|
||||
<a href="https://grafana.com/docs/grafana/latest/dashboards/dashboard-public/" className="text-link">
|
||||
docs
|
||||
</a>{' '}
|
||||
for supported datasources.
|
||||
</div>
|
||||
</Alert>
|
||||
) : null}
|
||||
{dashboardHasTemplateVariables(dashboardVariables) && !publicDashboardPersisted(publicDashboard) ? (
|
||||
<Alert
|
||||
severity="warning"
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { DataSourceRef, DataQuery } from '@grafana/data/src/types/query';
|
||||
import { updateConfig } from 'app/core/config';
|
||||
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
||||
import { VariableModel } from 'app/features/variables/types';
|
||||
|
||||
import {
|
||||
@ -6,6 +8,7 @@ import {
|
||||
dashboardHasTemplateVariables,
|
||||
publicDashboardPersisted,
|
||||
generatePublicDashboardUrl,
|
||||
getUnsupportedDashboardDatasources,
|
||||
} from './SharePublicDashboardUtils';
|
||||
|
||||
describe('dashboardHasTemplateVariables', () => {
|
||||
@ -45,3 +48,29 @@ describe('publicDashboardPersisted', () => {
|
||||
expect(publicDashboardPersisted(pubdash)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUnsupportedDashboardDatasources', () => {
|
||||
it('itIsSupported', () => {
|
||||
const pm = {
|
||||
targets: [
|
||||
{
|
||||
datasource: { type: 'prometheus' } as DataSourceRef,
|
||||
} as DataQuery,
|
||||
] as DataQuery[],
|
||||
} as PanelModel;
|
||||
const panelArray: PanelModel[] = [pm];
|
||||
expect(getUnsupportedDashboardDatasources(panelArray)).toEqual([]);
|
||||
});
|
||||
|
||||
it('itIsNotSupported', () => {
|
||||
const pm = {
|
||||
targets: [
|
||||
{
|
||||
datasource: { type: 'blah' } as DataSourceRef,
|
||||
} as DataQuery,
|
||||
] as DataQuery[],
|
||||
} as PanelModel;
|
||||
const panelArray: PanelModel[] = [pm];
|
||||
expect(getUnsupportedDashboardDatasources(panelArray)).toEqual(['blah']);
|
||||
});
|
||||
});
|
||||
|
@ -2,6 +2,10 @@ import { getConfig } from 'app/core/config';
|
||||
import { VariableModel } from 'app/features/variables/types';
|
||||
import { DashboardDataDTO, DashboardMeta } from 'app/types/dashboard';
|
||||
|
||||
import { PanelModel } from '../../../state';
|
||||
|
||||
import { supportedDatasources } from './SupportedPubdashDatasources';
|
||||
|
||||
export interface PublicDashboard {
|
||||
accessToken?: string;
|
||||
annotationsEnabled: boolean;
|
||||
@ -31,6 +35,24 @@ export const publicDashboardPersisted = (publicDashboard?: PublicDashboard): boo
|
||||
return publicDashboard?.uid !== '' && publicDashboard?.uid !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get unique datasource names from all panels that are not currently supported by public dashboards.
|
||||
*/
|
||||
export const getUnsupportedDashboardDatasources = (panels: PanelModel[]): string[] => {
|
||||
let unsupportedDS = new Set<string>();
|
||||
|
||||
for (const panel of panels) {
|
||||
for (const target of panel.targets) {
|
||||
let ds = target?.datasource?.type;
|
||||
if (ds && !supportedDatasources.has(ds)) {
|
||||
unsupportedDS.add(ds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(unsupportedDS).sort();
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate the public dashboard url. Uses the appUrl from the Grafana boot config, so urls will also be correct
|
||||
* when Grafana is hosted on a subpath.
|
||||
|
@ -0,0 +1,63 @@
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
|
||||
export const supportedDatasources = new Set<string>([
|
||||
'aquaqanalytics-kdbbackend-datasource',
|
||||
'cloudwatch',
|
||||
'dlopes7-appdynamics-datasource',
|
||||
'doitintl-bigquery-datasource',
|
||||
'elasticsearch',
|
||||
'frser-sqlite-datasource',
|
||||
'grafadruid-druid-datasource',
|
||||
'grafana-athena-datasource',
|
||||
'grafana-azure-data-explorer-datasource',
|
||||
'grafana-azure-monitor-datasource',
|
||||
'grafana-bigquery-datasource',
|
||||
'grafana-clickhouse-datasource',
|
||||
'grafana-databricks-datasource',
|
||||
'grafana-datadog-datasource',
|
||||
'grafana-db2-datasource',
|
||||
'grafana-dynatrace-datasource',
|
||||
'grafana-es-open-distro-datasource',
|
||||
'grafana-github-datasource',
|
||||
'grafana-honeycomb-datasource',
|
||||
'grafana-iot-sitewise-datasource',
|
||||
'grafana-jira-datasource',
|
||||
'grafana-mock-datasource',
|
||||
'grafana-mongodb-datasource',
|
||||
'grafana-newrelic-datasource',
|
||||
'grafana-odbc-datasource',
|
||||
'grafana-opcua-datasource',
|
||||
'grafana-opensearch-datasource',
|
||||
'grafana-oracle-datasource',
|
||||
'grafana-orbit-datasource',
|
||||
'grafana-redshift-datasource',
|
||||
'grafana-salesforce-datasource',
|
||||
'grafana-saphana-datasource',
|
||||
'grafana-sentry-datasource',
|
||||
'grafana-servicenow-datasource',
|
||||
'grafana-snowflake-datasource',
|
||||
'grafana-splunk-datasource',
|
||||
'grafana-splunk-monitoring-datasource',
|
||||
'grafana-timestream-datasource',
|
||||
'grafana-wavefront-datasource',
|
||||
'grafana-x-ray-datasource',
|
||||
'graphite',
|
||||
'hadesarchitect-cassandra-datasource',
|
||||
'influxdb',
|
||||
'innius-grpc-datasource',
|
||||
'kniepdennis-neo4j-datasource',
|
||||
'loki',
|
||||
'marcusolsson-csv-datasource',
|
||||
'marcusolsson-ynab-datasource',
|
||||
'mssql',
|
||||
'mysql',
|
||||
'opentsdb',
|
||||
'postgres',
|
||||
'prometheus',
|
||||
'redis-datasource',
|
||||
'sentinelone-dataset-datasource',
|
||||
'tdengine-datasource',
|
||||
'vertamedia-clickhouse-datasource',
|
||||
'vertica-grafana-datasource',
|
||||
'yesoreyeram-infinity-datasource',
|
||||
]);
|
Loading…
Reference in New Issue
Block a user