Amol Umbark 3ef9d96678
Pagerduty - Create, Edit and Test Features (#1016)
* enabled sending alerts to pagerduty
2022-05-03 11:28:00 +05:30

355 lines
9.1 KiB
TypeScript

import { Form, notification } from 'antd';
import createPagerApi from 'api/channels/createPager';
import createSlackApi from 'api/channels/createSlack';
import createWebhookApi from 'api/channels/createWebhook';
import testPagerApi from 'api/channels/testPager';
import testSlackApi from 'api/channels/testSlack';
import testWebhookApi from 'api/channels/testWebhook';
import ROUTES from 'constants/routes';
import FormAlertChannels from 'container/FormAlertChannels';
import history from 'lib/history';
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
ChannelType,
PagerChannel,
PagerType,
SlackChannel,
SlackType,
ValidatePagerChannel,
WebhookChannel,
WebhookType,
} from './config';
import { PagerInitialConfig } from './defaults';
function CreateAlertChannels({
preType = 'slack',
}: CreateAlertChannelsProps): JSX.Element {
// init namespace for translations
const { t } = useTranslation('channels');
const [formInstance] = Form.useForm();
const [selectedConfig, setSelectedConfig] = useState<
Partial<SlackChannel & WebhookChannel & PagerChannel>
>({
text: `{{ range .Alerts -}}
*Alert:* {{ .Labels.alertname }}{{ if .Labels.severity }} - {{ .Labels.severity }}{{ end }}
*Summary:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Details:*
{{ range .Labels.SortedPairs }} • *{{ .Name }}:* {{ .Value }}
{{ end }}
{{ end }}`,
title: `[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}
{{- if gt (len .CommonLabels) (len .GroupLabels) -}}
{{" "}}(
{{- with .CommonLabels.Remove .GroupLabels.Names }}
{{- range $index, $label := .SortedPairs -}}
{{ if $index }}, {{ end }}
{{- $label.Name }}="{{ $label.Value -}}"
{{- end }}
{{- end -}}
)
{{- end }}`,
});
const [savingState, setSavingState] = useState<boolean>(false);
const [testingState, setTestingState] = useState<boolean>(false);
const [notifications, NotificationElement] = notification.useNotification();
const [type, setType] = useState<ChannelType>(preType);
const onTypeChangeHandler = useCallback(
(value: string) => {
const currentType = type;
setType(value as ChannelType);
if (value === PagerType && currentType !== value) {
// reset config to pager defaults
setSelectedConfig({
name: selectedConfig?.name,
send_resolved: selectedConfig.send_resolved,
...PagerInitialConfig,
});
}
},
[type, selectedConfig],
);
const prepareSlackRequest = useCallback(() => {
return {
api_url: selectedConfig?.api_url || '',
channel: selectedConfig?.channel || '',
name: selectedConfig?.name || '',
send_resolved: true,
text: selectedConfig?.text || '',
title: selectedConfig?.title || '',
};
}, [selectedConfig]);
const onSlackHandler = useCallback(async () => {
setSavingState(true);
try {
const response = await createSlackApi(prepareSlackRequest());
if (response.statusCode === 200) {
notifications.success({
message: 'Success',
description: t('channel_creation_done'),
});
setTimeout(() => {
history.replace(ROUTES.SETTINGS);
}, 2000);
} else {
notifications.error({
message: 'Error',
description: response.error || t('channel_creation_failed'),
});
}
} catch (error) {
notifications.error({
message: 'Error',
description: t('channel_creation_failed'),
});
}
setSavingState(false);
}, [prepareSlackRequest, t, notifications]);
const prepareWebhookRequest = useCallback(() => {
// initial api request without auth params
let request: WebhookChannel = {
api_url: selectedConfig?.api_url || '',
name: selectedConfig?.name || '',
send_resolved: true,
};
if (selectedConfig?.username !== '' || selectedConfig?.password !== '') {
if (selectedConfig?.username !== '') {
// if username is not null then password must be passed
if (selectedConfig?.password !== '') {
request = {
...request,
username: selectedConfig.username,
password: selectedConfig.password,
};
} else {
notifications.error({
message: 'Error',
description: t('username_no_password'),
});
}
} else if (selectedConfig?.password !== '') {
// only password entered, set bearer token
request = {
...request,
username: '',
password: selectedConfig.password,
};
}
}
return request;
}, [notifications, t, selectedConfig]);
const onWebhookHandler = useCallback(async () => {
setSavingState(true);
try {
const request = prepareWebhookRequest();
const response = await createWebhookApi(request);
if (response.statusCode === 200) {
notifications.success({
message: 'Success',
description: t('channel_creation_done'),
});
setTimeout(() => {
history.replace(ROUTES.SETTINGS);
}, 2000);
} else {
notifications.error({
message: 'Error',
description: response.error || t('channel_creation_failed'),
});
}
} catch (error) {
notifications.error({
message: 'Error',
description: t('channel_creation_failed'),
});
}
setSavingState(false);
}, [prepareWebhookRequest, t, notifications]);
const preparePagerRequest = useCallback(() => {
const validationError = ValidatePagerChannel(selectedConfig as PagerChannel);
if (validationError !== '') {
notifications.error({
message: 'Error',
description: validationError,
});
return null;
}
return {
name: selectedConfig?.name || '',
send_resolved: true,
routing_key: selectedConfig?.routing_key || '',
client: selectedConfig?.client || '',
client_url: selectedConfig?.client_url || '',
description: selectedConfig?.description || '',
severity: selectedConfig?.severity || '',
component: selectedConfig?.component || '',
group: selectedConfig?.group || '',
class: selectedConfig?.class || '',
details: selectedConfig.details || '',
detailsArray: JSON.parse(selectedConfig.details || '{}'),
};
}, [selectedConfig, notifications]);
const onPagerHandler = useCallback(async () => {
setSavingState(true);
const request = preparePagerRequest();
if (request) {
try {
const response = await createPagerApi(request);
if (response.statusCode === 200) {
notifications.success({
message: 'Success',
description: t('channel_creation_done'),
});
setTimeout(() => {
history.replace(ROUTES.SETTINGS);
}, 2000);
} else {
notifications.error({
message: 'Error',
description: response.error || t('channel_creation_failed'),
});
}
} catch (e) {
notifications.error({
message: 'Error',
description: t('channel_creation_failed'),
});
}
}
setSavingState(false);
}, [t, notifications, preparePagerRequest]);
const onSaveHandler = useCallback(
async (value: ChannelType) => {
switch (value) {
case SlackType:
onSlackHandler();
break;
case WebhookType:
onWebhookHandler();
break;
case PagerType:
onPagerHandler();
break;
default:
notifications.error({
message: 'Error',
description: t('selected_channel_invalid'),
});
}
},
[onSlackHandler, t, onPagerHandler, onWebhookHandler, notifications],
);
const performChannelTest = useCallback(
async (channelType: ChannelType) => {
setTestingState(true);
try {
let request;
let response;
switch (channelType) {
case WebhookType:
request = prepareWebhookRequest();
response = await testWebhookApi(request);
break;
case SlackType:
request = prepareSlackRequest();
response = await testSlackApi(request);
break;
case PagerType:
request = preparePagerRequest();
if (request) response = await testPagerApi(request);
break;
default:
notifications.error({
message: 'Error',
description: t('test_unsupported'),
});
setTestingState(false);
return;
}
if (response && response.statusCode === 200) {
notifications.success({
message: 'Success',
description: t('channel_test_done'),
});
} else {
notifications.error({
message: 'Error',
description: t('channel_test_failed'),
});
}
} catch (error) {
notifications.error({
message: 'Error',
description: t('channel_test_unexpected'),
});
}
setTestingState(false);
},
[
prepareWebhookRequest,
t,
preparePagerRequest,
prepareSlackRequest,
notifications,
],
);
const onTestHandler = useCallback(
async (value: ChannelType) => {
performChannelTest(value);
},
[performChannelTest],
);
return (
<FormAlertChannels
{...{
formInstance,
onTypeChangeHandler,
setSelectedConfig,
type,
onTestHandler,
onSaveHandler,
savingState,
testingState,
NotificationElement,
title: t('page_title_create'),
initialValue: {
type,
...selectedConfig,
...PagerInitialConfig,
},
}}
/>
);
}
interface CreateAlertChannelsProps {
preType: ChannelType;
}
export default CreateAlertChannels;