mirror of https://github.com/grafana/grafana.git
fix: pyroscope datasource remove link extension (#89512)
It has been decided that we will not be using this moving forward.
This commit is contained in:
parent
7d8afd9578
commit
f5d9c247d9
|
@ -12,7 +12,6 @@ import { EditorRow } from './EditorRow';
|
||||||
import { EditorRows } from './EditorRows';
|
import { EditorRows } from './EditorRows';
|
||||||
import { LabelsEditor } from './LabelsEditor';
|
import { LabelsEditor } from './LabelsEditor';
|
||||||
import { ProfileTypesCascader, useProfileTypes } from './ProfileTypesCascader';
|
import { ProfileTypesCascader, useProfileTypes } from './ProfileTypesCascader';
|
||||||
import { PyroscopeQueryLinkExtensions } from './QueryLinkExtension';
|
|
||||||
import { QueryOptions } from './QueryOptions';
|
import { QueryOptions } from './QueryOptions';
|
||||||
|
|
||||||
export type Props = QueryEditorProps<PyroscopeDataSource, Query, PyroscopeDataSourceOptions>;
|
export type Props = QueryEditorProps<PyroscopeDataSource, Query, PyroscopeDataSourceOptions>;
|
||||||
|
@ -62,7 +61,6 @@ export function QueryEditor(props: Props) {
|
||||||
labels={labels}
|
labels={labels}
|
||||||
getLabelValues={getLabelValues}
|
getLabelValues={getLabelValues}
|
||||||
/>
|
/>
|
||||||
<PyroscopeQueryLinkExtensions {...props} />
|
|
||||||
</EditorRow>
|
</EditorRow>
|
||||||
<EditorRow>
|
<EditorRow>
|
||||||
<QueryOptions query={query} onQueryChange={props.onChange} app={props.app} labels={labels} />
|
<QueryOptions query={query} onQueryChange={props.onChange} app={props.app} labels={labels} />
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import React from 'react';
|
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
|
|
||||||
import { PluginType, rangeUtil, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data';
|
|
||||||
import { usePluginLinkExtensions } from '@grafana/runtime';
|
|
||||||
|
|
||||||
import { PyroscopeDataSource } from '../datasource';
|
|
||||||
import { mockFetchPyroscopeDatasourceSettings } from '../datasource.test';
|
|
||||||
|
|
||||||
import { Props, PyroscopeQueryLinkExtensions, resetPyroscopeQueryLinkExtensionsFetches } from './QueryLinkExtension';
|
|
||||||
|
|
||||||
// Constants copied from `QueryLinkExtension.tsx`
|
|
||||||
const EXTENSION_POINT_ID = 'plugins/grafana-pyroscope-datasource/query-links';
|
|
||||||
|
|
||||||
jest.mock('@grafana/runtime', () => ({
|
|
||||||
...jest.requireActual('@grafana/runtime'),
|
|
||||||
usePluginLinkExtensions: jest.fn(),
|
|
||||||
getTemplateSrv: () => {
|
|
||||||
return {
|
|
||||||
replace: (query: string): string => {
|
|
||||||
return query.replace(/\$var/g, 'interpolated');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const usePluginLinkExtensionsMock = jest.mocked(usePluginLinkExtensions);
|
|
||||||
|
|
||||||
const defaultPyroscopeDataSourceSettings = {
|
|
||||||
uid: 'default-pyroscope',
|
|
||||||
url: 'http://pyroscope',
|
|
||||||
basicAuthUser: 'pyroscope_user',
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('PyroscopeQueryLinkExtensions', () => {
|
|
||||||
const EXPECTED_BUTTON_LABEL = 'Profiles App';
|
|
||||||
const DEFAULT_EXTENSION_PATH = 'a/mock-path-app/fake-path';
|
|
||||||
|
|
||||||
function createExtension(overrides?: Partial<PluginExtensionLink>) {
|
|
||||||
return {
|
|
||||||
...{
|
|
||||||
description: 'unremarkable-description',
|
|
||||||
extensionPointId: EXTENSION_POINT_ID,
|
|
||||||
title: EXPECTED_BUTTON_LABEL,
|
|
||||||
path: DEFAULT_EXTENSION_PATH,
|
|
||||||
type: PluginExtensionTypes.link,
|
|
||||||
category: 'unremarkable-category',
|
|
||||||
icon: 'heart',
|
|
||||||
onClick() {},
|
|
||||||
pluginId: 'mock-path-app',
|
|
||||||
id: `${Date.now()}}`,
|
|
||||||
},
|
|
||||||
...overrides,
|
|
||||||
} as PluginExtensionLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
resetPyroscopeQueryLinkExtensionsFetches();
|
|
||||||
mockFetchPyroscopeDatasourceSettings(defaultPyroscopeDataSourceSettings);
|
|
||||||
|
|
||||||
usePluginLinkExtensionsMock.mockRestore();
|
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({ extensions: [], isLoading: false }); // Unless stated otherwise, no extensions
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render if extension present', async () => {
|
|
||||||
usePluginLinkExtensionsMock.mockReturnValue({ extensions: [createExtension()], isLoading: false }); // Default extension
|
|
||||||
|
|
||||||
await act(setup);
|
|
||||||
expect(await screen.findAllByText(EXPECTED_BUTTON_LABEL)).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should not render if no extension present', async () => {
|
|
||||||
await act(setup);
|
|
||||||
expect(screen.queryByText(EXPECTED_BUTTON_LABEL)).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function setupDs() {
|
|
||||||
const ds = new PyroscopeDataSource({
|
|
||||||
...defaultPyroscopeDataSourceSettings,
|
|
||||||
name: 'test',
|
|
||||||
type: PluginType.datasource,
|
|
||||||
access: 'proxy',
|
|
||||||
id: 1,
|
|
||||||
jsonData: {},
|
|
||||||
meta: {
|
|
||||||
name: '',
|
|
||||||
id: '',
|
|
||||||
type: PluginType.datasource,
|
|
||||||
baseUrl: '',
|
|
||||||
info: {
|
|
||||||
author: {
|
|
||||||
name: '',
|
|
||||||
},
|
|
||||||
description: '',
|
|
||||||
links: [],
|
|
||||||
logos: {
|
|
||||||
large: '',
|
|
||||||
small: '',
|
|
||||||
},
|
|
||||||
screenshots: [],
|
|
||||||
updated: '',
|
|
||||||
version: '',
|
|
||||||
},
|
|
||||||
module: '',
|
|
||||||
},
|
|
||||||
readOnly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setup(options: { props: Partial<Props> } = { props: {} }) {
|
|
||||||
const utils = render(
|
|
||||||
<PyroscopeQueryLinkExtensions
|
|
||||||
query={{
|
|
||||||
queryType: 'both',
|
|
||||||
labelSelector: '',
|
|
||||||
profileTypeId: 'process_cpu:cpu',
|
|
||||||
refId: 'A',
|
|
||||||
maxNodes: 1000,
|
|
||||||
groupBy: [],
|
|
||||||
}}
|
|
||||||
datasource={setupDs()}
|
|
||||||
range={rangeUtil.convertRawToRange({ from: 'now-1h', to: 'now' })}
|
|
||||||
{...options.props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
return { ...utils };
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
import { css } from '@emotion/css';
|
|
||||||
import React from 'react';
|
|
||||||
import { useAsync } from 'react-use';
|
|
||||||
|
|
||||||
import { GrafanaTheme2, QueryEditorProps, TimeRange } from '@grafana/data';
|
|
||||||
import { getBackendSrv, usePluginLinkExtensions } from '@grafana/runtime';
|
|
||||||
import { LinkButton, useStyles2 } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { PyroscopeDataSource } from '../datasource';
|
|
||||||
import { PyroscopeDataSourceOptions, Query } from '../types';
|
|
||||||
|
|
||||||
const EXTENSION_POINT_ID = 'plugins/grafana-pyroscope-datasource/query-links';
|
|
||||||
|
|
||||||
/** A subset of the datasource settings that are relevant for this integration */
|
|
||||||
type PyroscopeDatasourceSettings = {
|
|
||||||
uid: string;
|
|
||||||
url: string;
|
|
||||||
type: string;
|
|
||||||
basicAuthUser: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** The context object that will be shared with the link extension's configure function */
|
|
||||||
type ExtensionQueryLinksContext = {
|
|
||||||
datasourceUid: string;
|
|
||||||
query: Query;
|
|
||||||
range?: TimeRange | undefined;
|
|
||||||
datasourceSettings?: PyroscopeDatasourceSettings;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Global promises to fetch pyroscope datasource settings by uid as encountered */
|
|
||||||
const pyroscopeDatasourceSettingsByUid: Record<string, PyroscopeDatasourceSettings> = {};
|
|
||||||
|
|
||||||
/* Reset promises for testing purposes */
|
|
||||||
export function resetPyroscopeQueryLinkExtensionsFetches() {
|
|
||||||
Object.keys(pyroscopeDatasourceSettingsByUid).forEach((key) => delete pyroscopeDatasourceSettingsByUid[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A subset of the `PyroscopeDataSource` `QueryEditorProps` */
|
|
||||||
export type Props = Pick<
|
|
||||||
QueryEditorProps<PyroscopeDataSource, Query, PyroscopeDataSourceOptions>,
|
|
||||||
'datasource' | 'query' | 'range'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export function PyroscopeQueryLinkExtensions(props: Props) {
|
|
||||||
const {
|
|
||||||
datasource: { uid: datasourceUid },
|
|
||||||
query,
|
|
||||||
range,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const { value: datasourceSettings } = useAsync(async () => {
|
|
||||||
if (pyroscopeDatasourceSettingsByUid[datasourceUid]) {
|
|
||||||
return pyroscopeDatasourceSettingsByUid[datasourceUid];
|
|
||||||
}
|
|
||||||
const settings = await getBackendSrv().get<PyroscopeDatasourceSettings>(`/api/datasources/uid/${datasourceUid}`);
|
|
||||||
pyroscopeDatasourceSettingsByUid[datasourceUid] = settings;
|
|
||||||
return settings;
|
|
||||||
}, [datasourceUid]);
|
|
||||||
|
|
||||||
const context: ExtensionQueryLinksContext = {
|
|
||||||
datasourceUid,
|
|
||||||
query,
|
|
||||||
range,
|
|
||||||
datasourceSettings,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { extensions } = usePluginLinkExtensions({
|
|
||||||
extensionPointId: EXTENSION_POINT_ID,
|
|
||||||
context,
|
|
||||||
});
|
|
||||||
|
|
||||||
const styles = useStyles2(getStyles);
|
|
||||||
|
|
||||||
if (extensions.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{extensions.map((extension) => (
|
|
||||||
<LinkButton
|
|
||||||
className={styles.linkButton}
|
|
||||||
key={`${extension.id}`}
|
|
||||||
variant="secondary"
|
|
||||||
icon={extension.icon || 'external-link-alt'}
|
|
||||||
tooltip={extension.description}
|
|
||||||
target="_blank"
|
|
||||||
href={extension.path}
|
|
||||||
onClick={extension.onClick}
|
|
||||||
>
|
|
||||||
{extension.title}
|
|
||||||
</LinkButton>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStyles(theme: GrafanaTheme2) {
|
|
||||||
return {
|
|
||||||
linkButton: css({
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in New Issue