Azure Monitor: config editor updates, update sameas switch, fix test snaps (#22554)

* azure monitor config editor updates, do not show helper for sameas unless just switched, not create

* update snapshots
This commit is contained in:
Shavonn Brown 2020-03-04 09:11:11 -05:00 committed by GitHub
parent c5ceae3808
commit b27985ef38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 160 additions and 120 deletions

View File

@ -85,7 +85,10 @@ export const updateDatasourcePluginSecureJsonDataOption = <J, S extends {} = Key
});
};
export function updateDatasourcePluginResetOption(props: DataSourcePluginOptionsEditorProps, key: string) {
export const updateDatasourcePluginResetOption = <J, S extends {} = KeyValue>(
props: DataSourcePluginOptionsEditorProps,
key: string
) => {
const config = props.options;
props.onOptionsChange({
@ -99,4 +102,4 @@ export function updateDatasourcePluginResetOption(props: DataSourcePluginOptions
[key]: false,
},
});
}
};

View File

@ -39,9 +39,9 @@ const setup = (propOverrides?: object) => {
subscriptions: [],
workspaces: [],
makeSameAs: jest.fn(),
onUpdateOptions: jest.fn(),
onUpdateOption: jest.fn(),
onUpdateSecureOption: jest.fn(),
onUpdateDatasourceOptions: jest.fn(),
onUpdateJsonDataOption: jest.fn(),
onUpdateSecureJsonDataOption: jest.fn(),
onResetOptionKey: jest.fn(),
onLoadSubscriptions: jest.fn(),
onLoadWorkspaces: jest.fn(),

View File

@ -4,47 +4,59 @@ import { AzureCredentialsForm } from './AzureCredentialsForm';
import { Switch, FormLabel, Select, Button } from '@grafana/ui';
import { AzureDataSourceSettings } from '../types';
export interface State {
sameAsSwitched: boolean;
}
export interface Props {
options: AzureDataSourceSettings;
subscriptions: SelectableValue[];
workspaces: SelectableValue[];
makeSameAs: () => void;
onUpdateOptions: (options: AzureDataSourceSettings) => void;
onUpdateOption: (key: string, val: any) => void;
onUpdateSecureOption: (key: string, val: any) => void;
onUpdateDatasourceOptions: (options: AzureDataSourceSettings) => void;
onUpdateJsonDataOption: (key: string, val: any) => void;
onUpdateSecureJsonDataOption: (key: string, val: any) => void;
onResetOptionKey: (key: string) => void;
onLoadSubscriptions: (type?: string) => void;
onLoadWorkspaces: (type?: string) => void;
}
export class AnalyticsConfig extends PureComponent<Props> {
export class AnalyticsConfig extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
sameAsSwitched: false,
};
}
onLogAnalyticsTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateOption('logAnalyticsTenantId', event.target.value);
this.props.onUpdateJsonDataOption('logAnalyticsTenantId', event.target.value);
};
onLogAnalyticsClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateOption('logAnalyticsClientId', event.target.value);
this.props.onUpdateJsonDataOption('logAnalyticsClientId', event.target.value);
};
onLogAnalyticsClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateSecureOption('logAnalyticsClientSecret', event.target.value);
this.props.onUpdateSecureJsonDataOption('logAnalyticsClientSecret', event.target.value);
};
onLogAnalyticsSubscriptionSelect = (logAnalyticsSubscription: SelectableValue<string>) => {
this.props.onUpdateOption('logAnalyticsSubscriptionId', logAnalyticsSubscription.value);
this.props.onUpdateJsonDataOption('logAnalyticsSubscriptionId', logAnalyticsSubscription.value);
};
onWorkspaceSelectChange = (logAnalyticsDefaultWorkspace: SelectableValue<string>) => {
this.props.onUpdateOption('logAnalyticsDefaultWorkspace', logAnalyticsDefaultWorkspace.value);
this.props.onUpdateJsonDataOption('logAnalyticsDefaultWorkspace', logAnalyticsDefaultWorkspace.value);
};
onAzureLogAnalyticsSameAsChange = () => {
const { options, onUpdateOptions, makeSameAs } = this.props;
const { options, onUpdateDatasourceOptions, makeSameAs } = this.props;
if (!options.jsonData.azureLogAnalyticsSameAs && options.secureJsonData.clientSecret) {
makeSameAs();
} else if (!options.jsonData.azureLogAnalyticsSameAs) {
// if currently off, clear monitor secret
onUpdateOptions({
onUpdateDatasourceOptions({
...options,
jsonData: {
...options.jsonData,
@ -58,11 +70,13 @@ export class AnalyticsConfig extends PureComponent<Props> {
clientSecret: false,
},
});
} else {
this.props.onUpdateOption('azureLogAnalyticsSameAs', !options.jsonData.azureLogAnalyticsSameAs);
}
// init popover to warn secret needs to be re-entered
this.setState({
sameAsSwitched: true,
});
} else {
this.props.onUpdateJsonDataOption('azureLogAnalyticsSameAs', !options.jsonData.azureLogAnalyticsSameAs);
}
};
onLogAnalyticsResetClientSecret = () => {
@ -100,6 +114,8 @@ export class AnalyticsConfig extends PureComponent<Props> {
workspaces,
} = this.props;
const { sameAsSwitched } = this.state;
if (!jsonData.hasOwnProperty('azureLogAnalyticsSameAs')) {
jsonData.azureLogAnalyticsSameAs = true;
}
@ -111,6 +127,7 @@ export class AnalyticsConfig extends PureComponent<Props> {
};
const showSameAsHelpMsg =
sameAsSwitched &&
jsonData.azureLogAnalyticsSameAs &&
secureJsonFields &&
!secureJsonFields.clientSecret &&

View File

@ -68,23 +68,35 @@ export class ConfigEditor extends PureComponent<Props, State> {
}
};
updateOption = (key: keyof AzureDataSourceJsonData, val: any) => {
updateJsonDataOption = (key: keyof AzureDataSourceJsonData, val: any) => {
updateDatasourcePluginJsonDataOption(this.props, key, val);
};
updateSecureOption = (key: keyof AzureDataSourceSecureJsonData, val: any) => {
updateSecureJsonDataOption = (key: keyof AzureDataSourceSecureJsonData, val: any) => {
updateDatasourcePluginSecureJsonDataOption(this.props, key, val);
};
resetKey = (key: string) => {
resetSecureKey = (key: keyof AzureDataSourceSecureJsonData) => {
updateDatasourcePluginResetOption(this.props, key);
};
onUpdateJsonDataOption = (key: keyof AzureDataSourceJsonData) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
this.updateJsonDataOption(key, event.currentTarget.value);
};
onUpdateSecureJsonDataOption = (key: keyof AzureDataSourceSecureJsonData) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
this.updateSecureJsonDataOption(key, event.currentTarget.value);
};
makeSameAs = (updatedClientSecret?: string) => {
const { options } = this.props;
const clientSecret = updatedClientSecret || options.secureJsonData.clientSecret;
this.updateOptions({
this.props.onOptionsChange({
...options,
jsonData: {
...options.jsonData,
@ -101,32 +113,6 @@ export class ConfigEditor extends PureComponent<Props, State> {
});
};
updateOptions = (options: AzureDataSourceSettings) => {
if (options.hasOwnProperty('secureJsonData')) {
if (options.secureJsonData.hasOwnProperty('clientSecret') && options.secureJsonData.clientSecret.length === 0) {
delete options.secureJsonData.clientSecret;
}
if (
options.secureJsonData.hasOwnProperty('logAnalyticsClientSecret') &&
options.secureJsonData.logAnalyticsClientSecret.length === 0
) {
delete options.secureJsonData.logAnalyticsClientSecret;
}
if (
options.secureJsonData.hasOwnProperty('appInsightsApiKey') &&
options.secureJsonData.appInsightsApiKey.length === 0
) {
delete options.secureJsonData.appInsightsApiKey;
}
}
this.props.onOptionsChange({
...options,
});
};
hasNecessaryCredentials = () => {
if (!this.props.options.secureJsonFields.clientSecret && !this.props.options.secureJsonData.clientSecret) {
return false;
@ -214,7 +200,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
if (subscriptions && subscriptions.length > 0) {
this.setState({ subscriptions });
this.updateOption('subscriptionId', this.props.options.jsonData.subscriptionId || subscriptions[0].value);
this.updateJsonDataOption('subscriptionId', this.props.options.jsonData.subscriptionId || subscriptions[0].value);
}
if (this.props.options.jsonData.subscriptionId && this.props.options.jsonData.azureLogAnalyticsSameAs) {
@ -233,7 +219,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
if (logAnalyticsSubscriptions && logAnalyticsSubscriptions.length > 0) {
this.setState({ logAnalyticsSubscriptions });
this.updateOption(
this.updateJsonDataOption(
'logAnalyticsSubscriptionId',
this.props.options.jsonData.logAnalyticsSubscriptionId || logAnalyticsSubscriptions[0].value
);
@ -257,7 +243,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
if (logAnalyticsWorkspaces.length > 0) {
this.setState({ logAnalyticsWorkspaces });
this.updateOption(
this.updateJsonDataOption(
'logAnalyticsDefaultWorkspace',
this.props.options.jsonData.logAnalyticsDefaultWorkspace || logAnalyticsWorkspaces[0].value
);
@ -278,9 +264,9 @@ export class ConfigEditor extends PureComponent<Props, State> {
subscriptions={subscriptions}
makeSameAs={this.makeSameAs}
onLoadSubscriptions={this.onLoadSubscriptions}
onUpdateOption={this.updateOption}
onUpdateSecureOption={this.updateSecureOption}
onResetOptionKey={this.resetKey}
onUpdateJsonDataOption={this.updateJsonDataOption}
onUpdateSecureJsonDataOption={this.updateSecureJsonDataOption}
onResetOptionKey={this.resetSecureKey}
/>
<AnalyticsConfig
@ -288,19 +274,19 @@ export class ConfigEditor extends PureComponent<Props, State> {
workspaces={logAnalyticsWorkspaces}
subscriptions={logAnalyticsSubscriptions}
makeSameAs={this.makeSameAs}
onUpdateOptions={this.updateOptions}
onUpdateOption={this.updateOption}
onUpdateSecureOption={this.updateSecureOption}
onResetOptionKey={this.resetKey}
onUpdateDatasourceOptions={this.props.onOptionsChange}
onUpdateJsonDataOption={this.updateJsonDataOption}
onUpdateSecureJsonDataOption={this.updateSecureJsonDataOption}
onResetOptionKey={this.resetSecureKey}
onLoadSubscriptions={this.onLoadSubscriptions}
onLoadWorkspaces={this.getWorkspaces}
/>
<InsightsConfig
options={options}
onUpdateOption={this.updateOption}
onUpdateSecureOption={this.updateSecureOption}
onResetOptionKey={this.resetKey}
onUpdateJsonDataOption={this.onUpdateJsonDataOption}
onUpdateSecureJsonDataOption={this.onUpdateSecureJsonDataOption}
onResetOptionKey={this.resetSecureKey}
/>
</>
);

View File

@ -20,22 +20,17 @@ const setup = (propOverrides?: object) => {
basicAuthPassword: '',
withCredentials: false,
isDefault: false,
secureJsonFields: {
appInsightsApiKey: false,
},
secureJsonFields: {},
jsonData: {
cloudName: '',
subscriptionId: '',
appInsightsAppId: 'cvvcc020-2cpo-123a-a3d0-df6547fki792',
},
secureJsonData: {
appInsightsApiKey: 'e7f3f775-a987-4b3f-3835-51c4f982kl48',
},
secureJsonData: {},
version: 1,
readOnly: false,
},
onUpdateOption: jest.fn(),
onUpdateSecureOption: jest.fn(),
onUpdateJsonDataOption: jest.fn(),
onUpdateSecureJsonDataOption: jest.fn(),
onResetOptionKey: jest.fn(),
};
@ -53,7 +48,7 @@ describe('Render', () => {
it('should disable insights api key input', () => {
const wrapper = setup({
datasourceConfig: {
options: {
secureJsonFields: {
appInsightsApiKey: true,
},
@ -70,7 +65,7 @@ describe('Render', () => {
it('should enable insights api key input', () => {
const wrapper = setup({
datasourceConfig: {
options: {
secureJsonFields: {
appInsightsApiKey: false,
},

View File

@ -1,28 +1,24 @@
import React, { PureComponent, ChangeEvent } from 'react';
import React, { PureComponent } from 'react';
import { FormLabel, Button, Input } from '@grafana/ui';
import { AzureDataSourceSettings } from '../types';
import { AzureDataSourceSettings, AzureDataSourceJsonData, AzureDataSourceSecureJsonData } from '../types';
export interface Props {
options: AzureDataSourceSettings;
onUpdateOption: (key: string, val: any) => void;
onUpdateSecureOption: (key: string, val: any) => void;
onUpdateJsonDataOption: (
key: keyof AzureDataSourceJsonData
) => (event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>) => void;
onUpdateSecureJsonDataOption: (
key: keyof AzureDataSourceSecureJsonData
) => (event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>) => void;
onResetOptionKey: (key: string) => void;
}
export class InsightsConfig extends PureComponent<Props> {
onAppInsightsAppIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateOption('appInsightsAppId', event.target.value);
};
onAppInsightsApiKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateSecureOption('appInsightsApiKey', event.target.value);
};
onAppInsightsResetApiKey = () => {
this.props.onResetOptionKey('appInsightsApiKey');
};
render() {
const { options } = this.props;
const { options, onUpdateJsonDataOption, onUpdateSecureJsonDataOption } = this.props;
return (
<>
<h3 className="page-heading">Application Insights Details</h3>
@ -50,7 +46,7 @@ export class InsightsConfig extends PureComponent<Props> {
className="width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={options.secureJsonData.appInsightsApiKey || ''}
onChange={this.onAppInsightsApiKeyChange}
onChange={onUpdateSecureJsonDataOption('appInsightsApiKey')}
/>
</div>
</div>
@ -63,7 +59,7 @@ export class InsightsConfig extends PureComponent<Props> {
<Input
className="width-30"
value={options.jsonData.appInsightsAppId || ''}
onChange={this.onAppInsightsAppIdChange}
onChange={onUpdateJsonDataOption('appInsightsAppId')}
/>
</div>
</div>

View File

@ -14,23 +14,23 @@ export interface Props {
options: AzureDataSourceSettings;
subscriptions: SelectableValue[];
makeSameAs: (updatedClientSecret?: string) => void;
onUpdateOption: (key: string, val: any) => void;
onUpdateSecureOption: (key: string, val: any) => void;
onUpdateJsonDataOption: (key: string, val: any) => void;
onUpdateSecureJsonDataOption: (key: string, val: any) => void;
onResetOptionKey: (key: string) => void;
onLoadSubscriptions: () => void;
}
export class MonitorConfig extends PureComponent<Props> {
onAzureCloudSelect = (cloudName: SelectableValue<string>) => {
this.props.onUpdateOption('cloudName', cloudName.value);
this.props.onUpdateJsonDataOption('cloudName', cloudName.value);
};
onTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateOption('tenantId', event.target.value);
this.props.onUpdateJsonDataOption('tenantId', event.target.value);
};
onClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onUpdateOption('clientId', event.target.value);
this.props.onUpdateJsonDataOption('clientId', event.target.value);
};
onClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
@ -39,7 +39,7 @@ export class MonitorConfig extends PureComponent<Props> {
if (options.jsonData.azureLogAnalyticsSameAs && event.target.value) {
makeSameAs(event.target.value);
} else {
this.props.onUpdateSecureOption('clientSecret', event.target.value);
this.props.onUpdateSecureJsonDataOption('clientSecret', event.target.value);
}
};
@ -48,7 +48,7 @@ export class MonitorConfig extends PureComponent<Props> {
};
onSubscriptionSelect = (subscription: SelectableValue<string>) => {
this.props.onUpdateOption('subscriptionId', subscription.value);
this.props.onUpdateJsonDataOption('subscriptionId', subscription.value);
};
render() {

View File

@ -6,8 +6,8 @@ exports[`Render should render component 1`] = `
makeSameAs={[Function]}
onLoadSubscriptions={[Function]}
onResetOptionKey={[Function]}
onUpdateOption={[Function]}
onUpdateSecureOption={[Function]}
onUpdateJsonDataOption={[Function]}
onUpdateSecureJsonDataOption={[Function]}
options={
Object {
"access": "proxy",
@ -43,9 +43,47 @@ exports[`Render should render component 1`] = `
onLoadSubscriptions={[Function]}
onLoadWorkspaces={[Function]}
onResetOptionKey={[Function]}
onUpdateOption={[Function]}
onUpdateOptions={[Function]}
onUpdateSecureOption={[Function]}
onUpdateDatasourceOptions={
[MockFunction] {
"calls": Array [
Array [
Object {
"access": "proxy",
"basicAuth": false,
"basicAuthPassword": "",
"basicAuthUser": "",
"database": "",
"id": 21,
"isDefault": false,
"jsonData": Object {
"azureLogAnalyticsSameAs": true,
"cloudName": "azuremonitor",
"subscriptionId": "44987801-6nn6-49he-9b2d-9106972f9789",
},
"name": "Azure Monitor-10-10",
"orgId": 1,
"password": "",
"readOnly": false,
"secureJsonFields": Object {},
"type": "grafana-azure-monitor-datasource",
"typeLogoUrl": "",
"url": "/api/datasources/proxy/21",
"user": "",
"version": 1,
"withCredentials": false,
},
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
}
onUpdateJsonDataOption={[Function]}
onUpdateSecureJsonDataOption={[Function]}
options={
Object {
"access": "proxy",
@ -79,8 +117,8 @@ exports[`Render should render component 1`] = `
/>
<InsightsConfig
onResetOptionKey={[Function]}
onUpdateOption={[Function]}
onUpdateSecureOption={[Function]}
onUpdateJsonDataOption={[Function]}
onUpdateSecureJsonDataOption={[Function]}
options={
Object {
"access": "proxy",

View File

@ -21,15 +21,25 @@ exports[`Render should disable insights api key input 1`] = `
>
API Key
</Component>
<Input
className="width-25"
disabled={true}
placeholder="configured"
/>
</div>
<div
className="gf-form"
>
<div
className="width-15"
className="max-width-30 gf-form-inline"
>
<Input
className="width-30"
onChange={[Function]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
/>
<Button
onClick={[Function]}
type="button"
variant="secondary"
>
reset
</Button>
</div>
</div>
</div>
@ -49,8 +59,7 @@ exports[`Render should disable insights api key input 1`] = `
>
<Input
className="width-30"
onChange={[Function]}
value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
value="cddcc020-2c94-460a-a3d0-df3147ffa792"
/>
</div>
</div>
@ -85,9 +94,8 @@ exports[`Render should enable insights api key input 1`] = `
>
<Input
className="width-30"
onChange={[Function]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48"
/>
</div>
</div>
@ -108,8 +116,7 @@ exports[`Render should enable insights api key input 1`] = `
>
<Input
className="width-30"
onChange={[Function]}
value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
value="cddcc020-2c94-460a-a3d0-df3147ffa792"
/>
</div>
</div>
@ -144,9 +151,8 @@ exports[`Render should render component 1`] = `
>
<Input
className="width-30"
onChange={[Function]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
value=""
/>
</div>
</div>
@ -167,8 +173,7 @@ exports[`Render should render component 1`] = `
>
<Input
className="width-30"
onChange={[Function]}
value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
value=""
/>
</div>
</div>