Alerting: Skip rules that are managed by plugins when importing datasource-managed rules (#103573)
* skip rules that are managed by plugins when importing from data source rules to GMA * update translations * update text * update translations * handle no rules to import * filter out rules instead of groups * Reuse skipped rules alert * update translations keys * fix filter --------- Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
This commit is contained in:
co-authored by
Tom Ratcliffe
parent
04ac3960de
commit
1d5f51e383
+64
-6
@@ -4,7 +4,7 @@ import { ComponentProps } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { Alert, CodeEditor, ConfirmModal, Stack, Text, useStyles2 } from '@grafana/ui';
|
||||
import { Alert, CodeEditor, ConfirmModal, Modal, Stack, Text, useStyles2 } from '@grafana/ui';
|
||||
import { useAppNotification } from 'app/core/copy/appNotification';
|
||||
import { Trans, t } from 'app/core/internationalization';
|
||||
import { stringifyErrorLike } from 'app/features/alerting/unified/utils/misc';
|
||||
@@ -12,6 +12,7 @@ import { RulerRulesConfigDTO } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import { trackImportToGMAError, trackImportToGMASuccess } from '../../Analytics';
|
||||
import { convertToGMAApi } from '../../api/convertToGMAApi';
|
||||
import { GRAFANA_ORIGIN_LABEL } from '../../utils/labels';
|
||||
import { createListFilterLink } from '../../utils/navigation';
|
||||
import { useGetRulerRules } from '../rule-editor/useAlertRuleSuggestions';
|
||||
|
||||
@@ -21,8 +22,22 @@ type ModalProps = Pick<ComponentProps<typeof ConfirmModal>, 'isOpen' | 'onDismis
|
||||
isOpen: boolean;
|
||||
};
|
||||
|
||||
const AlertSomeRulesSkipped = () => (
|
||||
<Alert
|
||||
title={t('alerting.import-to-gma.confirm-modal.plugin-rules-warning.title', 'Some rules are excluded from import')}
|
||||
severity="info"
|
||||
>
|
||||
<Text variant="body">
|
||||
<Trans i18nKey="alerting.import-to-gma.confirm-modal.plugin-rules-warning.text">
|
||||
We have detected that some rules are managed by plugins. These rules will not be imported.
|
||||
</Trans>
|
||||
</Text>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => {
|
||||
const { watch } = useFormContext<ImportFormValues>();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const [
|
||||
targetFolder,
|
||||
@@ -46,7 +61,11 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => {
|
||||
const { rulerRules } = useGetRulerRules(selectedDatasourceName || undefined);
|
||||
const [convert] = convertToGMAApi.useConvertToGMAMutation();
|
||||
const notifyApp = useAppNotification();
|
||||
const rulerRulesToPayload = filterRulerRulesConfig(rulerRules, namespace, ruleGroup);
|
||||
const { filteredConfig: rulerRulesToPayload, someRulesAreSkipped } = filterRulerRulesConfig(
|
||||
rulerRules,
|
||||
namespace,
|
||||
ruleGroup
|
||||
);
|
||||
|
||||
async function onConvertConfirm() {
|
||||
try {
|
||||
@@ -79,6 +98,28 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const noRulesToImport = isEmpty(rulerRulesToPayload);
|
||||
if (noRulesToImport) {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
title={t('alerting.import-to-gma.confirm-modal.no-rules-title', 'No rules to import')}
|
||||
onDismiss={onDismiss}
|
||||
onClickBackdrop={onDismiss}
|
||||
>
|
||||
<Stack direction="column" gap={2}>
|
||||
{someRulesAreSkipped && <AlertSomeRulesSkipped />}
|
||||
<Text>
|
||||
{t(
|
||||
'alerting.import-to-gma.confirm-modal.no-rules-body',
|
||||
'There are no rules to import. Please select a different namespace or rule group.'
|
||||
)}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
// translations for texts in the modal
|
||||
const title = t('alerting.import-to-gma.confirm-modal.title', 'Confirm import');
|
||||
const confirmText = t('alerting.import-to-gma.confirm-modal.confirm', 'Yes, import');
|
||||
@@ -88,6 +129,7 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => {
|
||||
title={title}
|
||||
confirmText={confirmText}
|
||||
confirmButtonVariant="primary"
|
||||
modalClass={styles.modal}
|
||||
body={
|
||||
<Stack direction="column" gap={2}>
|
||||
<Alert title={t('alerting.to-gma.confirm-modal.title-warning', 'Warning')} severity="warning">
|
||||
@@ -98,6 +140,7 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => {
|
||||
</Trans>
|
||||
</Text>
|
||||
</Alert>
|
||||
{someRulesAreSkipped && <AlertSomeRulesSkipped />}
|
||||
<Text variant="h6">
|
||||
<Trans i18nKey="alerting.to-gma.confirm-modal.summary">
|
||||
These are the list of rules that will be imported:
|
||||
@@ -116,8 +159,9 @@ function filterRulerRulesConfig(
|
||||
rulerRulesConfig: RulerRulesConfigDTO,
|
||||
namespace?: string,
|
||||
groupName?: string
|
||||
): RulerRulesConfigDTO {
|
||||
): { filteredConfig: RulerRulesConfigDTO; someRulesAreSkipped: boolean } {
|
||||
const filteredConfig: RulerRulesConfigDTO = {};
|
||||
let someRulesAreSkipped = false;
|
||||
|
||||
Object.entries(rulerRulesConfig).forEach(([ns, groups]) => {
|
||||
if (namespace && ns !== namespace) {
|
||||
@@ -128,7 +172,21 @@ function filterRulerRulesConfig(
|
||||
if (groupName && group.name !== groupName) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
// Filter out rules that have the GRAFANA_ORIGIN_LABEL
|
||||
const filteredRules = group.rules.filter((rule) => {
|
||||
const hasGrafanaOriginLabel = rule.labels?.[GRAFANA_ORIGIN_LABEL];
|
||||
if (hasGrafanaOriginLabel) {
|
||||
someRulesAreSkipped = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return {
|
||||
...group,
|
||||
rules: filteredRules,
|
||||
};
|
||||
});
|
||||
|
||||
if (filteredGroups.length > 0) {
|
||||
@@ -136,7 +194,7 @@ function filterRulerRulesConfig(
|
||||
}
|
||||
});
|
||||
|
||||
return filteredConfig;
|
||||
return { filteredConfig, someRulesAreSkipped };
|
||||
}
|
||||
|
||||
function RulesPreview({ rules }: { rules: RulerRulesConfigDTO }) {
|
||||
@@ -166,6 +224,6 @@ const getStyles = () => ({
|
||||
flex: '1 1 100%',
|
||||
}),
|
||||
modal: css({
|
||||
width: '700px',
|
||||
width: '800px',
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1048,6 +1048,12 @@
|
||||
"alert-rules": "Alert rules",
|
||||
"confirm-modal": {
|
||||
"confirm": "Yes, import",
|
||||
"no-rules-body": "There are no rules to import. Please select a different namespace or rule group.",
|
||||
"no-rules-title": "No rules to import",
|
||||
"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"
|
||||
},
|
||||
"title": "Confirm import"
|
||||
},
|
||||
"datasource": {
|
||||
|
||||
Reference in New Issue
Block a user