Skip to content

Commit

Permalink
AzureMonitor: Hide App Insights for data sources not using it (grafan…
Browse files Browse the repository at this point in the history
…a#34725)

* AzureMonitor: Hide Application Insights and Insights Analytics for panels not using them

* AzureMonitor: Hide Application Insights config

* simplify

* fix test
  • Loading branch information
joshhunt authored May 27, 2021
1 parent 6d750c0 commit 7646246
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 167 deletions.
Original file line number Diff line number Diff line change
@@ -1,46 +1,63 @@
import { render, screen } from '@testing-library/react';
import React from 'react';
import { shallow } from 'enzyme';
import ConfigEditor, { Props } from './ConfigEditor';
import ConfigEditor from './ConfigEditor';

const setup = () => {
const props: Props = {
options: {
id: 21,
uid: 'y',
orgId: 1,
name: 'Azure Monitor-10-10',
type: 'grafana-azure-monitor-datasource',
typeLogoUrl: '',
typeName: 'Azure',
access: 'proxy',
url: '',
password: '',
user: '',
database: '',
basicAuth: false,
basicAuthUser: '',
basicAuthPassword: '',
withCredentials: false,
isDefault: false,
jsonData: {
subscriptionId: '44987801-6nn6-49he-9b2d-9106972f9789',
azureLogAnalyticsSameAs: true,
cloudName: 'azuremonitor',
},
secureJsonFields: {},
version: 1,
readOnly: false,
},
onOptionsChange: jest.fn(),
describe('AppInsights ConfigEditor', () => {
const baseOptions = {
id: 21,
uid: 'y',
orgId: 1,
name: 'Azure Monitor-10-10',
type: 'grafana-azure-monitor-datasource',
typeLogoUrl: '',
typeName: 'Azure',
access: 'proxy',
url: '',
password: '',
user: '',
database: '',
basicAuth: false,
basicAuthUser: '',
basicAuthPassword: '',
withCredentials: false,
isDefault: false,
jsonData: {},
secureJsonFields: {},
version: 1,
readOnly: false,
};

return shallow(<ConfigEditor {...props} />);
};
const jsonData = {
subscriptionId: '44987801-6nn6-49he-9b2d-9106972f9789',
azureLogAnalyticsSameAs: true,
cloudName: 'azuremonitor',
};

const onOptionsChange = jest.fn();

it('should not render application insights config for new data sources', () => {
const options = {
...baseOptions,
jsonData,
};
render(<ConfigEditor options={options} onOptionsChange={onOptionsChange} />);

describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
expect(screen.queryByText('Azure Application Insights')).not.toBeInTheDocument();
});

it('should render application insights config for data sources using application insights', () => {
const options = {
...baseOptions,
jsonData: {
...jsonData,
appInsightsAppId: 'abc-123',
},
secureJsonFields: {
appInsightsApiKey: true,
},
};
render(<ConfigEditor options={options} onOptionsChange={onOptionsChange} />);

expect(wrapper).toMatchSnapshot();
expect(screen.queryByText('Azure Application Insights')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import { getBackendSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { InsightsConfig } from './InsightsConfig';
import ResponseParser from '../azure_monitor/response_parser';
import { AzureDataSourceJsonData, AzureDataSourceSecureJsonData, AzureDataSourceSettings } from '../types';
import { getAzureCloud } from '../credentials';
import { getAzureCloud, isAppInsightsConfigured } from '../credentials';
import { getLogAnalyticsManagementApiRoute, getManagementApiRoute } from '../api/routes';

export type Props = DataSourcePluginOptionsEditorProps<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>;

export interface State {
unsaved: boolean;
appInsightsInitiallyConfigured: boolean;
}

export class ConfigEditor extends PureComponent<Props, State> {
Expand All @@ -30,6 +31,7 @@ export class ConfigEditor extends PureComponent<Props, State> {

this.state = {
unsaved: false,
appInsightsInitiallyConfigured: isAppInsightsConfigured(props.options),
};

if (this.props.options.id) {
Expand Down Expand Up @@ -138,12 +140,14 @@ export class ConfigEditor extends PureComponent<Props, State> {
getWorkspaces={this.getWorkspaces}
/>

<InsightsConfig
options={options}
onUpdateJsonDataOption={this.onUpdateJsonDataOption}
onUpdateSecureJsonDataOption={this.onUpdateSecureJsonDataOption}
onResetOptionKey={this.resetSecureKey}
/>
{this.state.appInsightsInitiallyConfigured && (
<InsightsConfig
options={options}
onUpdateJsonDataOption={this.onUpdateJsonDataOption}
onUpdateSecureJsonDataOption={this.onUpdateSecureJsonDataOption}
onResetOptionKey={this.resetSecureKey}
/>
)}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { InlineFormLabel, Button, LegacyForms } from '@grafana/ui';
import { InlineFormLabel, Button, LegacyForms, Alert } from '@grafana/ui';
const { Input } = LegacyForms;
import { AzureDataSourceSettings, AzureDataSourceJsonData, AzureDataSourceSecureJsonData } from '../types';

Expand Down Expand Up @@ -66,6 +66,10 @@ export class InsightsConfig extends PureComponent<Props> {
</div>
</div>
</div>

<Alert severity="info" title="Application Insights credentials are deprecated">
Configure using Azure AD App Registration above and update existing queries to use Metrics or Logs.
</Alert>
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,54 @@ describe('Azure Monitor QueryEditor', () => {

expect(screen.getByText("The resource namespace 'grafanadev' is invalid.")).toBeInTheDocument();
});

it('hides deprecated services', async () => {
const mockDatasource = createMockDatasource();
const mockQuery = {
...createMockQuery(),
queryType: AzureQueryType.AzureMonitor,
};

render(
<QueryEditor
query={mockQuery}
datasource={mockDatasource}
variableOptionGroup={variableOptionGroup}
onChange={() => {}}
/>
);
await waitFor(() => expect(screen.getByTestId('azure-monitor-metrics-query-editor')).toBeInTheDocument());

const metrics = await screen.findByLabelText('Service');
selectEvent.openMenu(metrics);

expect(screen.queryByText('Application Insights')).not.toBeInTheDocument();
});

it("shows deprecated services when they're selected", async () => {
const mockDatasource = createMockDatasource();
const mockQuery = {
...createMockQuery(),
queryType: AzureQueryType.ApplicationInsights,
};

render(
<QueryEditor
query={mockQuery}
datasource={mockDatasource}
variableOptionGroup={variableOptionGroup}
onChange={() => {}}
/>
);
await waitFor(() =>
expect(screen.getByTestId('azure-monitor-application-insights-query-editor')).toBeInTheDocument()
);

expect(screen.queryByText('Application Insights')).toBeInTheDocument();

const metrics = await screen.findByLabelText('Service');
await selectEvent.select(metrics, 'Logs');

expect(screen.queryByText('Application Insights')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
import React, { useCallback } from 'react';
import React, { useCallback, useState } from 'react';
import { Select } from '@grafana/ui';
import { Field } from '../Field';
import { AzureMonitorQuery, AzureQueryType } from '../../types';
import { SelectableValue } from '@grafana/data';
import { findOption } from '../../utils/common';

const QUERY_TYPES = [
{ value: AzureQueryType.AzureMonitor, label: 'Metrics' },
{ value: AzureQueryType.LogAnalytics, label: 'Logs' },
{ value: AzureQueryType.ApplicationInsights, label: 'Application Insights' },
{ value: AzureQueryType.InsightsAnalytics, label: 'Insights Analytics' },
{ value: AzureQueryType.AzureResourceGraph, label: 'Azure Resource Graph' },
];

interface QueryTypeFieldProps {
query: AzureMonitorQuery;
onQueryChange: (newQuery: AzureMonitorQuery) => void;
}

const QueryTypeField: React.FC<QueryTypeFieldProps> = ({ query, onQueryChange }) => {
// Use useState to capture the initial value on first mount. We're not interested in when it changes
// We only show App Insights and Insights Analytics if they were initially selected. Otherwise, hide them.
const [initialQueryType] = useState(query.queryType);
const showAppInsights =
initialQueryType === AzureQueryType.ApplicationInsights || initialQueryType === AzureQueryType.InsightsAnalytics;

const queryTypes = [
{ value: AzureQueryType.AzureMonitor, label: 'Metrics' },
{ value: AzureQueryType.LogAnalytics, label: 'Logs' },
{ value: AzureQueryType.AzureResourceGraph, label: 'Azure Resource Graph' },
];

if (showAppInsights) {
queryTypes.push(
{ value: AzureQueryType.ApplicationInsights, label: 'Application Insights' },
{ value: AzureQueryType.InsightsAnalytics, label: 'Insights Analytics' }
);
}

const handleChange = useCallback(
(change: SelectableValue<AzureQueryType>) => {
change.value &&
Expand All @@ -34,8 +45,8 @@ const QueryTypeField: React.FC<QueryTypeFieldProps> = ({ query, onQueryChange })
<Field label="Service">
<Select
inputId="azure-monitor-query-type-field"
value={findOption(QUERY_TYPES, query.queryType)}
options={QUERY_TYPES}
value={findOption(queryTypes, query.queryType)}
options={queryTypes}
onChange={handleChange}
width={38}
/>
Expand Down

This file was deleted.

Loading

0 comments on commit 7646246

Please sign in to comment.