mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Fix deleting rules when silencing/resuming rule from a panel alert tab (#87710)
* Fix deleting rules when silencing/resuming rule from a panel alert tab * fix test and return early when no group target is found * address pr review comment
This commit is contained in:
parent
194039c429
commit
6b1a662f6b
@ -36,21 +36,23 @@ import * as analytics from './Analytics';
|
||||
import RuleList from './RuleList';
|
||||
import { discoverFeatures } from './api/buildInfo';
|
||||
import { fetchRules } from './api/prometheus';
|
||||
import * as apiRuler from './api/ruler';
|
||||
import { deleteNamespace, deleteRulerRulesGroup, fetchRulerRules, setRulerRuleGroup } from './api/ruler';
|
||||
import {
|
||||
MockDataSourceSrv,
|
||||
getPotentiallyPausedRulerRules,
|
||||
grantUserPermissions,
|
||||
mockDataSource,
|
||||
mockFolder,
|
||||
mockPromAlert,
|
||||
mockPromAlertingRule,
|
||||
mockPromRecordingRule,
|
||||
mockPromRuleGroup,
|
||||
mockPromRuleNamespace,
|
||||
mockRulerGrafanaRule,
|
||||
pausedPromRules,
|
||||
getPotentiallyPausedRulerRules,
|
||||
somePromRules,
|
||||
someRulerRules,
|
||||
mockFolder,
|
||||
} from './mocks';
|
||||
import * as config from './utils/config';
|
||||
import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
@ -79,6 +81,7 @@ jest.mock('app/core/core', () => ({
|
||||
jest.spyOn(analytics, 'logInfo');
|
||||
jest.spyOn(config, 'getAllDataSources');
|
||||
jest.spyOn(actions, 'rulesInSameGroupHaveInvalidFor').mockReturnValue([]);
|
||||
jest.spyOn(apiRuler, 'rulerUrlBuilder');
|
||||
|
||||
const mocks = {
|
||||
getAllDataSourcesMock: jest.mocked(config.getAllDataSources),
|
||||
@ -93,6 +96,7 @@ const mocks = {
|
||||
deleteGroup: jest.mocked(deleteRulerRulesGroup),
|
||||
deleteNamespace: jest.mocked(deleteNamespace),
|
||||
setRulerRuleGroup: jest.mocked(setRulerRuleGroup),
|
||||
rulerBuilderMock: jest.mocked(apiRuler.rulerUrlBuilder),
|
||||
},
|
||||
};
|
||||
|
||||
@ -187,6 +191,11 @@ const configureMockServer = () => {
|
||||
message: 'rule group updated successfully',
|
||||
updated: ['foo', 'bar', 'baz'],
|
||||
});
|
||||
mockAlertRuleApi(server).rulerRuleGroup(GRAFANA_RULES_SOURCE_NAME, 'NAMESPACE_UID', 'groupPaused', {
|
||||
name: 'group-1',
|
||||
interval: '1m',
|
||||
rules: [mockRulerGrafanaRule()],
|
||||
});
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
@ -634,6 +643,13 @@ describe('RuleList', () => {
|
||||
mocks.api.fetchRules.mockImplementation((sourceName) =>
|
||||
Promise.resolve(sourceName === 'grafana' ? pausedPromRules('grafana') : [])
|
||||
);
|
||||
mocks.api.rulerBuilderMock.mockReturnValue({
|
||||
rules: () => ({ path: `api/ruler/${GRAFANA_RULES_SOURCE_NAME}/api/v1/rules` }),
|
||||
namespace: () => ({ path: 'ruler' }),
|
||||
namespaceGroup: () => ({
|
||||
path: `api/ruler/${GRAFANA_RULES_SOURCE_NAME}/api/v1/rules/NAMESPACE_UID/groupPaused`,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('resuming paused alert rule', async () => {
|
||||
|
@ -2,10 +2,13 @@ import { produce } from 'immer';
|
||||
import React from 'react';
|
||||
|
||||
import { Menu } from '@grafana/ui';
|
||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||
import { alertRuleApi } from 'app/features/alerting/unified/api/alertRuleApi';
|
||||
import { isGrafanaRulerRule, isGrafanaRulerRulePaused } from 'app/features/alerting/unified/utils/rules';
|
||||
import { CombinedRule } from 'app/types/unified-alerting';
|
||||
|
||||
import { grafanaRulerConfig } from '../hooks/useCombinedRule';
|
||||
|
||||
interface Props {
|
||||
rule: CombinedRule;
|
||||
/**
|
||||
@ -19,7 +22,11 @@ interface Props {
|
||||
* and triggering API call to do so
|
||||
*/
|
||||
const MenuItemPauseRule = ({ rule, onPauseChange }: Props) => {
|
||||
const { group } = rule;
|
||||
// we need to fetch the group again, as maybe the group has been filtered
|
||||
const [getGroup] = alertRuleApi.endpoints.rulerRuleGroup.useLazyQuery();
|
||||
const notifyApp = useAppNotification();
|
||||
|
||||
// Add any dependencies here
|
||||
const [updateRule] = alertRuleApi.endpoints.updateRule.useMutation();
|
||||
const isPaused = isGrafanaRulerRule(rule.rulerRule) && isGrafanaRulerRulePaused(rule.rulerRule);
|
||||
const icon = isPaused ? 'play' : 'pause';
|
||||
@ -33,21 +40,32 @@ const MenuItemPauseRule = ({ rule, onPauseChange }: Props) => {
|
||||
return;
|
||||
}
|
||||
const ruleUid = rule.rulerRule.grafana_alert.uid;
|
||||
const targetGroup = await getGroup({
|
||||
rulerConfig: grafanaRulerConfig,
|
||||
namespace: rule.namespace.uid || rule.rulerRule.grafana_alert.namespace_uid,
|
||||
group: rule.group.name,
|
||||
}).unwrap();
|
||||
|
||||
// Parse the rules into correct format for API
|
||||
const modifiedRules = group.rules.map((groupRule) => {
|
||||
if (!(isGrafanaRulerRule(groupRule.rulerRule) && groupRule.rulerRule.grafana_alert.uid === ruleUid)) {
|
||||
return groupRule.rulerRule!;
|
||||
if (!targetGroup) {
|
||||
notifyApp.error(
|
||||
`Failed to ${newIsPaused ? 'pause' : 'resume'} the rule. Could not get the target group to update the rule.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return produce(groupRule.rulerRule, (updatedGroupRule) => {
|
||||
// Parse the rules into correct format for API
|
||||
const modifiedRules = targetGroup.rules.map((groupRule) => {
|
||||
if (!(isGrafanaRulerRule(groupRule) && groupRule.grafana_alert.uid === ruleUid)) {
|
||||
return groupRule;
|
||||
}
|
||||
return produce(groupRule, (updatedGroupRule) => {
|
||||
updatedGroupRule.grafana_alert.is_paused = newIsPaused;
|
||||
});
|
||||
});
|
||||
|
||||
const payload = {
|
||||
interval: group.interval!,
|
||||
name: group.name,
|
||||
interval: targetGroup.interval!,
|
||||
name: targetGroup.name,
|
||||
rules: modifiedRules,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user