mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Use time_intervals instead of the deprecated mute_time_intervals in a… (#83147)
* Use time_intervals instead of the deprecated mute_time_intervals in alert manager config * don't send mute_time_intervals in the payload * Add and update tests * Fix usecase when having both fields in response from getting alert manager config * Use mute_timings for grafana data source and both for cloud data source when deleting mute timing * Use mute_timings for grafana data source and both for cloud data source when saving a new or existing alert rule * Address first code review * Address more review comments
This commit is contained in:
parent
90e7791086
commit
ed3c36bb46
@ -1,4 +1,4 @@
|
||||
import { render, waitFor, fireEvent, within } from '@testing-library/react';
|
||||
import { fireEvent, render, waitFor, within } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
@ -10,7 +10,7 @@ import { AccessControlAction } from 'app/types';
|
||||
|
||||
import MuteTimings from './MuteTimings';
|
||||
import { fetchAlertManagerConfig, updateAlertManagerConfig } from './api/alertmanager';
|
||||
import { grantUserPermissions, mockDataSource, MockDataSourceSrv } from './mocks';
|
||||
import { MockDataSourceSrv, grantUserPermissions, mockDataSource } from './mocks';
|
||||
import { DataSourceType } from './utils/datasource';
|
||||
|
||||
jest.mock('./api/alertmanager');
|
||||
@ -71,6 +71,21 @@ const muteTimeInterval: MuteTimeInterval = {
|
||||
},
|
||||
],
|
||||
};
|
||||
const muteTimeInterval2: MuteTimeInterval = {
|
||||
name: 'default-mute2',
|
||||
time_intervals: [
|
||||
{
|
||||
times: [
|
||||
{
|
||||
start_time: '12:00',
|
||||
end_time: '24:00',
|
||||
},
|
||||
],
|
||||
days_of_month: ['15', '-1'],
|
||||
months: ['august:december', 'march'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const defaultConfig: AlertManagerCortexConfig = {
|
||||
alertmanager_config: {
|
||||
@ -90,6 +105,44 @@ const defaultConfig: AlertManagerCortexConfig = {
|
||||
},
|
||||
template_files: {},
|
||||
};
|
||||
const defaultConfigWithNewTimeIntervalsField: AlertManagerCortexConfig = {
|
||||
alertmanager_config: {
|
||||
receivers: [{ name: 'default' }, { name: 'critical' }],
|
||||
route: {
|
||||
receiver: 'default',
|
||||
group_by: ['alertname'],
|
||||
routes: [
|
||||
{
|
||||
matchers: ['env=prod', 'region!=EU'],
|
||||
mute_time_intervals: [muteTimeInterval.name],
|
||||
},
|
||||
],
|
||||
},
|
||||
templates: [],
|
||||
time_intervals: [muteTimeInterval],
|
||||
},
|
||||
template_files: {},
|
||||
};
|
||||
|
||||
const defaultConfigWithBothTimeIntervalsField: AlertManagerCortexConfig = {
|
||||
alertmanager_config: {
|
||||
receivers: [{ name: 'default' }, { name: 'critical' }],
|
||||
route: {
|
||||
receiver: 'default',
|
||||
group_by: ['alertname'],
|
||||
routes: [
|
||||
{
|
||||
matchers: ['env=prod', 'region!=EU'],
|
||||
mute_time_intervals: [muteTimeInterval.name],
|
||||
},
|
||||
],
|
||||
},
|
||||
templates: [],
|
||||
time_intervals: [muteTimeInterval],
|
||||
mute_time_intervals: [muteTimeInterval2],
|
||||
},
|
||||
template_files: {},
|
||||
};
|
||||
|
||||
const resetMocks = () => {
|
||||
jest.resetAllMocks();
|
||||
@ -110,7 +163,7 @@ describe('Mute timings', () => {
|
||||
grantUserPermissions(Object.values(AccessControlAction));
|
||||
});
|
||||
|
||||
it('creates a new mute timing', async () => {
|
||||
it('creates a new mute timing, with mute_time_intervals in config', async () => {
|
||||
renderMuteTimings();
|
||||
|
||||
await waitFor(() => expect(mocks.api.fetchAlertManagerConfig).toHaveBeenCalled());
|
||||
@ -125,10 +178,12 @@ describe('Mute timings', () => {
|
||||
fireEvent.submit(ui.form.get());
|
||||
|
||||
await waitFor(() => expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalled());
|
||||
|
||||
const { mute_time_intervals: _, ...configWithoutMuteTimings } = defaultConfig.alertmanager_config;
|
||||
expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalledWith('grafana', {
|
||||
...defaultConfig,
|
||||
alertmanager_config: {
|
||||
...defaultConfig.alertmanager_config,
|
||||
...configWithoutMuteTimings,
|
||||
mute_time_intervals: [
|
||||
muteTimeInterval,
|
||||
{
|
||||
@ -151,6 +206,102 @@ describe('Mute timings', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a new mute timing, with time_intervals in config', async () => {
|
||||
mocks.api.fetchAlertManagerConfig.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
...defaultConfigWithNewTimeIntervalsField,
|
||||
});
|
||||
});
|
||||
renderMuteTimings();
|
||||
|
||||
await waitFor(() => expect(mocks.api.fetchAlertManagerConfig).toHaveBeenCalled());
|
||||
expect(ui.nameField.get()).toBeInTheDocument();
|
||||
|
||||
await userEvent.type(ui.nameField.get(), 'maintenance period');
|
||||
await userEvent.type(ui.startsAt.get(), '22:00');
|
||||
await userEvent.type(ui.endsAt.get(), '24:00');
|
||||
await userEvent.type(ui.days.get(), '-1');
|
||||
await userEvent.type(ui.months.get(), 'january, july');
|
||||
|
||||
fireEvent.submit(ui.form.get());
|
||||
|
||||
await waitFor(() => expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalled());
|
||||
|
||||
const { mute_time_intervals: _, ...configWithoutMuteTimings } = defaultConfig.alertmanager_config;
|
||||
expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalledWith('grafana', {
|
||||
...defaultConfig,
|
||||
alertmanager_config: {
|
||||
...configWithoutMuteTimings,
|
||||
mute_time_intervals: [
|
||||
muteTimeInterval,
|
||||
{
|
||||
name: 'maintenance period',
|
||||
time_intervals: [
|
||||
{
|
||||
days_of_month: ['-1'],
|
||||
months: ['january', 'july'],
|
||||
times: [
|
||||
{
|
||||
start_time: '22:00',
|
||||
end_time: '24:00',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
it('creates a new mute timing, with time_intervals and mute_time_intervals in config', async () => {
|
||||
mocks.api.fetchAlertManagerConfig.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
...defaultConfigWithBothTimeIntervalsField,
|
||||
});
|
||||
});
|
||||
renderMuteTimings();
|
||||
|
||||
await waitFor(() => expect(mocks.api.fetchAlertManagerConfig).toHaveBeenCalled());
|
||||
expect(ui.nameField.get()).toBeInTheDocument();
|
||||
|
||||
await userEvent.type(ui.nameField.get(), 'maintenance period');
|
||||
await userEvent.type(ui.startsAt.get(), '22:00');
|
||||
await userEvent.type(ui.endsAt.get(), '24:00');
|
||||
await userEvent.type(ui.days.get(), '-1');
|
||||
await userEvent.type(ui.months.get(), 'january, july');
|
||||
|
||||
fireEvent.submit(ui.form.get());
|
||||
|
||||
await waitFor(() => expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalled());
|
||||
|
||||
const { mute_time_intervals, time_intervals, ...configWithoutMuteTimings } = defaultConfig.alertmanager_config;
|
||||
expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalledWith('grafana', {
|
||||
...defaultConfig,
|
||||
alertmanager_config: {
|
||||
...configWithoutMuteTimings,
|
||||
mute_time_intervals: [
|
||||
muteTimeInterval,
|
||||
muteTimeInterval2,
|
||||
{
|
||||
name: 'maintenance period',
|
||||
time_intervals: [
|
||||
{
|
||||
days_of_month: ['-1'],
|
||||
months: ['january', 'july'],
|
||||
times: [
|
||||
{
|
||||
start_time: '22:00',
|
||||
end_time: '24:00',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('prepopulates the form when editing a mute timing', async () => {
|
||||
renderMuteTimings('/alerting/routes/mute-timing/edit' + `?muteName=${encodeURIComponent(muteTimeInterval.name)}`);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Route, Redirect, Switch, useRouteMatch } from 'react-router-dom';
|
||||
import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { Alert } from '@grafana/ui';
|
||||
@ -21,8 +21,9 @@ const MuteTimings = () => {
|
||||
const config = currentData?.alertmanager_config;
|
||||
|
||||
const getMuteTimingByName = useCallback(
|
||||
(id: string): MuteTimeInterval | undefined => {
|
||||
const timing = config?.mute_time_intervals?.find(({ name }: MuteTimeInterval) => name === id);
|
||||
(id: string, fromTimeIntervals: boolean): MuteTimeInterval | undefined => {
|
||||
const time_intervals = fromTimeIntervals ? config?.time_intervals ?? [] : config?.mute_time_intervals ?? [];
|
||||
const timing = time_intervals.find(({ name }: MuteTimeInterval) => name === id);
|
||||
|
||||
if (timing) {
|
||||
const provenance = config?.muteTimeProvenances?.[timing.name];
|
||||
@ -53,13 +54,17 @@ const MuteTimings = () => {
|
||||
<Route exact path="/alerting/routes/mute-timing/edit">
|
||||
{() => {
|
||||
if (queryParams['muteName']) {
|
||||
const muteTiming = getMuteTimingByName(String(queryParams['muteName']));
|
||||
const muteTimingInMuteTimings = getMuteTimingByName(String(queryParams['muteName']), false);
|
||||
const muteTimingInTimeIntervals = getMuteTimingByName(String(queryParams['muteName']), true);
|
||||
const inTimeIntervals = Boolean(muteTimingInTimeIntervals);
|
||||
const muteTiming = inTimeIntervals ? muteTimingInTimeIntervals : muteTimingInMuteTimings;
|
||||
const provenance = muteTiming?.provenance;
|
||||
|
||||
return (
|
||||
<MuteTimingForm
|
||||
loading={isLoading}
|
||||
muteTiming={muteTiming}
|
||||
fromLegacyTimeInterval={muteTimingInMuteTimings}
|
||||
fromTimeIntervals={muteTimingInTimeIntervals}
|
||||
showError={!muteTiming && !isLoading}
|
||||
provenance={provenance}
|
||||
/>
|
||||
|
@ -15,6 +15,7 @@ import { useGetContactPointsState } from './api/receiversApi';
|
||||
import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { MuteTimingsTable } from './components/mute-timings/MuteTimingsTable';
|
||||
import { mergeTimeIntervals } from './components/mute-timings/util';
|
||||
import {
|
||||
NotificationPoliciesFilter,
|
||||
findRoutesByMatchers,
|
||||
@ -191,8 +192,9 @@ const AmRoutes = () => {
|
||||
if (!selectedAlertmanager) {
|
||||
return null;
|
||||
}
|
||||
const time_intervals = result?.alertmanager_config ? mergeTimeIntervals(result?.alertmanager_config) : [];
|
||||
|
||||
const numberOfMuteTimings = result?.alertmanager_config.mute_time_intervals?.length ?? 0;
|
||||
const numberOfMuteTimings = time_intervals.length;
|
||||
const haveData = result && !resultError && !resultLoading;
|
||||
const isFetching = !result && resultLoading;
|
||||
const haveError = resultError && !resultLoading;
|
||||
|
@ -12,6 +12,7 @@ import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { updateAlertManagerConfigAction } from '../../state/actions';
|
||||
import { MuteTimingFields } from '../../types/mute-timing-form';
|
||||
import { renameMuteTimings } from '../../utils/alertmanager';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { makeAMLink } from '../../utils/misc';
|
||||
import { createMuteTiming, defaultTimeInterval } from '../../utils/mute-timings';
|
||||
import { ProvisionedResource, ProvisioningAlert } from '../Provisioning';
|
||||
@ -19,7 +20,8 @@ import { ProvisionedResource, ProvisioningAlert } from '../Provisioning';
|
||||
import { MuteTimingTimeInterval } from './MuteTimingTimeInterval';
|
||||
|
||||
interface Props {
|
||||
muteTiming?: MuteTimeInterval;
|
||||
fromLegacyTimeInterval?: MuteTimeInterval; // mute time interval when comes from the old config , mute_time_intervals
|
||||
fromTimeIntervals?: MuteTimeInterval; // mute time interval when comes from the new config , time_intervals. These two fields are mutually exclusive
|
||||
showError?: boolean;
|
||||
provenance?: string;
|
||||
loading?: boolean;
|
||||
@ -50,7 +52,26 @@ const useDefaultValues = (muteTiming?: MuteTimeInterval): MuteTimingFields => {
|
||||
};
|
||||
};
|
||||
|
||||
const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) => {
|
||||
const replaceMuteTiming = (
|
||||
originalTimings: MuteTimeInterval[],
|
||||
existingTiming: MuteTimeInterval | undefined,
|
||||
newTiming: MuteTimeInterval,
|
||||
addNew: boolean
|
||||
) => {
|
||||
// we only add new timing if addNew is true. Otherwise, we just remove the existing timing
|
||||
const originalTimingsWithoutNew = existingTiming
|
||||
? originalTimings?.filter(({ name }) => name !== existingTiming.name)
|
||||
: originalTimings;
|
||||
return addNew ? [...originalTimingsWithoutNew, newTiming] : [...originalTimingsWithoutNew];
|
||||
};
|
||||
|
||||
const MuteTimingForm = ({
|
||||
fromLegacyTimeInterval: fromMuteTimings,
|
||||
fromTimeIntervals,
|
||||
showError,
|
||||
loading,
|
||||
provenance,
|
||||
}: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const styles = useStyles2(getStyles);
|
||||
@ -60,6 +81,12 @@ const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) =
|
||||
const { currentData: result } = useAlertmanagerConfig(selectedAlertmanager);
|
||||
const config = result?.alertmanager_config;
|
||||
|
||||
const fromIntervals = Boolean(fromTimeIntervals);
|
||||
const muteTiming = fromIntervals ? fromTimeIntervals : fromMuteTimings;
|
||||
|
||||
const originalMuteTimings = config?.mute_time_intervals ?? [];
|
||||
const originalTimeIntervals = config?.time_intervals ?? [];
|
||||
|
||||
const defaultValues = useDefaultValues(muteTiming);
|
||||
const formApi = useForm({ defaultValues });
|
||||
|
||||
@ -70,19 +97,44 @@ const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) =
|
||||
|
||||
const newMuteTiming = createMuteTiming(values);
|
||||
|
||||
const muteTimings = muteTiming
|
||||
? config?.mute_time_intervals?.filter(({ name }) => name !== muteTiming.name)
|
||||
: config?.mute_time_intervals;
|
||||
const isGrafanaDataSource = selectedAlertmanager === GRAFANA_RULES_SOURCE_NAME;
|
||||
const isNewMuteTiming = fromTimeIntervals === undefined && fromMuteTimings === undefined;
|
||||
|
||||
// If is Grafana data source, we wil save mute timings in the alertmanager_config.mute_time_intervals
|
||||
// Otherwise, we will save it on alertmanager_config.time_intervals or alertmanager_config.mute_time_intervals depending on the original config
|
||||
|
||||
const newMutetimeIntervals = isGrafanaDataSource
|
||||
? {
|
||||
// for Grafana data source, we will save mute timings in the alertmanager_config.mute_time_intervals
|
||||
mute_time_intervals: [
|
||||
...replaceMuteTiming(originalTimeIntervals, fromTimeIntervals, newMuteTiming, false),
|
||||
...replaceMuteTiming(originalMuteTimings, fromMuteTimings, newMuteTiming, true),
|
||||
],
|
||||
}
|
||||
: {
|
||||
// for non-Grafana data source, we will save mute timings in the alertmanager_config.time_intervals or alertmanager_config.mute_time_intervals depending on the original config
|
||||
time_intervals: replaceMuteTiming(
|
||||
originalTimeIntervals,
|
||||
fromTimeIntervals,
|
||||
newMuteTiming,
|
||||
Boolean(fromTimeIntervals) || isNewMuteTiming
|
||||
),
|
||||
mute_time_intervals:
|
||||
Boolean(fromMuteTimings) && !isNewMuteTiming
|
||||
? replaceMuteTiming(originalMuteTimings, fromMuteTimings, newMuteTiming, true)
|
||||
: undefined,
|
||||
};
|
||||
|
||||
const { mute_time_intervals: _, time_intervals: __, ...configWithoutMuteTimings } = config ?? {};
|
||||
const newConfig: AlertManagerCortexConfig = {
|
||||
...result,
|
||||
alertmanager_config: {
|
||||
...config,
|
||||
...configWithoutMuteTimings,
|
||||
route:
|
||||
muteTiming && newMuteTiming.name !== muteTiming.name
|
||||
? renameMuteTimings(newMuteTiming.name, muteTiming.name, config?.route ?? {})
|
||||
: config?.route,
|
||||
mute_time_intervals: [...(muteTimings || []), newMuteTiming],
|
||||
...newMutetimeIntervals,
|
||||
},
|
||||
};
|
||||
|
||||
@ -123,13 +175,8 @@ const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) =
|
||||
<Input
|
||||
{...formApi.register('name', {
|
||||
required: true,
|
||||
validate: (value) => {
|
||||
if (!muteTiming) {
|
||||
const existingMuteTiming = config?.mute_time_intervals?.find(({ name }) => value === name);
|
||||
return existingMuteTiming ? `Mute timing already exists for "${value}"` : true;
|
||||
}
|
||||
return;
|
||||
},
|
||||
validate: (value) =>
|
||||
validateMuteTiming(value, muteTiming, originalMuteTimings, originalTimeIntervals),
|
||||
})}
|
||||
className={styles.input}
|
||||
data-testid={'mute-timing-name'}
|
||||
@ -156,6 +203,22 @@ const MuteTimingForm = ({ muteTiming, showError, loading, provenance }: Props) =
|
||||
);
|
||||
};
|
||||
|
||||
function validateMuteTiming(
|
||||
value: string,
|
||||
muteTiming: MuteTimeInterval | undefined,
|
||||
originalMuteTimings: MuteTimeInterval[],
|
||||
originalTimeIntervals: MuteTimeInterval[]
|
||||
) {
|
||||
if (!muteTiming) {
|
||||
const existingMuteTimingInMuteTimings = originalMuteTimings?.find(({ name }) => value === name);
|
||||
const existingMuteTimingInTimeIntervals = originalTimeIntervals?.find(({ name }) => value === name);
|
||||
return existingMuteTimingInMuteTimings || existingMuteTimingInTimeIntervals
|
||||
? `Mute timing already exists for "${value}"`
|
||||
: true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
input: css`
|
||||
width: 400px;
|
||||
|
@ -18,7 +18,7 @@ import { ProvisioningBadge } from '../Provisioning';
|
||||
import { Spacer } from '../Spacer';
|
||||
import { GrafanaMuteTimingsExporter } from '../export/GrafanaMuteTimingsExporter';
|
||||
|
||||
import { renderTimeIntervals } from './util';
|
||||
import { mergeTimeIntervals, renderTimeIntervals } from './util';
|
||||
|
||||
const ALL_MUTE_TIMINGS = Symbol('all mute timings');
|
||||
|
||||
@ -72,9 +72,9 @@ export const MuteTimingsTable = ({ alertManagerSourceName, muteTimingNames, hide
|
||||
const config = currentData?.alertmanager_config;
|
||||
|
||||
const [muteTimingName, setMuteTimingName] = useState<string>('');
|
||||
|
||||
const items = useMemo((): Array<DynamicTableItemProps<MuteTimeInterval>> => {
|
||||
const muteTimings = config?.mute_time_intervals ?? [];
|
||||
// merge both fields mute_time_intervals and time_intervals to support both old and new config
|
||||
const muteTimings = config ? mergeTimeIntervals(config) : [];
|
||||
const muteTimingsProvenances = config?.muteTimeProvenances ?? {};
|
||||
|
||||
return muteTimings
|
||||
@ -88,7 +88,7 @@ export const MuteTimingsTable = ({ alertManagerSourceName, muteTimingNames, hide
|
||||
},
|
||||
};
|
||||
});
|
||||
}, [config?.mute_time_intervals, config?.muteTimeProvenances, muteTimingNames]);
|
||||
}, [muteTimingNames, config]);
|
||||
|
||||
const [_, allowedToCreateMuteTiming] = useAlertmanagerAbility(AlertmanagerAction.CreateMuteTiming);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
|
||||
import { MuteTimeInterval } from 'app/plugins/datasource/alertmanager/types';
|
||||
import { AlertmanagerConfig, MuteTimeInterval } from 'app/plugins/datasource/alertmanager/types';
|
||||
|
||||
import {
|
||||
getDaysOfMonthString,
|
||||
@ -18,6 +18,12 @@ const isvalidTimeFormat = (timeString: string): boolean => {
|
||||
return timeString ? TIME_RANGE_REGEX.test(timeString) : true;
|
||||
};
|
||||
|
||||
// merge both fields mute_time_intervals and time_intervals to support both old and new config
|
||||
export const mergeTimeIntervals = (alertManagerConfig: AlertmanagerConfig) => {
|
||||
return [...(alertManagerConfig.mute_time_intervals ?? []), ...(alertManagerConfig.time_intervals ?? [])];
|
||||
};
|
||||
|
||||
// Usage
|
||||
const isValidStartAndEndTime = (startTime?: string, endTime?: string): boolean => {
|
||||
// empty time range is perfactly valid for a mute timing
|
||||
if (!startTime && !endTime) {
|
||||
@ -67,4 +73,4 @@ function renderTimeIntervals(muteTiming: MuteTimeInterval) {
|
||||
});
|
||||
}
|
||||
|
||||
export { isvalidTimeFormat, isValidStartAndEndTime, renderTimeIntervals };
|
||||
export { isValidStartAndEndTime, isvalidTimeFormat, renderTimeIntervals };
|
||||
|
@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
import { mergeTimeIntervals } from '../components/mute-timings/util';
|
||||
import { useAlertmanager } from '../state/AlertmanagerContext';
|
||||
import { timeIntervalToString } from '../utils/alertmanager';
|
||||
|
||||
@ -13,8 +14,9 @@ export function useMuteTimingOptions(): Array<SelectableValue<string>> {
|
||||
const config = currentData?.alertmanager_config;
|
||||
|
||||
return useMemo(() => {
|
||||
const time_intervals = config ? mergeTimeIntervals(config) : [];
|
||||
const muteTimingsOptions: Array<SelectableValue<string>> =
|
||||
config?.mute_time_intervals?.map((value) => ({
|
||||
time_intervals?.map((value) => ({
|
||||
value: value.name,
|
||||
label: value.name,
|
||||
description: value.time_intervals.map((interval) => timeIntervalToString(interval)).join(', AND '),
|
||||
|
@ -693,10 +693,24 @@ export const deleteMuteTimingAction = (alertManagerSourceName: string, muteTimin
|
||||
alertmanagerApi.endpoints.getAlertmanagerConfiguration.initiate(alertManagerSourceName)
|
||||
).unwrap();
|
||||
|
||||
const muteIntervals =
|
||||
config?.alertmanager_config?.mute_time_intervals?.filter(({ name }) => name !== muteTimingName) ?? [];
|
||||
const isGrafanaDatasource = alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME;
|
||||
|
||||
const muteIntervalsFiltered =
|
||||
(config?.alertmanager_config?.mute_time_intervals ?? [])?.filter(({ name }) => name !== muteTimingName) ?? [];
|
||||
const timeIntervalsFiltered =
|
||||
(config?.alertmanager_config?.time_intervals ?? [])?.filter(({ name }) => name !== muteTimingName) ?? [];
|
||||
|
||||
const time_intervals_without_mute_to_save = isGrafanaDatasource
|
||||
? {
|
||||
mute_time_intervals: [...muteIntervalsFiltered, ...timeIntervalsFiltered],
|
||||
}
|
||||
: {
|
||||
time_intervals: timeIntervalsFiltered,
|
||||
mute_time_intervals: muteIntervalsFiltered,
|
||||
};
|
||||
|
||||
if (config) {
|
||||
const { mute_time_intervals: _, ...configWithoutMuteTimings } = config?.alertmanager_config ?? {};
|
||||
withAppEvents(
|
||||
dispatch(
|
||||
updateAlertManagerConfigAction({
|
||||
@ -705,11 +719,11 @@ export const deleteMuteTimingAction = (alertManagerSourceName: string, muteTimin
|
||||
newConfig: {
|
||||
...config,
|
||||
alertmanager_config: {
|
||||
...config.alertmanager_config,
|
||||
...configWithoutMuteTimings,
|
||||
route: config.alertmanager_config.route
|
||||
? removeMuteTimingFromRoute(muteTimingName, config.alertmanager_config?.route)
|
||||
: undefined,
|
||||
mute_time_intervals: muteIntervals,
|
||||
...time_intervals_without_mute_to_save,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -157,6 +157,7 @@ export type AlertmanagerConfig = {
|
||||
inhibit_rules?: InhibitRule[];
|
||||
receivers?: Receiver[];
|
||||
mute_time_intervals?: MuteTimeInterval[];
|
||||
time_intervals?: MuteTimeInterval[];
|
||||
/** { [name]: provenance } */
|
||||
muteTimeProvenances?: Record<string, string>;
|
||||
last_applied?: boolean;
|
||||
|
Loading…
Reference in New Issue
Block a user