mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 20:59:35 +08:00
Alerting: Allow disabling recording rules write for a data source in the UI (#106664)
Adds a new "Allow as recording rules target" toggle to Prometheus datasource configuration that controls whether the datasource can be selected as a target for writing recording rules. --------- Co-authored-by: ismail simsek <ismailsimsek09@gmail.com> Co-authored-by: Konrad Lalik <konradlalik@gmail.com>
This commit is contained in:

committed by
GitHub

parent
6cb2c701e6
commit
f6e330b3d7
@ -25,7 +25,11 @@ import { NestedFolderPicker } from 'app/core/components/NestedFolderPicker/Neste
|
||||
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
|
||||
|
||||
import { Folder } from '../../types/rule-form';
|
||||
import { DataSourceType } from '../../utils/datasource';
|
||||
import {
|
||||
DataSourceType,
|
||||
isSupportedExternalPrometheusFlavoredRulesSourceType,
|
||||
isValidRecordingRulesTarget,
|
||||
} from '../../utils/datasource';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
@ -319,11 +323,11 @@ function YamlTargetDataSourceField() {
|
||||
noDefault
|
||||
inputId="yaml-target-data-source"
|
||||
alerting
|
||||
filter={(ds: DataSourceInstanceSettings) => ds.type === 'prometheus'}
|
||||
filter={(ds: DataSourceInstanceSettings) => isSupportedExternalPrometheusFlavoredRulesSourceType(ds.type)}
|
||||
onChange={(ds: DataSourceInstanceSettings) => {
|
||||
setValue('yamlImportTargetDatasourceUID', ds.uid);
|
||||
const recordingRulesTargetDs = getValues('targetDatasourceUID');
|
||||
if (!recordingRulesTargetDs) {
|
||||
if (!recordingRulesTargetDs && isValidRecordingRulesTarget(ds)) {
|
||||
setValue('targetDatasourceUID', ds.uid);
|
||||
}
|
||||
}}
|
||||
@ -367,7 +371,7 @@ function TargetDataSourceForRecordingRulesField() {
|
||||
current={field.value}
|
||||
inputId="recording-rules-target-data-source"
|
||||
noDefault
|
||||
filter={(ds: DataSourceInstanceSettings) => ds.type === 'prometheus'}
|
||||
filter={isValidRecordingRulesTarget}
|
||||
onChange={(ds: DataSourceInstanceSettings) => {
|
||||
setValue('targetDatasourceUID', ds.uid);
|
||||
}}
|
||||
@ -479,7 +483,7 @@ function DataSourceField() {
|
||||
// If we've chosen a Prometheus data source, we can set the recording rules target data source to the same as the source
|
||||
const recordingRulesTargetDs = getValues('targetDatasourceUID');
|
||||
if (!recordingRulesTargetDs) {
|
||||
const targetDataSourceUID = ds.type === DataSourceType.Prometheus ? ds.uid : undefined;
|
||||
const targetDataSourceUID = isValidRecordingRulesTarget(ds) ? ds.uid : undefined;
|
||||
setValue('targetDatasourceUID', targetDataSourceUID);
|
||||
}
|
||||
}}
|
||||
|
@ -7,7 +7,7 @@ import { Field, Input, Stack, Text } from '@grafana/ui';
|
||||
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
|
||||
|
||||
import { RuleFormType, RuleFormValues } from '../../types/rule-form';
|
||||
import { isSupportedExternalPrometheusFlavoredRulesSourceType } from '../../utils/datasource';
|
||||
import { isValidRecordingRulesTarget } from '../../utils/datasource';
|
||||
import { isCloudRecordingRuleByType, isGrafanaRecordingRuleByType, isRecordingRuleByType } from '../../utils/rules';
|
||||
|
||||
import { RuleEditorSection } from './RuleEditorSection';
|
||||
@ -128,9 +128,7 @@ export const AlertRuleNameAndMetric = () => {
|
||||
current={field.value}
|
||||
noDefault
|
||||
// Filter with `filter` prop instead of `type` prop to avoid showing the `-- Grafana --` data source
|
||||
filter={(ds: DataSourceInstanceSettings) =>
|
||||
isSupportedExternalPrometheusFlavoredRulesSourceType(ds.type)
|
||||
}
|
||||
filter={isValidRecordingRulesTarget}
|
||||
onChange={(ds: DataSourceInstanceSettings) => {
|
||||
setValue('targetDatasourceUid', ds.uid);
|
||||
}}
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { mockDataSource } from '../mocks';
|
||||
|
||||
import { isDataSourceManagingAlerts } from './datasource';
|
||||
import {
|
||||
SUPPORTED_EXTERNAL_PROMETHEUS_FLAVORED_RULE_SOURCE_TYPES,
|
||||
isDataSourceManagingAlerts,
|
||||
isValidRecordingRulesTarget,
|
||||
} from './datasource';
|
||||
|
||||
describe('isDataSourceManagingAlerts', () => {
|
||||
it('should return true when the prop is set as true', () => {
|
||||
@ -37,3 +41,48 @@ it('should return false when the prop is set as false', () => {
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
describe('isValidRecordingRulesTarget', () => {
|
||||
it.each(SUPPORTED_EXTERNAL_PROMETHEUS_FLAVORED_RULE_SOURCE_TYPES)(
|
||||
'should return true for %s datasource with manageRecordingRulesTarget enabled',
|
||||
(type) => {
|
||||
expect(
|
||||
isValidRecordingRulesTarget(
|
||||
mockDataSource({
|
||||
type,
|
||||
jsonData: {
|
||||
allowAsRecordingRulesTarget: true,
|
||||
},
|
||||
})
|
||||
)
|
||||
).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(SUPPORTED_EXTERNAL_PROMETHEUS_FLAVORED_RULE_SOURCE_TYPES)(
|
||||
'should return true for %s datasource when manageRecordingRulesTarget is undefined (defaults to true)',
|
||||
(type) => {
|
||||
expect(
|
||||
isValidRecordingRulesTarget(
|
||||
mockDataSource({
|
||||
type,
|
||||
jsonData: {},
|
||||
})
|
||||
)
|
||||
).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it('should return false for loki datasource (unsupported type)', () => {
|
||||
expect(
|
||||
isValidRecordingRulesTarget(
|
||||
mockDataSource({
|
||||
type: 'loki',
|
||||
jsonData: {
|
||||
allowAsRecordingRulesTarget: true,
|
||||
},
|
||||
})
|
||||
)
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -338,6 +338,10 @@ export function isDataSourceManagingAlerts(ds: DataSourceInstanceSettings<DataSo
|
||||
return ds.jsonData.manageAlerts !== false; //if this prop is undefined it defaults to true
|
||||
}
|
||||
|
||||
export function isDataSourceAllowedAsRecordingRulesTarget(ds: DataSourceInstanceSettings<DataSourceJsonData>) {
|
||||
return ds.jsonData.allowAsRecordingRulesTarget !== false; // if this prop is undefined it defaults to true
|
||||
}
|
||||
|
||||
export function ruleIdentifierToRuleSourceIdentifier(ruleIdentifier: RuleIdentifier): RulesSourceIdentifier {
|
||||
if (isGrafanaRuleIdentifier(ruleIdentifier)) {
|
||||
return { uid: GrafanaRulesSourceSymbol, name: GRAFANA_RULES_SOURCE_NAME, ruleSourceType: 'grafana' };
|
||||
@ -389,3 +393,7 @@ export const SUPPORTED_RULE_SOURCE_TYPES = [
|
||||
GRAFANA_RULES_SOURCE_NAME,
|
||||
...SUPPORTED_EXTERNAL_RULE_SOURCE_TYPES,
|
||||
] as const satisfies string[];
|
||||
|
||||
export function isValidRecordingRulesTarget(ds: DataSourceInstanceSettings<DataSourceJsonData>): boolean {
|
||||
return isSupportedExternalPrometheusFlavoredRulesSourceType(ds.type) && isDataSourceAllowedAsRecordingRulesTarget(ds);
|
||||
}
|
||||
|
Reference in New Issue
Block a user