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 >({ 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(false); const [testingState, setTestingState] = useState(false); const [notifications, NotificationElement] = notification.useNotification(); const [type, setType] = useState(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 ( ); } interface CreateAlertChannelsProps { preType: ChannelType; } export default CreateAlertChannels;