-
}
- >
+
}>
{`Error: ${firstLog.message} `}
@@ -71,9 +67,7 @@ const rfc5322EmailAddressRegex =
/^((([^ ]+ )+<[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*>|[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*|<[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*>)(, ?)?)+$/i;
const schema = Joi.object({
- enabled: Joi.boolean()
- .required()
- .label('Enable Email Notification Configuration'),
+ enabled: Joi.boolean().required().label('Enable Email Notification Configuration'),
host: Joi.string().required().label('SMTP Host'),
port: Joi.number().required().min(1).label('SMTP Port'),
isTLSEnabled: Joi.boolean().required().label('Enable SMTP Over TLS'),
@@ -99,44 +93,26 @@ const schema = Joi.object({
then: Joi.string().required().label('Password'),
otherwise: Joi.valid(),
}),
- from: Joi.string()
- .required()
- .label('Sender Email Address')
- .regex(emailRegex)
- .message('The email address is invalid'),
+ from: Joi.string().required().label('Sender Email Address').regex(emailRegex).message('The email address is invalid'),
to: Joi.string()
.required()
.label('Recipient Email Addresses')
.regex(rfc5322EmailAddressRegex)
.message('The email addresses are invalid'),
- sendResolved: Joi.boolean()
- .required()
- .label('Enable Receive Resolved Alerts'),
+ sendResolved: Joi.boolean().required().label('Enable Receive Resolved Alerts'),
});
export default function ConfigureAlerting() {
const theme = useTheme();
const navigate = useBasenameRelativeNavigate();
const dispatch = useDispatch();
- const {
- register,
- reset,
- handleSubmit,
- control,
- watch,
- getValues,
- formState,
- } = useForm
({
+ const { register, reset, handleSubmit, control, watch, getValues, formState } = useForm({
mode: 'onChange',
resolver: joiResolver(schema),
});
const credsType = watch('type');
- const {
- url: kubernetesApiUrl,
- url_salt: saltApiUrl,
- url_alertmanager: alertManagerUrl,
- } = useConfig();
+ const { url: kubernetesApiUrl, url_salt: saltApiUrl, url_alertmanager: alertManagerUrl } = useConfig();
const { userData, getToken } = useAuth();
const email = userData?.email || '';
@@ -175,10 +151,9 @@ export default function ConfigureAlerting() {
}
}, [alertConfiguration.status]);
- const { sendTestAlertMutation, logs: testAlertlogs } =
- useTestAlertConfiguration({
- alertConfigurationStore,
- });
+ const { sendTestAlertMutation, logs: testAlertlogs } = useTestAlertConfiguration({
+ alertConfigurationStore,
+ });
useEffect(() => {
if (sendTestAlertMutation.status === 'success') {
@@ -193,10 +168,7 @@ export default function ConfigureAlerting() {
const labelWidth = 270;
- const disableFormButton =
- editAlertMutation.isLoading ||
- sendTestAlertMutation.isLoading ||
- !formState.isDirty;
+ const disableFormButton = editAlertMutation.isLoading || sendTestAlertMutation.isLoading || !formState.isDirty;
if (alertConfiguration.status === 'loading') {
return Loading...
;
@@ -225,19 +197,14 @@ export default function ConfigureAlerting() {
type="button"
variant="secondary"
tooltip={
- Object.entries(formState.dirtyFields).filter(
- ([key]) => key !== 'enabled',
- ).length > 0
+ Object.entries(formState.dirtyFields).filter(([key]) => key !== 'enabled').length > 0
? {
overlay:
'Triggering a test mail will restart alerting service, alerts will be retriggered few minutes after.',
}
: undefined
}
- disabled={
- sendTestAlertMutation.isLoading ||
- editAlertMutation.isLoading
- }
+ disabled={sendTestAlertMutation.isLoading || editAlertMutation.isLoading}
label={
sendTestAlertMutation.isLoading ? (
- {sendTestAlertMutation.status === 'success' && (
-
- )}
+ {sendTestAlertMutation.status === 'success' && }
>
}
>
@@ -306,23 +271,14 @@ export default function ConfigureAlerting() {
content={}
/>
-
+
- }
+ content={}
/>
- }
+ content={}
/>
- }
+ content={}
/>
-
+
field.onChange(value)}
onBlur={field.onBlur}
>
-
- NO AUTHENTICATION
-
+ NO AUTHENTICATION
LOGIN
-
- CRAM-MD5
-
+ CRAM-MD5
PLAIN
);
@@ -395,13 +335,7 @@ export default function ConfigureAlerting() {
// @ts-expect-error - FIXME when you are working on it
error={formState.errors?.username?.message ?? ''}
helpErrorPosition="bottom"
- content={
-
- }
+ content={}
/>
- }
+ content={}
/>
>
) : (
@@ -433,13 +360,7 @@ export default function ConfigureAlerting() {
// @ts-expect-error - FIXME when you are working on it
error={formState.errors?.identity?.message ?? ''}
helpErrorPosition="bottom"
- content={
-
- }
+ content={}
/>
- }
+ content={}
/>
- }
+ content={}
/>
>
) : (
@@ -486,13 +394,7 @@ export default function ConfigureAlerting() {
// @ts-expect-error - FIXME when you are working on it
error={formState.errors?.username?.message ?? ''}
helpErrorPosition="bottom"
- content={
-
- }
+ content={}
/>
- }
+ content={}
/>
>
) : (
<>>
)}
-
+
- }
+ content={}
/>
- }
+ content={}
/>
diff --git a/ui/src/alert-configuration/domain/AlertConfigurationDomain.ts b/ui/src/alert-configuration/domain/AlertConfigurationDomain.ts
index e0e7bf9120..f41fa5b612 100644
--- a/ui/src/alert-configuration/domain/AlertConfigurationDomain.ts
+++ b/ui/src/alert-configuration/domain/AlertConfigurationDomain.ts
@@ -1,12 +1,7 @@
import { useMemo, useRef, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
-export const SMTPAuthTypes = [
- 'CRAM-MD5',
- 'PLAIN',
- 'LOGIN',
- 'NO_AUTHENTICATION',
-] as const;
+export const SMTPAuthTypes = ['CRAM-MD5', 'PLAIN', 'LOGIN', 'NO_AUTHENTICATION'] as const;
export type AuthType = (typeof SMTPAuthTypes)[number];
@@ -41,12 +36,7 @@ export type AlertConfiguration = {
from: string;
to: string;
sendResolved: boolean;
-} & (
- | PLAINCRedentials
- | LOGINCRedentials
- | CRAMMD5Credentials
- | NO_AUTHENCATIONCredentials
-);
+} & (PLAINCRedentials | LOGINCRedentials | CRAMMD5Credentials | NO_AUTHENCATIONCredentials);
type Loading = 'loading';
type Success = 'success';
@@ -69,10 +59,7 @@ export interface PromiseLoadingResult {
status: Loading;
}
-export type PromiseResult =
- | PromiseLoadingResult
- | PromiseSucceedResult
- | PromiseRejectedResult;
+export type PromiseResult = PromiseLoadingResult | PromiseSucceedResult | PromiseRejectedResult;
export const useAlertConfiguration = ({
alertConfigurationStore,
@@ -149,10 +136,7 @@ export interface IAlertConfigurationStore {
getAlertConfiguration(): Promise;
putAlertConfiguration(alertConfiguration: AlertConfiguration): Promise;
getTestConfiguration(): Promise;
- testAlertConfiguration(
- alertConfiguration: AlertConfiguration,
- configurationHasChanged: boolean,
- ): Promise;
+ testAlertConfiguration(alertConfiguration: AlertConfiguration, configurationHasChanged: boolean): Promise;
getAlertStoreLogsForTestAlert(): Promise;
getAlertStoreLogs(): Promise;
}
@@ -170,10 +154,7 @@ export const useEditAlertConfiguration = ({
onSuccess: (_, alertConfiguration) => {
queryClient.refetchQueries(['alertstorelogs']);
queryClient.setQueryData(['alertstoretestlogs'], []);
- queryClient.setQueriesData(
- ['alertConfiguration'],
- alertConfiguration,
- );
+ queryClient.setQueriesData(['alertConfiguration'], alertConfiguration);
},
});
@@ -205,8 +186,7 @@ export const useTestAlertConfiguration = ({
return alertConfigurationStore.testAlertConfiguration(
alertConfiguration,
- JSON.stringify(data) !==
- JSON.stringify({ ...alertConfiguration, enabled: true }),
+ JSON.stringify(data) !== JSON.stringify({ ...alertConfiguration, enabled: true }),
);
},
onSuccess: () => {
@@ -223,9 +203,7 @@ export const useTestAlertConfiguration = ({
refetchInterval: isTestInProgress ? 1_000 : Infinity,
});
- const hasFailedToSendTestAlert = !!logsData?.find(
- (logLine) => logLine.level === 'ERROR',
- );
+ const hasFailedToSendTestAlert = !!logsData?.find((logLine) => logLine.level === 'ERROR');
const overOneMinute = testDateRef.current < new Date(Date.now() - 60_000);
useMemo(() => {
diff --git a/ui/src/alert-configuration/infrastructure/Metalk8sCSCAlertConfigurationStore.ts b/ui/src/alert-configuration/infrastructure/Metalk8sCSCAlertConfigurationStore.ts
index 9faab0c40f..cb23726992 100644
--- a/ui/src/alert-configuration/infrastructure/Metalk8sCSCAlertConfigurationStore.ts
+++ b/ui/src/alert-configuration/infrastructure/Metalk8sCSCAlertConfigurationStore.ts
@@ -1,19 +1,12 @@
import { AlertManagerConfig, Receiver, Route } from './AlertManagerTypes';
-import {
- AlertConfiguration,
- AlertStoreLogLine,
- IAlertConfigurationStore,
-} from '../domain/AlertConfigurationDomain';
+import { AlertConfiguration, AlertStoreLogLine, IAlertConfigurationStore } from '../domain/AlertConfigurationDomain';
import YAML from 'yaml';
import { V1ConfigMap, V1NodeList } from '@kubernetes/client-node';
import { getTokenType } from '../../services/platformlibrary/k8s';
type AlertmanagerConfigKind = 'AlertmanagerConfig';
-type Metalk8sCSCConfiguration<
- KIND extends string,
- T extends Record,
-> = {
+type Metalk8sCSCConfiguration> = {
apiVersion: 'addons.metalk8s.scality.com';
kind: KIND;
spec: T;
@@ -50,9 +43,7 @@ export type SaltLoginResponse =
error: string;
};
-export class Metalk8sCSCAlertConfigurationStore
- implements IAlertConfigurationStore
-{
+export class Metalk8sCSCAlertConfigurationStore implements IAlertConfigurationStore {
constructor(
private k8sApiBaseUrl: string,
private saltApiBaseUrl: string,
@@ -84,30 +75,23 @@ export class Metalk8sCSCAlertConfigurationStore
const configMap: V1ConfigMap = await configMapResponse.json();
const rawAlertManagerConfig = configMap.data?.['config.yaml'] || '';
- const alertManagerConfig: Metalk8sAlertManagerConfig = YAML.parse(
- rawAlertManagerConfig,
- );
+ const alertManagerConfig: Metalk8sAlertManagerConfig = YAML.parse(rawAlertManagerConfig);
return alertManagerConfig;
}
- async _applyConfigMapChangesAndCallSalt(
- newConfig: Metalk8sAlertManagerConfig,
- ) {
- await fetch(
- `${this.k8sApiBaseUrl}/api/v1/namespaces/metalk8s-monitoring/configmaps/metalk8s-alertmanager-config`,
- {
- method: 'PATCH',
- headers: {
- 'Content-Type': 'application/merge-patch+json',
- Authorization: `Bearer ${await this.getToken()}`,
- },
- body: JSON.stringify({
- data: {
- ['config.yaml']: YAML.stringify(newConfig),
- },
- }),
+ async _applyConfigMapChangesAndCallSalt(newConfig: Metalk8sAlertManagerConfig) {
+ await fetch(`${this.k8sApiBaseUrl}/api/v1/namespaces/metalk8s-monitoring/configmaps/metalk8s-alertmanager-config`, {
+ method: 'PATCH',
+ headers: {
+ 'Content-Type': 'application/merge-patch+json',
+ Authorization: `Bearer ${await this.getToken()}`,
},
- );
+ body: JSON.stringify({
+ data: {
+ ['config.yaml']: YAML.stringify(newConfig),
+ },
+ }),
+ });
//Login salt api
const saltLoginFetchResponse = await fetch(`${this.saltApiBaseUrl}/login`, {
@@ -126,33 +110,26 @@ export class Metalk8sCSCAlertConfigurationStore
throw new Error('Error login with salt api');
}
- const saltLoginResponse: SaltLoginResponse =
- await saltLoginFetchResponse.json();
+ const saltLoginResponse: SaltLoginResponse = await saltLoginFetchResponse.json();
if ('error' in saltLoginResponse) {
throw new Error('Error login with salt api');
}
- const nodesFetchResponse = await fetch(
- `${this.k8sApiBaseUrl}/api/v1/nodes`,
- {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${await this.getToken()}`,
- },
+ const nodesFetchResponse = await fetch(`${this.k8sApiBaseUrl}/api/v1/nodes`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${await this.getToken()}`,
},
- );
+ });
if (nodesFetchResponse.status !== 200) {
throw new Error('Error fetching nodes information');
}
const nodesResponse: V1NodeList = await nodesFetchResponse.json();
- const metalk8sVersion =
- nodesResponse.items[0].metadata?.labels?.[
- 'metalk8s.scality.com/version'
- ] || null;
+ const metalk8sVersion = nodesResponse.items[0].metadata?.labels?.['metalk8s.scality.com/version'] || null;
if (!metalk8sVersion) {
throw new Error('Error fetching metalk8s version');
@@ -176,32 +153,25 @@ export class Metalk8sCSCAlertConfigurationStore
});
}
- async _getAlertConfiguration(
- selectTestConfig: boolean,
- ): Promise {
- const alertManagerConfig: Metalk8sAlertManagerConfig =
- await this._getAlertManagerConfig();
+ async _getAlertConfiguration(selectTestConfig: boolean): Promise {
+ const alertManagerConfig: Metalk8sAlertManagerConfig = await this._getAlertManagerConfig();
- const currentEmailreceiver: Receiver =
- alertManagerConfig.spec.notification?.config?.receivers?.find(
- (receiver) => {
- return (
- receiver.email_configs &&
- receiver.email_configs.length > 0 &&
- (selectTestConfig
- ? receiver.name === 'test-receiver-config-from-ui'
- : receiver.name !== 'test-receiver-config-from-ui')
- );
- },
- ) || {
- name: selectTestConfig ? 'test-receiver-config-from-ui' : 'default',
- };
+ const currentEmailreceiver: Receiver = alertManagerConfig.spec.notification?.config?.receivers?.find((receiver) => {
+ return (
+ receiver.email_configs &&
+ receiver.email_configs.length > 0 &&
+ (selectTestConfig
+ ? receiver.name === 'test-receiver-config-from-ui'
+ : receiver.name !== 'test-receiver-config-from-ui')
+ );
+ }) || {
+ name: selectTestConfig ? 'test-receiver-config-from-ui' : 'default',
+ };
const receiverName = currentEmailreceiver.name;
- const isEnable =
- alertManagerConfig.spec.notification?.config?.route?.routes?.find(
- (r) => r.receiver === receiverName,
- );
+ const isEnable = alertManagerConfig.spec.notification?.config?.route?.routes?.find(
+ (r) => r.receiver === receiverName,
+ );
const smtpHostAndPort = parseHostAndPort(
currentEmailreceiver?.email_configs?.[0].smarthost ||
@@ -209,26 +179,21 @@ export class Metalk8sCSCAlertConfigurationStore
'',
);
- const alertConfiguration: Omit<
- AlertConfiguration,
- 'type' | 'username' | 'password' | 'secret' | 'identity'
- > = {
+ const alertConfiguration: Omit = {
enabled: !!isEnable,
host: smtpHostAndPort.host,
port: smtpHostAndPort.port,
isTLSEnabled: !!(
currentEmailreceiver?.email_configs?.[0].require_tls === true ||
(currentEmailreceiver?.email_configs?.[0].require_tls !== false &&
- alertManagerConfig.spec.notification?.config?.global
- ?.smtp_require_tls)
+ alertManagerConfig.spec.notification?.config?.global?.smtp_require_tls)
),
from:
currentEmailreceiver?.email_configs?.[0].from ||
alertManagerConfig.spec.notification?.config?.global?.smtp_from ||
'',
to: currentEmailreceiver?.email_configs?.[0].to || '',
- sendResolved:
- currentEmailreceiver?.email_configs?.[0].send_resolved === true,
+ sendResolved: currentEmailreceiver?.email_configs?.[0].send_resolved === true,
};
const username =
@@ -312,17 +277,17 @@ export class Metalk8sCSCAlertConfigurationStore
auth_secret: alertConfiguration.secret,
}
: alertConfiguration.type === 'LOGIN'
- ? {
- auth_username: alertConfiguration.username,
- auth_password: alertConfiguration.password,
- }
- : alertConfiguration.type === 'PLAIN'
- ? {
- auth_identity: alertConfiguration.identity,
- auth_username: alertConfiguration.username,
- auth_password: alertConfiguration.password,
- }
- : {}),
+ ? {
+ auth_username: alertConfiguration.username,
+ auth_password: alertConfiguration.password,
+ }
+ : alertConfiguration.type === 'PLAIN'
+ ? {
+ auth_identity: alertConfiguration.identity,
+ auth_username: alertConfiguration.username,
+ auth_password: alertConfiguration.password,
+ }
+ : {}),
},
...(currentEmailreceiver.email_configs?.slice(1) || []),
],
@@ -330,29 +295,20 @@ export class Metalk8sCSCAlertConfigurationStore
}
async putAlertConfiguration(alertConfiguration: AlertConfiguration) {
- const alertManagerConfig: Metalk8sAlertManagerConfig =
- await this._getAlertManagerConfig();
+ const alertManagerConfig: Metalk8sAlertManagerConfig = await this._getAlertManagerConfig();
- const currentEmailreceiver: Receiver =
- alertManagerConfig.spec.notification?.config?.receivers?.find(
- (receiver) => {
- return (
- receiver.email_configs &&
- receiver.email_configs.length > 0 &&
- receiver.name !== 'test-receiver-config-from-ui'
- );
- },
- ) || { name: 'default' };
+ const currentEmailreceiver: Receiver = alertManagerConfig.spec.notification?.config?.receivers?.find((receiver) => {
+ return (
+ receiver.email_configs && receiver.email_configs.length > 0 && receiver.name !== 'test-receiver-config-from-ui'
+ );
+ }) || { name: 'default' };
const receiverWithoutTest =
alertManagerConfig.spec.notification?.config?.receivers?.filter(
(r) => r.name !== 'test-receiver-config-from-ui',
) || [];
const emailReceiverIndexToPatch =
- receiverWithoutTest.findIndex(
- (receiver) =>
- receiver.email_configs && receiver.email_configs.length > 0,
- ) || 0;
+ receiverWithoutTest.findIndex((receiver) => receiver.email_configs && receiver.email_configs.length > 0) || 0;
const newEmailReceiver: Receiver = await this._convertAndMergeEmailReceiver(
alertConfiguration,
@@ -372,9 +328,7 @@ export class Metalk8sCSCAlertConfigurationStore
) ?? [];
const defaultReceiverRouteIndex =
- routesWithoutTest.findIndex(
- (route) => route.receiver === currentEmailreceiver.name,
- ) || 0;
+ routesWithoutTest.findIndex((route) => route.receiver === currentEmailreceiver.name) || 0;
const routes = alertConfiguration.enabled
? [
@@ -382,9 +336,7 @@ export class Metalk8sCSCAlertConfigurationStore
newDefaultReceiverRoute,
...(routesWithoutTest?.slice(defaultReceiverRouteIndex + 1) || []),
]
- : routesWithoutTest?.filter(
- (r) => r.receiver !== currentEmailreceiver.name,
- );
+ : routesWithoutTest?.filter((r) => r.receiver !== currentEmailreceiver.name);
const newConfig: Metalk8sAlertManagerConfig = {
...alertManagerConfig,
@@ -399,11 +351,9 @@ export class Metalk8sCSCAlertConfigurationStore
routes: routes,
},
receivers: [
- ...(receiverWithoutTest?.slice(0, emailReceiverIndexToPatch) ||
- []),
+ ...(receiverWithoutTest?.slice(0, emailReceiverIndexToPatch) || []),
newEmailReceiver,
- ...(receiverWithoutTest?.slice(emailReceiverIndexToPatch + 1) ||
- []),
+ ...(receiverWithoutTest?.slice(emailReceiverIndexToPatch + 1) || []),
],
},
},
@@ -413,25 +363,17 @@ export class Metalk8sCSCAlertConfigurationStore
await this._applyConfigMapChangesAndCallSalt(newConfig);
}
- async testAlertConfiguration(
- alertConfiguration: AlertConfiguration,
- configurationHasChanged: boolean,
- ) {
+ async testAlertConfiguration(alertConfiguration: AlertConfiguration, configurationHasChanged: boolean) {
if (configurationHasChanged) {
// Edit configmap
- const alertManagerConfig: Metalk8sAlertManagerConfig =
- await this._getAlertManagerConfig();
+ const alertManagerConfig: Metalk8sAlertManagerConfig = await this._getAlertManagerConfig();
const testReceiverName = 'test-receiver-config-from-ui';
const emptyReceiver: Receiver = {
name: testReceiverName,
};
- const newEmailReceiver: Receiver =
- await this._convertAndMergeEmailReceiver(
- alertConfiguration,
- emptyReceiver,
- );
+ const newEmailReceiver: Receiver = await this._convertAndMergeEmailReceiver(alertConfiguration, emptyReceiver);
delete newEmailReceiver.email_configs?.[0].send_resolved;
@@ -478,15 +420,12 @@ export class Metalk8sCSCAlertConfigurationStore
// We need to wait that alert manager pods is ready to receive alert
const fetchAlertManagerPods = async (): Promise => {
- const podsResponse = await fetch(
- `${this.k8sApiBaseUrl}/api/v1/namespaces/metalk8s-monitoring/pods`,
- {
- method: 'GET',
- headers: {
- Authorization: `Bearer ${await this.getToken()}`,
- },
+ const podsResponse = await fetch(`${this.k8sApiBaseUrl}/api/v1/namespaces/metalk8s-monitoring/pods`, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${await this.getToken()}`,
},
- );
+ });
if (podsResponse.status !== 200) {
return;
@@ -495,22 +434,17 @@ export class Metalk8sCSCAlertConfigurationStore
const pods: V1NodeList = await podsResponse.json();
const alertManagerPods = pods.items.filter((pod) => {
- return pod.metadata?.name?.includes(
- 'alertmanager-prometheus-operator-alertmanager',
- );
+ return pod.metadata?.name?.includes('alertmanager-prometheus-operator-alertmanager');
});
// compare each pods metadata creation timestamp with the date and check if they status is ready
const podsReady = alertManagerPods.every((pod) => {
- const podCreationDate = new Date(
- pod.metadata?.creationTimestamp || '',
- );
+ const podCreationDate = new Date(pod.metadata?.creationTimestamp || '');
return (
pod.status?.conditions?.findIndex(
- (condition) =>
- condition.type === 'Ready' && condition.status === 'True',
+ (condition) => condition.type === 'Ready' && condition.status === 'True',
) !== -1 && podCreationDate.getTime() > date.getTime()
);
});
@@ -545,32 +479,27 @@ export class Metalk8sCSCAlertConfigurationStore
TLS(${alertConfWithoutCreds.isTLSEnabled ? 'enabled' : 'disabled'}),
From(${alertConfWithoutCreds.from}),
To(${alertConfWithoutCreds.to}),
- Send resolved(${
- alertConfWithoutCreds.sendResolved ? 'enabled' : 'disabled'
- })
+ Send resolved(${alertConfWithoutCreds.sendResolved ? 'enabled' : 'disabled'})
${credsTemplate}.`;
- const alertFetchResponse = await fetch(
- `${this.alertManagerApiBaseUrl}/api/v2/alerts`,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify([
- {
- labels: {
- alertname: 'dummy_alert',
- severity: 'critical',
- testedOn: new Date().toISOString(),
- },
- annotations: {
- description: descriptionTemplate,
- },
- },
- ]),
+ const alertFetchResponse = await fetch(`${this.alertManagerApiBaseUrl}/api/v2/alerts`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
},
- );
+ body: JSON.stringify([
+ {
+ labels: {
+ alertname: 'dummy_alert',
+ severity: 'critical',
+ testedOn: new Date().toISOString(),
+ },
+ annotations: {
+ description: descriptionTemplate,
+ },
+ },
+ ]),
+ });
if (alertFetchResponse.status !== 200) {
throw new Error(`Error while sending test alert`);
@@ -578,9 +507,7 @@ export class Metalk8sCSCAlertConfigurationStore
const alertResponse = await alertFetchResponse.json();
if (alertResponse.status !== 'success') {
- throw new Error(
- `Error while sending test alert : ${alertResponse.error.message}`,
- );
+ throw new Error(`Error while sending test alert : ${alertResponse.error.message}`);
}
}
@@ -608,20 +535,21 @@ export class Metalk8sCSCAlertConfigurationStore
line.includes(`receiver="${receiverName}`) ||
line.includes(`err="${receiverName}`))
) {
- const components = line.match(
- /(?\w+)=("(?(\\"|[^"])+)"|(?[^ ]*))/g,
- );
+ const components = line.match(/(?\w+)=("(?(\\"|[^"])+)"|(?[^ ]*))/g);
- const obj = components?.reduce((acc, component) => {
- let [key, value] = component.split('=');
+ const obj = components?.reduce(
+ (acc, component) => {
+ let [key, value] = component.split('=');
- value = value.replace(/"/g, '');
+ value = value.replace(/"/g, '');
- return {
- ...acc,
- [key]: value,
- };
- }, {} as { err: string; ts: string });
+ return {
+ ...acc,
+ [key]: value,
+ };
+ },
+ {} as { err: string; ts: string },
+ );
if (!obj) {
return [];
diff --git a/ui/src/components/ActiveAlertsCounter.tsx b/ui/src/components/ActiveAlertsCounter.tsx
index 7adf450943..ccea30b211 100644
--- a/ui/src/components/ActiveAlertsCounter.tsx
+++ b/ui/src/components/ActiveAlertsCounter.tsx
@@ -66,20 +66,14 @@ const ActiveAlertsCounter = (props) => {
return (
- navigate(getLink(STATUS_CRITICAL))}
- data-cy="critical_counter_node"
- >
+ navigate(getLink(STATUS_CRITICAL))} data-cy="critical_counter_node">
Critical
{criticalCounter}
- navigate(getLink(STATUS_WARNING))}
- data-cy="warning_counter_node"
- >
+ navigate(getLink(STATUS_WARNING))} data-cy="warning_counter_node">
Warning
diff --git a/ui/src/components/ActiveAlertsFilters.spec.tsx b/ui/src/components/ActiveAlertsFilters.spec.tsx
index c2d9c6c658..a559950205 100644
--- a/ui/src/components/ActiveAlertsFilters.spec.tsx
+++ b/ui/src/components/ActiveAlertsFilters.spec.tsx
@@ -27,9 +27,7 @@ describe('ActiveAlertsFilter', () => {
,
);
- await userEvent.click(
- screen.getByRole('textbox', { name: 'Filter by severity' }),
- );
+ await userEvent.click(screen.getByRole('textbox', { name: 'Filter by severity' }));
await userEvent.click(screen.getByRole('option', { name: 'Critical' }));
expect(SUT).toHaveBeenCalledWith(
@@ -38,9 +36,7 @@ describe('ActiveAlertsFilter', () => {
}),
);
- await userEvent.click(
- screen.getByRole('textbox', { name: 'Filter by severity' }),
- );
+ await userEvent.click(screen.getByRole('textbox', { name: 'Filter by severity' }));
await userEvent.click(screen.getByRole('option', { name: 'Warning' }));
expect(SUT).toHaveBeenCalledWith(
expect.objectContaining({
diff --git a/ui/src/components/ActiveAlertsFilters.tsx b/ui/src/components/ActiveAlertsFilters.tsx
index f539e0c16e..cfb35afd0c 100644
--- a/ui/src/components/ActiveAlertsFilters.tsx
+++ b/ui/src/components/ActiveAlertsFilters.tsx
@@ -10,9 +10,7 @@ const ActiveAlertsFilter = () => {
const selectedFilter = query.get('severity') ?? 'all';
const displayOptions = ['all', 'warning', 'critical'];
- const options = defaultOptions.filter((option) =>
- displayOptions.includes(option.value),
- );
+ const options = defaultOptions.filter((option) => displayOptions.includes(option.value));
return (
{
};
const WATCHDOG_ALERT = {
id: 'fc30b79dbdb0a043',
- summary:
- 'An alert that should always be firing to certify that Alertmanager is working properly.',
+ summary: 'An alert that should always be firing to certify that Alertmanager is working properly.',
description:
'This is an alert meant to ensure that the entire alerting pipeline is functional.\nThis alert is always firing, therefore it should always be firing in Alertmanager\nand always fire against a receiver. There are integrations with various notification\nmechanisms that send a notification when this alert is not firing. For example the\n"DeadMansSnitch" integration in PagerDuty.',
startsAt: '2023-08-11T06:02:15.628Z',
@@ -91,8 +90,7 @@ describe('AlertNavbarUpdaterComponent', () => {
expect(publishNotification).toBeCalledWith({
id: 'CriticalNotification',
title: 'Alerts',
- description:
- 'There is 1 critical alert currently firing on the platform.',
+ description: 'There is 1 critical alert currently firing on the platform.',
severity: 'critical',
createdOn: new Date('2023-08-11T06:03:19.730Z'),
redirectUrl: '/platform/alerts',
@@ -177,8 +175,7 @@ describe('AlertNavbarUpdaterComponent', () => {
expect(publishNotification).toBeCalledWith({
id: 'CriticalNotification',
title: 'Alerts',
- description:
- 'There are 1 critical alert and 1 warning alert currently firing on the platform.',
+ description: 'There are 1 critical alert and 1 warning alert currently firing on the platform.',
severity: 'critical',
createdOn: new Date('2023-08-11T06:03:19.730Z'),
redirectUrl: '/platform/alerts',
diff --git a/ui/src/components/AlertNavbarUpdaterComponent.tsx b/ui/src/components/AlertNavbarUpdaterComponent.tsx
index f769548232..7555e1c3b9 100644
--- a/ui/src/components/AlertNavbarUpdaterComponent.tsx
+++ b/ui/src/components/AlertNavbarUpdaterComponent.tsx
@@ -2,11 +2,7 @@ import { useEffect } from 'react';
import AlertProvider, { useAlerts } from '../containers/AlertProvider';
import { Alert } from '../services/alertUtils';
import FederatedIntlProvider from '../containers/IntlProvider';
-import {
- AppConfigProvider,
- AppConfigProviderWithoutRedux,
- useConfig,
-} from '../FederableApp';
+import { AppConfigProvider, AppConfigProviderWithoutRedux, useConfig } from '../FederableApp';
type Notification = {
id: string;
@@ -61,14 +57,10 @@ function publishCriticalNotification(
warningAlerts.length > 0
? `There ${alertsNum > 1 ? 'are' : 'is'} ${
criticalAlerts.length
- } critical alert${criticalAlerts.length > 1 ? 's' : ''} and ${
- warningAlerts.length
- } warning alert${
+ } critical alert${criticalAlerts.length > 1 ? 's' : ''} and ${warningAlerts.length} warning alert${
warningAlerts.length > 1 ? 's' : ''
} currently firing on the platform.`
- : `There ${alertsNum > 1 ? 'are' : 'is'} ${
- criticalAlerts.length
- } critical alert${
+ : `There ${alertsNum > 1 ? 'are' : 'is'} ${criticalAlerts.length} critical alert${
criticalAlerts.length > 1 ? 's' : ''
} currently firing on the platform.`,
severity: 'critical',
@@ -85,9 +77,7 @@ function publishWarningNotification(
publishNotification({
id: WARNING_NOTIFICATION_ID,
title: 'Alerts',
- description: `There ${alertsNum > 1 ? 'are' : 'is'} ${
- warningAlerts.length
- } warning alert${
+ description: `There ${alertsNum > 1 ? 'are' : 'is'} ${warningAlerts.length} warning alert${
warningAlerts.length > 1 ? 's' : ''
} currently firing on the platform.`,
severity: 'warning',
@@ -108,13 +98,9 @@ export const AlertNavbarUpdaterComponentInternal = ({
return new Date(b.startsAt) > new Date(a.startsAt) ? 1 : -1;
});
const { ui_base_path } = useConfig();
- const watchdogAlert = alerts?.find(
- (alert: Alert) => alert.labels.alertname === WATCHDOG_ALERT_NAME,
- );
- const criticalAlerts =
- alerts?.filter((alert: Alert) => alert.severity === 'critical') ?? [];
- const warningAlerts =
- alerts?.filter((alert: Alert) => alert.severity === 'warning') ?? [];
+ const watchdogAlert = alerts?.find((alert: Alert) => alert.labels.alertname === WATCHDOG_ALERT_NAME);
+ const criticalAlerts = alerts?.filter((alert: Alert) => alert.severity === 'critical') ?? [];
+ const warningAlerts = alerts?.filter((alert: Alert) => alert.severity === 'warning') ?? [];
useEffect(() => {
// We have initialData when loading alerts, so we should check if the query is fetching or not.
@@ -150,23 +136,14 @@ export const AlertNavbarUpdaterComponentInternal = ({
if (newlyRaisedAlertNum) {
unPublishNotification(CRITICAL_NOTIFICATION_ID);
}
- publishCriticalNotification(
- publishNotification,
- warningAlerts,
- criticalAlerts,
- ui_base_path,
- );
+ publishCriticalNotification(publishNotification, warningAlerts, criticalAlerts, ui_base_path);
} else if (warningAlerts.length) {
unPublishNotification(WATCHDOG_ALERT_NAME);
unPublishNotification(CRITICAL_NOTIFICATION_ID);
if (newlyRaisedAlertNum) {
unPublishNotification(WARNING_NOTIFICATION_ID);
}
- publishWarningNotification(
- publishNotification,
- warningAlerts,
- ui_base_path,
- );
+ publishWarningNotification(publishNotification, warningAlerts, ui_base_path);
} else {
unPublishNotification(CRITICAL_NOTIFICATION_ID);
unPublishNotification(WARNING_NOTIFICATION_ID);
@@ -174,17 +151,8 @@ export const AlertNavbarUpdaterComponentInternal = ({
}
// Update the alerts Id in the localstorage
- localStorage.setItem(
- LOCAL_STORAGE_ALL_ALERTS_ID,
- `${alerts?.map((alert) => alert.id).join(',')}`,
- );
- }, [
- criticalAlerts.length,
- warningAlerts.length,
- watchdogAlert === undefined,
- status,
- isFetching,
- ]);
+ localStorage.setItem(LOCAL_STORAGE_ALL_ALERTS_ID, `${alerts?.map((alert) => alert.id).join(',')}`);
+ }, [criticalAlerts.length, warningAlerts.length, watchdogAlert === undefined, status, isFetching]);
return <>>;
};
diff --git a/ui/src/components/AlertsTab.tsx b/ui/src/components/AlertsTab.tsx
index 0a9ed0ae7c..cbb6a920fc 100644
--- a/ui/src/components/AlertsTab.tsx
+++ b/ui/src/components/AlertsTab.tsx
@@ -8,13 +8,7 @@ import CircleStatus from './CircleStatus';
import { useIntl } from 'react-intl';
import { NotBoundContainer } from './style/CommonLayoutStyle';
-const AlertsTab = ({
- alerts,
- status,
-}: {
- alerts: Alert[];
- status: 'idle' | 'loading' | 'error' | 'success';
-}) => {
+const AlertsTab = ({ alerts, status }: { alerts: Alert[]; status: 'idle' | 'loading' | 'error' | 'success' }) => {
const query = useURLQuery();
// Retrieve the severity filter from URL.
// Filter more than one severity, the URL should be:
@@ -78,12 +72,7 @@ const AlertsTab = ({
width: 'unset',
},
Cell: ({ value }) => {
- return (
-
- );
+ return ;
},
},
];
@@ -103,10 +92,7 @@ const AlertsTab = ({
},
}}
>
-
+
);
diff --git a/ui/src/components/DashboardAlerts.test.tsx b/ui/src/components/DashboardAlerts.test.tsx
index fca56d9fd1..957ef319a5 100644
--- a/ui/src/components/DashboardAlerts.test.tsx
+++ b/ui/src/components/DashboardAlerts.test.tsx
@@ -90,9 +90,7 @@ describe('the dashboard alerts sub-panel', () => {
(useAlerts as any).mockImplementation(() => ({
alerts: [],
}));
- const { queryByTestId, getByTestId, getByText } = render(
- ,
- );
+ const { queryByTestId, getByTestId, getByText } = render();
expect(getByText('No active alerts')).toBeInTheDocument();
expect(getByTestId('all-alert-badge')).toHaveTextContent('0');
expect(queryByTestId('warning-alert-badge')).not.toBeInTheDocument();
diff --git a/ui/src/components/DashboardAlerts.tsx b/ui/src/components/DashboardAlerts.tsx
index 3e307aa53c..89e1a11c61 100644
--- a/ui/src/components/DashboardAlerts.tsx
+++ b/ui/src/components/DashboardAlerts.tsx
@@ -5,10 +5,7 @@ import { useMemo } from 'react';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
import { useAlertLibrary, useAlerts } from '../containers/AlertProvider';
-import {
- useDiscoveredViews,
- useLinkOpener,
-} from '../containers/ConfigProvider';
+import { useDiscoveredViews, useLinkOpener } from '../containers/ConfigProvider';
import { getChildrenAlerts } from '../services/alertUtils';
import { useBasenameRelativeNavigate } from '@scality/module-federation';
@@ -47,18 +44,11 @@ const DashboardAlerts = () => {
// in MetalK8s dashboard, we want to display the number of the alerts only for metalk8s namespace
const metalk8sAtomicAlerts = useMemo(() => {
if (topLevelAlerts?.alerts?.length && alerts?.alerts?.length)
- return getChildrenAlerts(
- topLevelAlerts.alerts.map((alert) => alert.childrenJsonPath) || [],
- alerts.alerts,
- );
+ return getChildrenAlerts(topLevelAlerts.alerts.map((alert) => alert.childrenJsonPath) || [], alerts.alerts);
else return [];
}, [JSON.stringify(alerts.alerts), JSON.stringify(topLevelAlerts.alerts)]);
- const criticalAlerts = metalk8sAtomicAlerts.filter(
- (alert) => alert.severity === 'critical',
- );
- const warningAlerts = metalk8sAtomicAlerts.filter(
- (alert) => alert.severity === 'warning',
- );
+ const criticalAlerts = metalk8sAtomicAlerts.filter((alert) => alert.severity === 'critical');
+ const warningAlerts = metalk8sAtomicAlerts.filter((alert) => alert.severity === 'warning');
const totalAlerts = criticalAlerts.length + warningAlerts.length;
return (
@@ -68,11 +58,7 @@ const DashboardAlerts = () => {
id: 'platform_active_alerts',
})}
-
+
{totalAlerts === 0 ? (