From 18b0eec0a3499c910e618f5efec7aceab5102ef2 Mon Sep 17 00:00:00 2001
From: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com>
Date: Fri, 13 Jun 2025 17:21:47 +0200
Subject: [PATCH] Alerting: Filter out rules managed by integrations and add an
info alert (#106602)
* Filter out rules managed by integrations and add an info alert
* address review comments
---
.../ConfirmConvertModal.test.tsx | 9 +++-
.../import-to-gma/ConfirmConvertModal.tsx | 42 +++++++++++++++----
public/locales/en-US/grafana.json | 4 ++
3 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.test.tsx b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.test.tsx
index 1b3ff9d002e..2fe703a1347 100644
--- a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.test.tsx
+++ b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.test.tsx
@@ -43,6 +43,13 @@ describe('filterRulerRulesConfig', () => {
namespace: 'synthetic_monitoring',
},
},
+ {
+ alert: 'Alert7',
+ expr: 'test == 0',
+ labels: {
+ namespace: 'integrations-test',
+ },
+ },
],
},
],
@@ -196,7 +203,7 @@ describe('filterRulerRulesConfig', () => {
expect(someRulesAreSkipped).toBe(false);
});
- it('should filter out synthetics rules', () => {
+ it('should filter out synthetics rules and rules from integrations', () => {
const { filteredConfig, someRulesAreSkipped } = filterRulerRulesConfig(mockRulesConfig);
expect(filteredConfig).toEqual({
diff --git a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx
index 2aaf5797653..4f2c364859a 100644
--- a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx
+++ b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx
@@ -49,6 +49,24 @@ const AlertSomeRulesSkipped = () => {
);
};
+const WarningForImportingRulesManagedByIntegrations = () => {
+ return (
+
+
+
+ Rules managed by integrations or plugins should not be imported to Grafana-managed rules.
+
+
+
+ );
+};
+
const emptyObject = {};
export const ConfirmConversionModal = ({ importPayload, isOpen, onDismiss }: ModalProps) => {
@@ -217,6 +235,7 @@ export const ConfirmConversionModal = ({ importPayload, isOpen, onDismiss }: Mod
{!isEmpty(rulesThatMightBeOverwritten) && (
)}
+
{someRulesAreSkipped && }
The following alert rules will be imported:
@@ -232,8 +251,7 @@ export const ConfirmConversionModal = ({ importPayload, isOpen, onDismiss }: Mod
/**
* Filter the ruler rules config to be imported. It filters the rules by namespace and group name.
- * It also filters out the rules that have the '__grafana_origin' label, and rules from synthetics that have the
- * 'namespace: synthetic_monitoring' label.
+ * It also filters out the rules that are managed by integrations or plugins.
* Precondition: these rules are cloud rules.
* @param rulerRulesConfig - The ruler rules config to be imported
* @param namespace - The namespace to filter the rules by
@@ -262,7 +280,7 @@ export function filterRulerRulesConfig(
})
.map((group) => {
const filteredRules = group.rules.filter((rule) => {
- const shouldSkip = shouldSkipRule(rule);
+ const shouldSkip = isRuleManagedByExternalSystem(rule);
if (shouldSkip) {
someRulesAreSkipped = true;
return false;
@@ -286,18 +304,25 @@ export function filterRulerRulesConfig(
}
/*
-This function is used to check if the rule should be skipped.
+This function is used to check if the rule is managed by external system.
It checks if the rule has the '__grafana_origin' label, and if the rule is from synthetics.
-If the rule has the '__grafana_origin' label, it is skipped.
-If the rule is from synthetics, it is skipped.
+These are the conditions for a rule to be managed by external system:
+- If the rule has the '__grafana_origin' label
+- If the rule is from synthetics
+- If the rule is from integrations
*/
-function shouldSkipRule(rule: RulerRuleDTO): boolean {
+function isRuleManagedByExternalSystem(rule: RulerRuleDTO): boolean {
// check if the rule has the '__grafana_origin' label
const hasGrafanaOriginLabel = isPluginProvidedRule(rule);
if (hasGrafanaOriginLabel) {
return true;
}
- // check if the rule is from synthetics
+ // check if the rule is from intergrations by checking if the namespace starts with 'integrations-'
+ const isIntegration = rule.labels?.namespace?.startsWith('integrations-');
+ if (isIntegration) {
+ return true;
+ }
+ // check if the rule is from synthetics by checking if the namespace is 'synthetic_monitoring'
const hasSyntheticsLabels = rule.labels?.namespace === 'synthetic_monitoring';
if (!hasSyntheticsLabels) {
@@ -342,7 +367,6 @@ const getStyles = () => ({
function TargetFolderNotEmptyWarning({ targetFolderRules }: { targetFolderRules: RulerRulesConfigDTO }) {
const [showTargetRules, toggleShowTargetRules] = useToggle(false);
-
return (
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 26438629429..09cbbc4dbf6 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -1528,6 +1528,10 @@
"no-rules-body": "There are no rules to import. Please select a different namespace or rule group.",
"no-rules-body-yaml": "There are no rules to import. Please select a different yaml file.",
"no-rules-title": "No rules to import",
+ "not-using-rules-managed-by-integrations-or-plugins": {
+ "text": "Rules managed by integrations or plugins should not be imported to Grafana-managed rules.",
+ "title": "Information"
+ },
"plugin-rules-warning": {
"text": "We have detected that some rules are managed by plugins. These rules will not be imported.",
"title": "Some rules are excluded from import"