Cloud Watch: Standardize Config Editor Implementation (#20489)
* remove anon funcs, removed options from state, removed update method, static selects as constants * cancellable promise * cancel promise on unmount * use new datasource funcs for dryer component
This commit is contained in:
@@ -1,18 +1,26 @@
|
|||||||
import React, { PureComponent, ChangeEvent } from 'react';
|
import React, { PureComponent, ChangeEvent } from 'react';
|
||||||
import { FormLabel, Select, Input, Button } from '@grafana/ui';
|
import { FormLabel, Select, Input, Button } from '@grafana/ui';
|
||||||
import { DataSourcePluginOptionsEditorProps, DataSourceSettings } from '@grafana/data';
|
import {
|
||||||
|
DataSourcePluginOptionsEditorProps,
|
||||||
|
updateDatasourcePluginJsonDataOption,
|
||||||
|
updateDatasourcePluginResetKeyOption,
|
||||||
|
updateDatasourcePluginOption,
|
||||||
|
} from '@grafana/data';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import CloudWatchDatasource from '../datasource';
|
import CloudWatchDatasource from '../datasource';
|
||||||
import { CloudWatchJsonData, CloudWatchSecureJsonData } from '../types';
|
import { CloudWatchJsonData, CloudWatchSecureJsonData } from '../types';
|
||||||
|
import { CancelablePromise, makePromiseCancelable } from 'app/core/utils/CancelablePromise';
|
||||||
|
|
||||||
export type Props = DataSourcePluginOptionsEditorProps<CloudWatchJsonData>;
|
const authProviderOptions = [
|
||||||
|
{ label: 'Access & secret key', value: 'keys' },
|
||||||
|
{ label: 'Credentials file', value: 'credentials' },
|
||||||
|
{ label: 'ARN', value: 'arn' },
|
||||||
|
] as SelectableValue[];
|
||||||
|
|
||||||
type CloudwatchSettings = DataSourceSettings<CloudWatchJsonData, CloudWatchSecureJsonData>;
|
export type Props = DataSourcePluginOptionsEditorProps<CloudWatchJsonData, CloudWatchSecureJsonData>;
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
config: CloudwatchSettings;
|
|
||||||
authProviderOptions: SelectableValue[];
|
|
||||||
regions: SelectableValue[];
|
regions: SelectableValue[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,54 +28,39 @@ 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),
|
|
||||||
authProviderOptions: [
|
|
||||||
{ label: 'Access & secret key', value: 'keys' },
|
|
||||||
{ label: 'Credentials file', value: 'credentials' },
|
|
||||||
{ label: 'ARN', value: 'arn' },
|
|
||||||
],
|
|
||||||
regions: [],
|
regions: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateDatasource(this.state.config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromProps(props: Props, state: State) {
|
loadRegionsPromise: CancelablePromise<any> = null;
|
||||||
return {
|
|
||||||
...state,
|
componentDidMount() {
|
||||||
config: ConfigEditor.defaults(props.options),
|
this.loadRegionsPromise = makePromiseCancelable(this.loadRegions());
|
||||||
};
|
this.loadRegionsPromise.promise.catch(({ isCanceled }) => {
|
||||||
|
if (isCanceled) {
|
||||||
|
console.warn('Cloud Watch ConfigEditor has unmounted, intialization was canceled');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaults = (options: any) => {
|
componentWillUnmount() {
|
||||||
options.jsonData.authType = options.jsonData.authType || 'credentials';
|
if (this.loadRegionsPromise) {
|
||||||
options.jsonData.timeField = options.jsonData.timeField || '@timestamp';
|
this.loadRegionsPromise.cancel();
|
||||||
|
|
||||||
if (!options.hasOwnProperty('secureJsonData')) {
|
|
||||||
options.secureJsonData = {};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.hasOwnProperty('jsonData')) {
|
onUpdateOption = (key: string, val: any, secure: boolean) => {
|
||||||
options.jsonData = {};
|
updateDatasourcePluginJsonDataOption(this.props, key, val, secure);
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.hasOwnProperty('secureJsonFields')) {
|
|
||||||
options.secureJsonFields = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
onResetKey = (key: string) => {
|
||||||
this.loadRegions();
|
updateDatasourcePluginResetKeyOption(this.props, key);
|
||||||
}
|
};
|
||||||
|
|
||||||
loadRegions() {
|
async loadRegions() {
|
||||||
getDatasourceSrv()
|
await getDatasourceSrv()
|
||||||
.loadDatasource(this.state.config.name)
|
.loadDatasource(this.props.options.name)
|
||||||
.then((ds: CloudWatchDatasource) => {
|
.then((ds: CloudWatchDatasource) => {
|
||||||
return ds.getRegions();
|
return ds.getRegions();
|
||||||
})
|
})
|
||||||
@@ -126,113 +119,46 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDatasource = async (config: any) => {
|
|
||||||
for (const j in config.jsonData) {
|
|
||||||
if (config.jsonData[j].length === 0) {
|
|
||||||
delete config.jsonData[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const k in config.secureJsonData) {
|
|
||||||
if (config.secureJsonData[k].length === 0) {
|
|
||||||
delete config.secureJsonData[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onOptionsChange({
|
|
||||||
...config,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onAuthProviderChange = (authType: SelectableValue<string>) => {
|
onAuthProviderChange = (authType: SelectableValue<string>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('authType', authType.value, false);
|
||||||
...this.state.config,
|
|
||||||
jsonData: {
|
|
||||||
...this.state.config.jsonData,
|
|
||||||
authType: authType.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onRegionChange = (defaultRegion: SelectableValue<string>) => {
|
onRegionChange = (defaultRegion: SelectableValue<string>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('defaultRegion', defaultRegion.value, false);
|
||||||
...this.state.config,
|
|
||||||
jsonData: {
|
|
||||||
...this.state.config.jsonData,
|
|
||||||
defaultRegion: defaultRegion.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onResetAccessKey = () => {
|
onResetAccessKey = () => {
|
||||||
this.updateDatasource({
|
this.onResetKey('accessKey');
|
||||||
...this.state.config,
|
|
||||||
secureJsonFields: {
|
|
||||||
...this.state.config.secureJsonFields,
|
|
||||||
accessKey: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onAccessKeyChange = (accessKey: string) => {
|
onAccessKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('accessKey', event.target.value, true);
|
||||||
...this.state.config,
|
|
||||||
secureJsonData: {
|
|
||||||
...this.state.config.secureJsonData,
|
|
||||||
accessKey,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onResetSecretKey = () => {
|
onResetSecretKey = () => {
|
||||||
this.updateDatasource({
|
this.onResetKey('secretKey');
|
||||||
...this.state.config,
|
|
||||||
secureJsonFields: {
|
|
||||||
...this.state.config.secureJsonFields,
|
|
||||||
secretKey: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onSecretKeyChange = (secretKey: string) => {
|
onSecretKeyChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('secretKey', event.target.value, true);
|
||||||
...this.state.config,
|
|
||||||
secureJsonData: {
|
|
||||||
...this.state.config.secureJsonData,
|
|
||||||
secretKey,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onCredentialProfileNameChange = (database: string) => {
|
onCredentialProfileNameChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
this.updateDatasource({
|
updateDatasourcePluginOption(this.props, 'database', event.target.value);
|
||||||
...this.state.config,
|
|
||||||
database,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onArnAssumeRoleChange = (assumeRoleArn: string) => {
|
onArnAssumeRoleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('assumeRoleArn', event.target.value, false);
|
||||||
...this.state.config,
|
|
||||||
jsonData: {
|
|
||||||
...this.state.config.jsonData,
|
|
||||||
assumeRoleArn,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onCustomMetricsNamespacesChange = (customMetricsNamespaces: string) => {
|
onCustomMetricsNamespacesChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
this.updateDatasource({
|
this.onUpdateOption('customMetricsNamespaces', event.target.value, false);
|
||||||
...this.state.config,
|
|
||||||
jsonData: {
|
|
||||||
...this.state.config.jsonData,
|
|
||||||
customMetricsNamespaces,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { config, authProviderOptions, regions } = this.state;
|
const { regions } = this.state;
|
||||||
|
const { options } = this.props;
|
||||||
|
const secureJsonData = (options.secureJsonData || {}) as CloudWatchSecureJsonData;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -243,14 +169,14 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<FormLabel className="width-14">Auth Provider</FormLabel>
|
<FormLabel className="width-14">Auth Provider</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
className="width-30"
|
className="width-30"
|
||||||
value={authProviderOptions.find(authProvider => authProvider.value === config.jsonData.authType)}
|
value={authProviderOptions.find(authProvider => authProvider.value === options.jsonData.authType)}
|
||||||
options={authProviderOptions}
|
options={authProviderOptions}
|
||||||
defaultValue={config.jsonData.authType}
|
defaultValue={options.jsonData.authType}
|
||||||
onChange={this.onAuthProviderChange}
|
onChange={this.onAuthProviderChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{config.jsonData.authType === 'credentials' && (
|
{options.jsonData.authType === 'credentials' && (
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
@@ -263,18 +189,16 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<Input
|
<Input
|
||||||
className="width-30"
|
className="width-30"
|
||||||
placeholder="default"
|
placeholder="default"
|
||||||
value={config.jsonData.database}
|
value={options.jsonData.database}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
onChange={this.onCredentialProfileNameChange}
|
||||||
this.onCredentialProfileNameChange(event.target.value)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{config.jsonData.authType === 'keys' && (
|
{options.jsonData.authType === 'keys' && (
|
||||||
<div>
|
<div>
|
||||||
{config.secureJsonFields.accessKey ? (
|
{options.secureJsonFields.accessKey ? (
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<FormLabel className="width-14">Access Key ID</FormLabel>
|
<FormLabel className="width-14">Access Key ID</FormLabel>
|
||||||
@@ -295,14 +219,14 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<div className="width-30">
|
<div className="width-30">
|
||||||
<Input
|
<Input
|
||||||
className="width-30"
|
className="width-30"
|
||||||
value={config.secureJsonData.accessKey || ''}
|
value={secureJsonData.accessKey || ''}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onAccessKeyChange(event.target.value)}
|
onChange={this.onAccessKeyChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{config.secureJsonFields.secretKey ? (
|
{options.secureJsonFields.secretKey ? (
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<FormLabel className="width-14">Secret Access Key</FormLabel>
|
<FormLabel className="width-14">Secret Access Key</FormLabel>
|
||||||
@@ -323,8 +247,8 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<div className="width-30">
|
<div className="width-30">
|
||||||
<Input
|
<Input
|
||||||
className="width-30"
|
className="width-30"
|
||||||
value={config.secureJsonData.secretKey || ''}
|
value={secureJsonData.secretKey || ''}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onSecretKeyChange(event.target.value)}
|
onChange={this.onSecretKeyChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -332,7 +256,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{config.jsonData.authType === 'arn' && (
|
{options.jsonData.authType === 'arn' && (
|
||||||
<div className="gf-form-inline">
|
<div className="gf-form-inline">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<FormLabel className="width-14" tooltip="ARN of Assume Role">
|
<FormLabel className="width-14" tooltip="ARN of Assume Role">
|
||||||
@@ -342,8 +266,8 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<Input
|
<Input
|
||||||
className="width-30"
|
className="width-30"
|
||||||
placeholder="arn:aws:iam:*"
|
placeholder="arn:aws:iam:*"
|
||||||
value={config.jsonData.assumeRoleArn || ''}
|
value={options.jsonData.assumeRoleArn || ''}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onArnAssumeRoleChange(event.target.value)}
|
onChange={this.onArnAssumeRoleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -359,9 +283,9 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
className="width-30"
|
className="width-30"
|
||||||
value={regions.find(region => region.value === config.jsonData.defaultRegion)}
|
value={regions.find(region => region.value === options.jsonData.defaultRegion)}
|
||||||
options={regions}
|
options={regions}
|
||||||
defaultValue={config.jsonData.defaultRegion}
|
defaultValue={options.jsonData.defaultRegion}
|
||||||
onChange={this.onRegionChange}
|
onChange={this.onRegionChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -374,10 +298,8 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
|||||||
<Input
|
<Input
|
||||||
className="width-30"
|
className="width-30"
|
||||||
placeholder="Namespace1,Namespace2"
|
placeholder="Namespace1,Namespace2"
|
||||||
value={config.jsonData.customMetricsNamespaces || ''}
|
value={options.jsonData.customMetricsNamespaces || ''}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
onChange={this.onCustomMetricsNamespacesChange}
|
||||||
this.onCustomMetricsNamespacesChange(event.target.value)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user