diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts index 071aefa3377..51486d9859b 100644 --- a/public/app/features/alerting/unified/state/actions.ts +++ b/public/app/features/alerting/unified/state/actions.ts @@ -402,6 +402,9 @@ export const saveRuleFormAction = createAsyncThunk( const newLocation = `/alerting/${encodeURIComponent(stringifiedIdentifier)}/edit`; if (locationService.getLocation().pathname !== newLocation) { locationService.replace(newLocation); + } else { + // refresh the details of the current editable rule after saving + thunkAPI.dispatch(fetchEditableRuleAction(identifier)); } } })() diff --git a/public/app/features/alerting/unified/utils/rulerClient.ts b/public/app/features/alerting/unified/utils/rulerClient.ts index f8fd8ffab05..0398bd47872 100644 --- a/public/app/features/alerting/unified/utils/rulerClient.ts +++ b/public/app/features/alerting/unified/utils/rulerClient.ts @@ -188,29 +188,23 @@ export function getRulerClient(rulerConfig: RulerDataSourceConfig): RulerClient await setRulerRuleGroup(rulerConfig, namespace, payload); - return { uid: '', ruleSourceName: GRAFANA_RULES_SOURCE_NAME }; + return { uid: newRule.grafana_alert.uid ?? '', ruleSourceName: GRAFANA_RULES_SOURCE_NAME }; }; - // we can't move the rule in a single atomic operation so we have to - // 1. add the rule to the new group - // 2. remove the rule from the old one + // move the rule to another namespace / groupname const moveGrafanaRule = async ( namespace: string, group: { name: string; interval: string }, existingRule: RuleWithLocation, newRule: PostableRuleGrafanaRuleDTO ): Promise => { + // make sure our updated alert has the same UID as before + // that way the rule is automatically moved to the new namespace / group name + copyGrafanaUID(existingRule, newRule); + // add the new rule to the requested namespace and group const identifier = await addRuleToNamespaceAndGroup(namespace, group, newRule); - // remove the rule from the previous namespace and group - await deleteRule({ - ruleSourceName: existingRule.ruleSourceName, - namespace: existingRule.namespace, - group: existingRule.group, - rule: newRule as RulerGrafanaRuleDTO, - }); - return identifier; }; @@ -219,19 +213,13 @@ export function getRulerClient(rulerConfig: RulerDataSourceConfig): RulerClient newRule: PostableRuleGrafanaRuleDTO, interval: string ): Promise => { - // type guard to make sure we're working with a Grafana managed rule - if (!isGrafanaRulerRule(existingRule.rule)) { - throw new Error('The rule is not a Grafana managed rule'); - } - // make sure our updated alert has the same UID as before - const uid = existingRule.rule.grafana_alert.uid; - newRule.grafana_alert.uid = uid; + copyGrafanaUID(existingRule, newRule); // create the new array of rules we want to send to the group const newRules = existingRule.group.rules .filter((rule): rule is RulerGrafanaRuleDTO => isGrafanaRulerRule(rule)) - .filter((rule) => rule.grafana_alert.uid !== uid) + .filter((rule) => rule.grafana_alert.uid !== existingRule.rule.grafana_alert.uid) .concat(newRule as RulerGrafanaRuleDTO); await setRulerRuleGroup(rulerConfig, existingRule.namespace, { @@ -240,7 +228,7 @@ export function getRulerClient(rulerConfig: RulerDataSourceConfig): RulerClient rules: newRules, }); - return { uid: '', ruleSourceName: GRAFANA_RULES_SOURCE_NAME }; + return { uid: existingRule.rule.grafana_alert.uid, ruleSourceName: GRAFANA_RULES_SOURCE_NAME }; }; // Would be nice to somehow align checking of ruler type between different methods @@ -252,3 +240,17 @@ export function getRulerClient(rulerConfig: RulerDataSourceConfig): RulerClient saveGrafanaRule, }; } + +//copy the Grafana rule UID from the old rule to the new rule +function copyGrafanaUID( + oldRule: RuleWithLocation, + newRule: PostableRuleGrafanaRuleDTO +): asserts oldRule is RuleWithLocation { + // type guard to make sure we're working with a Grafana managed rule + if (!isGrafanaRulerRule(oldRule.rule)) { + throw new Error('The rule is not a Grafana managed rule'); + } + + const uid = oldRule.rule.grafana_alert.uid; + newRule.grafana_alert.uid = uid; +} diff --git a/public/app/types/unified-alerting.ts b/public/app/types/unified-alerting.ts index 5c98037378e..09df8ca9589 100644 --- a/public/app/types/unified-alerting.ts +++ b/public/app/types/unified-alerting.ts @@ -97,11 +97,11 @@ export interface CombinedRuleNamespace { groups: CombinedRuleGroup[]; } -export interface RuleWithLocation { +export interface RuleWithLocation { ruleSourceName: string; namespace: string; group: RulerRuleGroupDTO; - rule: RulerRuleDTO; + rule: T; } export interface PromRuleWithLocation {