Azure Monitor: Standardize Config Editor Implementation (#20455)

* initial changes - removal from state, remove anon functions, reset secrets empty

* post testing cleanup

* init promise cancellation, other cleanup

* workspaces response parser, remove version incrementing

* update datasource funcs - DRYer

* remove prop mutation

* func to modify root config opt

* fix version issue

* update snapshot
This commit is contained in:
Shavonn Brown 2019-12-04 14:35:53 -05:00 committed by GitHub
parent 5f72bfe6e7
commit 2098b9eb44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 391 additions and 514 deletions

View File

@ -272,6 +272,64 @@ export abstract class DataSourceApi<
interpolateVariablesInQueries?(queries: TQuery[]): TQuery[]; interpolateVariablesInQueries?(queries: TQuery[]): TQuery[];
} }
export function updateDatasourcePluginOption(props: DataSourcePluginOptionsEditorProps, key: string, val: any) {
let config = props.options;
config = {
...config,
[key]: val,
};
props.onOptionsChange(config);
}
export function updateDatasourcePluginJsonDataOption(
props: DataSourcePluginOptionsEditorProps,
key: string,
val: any,
secure: boolean
) {
let config = props.options;
if (secure) {
config = {
...config,
secureJsonData: {
...config.secureJsonData,
[key]: val,
},
};
} else {
config = {
...config,
jsonData: {
...config.jsonData,
[key]: val,
},
};
}
props.onOptionsChange(config);
}
export function updateDatasourcePluginResetKeyOption(props: DataSourcePluginOptionsEditorProps, key: string) {
let config = props.options;
config = {
...config,
secureJsonData: {
...config.secureJsonData,
[key]: '',
},
secureJsonFields: {
...config.secureJsonFields,
[key]: false,
},
};
props.onOptionsChange(config);
}
export interface QueryEditorProps< export interface QueryEditorProps<
DSType extends DataSourceApi<TQuery, TOptions>, DSType extends DataSourceApi<TQuery, TOptions>,
TQuery extends DataQuery = DataQuery, TQuery extends DataQuery = DataQuery,

View File

@ -149,4 +149,25 @@ export default class ResponseParser {
return list; return list;
} }
static parseWorkspacesForSelect(result: any): Array<{ label: string; value: string }> {
const list: Array<{ label: string; value: string }> = [];
if (!result) {
return list;
}
const valueFieldName = 'customerId';
const textFieldName = 'name';
for (let i = 0; i < result.data.value.length; i++) {
if (!_.find(list, ['value', _.get(result.data.value[i].properties, valueFieldName)])) {
list.push({
label: _.get(result.data.value[i], textFieldName),
value: _.get(result.data.value[i].properties, valueFieldName),
});
}
}
return list;
}
} }

View File

@ -4,7 +4,7 @@ import AnalyticsConfig, { Props } from './AnalyticsConfig';
const setup = (propOverrides?: object) => { const setup = (propOverrides?: object) => {
const props: Props = { const props: Props = {
datasourceConfig: { options: {
id: 21, id: 21,
orgId: 1, orgId: 1,
name: 'Azure Monitor-10-10', name: 'Azure Monitor-10-10',
@ -24,9 +24,10 @@ const setup = (propOverrides?: object) => {
logAnalyticsClientSecret: false, logAnalyticsClientSecret: false,
}, },
jsonData: { jsonData: {
cloudName: '',
subscriptionId: '',
azureLogAnalyticsSameAs: false, azureLogAnalyticsSameAs: false,
logAnalyticsDefaultWorkspace: '', logAnalyticsDefaultWorkspace: '',
logAnalyticsClientSecret: '',
logAnalyticsTenantId: '', logAnalyticsTenantId: '',
}, },
secureJsonData: { secureJsonData: {
@ -35,9 +36,10 @@ const setup = (propOverrides?: object) => {
version: 1, version: 1,
readOnly: false, readOnly: false,
}, },
logAnalyticsSubscriptions: [], subscriptions: [],
logAnalyticsWorkspaces: [], workspaces: [],
onDatasourceUpdate: jest.fn(), onUpdateOption: jest.fn(),
onResetOptionKey: jest.fn(),
onLoadSubscriptions: jest.fn(), onLoadSubscriptions: jest.fn(),
onLoadWorkspaces: jest.fn(), onLoadWorkspaces: jest.fn(),
}; };

View File

@ -1,117 +1,52 @@
import React, { PureComponent } from 'react'; import React, { PureComponent, ChangeEvent } from 'react';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { AzureCredentialsForm } from './AzureCredentialsForm'; import { AzureCredentialsForm } from './AzureCredentialsForm';
import { Switch, FormLabel, Select, Button } from '@grafana/ui'; import { Switch, FormLabel, Select, Button } from '@grafana/ui';
import { AzureDataSourceSettings } from '../types';
export interface Props { export interface Props {
datasourceConfig: any; options: AzureDataSourceSettings;
logAnalyticsSubscriptions: SelectableValue[]; subscriptions: SelectableValue[];
logAnalyticsWorkspaces: SelectableValue[]; workspaces: SelectableValue[];
onDatasourceUpdate: (config: any) => void; onUpdateOption: (key: string, val: any, secure: boolean) => void;
onResetOptionKey: (key: string) => void;
onLoadSubscriptions: (type?: string) => void; onLoadSubscriptions: (type?: string) => void;
onLoadWorkspaces: (type?: string) => void; onLoadWorkspaces: (type?: string) => void;
} }
export class AnalyticsConfig extends PureComponent<Props> {
export interface State { onLogAnalyticsTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
config: any; this.props.onUpdateOption('logAnalyticsTenantId', event.target.value, false);
logAnalyticsSubscriptions: SelectableValue[];
logAnalyticsWorkspaces: SelectableValue[];
}
export class AnalyticsConfig extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const { datasourceConfig } = this.props;
this.state = {
config: datasourceConfig,
logAnalyticsSubscriptions: [],
logAnalyticsWorkspaces: [],
};
}
static getDerivedStateFromProps(props: Props, state: State) {
return {
...state,
config: props.datasourceConfig,
logAnalyticsSubscriptions: props.logAnalyticsSubscriptions,
logAnalyticsWorkspaces: props.logAnalyticsWorkspaces,
};
}
onLogAnalyticsTenantIdChange = (logAnalyticsTenantId: string) => {
this.props.onDatasourceUpdate({
...this.state.config,
jsonData: {
...this.state.config.jsonData,
logAnalyticsTenantId,
},
});
}; };
onLogAnalyticsClientIdChange = (logAnalyticsClientId: string) => { onLogAnalyticsClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('logAnalyticsClientId', event.target.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
logAnalyticsClientId,
},
});
}; };
onLogAnalyticsClientSecretChange = (logAnalyticsClientSecret: string) => { onLogAnalyticsClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('logAnalyticsClientSecret', event.target.value, true);
...this.state.config,
secureJsonData: {
...this.state.config.secureJsonData,
logAnalyticsClientSecret,
},
});
};
onLogAnalyticsResetClientSecret = () => {
this.props.onDatasourceUpdate({
...this.state.config,
version: this.state.config.version + 1,
secureJsonFields: { ...this.state.config.secureJsonFields, logAnalyticsClientSecret: false },
});
}; };
onLogAnalyticsSubscriptionSelect = (logAnalyticsSubscription: SelectableValue<string>) => { onLogAnalyticsSubscriptionSelect = (logAnalyticsSubscription: SelectableValue<string>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('logAnalyticsSubscriptionId', logAnalyticsSubscription.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
logAnalyticsSubscriptionId: logAnalyticsSubscription.value,
},
});
}; };
onWorkspaceSelectChange = (logAnalyticsDefaultWorkspace: SelectableValue<string>) => { onWorkspaceSelectChange = (logAnalyticsDefaultWorkspace: SelectableValue<string>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('logAnalyticsDefaultWorkspace', logAnalyticsDefaultWorkspace.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
logAnalyticsDefaultWorkspace: logAnalyticsDefaultWorkspace.value,
},
});
}; };
onAzureLogAnalyticsSameAsChange = (azureLogAnalyticsSameAs: boolean) => { onAzureLogAnalyticsSameAsChange = () => {
this.props.onDatasourceUpdate({ const { options } = this.props;
...this.state.config, this.props.onUpdateOption('azureLogAnalyticsSameAs', !options.jsonData.azureLogAnalyticsSameAs, false);
jsonData: { };
...this.state.config.jsonData,
azureLogAnalyticsSameAs, onLogAnalyticsResetClientSecret = () => {
}, this.props.onResetOptionKey('logAnalyticsClientSecret');
});
}; };
hasWorkspaceRequiredFields = () => { hasWorkspaceRequiredFields = () => {
const { const {
config: { jsonData, secureJsonData, secureJsonFields }, options: { jsonData, secureJsonData, secureJsonFields },
} = this.state; } = this.props;
if (jsonData.azureLogAnalyticsSameAs) { if (jsonData.azureLogAnalyticsSameAs) {
return ( return (
@ -134,10 +69,14 @@ export class AnalyticsConfig extends PureComponent<Props, State> {
render() { render() {
const { const {
config: { jsonData, secureJsonData, secureJsonFields }, options: { jsonData, secureJsonData, secureJsonFields },
logAnalyticsSubscriptions, subscriptions,
logAnalyticsWorkspaces, workspaces,
} = this.state; } = this.props;
if (!jsonData.hasOwnProperty('azureLogAnalyticsSameAs')) {
jsonData.azureLogAnalyticsSameAs = true;
}
const addtlAttrs = { const addtlAttrs = {
...(jsonData.azureLogAnalyticsSameAs && { ...(jsonData.azureLogAnalyticsSameAs && {
@ -150,12 +89,12 @@ export class AnalyticsConfig extends PureComponent<Props, State> {
<Switch <Switch
label="Same details as Azure Monitor API" label="Same details as Azure Monitor API"
checked={jsonData.azureLogAnalyticsSameAs} checked={jsonData.azureLogAnalyticsSameAs}
onChange={event => this.onAzureLogAnalyticsSameAsChange(!jsonData.azureLogAnalyticsSameAs)} onChange={this.onAzureLogAnalyticsSameAsChange}
{...addtlAttrs} {...addtlAttrs}
/> />
{!jsonData.azureLogAnalyticsSameAs && ( {!jsonData.azureLogAnalyticsSameAs && (
<AzureCredentialsForm <AzureCredentialsForm
subscriptionOptions={logAnalyticsSubscriptions} subscriptionOptions={subscriptions}
selectedSubscription={jsonData.logAnalyticsSubscriptionId} selectedSubscription={jsonData.logAnalyticsSubscriptionId}
tenantId={jsonData.logAnalyticsTenantId} tenantId={jsonData.logAnalyticsTenantId}
clientId={jsonData.logAnalyticsClientId} clientId={jsonData.logAnalyticsClientId}
@ -180,10 +119,8 @@ export class AnalyticsConfig extends PureComponent<Props, State> {
</FormLabel> </FormLabel>
<div className="width-25"> <div className="width-25">
<Select <Select
value={logAnalyticsWorkspaces.find( value={workspaces.find(workspace => workspace.value === jsonData.logAnalyticsDefaultWorkspace)}
workspace => workspace.value === jsonData.logAnalyticsDefaultWorkspace options={workspaces}
)}
options={logAnalyticsWorkspaces}
defaultValue={jsonData.logAnalyticsDefaultWorkspace} defaultValue={jsonData.logAnalyticsDefaultWorkspace}
onChange={this.onWorkspaceSelectChange} onChange={this.onWorkspaceSelectChange}
/> />

View File

@ -5,15 +5,15 @@ import AzureCredentialsForm, { Props } from './AzureCredentialsForm';
const setup = (propOverrides?: object) => { const setup = (propOverrides?: object) => {
const props: Props = { const props: Props = {
selectedAzureCloud: 'azuremonitor', selectedAzureCloud: 'azuremonitor',
selectedSubscription: '44693801-6ee6-49de-9b2d-9106972f9572', selectedSubscription: '44987801-6nn6-49he-9b2d-9106972f9789',
azureCloudOptions: [ azureCloudOptions: [
{ value: 'azuremonitor', label: 'Azure' }, { value: 'azuremonitor', label: 'Azure' },
{ value: 'govazuremonitor', label: 'Azure US Government' }, { value: 'govazuremonitor', label: 'Azure US Government' },
{ value: 'germanyazuremonitor', label: 'Azure Germany' }, { value: 'germanyazuremonitor', label: 'Azure Germany' },
{ value: 'chinaazuremonitor', label: 'Azure China' }, { value: 'chinaazuremonitor', label: 'Azure China' },
], ],
tenantId: 'e7f3f661-a933-4b3f-8176-51c4f982ec48', tenantId: 'e7f3f661-a933-3h3f-0294-31c4f962ec48',
clientId: '77409fad-c0a9-45df-9e25-f1ff95af6554', clientId: '34509fad-c0r9-45df-9e25-f1ee34af6900',
clientSecret: '', clientSecret: '',
clientSecretConfigured: false, clientSecretConfigured: false,
subscriptionOptions: [], subscriptionOptions: [],

View File

@ -13,58 +13,22 @@ export interface Props {
subscriptionOptions?: SelectableValue[]; subscriptionOptions?: SelectableValue[];
onAzureCloudChange?: (value: SelectableValue<string>) => void; onAzureCloudChange?: (value: SelectableValue<string>) => void;
onSubscriptionSelectChange?: (value: SelectableValue<string>) => void; onSubscriptionSelectChange?: (value: SelectableValue<string>) => void;
onTenantIdChange: (tenantId: string) => void; onTenantIdChange: (event: ChangeEvent<HTMLInputElement>) => void;
onClientIdChange: (clientId: string) => void; onClientIdChange: (event: ChangeEvent<HTMLInputElement>) => void;
onClientSecretChange: (clientSecret: string) => void; onClientSecretChange: (event: ChangeEvent<HTMLInputElement>) => void;
onResetClientSecret: () => void; onResetClientSecret: () => void;
onLoadSubscriptions?: () => void; onLoadSubscriptions?: () => void;
} }
export interface State { export class AzureCredentialsForm extends PureComponent<Props> {
selectedAzureCloud?: string;
selectedSubscription: string;
tenantId: string;
clientId: string;
clientSecret: string;
clientSecretConfigured: boolean;
}
export class AzureCredentialsForm extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const {
selectedAzureCloud,
selectedSubscription,
tenantId,
clientId,
clientSecret,
clientSecretConfigured,
} = this.props;
this.state = {
selectedAzureCloud,
selectedSubscription,
tenantId,
clientId,
clientSecret,
clientSecretConfigured,
};
}
static getDerivedStateFromProps(nextProps: Props, prevState: Props) {
const { selectedAzureCloud, tenantId, clientId, clientSecret, clientSecretConfigured } = nextProps;
return {
selectedAzureCloud,
tenantId,
clientId,
clientSecret,
clientSecretConfigured,
};
}
render() { render() {
const { const {
selectedAzureCloud,
selectedSubscription,
tenantId,
clientId,
clientSecret,
clientSecretConfigured,
azureCloudOptions, azureCloudOptions,
subscriptionOptions, subscriptionOptions,
onAzureCloudChange, onAzureCloudChange,
@ -75,16 +39,9 @@ export class AzureCredentialsForm extends PureComponent<Props, State> {
onResetClientSecret, onResetClientSecret,
onLoadSubscriptions, onLoadSubscriptions,
} = this.props; } = this.props;
const {
selectedAzureCloud,
selectedSubscription,
tenantId,
clientId,
clientSecret,
clientSecretConfigured,
} = this.state;
const hasRequiredFields = tenantId && clientId && (clientSecret || clientSecretConfigured); const hasRequiredFields = tenantId && clientId && (clientSecret || clientSecretConfigured);
const hasSubscriptions = onLoadSubscriptions && subscriptionOptions; const hasSubscriptions = onLoadSubscriptions && subscriptionOptions;
return ( return (
<> <>
<div className="gf-form-group"> <div className="gf-form-group">
@ -112,7 +69,7 @@ export class AzureCredentialsForm extends PureComponent<Props, State> {
className="width-30" className="width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={tenantId || ''} value={tenantId || ''}
onChange={(event: ChangeEvent<HTMLInputElement>) => onTenantIdChange(event.target.value)} onChange={onTenantIdChange}
/> />
</div> </div>
</div> </div>
@ -125,7 +82,7 @@ export class AzureCredentialsForm extends PureComponent<Props, State> {
className="width-30" className="width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={clientId || ''} value={clientId || ''}
onChange={(event: ChangeEvent<HTMLInputElement>) => onClientIdChange(event.target.value)} onChange={onClientIdChange}
/> />
</div> </div>
</div> </div>
@ -153,7 +110,7 @@ export class AzureCredentialsForm extends PureComponent<Props, State> {
className="width-30" className="width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={clientSecret || ''} value={clientSecret || ''}
onChange={(event: ChangeEvent<HTMLInputElement>) => onClientSecretChange(event.target.value)} onChange={onClientSecretChange}
/> />
</div> </div>
</div> </div>

View File

@ -21,7 +21,7 @@ const setup = () => {
withCredentials: false, withCredentials: false,
isDefault: false, isDefault: false,
jsonData: { jsonData: {
subscriptionId: '', subscriptionId: '44987801-6nn6-49he-9b2d-9106972f9789',
azureLogAnalyticsSameAs: true, azureLogAnalyticsSameAs: true,
cloudName: 'azuremonitor', cloudName: 'azuremonitor',
}, },

View File

@ -1,112 +1,114 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { SelectableValue, DataSourcePluginOptionsEditorProps, DataSourceSettings } from '@grafana/data'; import {
SelectableValue,
DataSourcePluginOptionsEditorProps,
updateDatasourcePluginOption,
updateDatasourcePluginResetKeyOption,
updateDatasourcePluginJsonDataOption,
} from '@grafana/data';
import { MonitorConfig } from './MonitorConfig'; import { MonitorConfig } from './MonitorConfig';
import { AnalyticsConfig } from './AnalyticsConfig'; import { AnalyticsConfig } from './AnalyticsConfig';
import { TemplateSrv } from 'app/features/templating/template_srv'; import { TemplateSrv } from 'app/features/templating/template_srv';
import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv'; import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
import { InsightsConfig } from './InsightsConfig'; import { InsightsConfig } from './InsightsConfig';
import ResponseParser from '../azure_monitor/response_parser'; import ResponseParser from '../azure_monitor/response_parser';
import { AzureDataSourceJsonData, AzureDataSourceSecureJsonData } from '../types'; import { AzureDataSourceJsonData, AzureDataSourceSecureJsonData, AzureDataSourceSettings } from '../types';
import { makePromiseCancelable, CancelablePromise } from 'app/core/utils/CancelablePromise';
export type Props = DataSourcePluginOptionsEditorProps<AzureDataSourceJsonData>; export type Props = DataSourcePluginOptionsEditorProps<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>;
type AzureDataSourceSettings = DataSourceSettings<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>;
export interface State { export interface State {
config: AzureDataSourceSettings;
subscriptions: SelectableValue[]; subscriptions: SelectableValue[];
logAnalyticsSubscriptions: SelectableValue[]; logAnalyticsSubscriptions: SelectableValue[];
logAnalyticsWorkspaces: SelectableValue[]; logAnalyticsWorkspaces: SelectableValue[];
subscriptionId: string;
logAnalyticsSubscriptionId: string;
} }
export class ConfigEditor extends PureComponent<Props, State> { export class ConfigEditor extends PureComponent<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
const { options } = this.props;
this.state = { this.state = {
config: ConfigEditor.defaults(options),
subscriptions: [], subscriptions: [],
logAnalyticsSubscriptions: [], logAnalyticsSubscriptions: [],
logAnalyticsWorkspaces: [], logAnalyticsWorkspaces: [],
subscriptionId: '',
logAnalyticsSubscriptionId: '',
}; };
this.backendSrv = getBackendSrv(); this.backendSrv = getBackendSrv();
this.templateSrv = new TemplateSrv(); this.templateSrv = new TemplateSrv();
if (this.props.options.id) {
if (options.id) { updateDatasourcePluginOption(this.props, 'url', '/api/datasources/proxy/' + this.props.options.id);
this.state.config.url = '/api/datasources/proxy/' + options.id;
this.init();
} }
this.updateDatasource(this.state.config);
} }
static getDerivedStateFromProps(props: Props, state: State) { initPromise: CancelablePromise<any> = null;
return {
...state,
config: ConfigEditor.defaults(props.options),
};
}
static defaults = (options: any) => {
options.jsonData.cloudName = options.jsonData.cloudName || 'azuremonitor';
if (!options.jsonData.hasOwnProperty('azureLogAnalyticsSameAs')) {
options.jsonData.azureLogAnalyticsSameAs = true;
}
if (!options.hasOwnProperty('secureJsonData')) {
options.secureJsonData = {};
}
if (!options.hasOwnProperty('secureJsonFields')) {
options.secureJsonFields = {
clientSecret: false,
logAnalyticsClientSecret: false,
appInsightsApiKey: false,
};
}
return options;
};
backendSrv: BackendSrv = null; backendSrv: BackendSrv = null;
templateSrv: TemplateSrv = null; templateSrv: TemplateSrv = null;
componentDidMount() {
this.initPromise = makePromiseCancelable(this.init());
this.initPromise.promise.catch(({ isCanceled }) => {
if (isCanceled) {
console.warn('Azure Monitor ConfigEditor has unmounted, intialization was canceled');
}
});
}
componentWillUnmount() {
this.initPromise.cancel();
}
init = async () => { init = async () => {
await this.getSubscriptions(); await this.getSubscriptions();
if (!this.state.config.jsonData.azureLogAnalyticsSameAs) { if (!this.props.options.jsonData.azureLogAnalyticsSameAs) {
await this.getLogAnalyticsSubscriptions(); await this.getLogAnalyticsSubscriptions();
} }
}; };
updateDatasource = async (config: any) => { updateOption = (key: string, val: any, secure: boolean) => {
for (const j in config.jsonData) { updateDatasourcePluginJsonDataOption(this.props, key, val, secure);
if (config.jsonData[j].length === 0) { };
delete config.jsonData[j];
}
}
for (const k in config.secureJsonData) { resetKey = (key: string) => {
if (config.secureJsonData[k].length === 0) { updateDatasourcePluginResetKeyOption(this.props, key);
delete config.secureJsonData[k]; };
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({ this.props.onOptionsChange({
...config, ...options,
}); });
}; };
hasNecessaryCredentials = () => { hasNecessaryCredentials = () => {
if (!this.state.config.secureJsonFields.clientSecret && !this.state.config.secureJsonData.clientSecret) { if (!this.props.options.secureJsonFields.clientSecret && !this.props.options.secureJsonData.clientSecret) {
return false; return false;
} }
if (!this.state.config.jsonData.clientId || !this.state.config.jsonData.tenantId) { if (!this.props.options.jsonData.clientId || !this.props.options.jsonData.tenantId) {
return false; return false;
} }
@ -115,30 +117,28 @@ export class ConfigEditor extends PureComponent<Props, State> {
logAnalyticsHasNecessaryCredentials = () => { logAnalyticsHasNecessaryCredentials = () => {
if ( if (
!this.state.config.secureJsonFields.logAnalyticsClientSecret && !this.props.options.secureJsonFields.logAnalyticsClientSecret &&
!this.state.config.secureJsonData.logAnalyticsClientSecret !this.props.options.secureJsonData.logAnalyticsClientSecret
) { ) {
return false; return false;
} }
if (!this.state.config.jsonData.logAnalyticsClientId || !this.state.config.jsonData.logAnalyticsTenantId) { if (!this.props.options.jsonData.logAnalyticsClientId || !this.props.options.jsonData.logAnalyticsTenantId) {
return false; return false;
} }
return true; return true;
}; };
onConfigUpdate = (config: any) => {
this.updateDatasource(config);
};
onLoadSubscriptions = async (type?: string) => { onLoadSubscriptions = async (type?: string) => {
await this.backendSrv.put(`/api/datasources/${this.state.config.id}`, this.state.config).then(() => { await this.backendSrv
this.updateDatasource({ .put(`/api/datasources/${this.props.options.id}`, this.props.options)
...this.state.config, .then((result: AzureDataSourceSettings) => {
version: this.state.config.version + 1, this.updateOptions({
...this.props.options,
version: result.version,
});
}); });
});
if (type && type === 'workspacesloganalytics') { if (type && type === 'workspacesloganalytics') {
this.getLogAnalyticsSubscriptions(); this.getLogAnalyticsSubscriptions();
@ -148,25 +148,20 @@ export class ConfigEditor extends PureComponent<Props, State> {
}; };
loadSubscriptions = async (route?: string) => { loadSubscriptions = async (route?: string) => {
const url = `/${route || this.state.config.jsonData.cloudName}/subscriptions?api-version=2019-03-01`; const url = `/${route || this.props.options.jsonData.cloudName}/subscriptions?api-version=2019-03-01`;
return this.backendSrv const result = await this.backendSrv.datasourceRequest({
.datasourceRequest({ url: this.props.options.url + url,
url: this.state.config.url + url, method: 'GET',
method: 'GET', });
})
.then((result: any) => { return ResponseParser.parseSubscriptionsForSelect(result);
return ResponseParser.parseSubscriptionsForSelect(result);
})
.catch((error: any) => {
throw error;
});
}; };
loadWorkspaces = async (subscription: string) => { loadWorkspaces = async (subscription: string) => {
const { azureLogAnalyticsSameAs, cloudName, logAnalyticsSubscriptionId } = this.state.config.jsonData; const { azureLogAnalyticsSameAs, cloudName, logAnalyticsSubscriptionId } = this.props.options.jsonData;
let azureMonitorUrl = '', let azureMonitorUrl = '',
subscriptionId = this.templateSrv.replace(subscription || this.state.config.jsonData.subscriptionId); subscriptionId = this.templateSrv.replace(subscription || this.props.options.jsonData.subscriptionId);
if (!!subscriptionId || !!azureLogAnalyticsSameAs) { if (!!subscriptionId || !!azureLogAnalyticsSameAs) {
const azureCloud = cloudName || 'azuremonitor'; const azureCloud = cloudName || 'azuremonitor';
@ -180,22 +175,12 @@ export class ConfigEditor extends PureComponent<Props, State> {
azureMonitorUrl + azureMonitorUrl +
`/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`; `/${subscriptionId}/providers/Microsoft.OperationalInsights/workspaces?api-version=2017-04-26-preview`;
return this.backendSrv const result = await this.backendSrv.datasourceRequest({
.datasourceRequest({ url: this.props.options.url + workspaceListUrl,
url: this.state.config.url + workspaceListUrl, method: 'GET',
method: 'GET', });
})
.then((result: any) => { return ResponseParser.parseWorkspacesForSelect(result);
return result.data.value.map((val: any) => {
return {
value: val.properties.customerId,
label: val.name,
};
});
})
.catch((error: any) => {
throw error;
});
}; };
getSubscriptions = async () => { getSubscriptions = async () => {
@ -203,15 +188,15 @@ export class ConfigEditor extends PureComponent<Props, State> {
return; return;
} }
const subscriptions = (await this.loadSubscriptions()) || []; const subscriptions = ((await this.loadSubscriptions()) || []) as SelectableValue[];
if (subscriptions && subscriptions.length > 0) { if (subscriptions && subscriptions.length > 0) {
this.setState({ subscriptions }); this.setState({ subscriptions });
this.state.config.jsonData.subscriptionId = this.state.config.jsonData.subscriptionId || subscriptions[0].value; this.updateOption('subscriptionId', this.props.options.jsonData.subscriptionId || subscriptions[0].value, false);
} }
if (this.state.config.jsonData.subscriptionId && this.state.config.jsonData.azureLogAnalyticsSameAs) { if (this.props.options.jsonData.subscriptionId && this.props.options.jsonData.azureLogAnalyticsSameAs) {
await this.getWorkspaces(); await this.getWorkspaces();
} }
}; };
@ -221,60 +206,73 @@ export class ConfigEditor extends PureComponent<Props, State> {
return; return;
} }
const logAnalyticsSubscriptions = (await this.loadSubscriptions('workspacesloganalytics')) || []; const logAnalyticsSubscriptions = ((await this.loadSubscriptions('workspacesloganalytics')) ||
[]) as SelectableValue[];
if (logAnalyticsSubscriptions && logAnalyticsSubscriptions.length > 0) { if (logAnalyticsSubscriptions && logAnalyticsSubscriptions.length > 0) {
this.setState({ logAnalyticsSubscriptions }); this.setState({ logAnalyticsSubscriptions });
this.state.config.jsonData.logAnalyticsSubscriptionId = this.updateOption(
this.state.config.jsonData.logAnalyticsSubscriptionId || logAnalyticsSubscriptions[0].value; 'logAnalyticsSubscriptionId',
this.props.options.jsonData.logAnalyticsSubscriptionId || logAnalyticsSubscriptions[0].value,
false
);
} }
if (this.state.config.jsonData.logAnalyticsSubscriptionId) { if (this.props.options.jsonData.logAnalyticsSubscriptionId) {
await this.getWorkspaces(); await this.getWorkspaces();
} }
}; };
getWorkspaces = async () => { getWorkspaces = async () => {
const sameAs = this.state.config.jsonData.azureLogAnalyticsSameAs && this.state.config.jsonData.subscriptionId; const sameAs = this.props.options.jsonData.azureLogAnalyticsSameAs && this.props.options.jsonData.subscriptionId;
if (!sameAs && !this.state.config.jsonData.logAnalyticsSubscriptionId) { if (!sameAs && !this.props.options.jsonData.logAnalyticsSubscriptionId) {
return; return;
} }
const logAnalyticsWorkspaces = await this.loadWorkspaces( const logAnalyticsWorkspaces = await this.loadWorkspaces(
sameAs ? this.state.config.jsonData.subscriptionId : this.state.config.jsonData.logAnalyticsSubscriptionId sameAs ? this.props.options.jsonData.subscriptionId : this.props.options.jsonData.logAnalyticsSubscriptionId
); );
if (logAnalyticsWorkspaces.length > 0) { if (logAnalyticsWorkspaces.length > 0) {
this.setState({ logAnalyticsWorkspaces }); this.setState({ logAnalyticsWorkspaces });
this.state.config.jsonData.logAnalyticsDefaultWorkspace = this.updateOption(
this.state.config.jsonData.logAnalyticsDefaultWorkspace || logAnalyticsWorkspaces[0].value; 'logAnalyticsDefaultWorkspace',
this.props.options.jsonData.logAnalyticsDefaultWorkspace || logAnalyticsWorkspaces[0].value,
false
);
} }
}; };
render() { render() {
const { config, subscriptions, logAnalyticsSubscriptions, logAnalyticsWorkspaces } = this.state; const { subscriptions, logAnalyticsSubscriptions, logAnalyticsWorkspaces } = this.state;
const { options } = this.props;
options.jsonData.cloudName = options.jsonData.cloudName || 'azuremonitor';
options.secureJsonData = (options.secureJsonData || {}) as AzureDataSourceSecureJsonData;
return ( return (
<> <>
<MonitorConfig <MonitorConfig
datasourceConfig={config} options={options}
subscriptions={subscriptions} subscriptions={subscriptions}
onLoadSubscriptions={this.onLoadSubscriptions} onLoadSubscriptions={this.onLoadSubscriptions}
onDatasourceUpdate={this.onConfigUpdate} onUpdateOption={this.updateOption}
onResetOptionKey={this.resetKey}
/> />
<AnalyticsConfig <AnalyticsConfig
datasourceConfig={config} options={options}
logAnalyticsWorkspaces={logAnalyticsWorkspaces} workspaces={logAnalyticsWorkspaces}
logAnalyticsSubscriptions={logAnalyticsSubscriptions} subscriptions={logAnalyticsSubscriptions}
onUpdateOption={this.updateOption}
onResetOptionKey={this.resetKey}
onLoadSubscriptions={this.onLoadSubscriptions} onLoadSubscriptions={this.onLoadSubscriptions}
onDatasourceUpdate={this.onConfigUpdate}
onLoadWorkspaces={this.getWorkspaces} onLoadWorkspaces={this.getWorkspaces}
/> />
<InsightsConfig datasourceConfig={config} onDatasourceUpdate={this.onConfigUpdate} /> <InsightsConfig options={options} onUpdateOption={this.updateOption} onResetOptionKey={this.resetKey} />
</> </>
); );
} }

View File

@ -4,7 +4,7 @@ import InsightsConfig, { Props } from './InsightsConfig';
const setup = (propOverrides?: object) => { const setup = (propOverrides?: object) => {
const props: Props = { const props: Props = {
datasourceConfig: { options: {
id: 21, id: 21,
orgId: 1, orgId: 1,
name: 'Azure Monitor-10-10', name: 'Azure Monitor-10-10',
@ -24,15 +24,18 @@ const setup = (propOverrides?: object) => {
appInsightsApiKey: false, appInsightsApiKey: false,
}, },
jsonData: { jsonData: {
appInsightsAppId: 'cddcc020-2c94-460a-a3d0-df3147ffa792', cloudName: '',
subscriptionId: '',
appInsightsAppId: 'cvvcc020-2cpo-123a-a3d0-df6547fki792',
}, },
secureJsonData: { secureJsonData: {
appInsightsApiKey: 'e7f3f661-a933-4b3f-8176-51c4f982ec48', appInsightsApiKey: 'e7f3f775-a987-4b3f-3835-51c4f982kl48',
}, },
version: 1, version: 1,
readOnly: false, readOnly: false,
}, },
onDatasourceUpdate: jest.fn(), onUpdateOption: jest.fn(),
onResetOptionKey: jest.fn(),
}; };
Object.assign(props, propOverrides); Object.assign(props, propOverrides);

View File

@ -1,71 +1,32 @@
import React, { PureComponent } from 'react'; import React, { PureComponent, ChangeEvent } from 'react';
import { FormLabel, Button, Input } from '@grafana/ui'; import { FormLabel, Button, Input } from '@grafana/ui';
import { AzureDataSourceSettings } from '../types';
export interface Props { export interface Props {
datasourceConfig: any; options: AzureDataSourceSettings;
onDatasourceUpdate: (config: any) => void; onUpdateOption: (key: string, val: any, secure: boolean) => void;
onResetOptionKey: (key: string) => void;
} }
export class InsightsConfig extends PureComponent<Props> {
export interface State { onAppInsightsAppIdChange = (event: ChangeEvent<HTMLInputElement>) => {
config: any; this.props.onUpdateOption('appInsightsAppId', event.target.value, false);
}
export class InsightsConfig extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const { datasourceConfig } = this.props;
this.state = {
config: datasourceConfig,
};
}
static getDerivedStateFromProps(props: Props, state: State) {
return {
...state,
config: props.datasourceConfig,
};
}
onAppInsightsAppIdChange = (appInsightsAppId: string) => {
this.props.onDatasourceUpdate({
...this.state.config,
jsonData: {
...this.state.config.jsonData,
appInsightsAppId,
},
});
}; };
onAppInsightsApiKeyChange = (appInsightsApiKey: string) => { onAppInsightsApiKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('appInsightsApiKey', event.target.value, true);
...this.state.config,
secureJsonData: {
...this.state.config.secureJsonData,
appInsightsApiKey,
},
});
}; };
onAppInsightsResetApiKey = () => { onAppInsightsResetApiKey = () => {
this.props.onDatasourceUpdate({ this.props.onResetOptionKey('appInsightsApiKey');
...this.state.config,
version: this.state.config.version + 1,
secureJsonFields: {
...this.state.config.secureJsonFields,
appInsightsApiKey: false,
},
});
}; };
render() { render() {
const { config } = this.state; const { options } = this.props;
return ( return (
<> <>
<h3 className="page-heading">Application Insights Details</h3> <h3 className="page-heading">Application Insights Details</h3>
<div className="gf-form-group"> <div className="gf-form-group">
{config.secureJsonFields.appInsightsApiKey ? ( {options.secureJsonFields.appInsightsApiKey ? (
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">
<FormLabel className="width-12">API Key</FormLabel> <FormLabel className="width-12">API Key</FormLabel>
@ -87,8 +48,8 @@ export class InsightsConfig extends PureComponent<Props, State> {
<Input <Input
className="width-30" className="width-30"
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value={config.secureJsonData.appInsightsApiKey || ''} value={options.secureJsonData.appInsightsApiKey || ''}
onChange={event => this.onAppInsightsApiKeyChange(event.target.value)} onChange={this.onAppInsightsApiKeyChange}
/> />
</div> </div>
</div> </div>
@ -100,8 +61,8 @@ export class InsightsConfig extends PureComponent<Props, State> {
<div className="width-15"> <div className="width-15">
<Input <Input
className="width-30" className="width-30"
value={config.jsonData.appInsightsAppId || ''} value={options.jsonData.appInsightsAppId || ''}
onChange={event => this.onAppInsightsAppIdChange(event.target.value)} onChange={this.onAppInsightsAppIdChange}
/> />
</div> </div>
</div> </div>

View File

@ -1,121 +1,62 @@
import React, { PureComponent } from 'react'; import React, { PureComponent, ChangeEvent } from 'react';
import { SelectableValue } from '@grafana/data'; import { SelectableValue } from '@grafana/data';
import { AzureCredentialsForm } from './AzureCredentialsForm'; import { AzureCredentialsForm } from './AzureCredentialsForm';
import { AzureDataSourceSettings } from '../types';
const azureClouds = [
{ value: 'azuremonitor', label: 'Azure' },
{ value: 'govazuremonitor', label: 'Azure US Government' },
{ value: 'germanyazuremonitor', label: 'Azure Germany' },
{ value: 'chinaazuremonitor', label: 'Azure China' },
] as SelectableValue[];
export interface Props { export interface Props {
datasourceConfig: any; options: AzureDataSourceSettings;
subscriptions: SelectableValue[]; subscriptions: SelectableValue[];
onDatasourceUpdate: (config: any) => void; onUpdateOption: (key: string, val: any, secure: boolean) => void;
onResetOptionKey: (key: string) => void;
onLoadSubscriptions: () => void; onLoadSubscriptions: () => void;
} }
export interface State { export class MonitorConfig extends PureComponent<Props> {
config: any;
azureClouds: SelectableValue[];
subscriptions: SelectableValue[];
}
export class MonitorConfig extends PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const { datasourceConfig } = this.props;
this.state = {
config: datasourceConfig,
azureClouds: [
{ value: 'azuremonitor', label: 'Azure' },
{ value: 'govazuremonitor', label: 'Azure US Government' },
{ value: 'germanyazuremonitor', label: 'Azure Germany' },
{ value: 'chinaazuremonitor', label: 'Azure China' },
],
subscriptions: [],
};
}
static getDerivedStateFromProps(props: Props, state: State) {
return {
...state,
config: props.datasourceConfig,
subscriptions: props.subscriptions,
};
}
onAzureCloudSelect = (cloudName: SelectableValue<string>) => { onAzureCloudSelect = (cloudName: SelectableValue<string>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('cloudName', cloudName.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
cloudName: cloudName.value,
},
});
}; };
onTenantIdChange = (tenantId: string) => { onTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('tenantId', event.target.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
tenantId,
},
});
}; };
onClientIdChange = (clientId: string) => { onClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('clientId', event.target.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
clientId,
},
});
}; };
onClientSecretChange = (clientSecret: string) => { onClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('clientSecret', event.target.value, true);
...this.state.config,
secureJsonData: {
...this.state.config.secureJsonData,
clientSecret,
},
});
}; };
onResetClientSecret = () => { onResetClientSecret = () => {
this.props.onDatasourceUpdate({ this.props.onResetOptionKey('clientSecret');
...this.state.config,
version: this.state.config.version + 1,
secureJsonFields: {
...this.state.config.secureJsonFields,
clientSecret: false,
},
});
}; };
onSubscriptionSelect = (subscription: SelectableValue<string>) => { onSubscriptionSelect = (subscription: SelectableValue<string>) => {
this.props.onDatasourceUpdate({ this.props.onUpdateOption('subscriptionId', subscription.value, false);
...this.state.config,
jsonData: {
...this.state.config.jsonData,
subscriptionId: subscription.value,
},
});
}; };
render() { render() {
const { azureClouds, config, subscriptions } = this.state; const { options, subscriptions } = this.props;
return ( return (
<> <>
<h3 className="page-heading">Azure Monitor Details</h3> <h3 className="page-heading">Azure Monitor Details</h3>
<AzureCredentialsForm <AzureCredentialsForm
selectedAzureCloud={config.jsonData.cloudName} selectedAzureCloud={options.jsonData.cloudName || 'azuremonitor'}
azureCloudOptions={azureClouds} azureCloudOptions={azureClouds}
subscriptionOptions={subscriptions} subscriptionOptions={subscriptions}
selectedSubscription={config.jsonData.subscriptionId} selectedSubscription={options.jsonData.subscriptionId}
tenantId={config.jsonData.tenantId} tenantId={options.jsonData.tenantId}
clientId={config.jsonData.clientId} clientId={options.jsonData.clientId}
clientSecret={config.secureJsonData.clientSecret} clientSecret={options.secureJsonData.clientSecret}
clientSecretConfigured={config.secureJsonFields.clientSecret} clientSecretConfigured={options.secureJsonFields.clientSecret}
onAzureCloudChange={this.onAzureCloudSelect} onAzureCloudChange={this.onAzureCloudSelect}
onSubscriptionSelectChange={this.onSubscriptionSelect} onSubscriptionSelectChange={this.onSubscriptionSelect}
onTenantIdChange={this.onTenantIdChange} onTenantIdChange={this.onTenantIdChange}

View File

@ -86,9 +86,9 @@ exports[`Render should disable azure monitor secret input 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f661-a933-3h3f-0294-31c4f962ec48"
/> />
</div> </div>
</div> </div>
@ -109,9 +109,9 @@ exports[`Render should disable azure monitor secret input 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="77409fad-c0a9-45df-9e25-f1ff95af6554" value="34509fad-c0r9-45df-9e25-f1ee34af6900"
/> />
</div> </div>
</div> </div>
@ -177,7 +177,7 @@ exports[`Render should disable azure monitor secret input 1`] = `
"SingleValue": [Function], "SingleValue": [Function],
} }
} }
defaultValue="44693801-6ee6-49de-9b2d-9106972f9572" defaultValue="44987801-6nn6-49he-9b2d-9106972f9789"
isClearable={false} isClearable={false}
isDisabled={false} isDisabled={false}
isLoading={false} isLoading={false}
@ -303,9 +303,9 @@ exports[`Render should enable azure monitor load subscriptions button 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f661-a933-3h3f-0294-31c4f962ec48"
/> />
</div> </div>
</div> </div>
@ -326,9 +326,9 @@ exports[`Render should enable azure monitor load subscriptions button 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="77409fad-c0a9-45df-9e25-f1ff95af6554" value="34509fad-c0r9-45df-9e25-f1ee34af6900"
/> />
</div> </div>
</div> </div>
@ -349,7 +349,7 @@ exports[`Render should enable azure monitor load subscriptions button 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f661-a933-4b3f-8176-51c4f982ec48"
/> />
@ -384,7 +384,7 @@ exports[`Render should enable azure monitor load subscriptions button 1`] = `
"SingleValue": [Function], "SingleValue": [Function],
} }
} }
defaultValue="44693801-6ee6-49de-9b2d-9106972f9572" defaultValue="44987801-6nn6-49he-9b2d-9106972f9789"
isClearable={false} isClearable={false}
isDisabled={false} isDisabled={false}
isLoading={false} isLoading={false}
@ -510,9 +510,9 @@ exports[`Render should render component 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f661-a933-3h3f-0294-31c4f962ec48"
/> />
</div> </div>
</div> </div>
@ -533,9 +533,9 @@ exports[`Render should render component 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="77409fad-c0a9-45df-9e25-f1ff95af6554" value="34509fad-c0r9-45df-9e25-f1ee34af6900"
/> />
</div> </div>
</div> </div>
@ -556,7 +556,7 @@ exports[`Render should render component 1`] = `
> >
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[MockFunction]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="" value=""
/> />
@ -591,7 +591,7 @@ exports[`Render should render component 1`] = `
"SingleValue": [Function], "SingleValue": [Function],
} }
} }
defaultValue="44693801-6ee6-49de-9b2d-9106972f9572" defaultValue="44987801-6nn6-49he-9b2d-9106972f9789"
isClearable={false} isClearable={false}
isDisabled={false} isDisabled={false}
isLoading={false} isLoading={false}

View File

@ -3,7 +3,10 @@
exports[`Render should render component 1`] = ` exports[`Render should render component 1`] = `
<Fragment> <Fragment>
<MonitorConfig <MonitorConfig
datasourceConfig={ onLoadSubscriptions={[Function]}
onResetOptionKey={[Function]}
onUpdateOption={[Function]}
options={
Object { Object {
"access": "proxy", "access": "proxy",
"basicAuth": false, "basicAuth": false,
@ -15,6 +18,7 @@ exports[`Render should render component 1`] = `
"jsonData": Object { "jsonData": Object {
"azureLogAnalyticsSameAs": true, "azureLogAnalyticsSameAs": true,
"cloudName": "azuremonitor", "cloudName": "azuremonitor",
"subscriptionId": "44987801-6nn6-49he-9b2d-9106972f9789",
}, },
"name": "Azure Monitor-10-10", "name": "Azure Monitor-10-10",
"orgId": 1, "orgId": 1,
@ -24,52 +28,20 @@ exports[`Render should render component 1`] = `
"secureJsonFields": Object {}, "secureJsonFields": Object {},
"type": "grafana-azure-monitor-datasource", "type": "grafana-azure-monitor-datasource",
"typeLogoUrl": "", "typeLogoUrl": "",
"url": "/api/datasources/proxy/21", "url": "",
"user": "", "user": "",
"version": 1, "version": 1,
"withCredentials": false, "withCredentials": false,
} }
} }
onDatasourceUpdate={[Function]}
onLoadSubscriptions={[Function]}
subscriptions={Array []} subscriptions={Array []}
/> />
<AnalyticsConfig <AnalyticsConfig
datasourceConfig={
Object {
"access": "proxy",
"basicAuth": false,
"basicAuthPassword": "",
"basicAuthUser": "",
"database": "",
"id": 21,
"isDefault": false,
"jsonData": Object {
"azureLogAnalyticsSameAs": true,
"cloudName": "azuremonitor",
},
"name": "Azure Monitor-10-10",
"orgId": 1,
"password": "",
"readOnly": false,
"secureJsonData": Object {},
"secureJsonFields": Object {},
"type": "grafana-azure-monitor-datasource",
"typeLogoUrl": "",
"url": "/api/datasources/proxy/21",
"user": "",
"version": 1,
"withCredentials": false,
}
}
logAnalyticsSubscriptions={Array []}
logAnalyticsWorkspaces={Array []}
onDatasourceUpdate={[Function]}
onLoadSubscriptions={[Function]} onLoadSubscriptions={[Function]}
onLoadWorkspaces={[Function]} onLoadWorkspaces={[Function]}
/> onResetOptionKey={[Function]}
<InsightsConfig onUpdateOption={[Function]}
datasourceConfig={ options={
Object { Object {
"access": "proxy", "access": "proxy",
"basicAuth": false, "basicAuth": false,
@ -81,6 +53,7 @@ exports[`Render should render component 1`] = `
"jsonData": Object { "jsonData": Object {
"azureLogAnalyticsSameAs": true, "azureLogAnalyticsSameAs": true,
"cloudName": "azuremonitor", "cloudName": "azuremonitor",
"subscriptionId": "44987801-6nn6-49he-9b2d-9106972f9789",
}, },
"name": "Azure Monitor-10-10", "name": "Azure Monitor-10-10",
"orgId": 1, "orgId": 1,
@ -90,13 +63,46 @@ exports[`Render should render component 1`] = `
"secureJsonFields": Object {}, "secureJsonFields": Object {},
"type": "grafana-azure-monitor-datasource", "type": "grafana-azure-monitor-datasource",
"typeLogoUrl": "", "typeLogoUrl": "",
"url": "/api/datasources/proxy/21", "url": "",
"user": "",
"version": 1,
"withCredentials": false,
}
}
subscriptions={Array []}
workspaces={Array []}
/>
<InsightsConfig
onResetOptionKey={[Function]}
onUpdateOption={[Function]}
options={
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,
"secureJsonData": Object {},
"secureJsonFields": Object {},
"type": "grafana-azure-monitor-datasource",
"typeLogoUrl": "",
"url": "",
"user": "", "user": "",
"version": 1, "version": 1,
"withCredentials": false, "withCredentials": false,
} }
} }
onDatasourceUpdate={[Function]}
/> />
</Fragment> </Fragment>
`; `;

View File

@ -21,25 +21,15 @@ exports[`Render should disable insights api key input 1`] = `
> >
API Key API Key
</Component> </Component>
<Input
className="width-25"
disabled={true}
placeholder="configured"
/>
</div>
<div
className="gf-form"
>
<div <div
className="max-width-30 gf-form-inline" className="width-15"
> >
<Button <Input
onClick={[Function]} className="width-30"
type="button" onChange={[Function]}
variant="secondary" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
> value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
reset />
</Button>
</div> </div>
</div> </div>
</div> </div>
@ -60,7 +50,7 @@ exports[`Render should disable insights api key input 1`] = `
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[Function]}
value="cddcc020-2c94-460a-a3d0-df3147ffa792" value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
/> />
</div> </div>
</div> </div>
@ -97,7 +87,7 @@ exports[`Render should enable insights api key input 1`] = `
className="width-30" className="width-30"
onChange={[Function]} onChange={[Function]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
/> />
</div> </div>
</div> </div>
@ -119,7 +109,7 @@ exports[`Render should enable insights api key input 1`] = `
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[Function]}
value="cddcc020-2c94-460a-a3d0-df3147ffa792" value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
/> />
</div> </div>
</div> </div>
@ -156,7 +146,7 @@ exports[`Render should render component 1`] = `
className="width-30" className="width-30"
onChange={[Function]} onChange={[Function]}
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
value="e7f3f661-a933-4b3f-8176-51c4f982ec48" value="e7f3f775-a987-4b3f-3835-51c4f982kl48"
/> />
</div> </div>
</div> </div>
@ -178,7 +168,7 @@ exports[`Render should render component 1`] = `
<Input <Input
className="width-30" className="width-30"
onChange={[Function]} onChange={[Function]}
value="cddcc020-2c94-460a-a3d0-df3147ffa792" value="cvvcc020-2cpo-123a-a3d0-df6547fki792"
/> />
</div> </div>
</div> </div>

View File

@ -1,4 +1,6 @@
import { DataQuery, DataSourceJsonData } from '@grafana/data'; import { DataQuery, DataSourceJsonData, DataSourceSettings } from '@grafana/data';
export type AzureDataSourceSettings = DataSourceSettings<AzureDataSourceJsonData, AzureDataSourceSecureJsonData>;
export interface AzureMonitorQuery extends DataQuery { export interface AzureMonitorQuery extends DataQuery {
refId: string; refId: string;
@ -29,8 +31,9 @@ export interface AzureDataSourceJsonData extends DataSourceJsonData {
} }
export interface AzureDataSourceSecureJsonData { export interface AzureDataSourceSecureJsonData {
clientSecret: string; clientSecret?: string;
logAnalyticsClientSecret: string; logAnalyticsClientSecret?: string;
appInsightsApiKey?: string;
} }
export interface AzureMetricQuery { export interface AzureMetricQuery {