Alerting: Patch missing expression model refIds (#114477)
This commit is contained in:
@@ -48,7 +48,6 @@ interface ExpressionProps {
|
|||||||
onSetCondition: (refId: string) => void;
|
onSetCondition: (refId: string) => void;
|
||||||
onUpdateRefId: (oldRefId: string, newRefId: string) => void;
|
onUpdateRefId: (oldRefId: string, newRefId: string) => void;
|
||||||
onRemoveExpression: (refId: string) => void;
|
onRemoveExpression: (refId: string) => void;
|
||||||
onUpdateExpressionType: (refId: string, type: ExpressionQueryType) => void;
|
|
||||||
onChangeQuery: (query: ExpressionQuery) => void;
|
onChangeQuery: (query: ExpressionQuery) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +61,6 @@ export const Expression: FC<ExpressionProps> = ({
|
|||||||
onSetCondition,
|
onSetCondition,
|
||||||
onUpdateRefId,
|
onUpdateRefId,
|
||||||
onRemoveExpression,
|
onRemoveExpression,
|
||||||
onUpdateExpressionType, // this method is not used? maybe we should remove it
|
|
||||||
onChangeQuery,
|
onChangeQuery,
|
||||||
}) => {
|
}) => {
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useMemo } from 'react';
|
|||||||
import { GrafanaTheme2, PanelData } from '@grafana/data';
|
import { GrafanaTheme2, PanelData } from '@grafana/data';
|
||||||
import { useStyles2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
import { isExpressionQuery } from 'app/features/expressions/guards';
|
import { isExpressionQuery } from 'app/features/expressions/guards';
|
||||||
import { ExpressionQuery, ExpressionQueryType } from 'app/features/expressions/types';
|
import { ExpressionQuery } from 'app/features/expressions/types';
|
||||||
import { AlertQuery } from 'app/types/unified-alerting-dto';
|
import { AlertQuery } from 'app/types/unified-alerting-dto';
|
||||||
|
|
||||||
import { Expression } from '../expressions/Expression';
|
import { Expression } from '../expressions/Expression';
|
||||||
@@ -18,7 +18,6 @@ interface Props {
|
|||||||
queries: AlertQuery[];
|
queries: AlertQuery[];
|
||||||
onRemoveExpression: (refId: string) => void;
|
onRemoveExpression: (refId: string) => void;
|
||||||
onUpdateRefId: (oldRefId: string, newRefId: string) => void;
|
onUpdateRefId: (oldRefId: string, newRefId: string) => void;
|
||||||
onUpdateExpressionType: (refId: string, type: ExpressionQueryType) => void;
|
|
||||||
onUpdateQueryExpression: (query: ExpressionQuery) => void;
|
onUpdateQueryExpression: (query: ExpressionQuery) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,12 +28,15 @@ export const ExpressionsEditor = ({
|
|||||||
panelData,
|
panelData,
|
||||||
onUpdateRefId,
|
onUpdateRefId,
|
||||||
onRemoveExpression,
|
onRemoveExpression,
|
||||||
onUpdateExpressionType,
|
|
||||||
onUpdateQueryExpression,
|
onUpdateQueryExpression,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const expressionQueries = useMemo(() => {
|
const expressionQueries = useMemo(() => {
|
||||||
return queries.reduce((acc: ExpressionQuery[], query) => {
|
return queries.reduce((acc: ExpressionQuery[], query) => {
|
||||||
return isExpressionQuery(query.model) ? acc.concat(query.model) : acc;
|
if (isExpressionQuery(query.model)) {
|
||||||
|
acc.push(query.model);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
}, [queries]);
|
}, [queries]);
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
@@ -64,7 +66,6 @@ export const ExpressionsEditor = ({
|
|||||||
onSetCondition={onSetCondition}
|
onSetCondition={onSetCondition}
|
||||||
onRemoveExpression={onRemoveExpression}
|
onRemoveExpression={onRemoveExpression}
|
||||||
onUpdateRefId={onUpdateRefId}
|
onUpdateRefId={onUpdateRefId}
|
||||||
onUpdateExpressionType={onUpdateExpressionType}
|
|
||||||
onChangeQuery={onUpdateQueryExpression}
|
onChangeQuery={onUpdateQueryExpression}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
-4
@@ -73,7 +73,6 @@ import {
|
|||||||
updateExpression,
|
updateExpression,
|
||||||
updateExpressionRefId,
|
updateExpressionRefId,
|
||||||
updateExpressionTimeRange,
|
updateExpressionTimeRange,
|
||||||
updateExpressionType,
|
|
||||||
} from './reducer';
|
} from './reducer';
|
||||||
import { useAdvancedMode } from './useAdvancedMode';
|
import { useAdvancedMode } from './useAdvancedMode';
|
||||||
import { useAlertQueryRunner } from './useAlertQueryRunner';
|
import { useAlertQueryRunner } from './useAlertQueryRunner';
|
||||||
@@ -591,9 +590,6 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange, mod
|
|||||||
dispatch(removeExpression(refId));
|
dispatch(removeExpression(refId));
|
||||||
}}
|
}}
|
||||||
onUpdateRefId={onUpdateRefId}
|
onUpdateRefId={onUpdateRefId}
|
||||||
onUpdateExpressionType={(refId, type) => {
|
|
||||||
dispatch(updateExpressionType({ refId, type }));
|
|
||||||
}}
|
|
||||||
onUpdateQueryExpression={(model) => {
|
onUpdateQueryExpression={(model) => {
|
||||||
dispatch(updateExpression(model));
|
dispatch(updateExpression(model));
|
||||||
}}
|
}}
|
||||||
|
|||||||
-52
@@ -442,55 +442,3 @@ exports[`Query and expressions reducer should update an expression refId and rew
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Query and expressions reducer should update expression type 1`] = `
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{
|
|
||||||
"datasourceUid": "abc123",
|
|
||||||
"model": {
|
|
||||||
"refId": "A",
|
|
||||||
},
|
|
||||||
"queryType": "query",
|
|
||||||
"refId": "A",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"datasourceUid": "__expr__",
|
|
||||||
"model": {
|
|
||||||
"conditions": [
|
|
||||||
{
|
|
||||||
"evaluator": {
|
|
||||||
"params": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
"type": "gt",
|
|
||||||
},
|
|
||||||
"operator": {
|
|
||||||
"type": "and",
|
|
||||||
},
|
|
||||||
"query": {
|
|
||||||
"params": [],
|
|
||||||
},
|
|
||||||
"reducer": {
|
|
||||||
"params": [],
|
|
||||||
"type": "avg",
|
|
||||||
},
|
|
||||||
"type": "query",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"datasource": {
|
|
||||||
"name": "Expression",
|
|
||||||
"type": "__expr__",
|
|
||||||
"uid": "__expr__",
|
|
||||||
},
|
|
||||||
"expression": "",
|
|
||||||
"refId": "B",
|
|
||||||
"type": "reduce",
|
|
||||||
},
|
|
||||||
"queryType": "",
|
|
||||||
"refId": "B",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|||||||
-17
@@ -22,7 +22,6 @@ import {
|
|||||||
updateExpression,
|
updateExpression,
|
||||||
updateExpressionRefId,
|
updateExpressionRefId,
|
||||||
updateExpressionTimeRange,
|
updateExpressionTimeRange,
|
||||||
updateExpressionType,
|
|
||||||
} from './reducer';
|
} from './reducer';
|
||||||
|
|
||||||
const reduceExpression: AlertQuery<ExpressionQuery> = {
|
const reduceExpression: AlertQuery<ExpressionQuery> = {
|
||||||
@@ -388,22 +387,6 @@ describe('Query and expressions reducer', () => {
|
|||||||
|
|
||||||
expect(newState).toMatchSnapshot();
|
expect(newState).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update expression type', () => {
|
|
||||||
const initialState: QueriesAndExpressionsState = {
|
|
||||||
queries: [alertQuery, expressionQuery],
|
|
||||||
};
|
|
||||||
|
|
||||||
const newState = queriesAndExpressionsReducer(
|
|
||||||
initialState,
|
|
||||||
updateExpressionType({
|
|
||||||
refId: 'B',
|
|
||||||
type: ExpressionQueryType.reduce,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(newState).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
it('should remove first reducer', () => {
|
it('should remove first reducer', () => {
|
||||||
const initialState: QueriesAndExpressionsState = {
|
const initialState: QueriesAndExpressionsState = {
|
||||||
queries: [alertQuery, reduceExpression, thresholdExpression],
|
queries: [alertQuery, reduceExpression, thresholdExpression],
|
||||||
|
|||||||
-17
@@ -283,23 +283,6 @@ export const queriesAndExpressionsReducer = createReducer(initialState, (builder
|
|||||||
queryType: 'expression',
|
queryType: 'expression',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.addCase(updateExpressionType, (state, action) => {
|
|
||||||
state.queries = state.queries.map((query) => {
|
|
||||||
return query.refId === action.payload.refId
|
|
||||||
? {
|
|
||||||
...query,
|
|
||||||
model: {
|
|
||||||
...expressionDatasource.newQuery({
|
|
||||||
type: action.payload.type,
|
|
||||||
conditions: [{ ...defaultCondition, query: { params: [] } }],
|
|
||||||
expression: '',
|
|
||||||
}),
|
|
||||||
refId: action.payload.refId,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: query;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
GrafanaAlertStateDecision,
|
GrafanaAlertStateDecision,
|
||||||
GrafanaRuleDefinition,
|
GrafanaRuleDefinition,
|
||||||
RulerAlertingRuleDTO,
|
RulerAlertingRuleDTO,
|
||||||
|
RulerGrafanaRuleDTO,
|
||||||
} from 'app/types/unified-alerting-dto';
|
} from 'app/types/unified-alerting-dto';
|
||||||
|
|
||||||
import { EvalFunction } from '../../state/alertDef';
|
import { EvalFunction } from '../../state/alertDef';
|
||||||
@@ -20,6 +21,7 @@ import {
|
|||||||
alertingRulerRuleToRuleForm,
|
alertingRulerRuleToRuleForm,
|
||||||
cleanAnnotations,
|
cleanAnnotations,
|
||||||
cleanLabels,
|
cleanLabels,
|
||||||
|
fixMissingRefIdsInExpressionModel,
|
||||||
formValuesToRulerGrafanaRuleDTO,
|
formValuesToRulerGrafanaRuleDTO,
|
||||||
formValuesToRulerRuleDTO,
|
formValuesToRulerRuleDTO,
|
||||||
getContactPointsFromDTO,
|
getContactPointsFromDTO,
|
||||||
@@ -520,3 +522,70 @@ describe('getDefaultExpressions', () => {
|
|||||||
expect(thresholdModel.expression).toBe('X');
|
expect(thresholdModel.expression).toBe('X');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('fixMissingRefIdsInExpressionModel', () => {
|
||||||
|
it('should return non-Grafana managed rules unchanged', () => {
|
||||||
|
const cloudAlertingRule: RulerAlertingRuleDTO = {
|
||||||
|
alert: 'CloudAlert',
|
||||||
|
expr: 'up == 0',
|
||||||
|
for: '5m',
|
||||||
|
labels: { severity: 'critical' },
|
||||||
|
annotations: { summary: 'Instance down' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = fixMissingRefIdsInExpressionModel(cloudAlertingRule);
|
||||||
|
|
||||||
|
expect(result).toEqual(cloudAlertingRule);
|
||||||
|
expect(result).toBe(cloudAlertingRule); // should be the exact same reference
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should copy refId from query to model when model.refId is missing in Grafana managed rules', () => {
|
||||||
|
const ruleWithMissingRefId: RulerGrafanaRuleDTO = {
|
||||||
|
grafana_alert: {
|
||||||
|
uid: 'test-uid',
|
||||||
|
title: 'Test Alert',
|
||||||
|
namespace_uid: 'namespace-uid',
|
||||||
|
rule_group: 'test-group',
|
||||||
|
condition: 'B',
|
||||||
|
no_data_state: GrafanaAlertStateDecision.NoData,
|
||||||
|
exec_err_state: GrafanaAlertStateDecision.Alerting,
|
||||||
|
is_paused: false,
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
refId: 'A',
|
||||||
|
datasourceUid: 'datasource-uid',
|
||||||
|
queryType: '',
|
||||||
|
relativeTimeRange: { from: 600, to: 0 },
|
||||||
|
// @ts-ignore
|
||||||
|
model: {
|
||||||
|
// refId is missing here
|
||||||
|
datasource: {
|
||||||
|
type: 'grafana-testdata-datasource',
|
||||||
|
uid: 'PD8C576611E62080A',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refId: 'B',
|
||||||
|
datasourceUid: ExpressionDatasourceUID,
|
||||||
|
queryType: '',
|
||||||
|
// @ts-ignore
|
||||||
|
model: {
|
||||||
|
// refId is missing here
|
||||||
|
type: ExpressionQueryType.reduce,
|
||||||
|
expression: 'A',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
for: '5m',
|
||||||
|
labels: {},
|
||||||
|
annotations: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = fixMissingRefIdsInExpressionModel(ruleWithMissingRefId);
|
||||||
|
|
||||||
|
expect(result.grafana_alert.data[0].model.refId).toBe('A');
|
||||||
|
expect(result.grafana_alert.data[1].model.refId).toBe('B');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { produce } from 'immer';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataSourceInstanceSettings,
|
DataSourceInstanceSettings,
|
||||||
IntervalValues,
|
IntervalValues,
|
||||||
@@ -278,14 +280,16 @@ function getEditorSettingsFromDTO(ga: GrafanaRuleDefinition) {
|
|||||||
|
|
||||||
export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleFormValues {
|
export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleFormValues {
|
||||||
const { ruleSourceName, namespace, group, rule } = ruleWithLocation;
|
const { ruleSourceName, namespace, group, rule } = ruleWithLocation;
|
||||||
const isGrafanaRecordingRule = rulerRuleType.grafana.recordingRule(rule);
|
const normalizedRule = fixMissingRefIdsInExpressionModel(rule);
|
||||||
|
|
||||||
|
const isGrafanaRecordingRule = rulerRuleType.grafana.recordingRule(normalizedRule);
|
||||||
|
|
||||||
const defaultFormValues = getDefaultFormValues(isGrafanaRecordingRule ? RuleFormType.grafanaRecording : undefined);
|
const defaultFormValues = getDefaultFormValues(isGrafanaRecordingRule ? RuleFormType.grafanaRecording : undefined);
|
||||||
if (isGrafanaRulesSource(ruleSourceName)) {
|
if (isGrafanaRulesSource(ruleSourceName)) {
|
||||||
// GRAFANA-MANAGED RULES
|
// GRAFANA-MANAGED RULES
|
||||||
if (isGrafanaRecordingRule) {
|
if (isGrafanaRecordingRule) {
|
||||||
// grafana recording rule
|
// grafana recording rule
|
||||||
const ga = rule.grafana_alert;
|
const ga = normalizedRule.grafana_alert;
|
||||||
return {
|
return {
|
||||||
...defaultFormValues,
|
...defaultFormValues,
|
||||||
name: ga.title,
|
name: ga.title,
|
||||||
@@ -294,16 +298,16 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
||||||
queries: ga.data,
|
queries: ga.data,
|
||||||
condition: ga.condition,
|
condition: ga.condition,
|
||||||
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(rule.annotations, false)),
|
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(normalizedRule.annotations, false)),
|
||||||
labels: listifyLabelsOrAnnotations(rule.labels, true),
|
labels: listifyLabelsOrAnnotations(normalizedRule.labels, true),
|
||||||
folder: { title: namespace, uid: ga.namespace_uid },
|
folder: { title: namespace, uid: ga.namespace_uid },
|
||||||
isPaused: ga.is_paused,
|
isPaused: ga.is_paused,
|
||||||
metric: ga.record?.metric,
|
metric: ga.record?.metric,
|
||||||
targetDatasourceUid: ga.record?.target_datasource_uid || defaultFormValues.targetDatasourceUid,
|
targetDatasourceUid: ga.record?.target_datasource_uid || defaultFormValues.targetDatasourceUid,
|
||||||
};
|
};
|
||||||
} else if (rulerRuleType.grafana.rule(rule)) {
|
} else if (rulerRuleType.grafana.rule(normalizedRule)) {
|
||||||
// grafana alerting rule
|
// grafana alerting rule
|
||||||
const ga = rule.grafana_alert;
|
const ga = normalizedRule.grafana_alert;
|
||||||
const routingSettings: AlertManagerManualRouting | undefined = getContactPointsFromDTO(ga);
|
const routingSettings: AlertManagerManualRouting | undefined = getContactPointsFromDTO(ga);
|
||||||
if (ga.no_data_state !== undefined && ga.exec_err_state !== undefined) {
|
if (ga.no_data_state !== undefined && ga.exec_err_state !== undefined) {
|
||||||
return {
|
return {
|
||||||
@@ -312,14 +316,14 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
type: RuleFormType.grafana,
|
type: RuleFormType.grafana,
|
||||||
group: group.name,
|
group: group.name,
|
||||||
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
||||||
evaluateFor: rule.for || '0',
|
evaluateFor: normalizedRule.for || '0',
|
||||||
keepFiringFor: rule.keep_firing_for || '0',
|
keepFiringFor: normalizedRule.keep_firing_for || '0',
|
||||||
noDataState: ga.no_data_state,
|
noDataState: ga.no_data_state,
|
||||||
execErrState: ga.exec_err_state,
|
execErrState: ga.exec_err_state,
|
||||||
queries: ga.data,
|
queries: ga.data,
|
||||||
condition: ga.condition,
|
condition: ga.condition,
|
||||||
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(rule.annotations, false)),
|
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(normalizedRule.annotations, false)),
|
||||||
labels: listifyLabelsOrAnnotations(rule.labels, true),
|
labels: listifyLabelsOrAnnotations(normalizedRule.labels, true),
|
||||||
folder: { title: namespace, uid: ga.namespace_uid },
|
folder: { title: namespace, uid: ga.namespace_uid },
|
||||||
isPaused: ga.is_paused,
|
isPaused: ga.is_paused,
|
||||||
|
|
||||||
@@ -338,7 +342,7 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// DATASOURCE-MANAGED RULES
|
// DATASOURCE-MANAGED RULES
|
||||||
if (rulerRuleType.dataSource.alertingRule(rule)) {
|
if (rulerRuleType.dataSource.alertingRule(normalizedRule)) {
|
||||||
const datasourceUid = getDataSourceSrv().getInstanceSettings(ruleSourceName)?.uid ?? '';
|
const datasourceUid = getDataSourceSrv().getInstanceSettings(ruleSourceName)?.uid ?? '';
|
||||||
|
|
||||||
const defaultQuery = {
|
const defaultQuery = {
|
||||||
@@ -346,27 +350,27 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
datasourceUid,
|
datasourceUid,
|
||||||
queryType: '',
|
queryType: '',
|
||||||
relativeTimeRange: getDefaultRelativeTimeRange(),
|
relativeTimeRange: getDefaultRelativeTimeRange(),
|
||||||
expr: rule.expr,
|
expr: normalizedRule.expr,
|
||||||
model: {
|
model: {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
hide: false,
|
hide: false,
|
||||||
expr: rule.expr,
|
expr: normalizedRule.expr,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const alertingRuleValues = alertingRulerRuleToRuleForm(rule);
|
const alertingRuleValues = alertingRulerRuleToRuleForm(normalizedRule);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...defaultFormValues,
|
...defaultFormValues,
|
||||||
...alertingRuleValues,
|
...alertingRuleValues,
|
||||||
queries: [defaultQuery],
|
queries: [defaultQuery],
|
||||||
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(rule.annotations, false)),
|
annotations: normalizeDefaultAnnotations(listifyLabelsOrAnnotations(normalizedRule.annotations, false)),
|
||||||
type: RuleFormType.cloudAlerting,
|
type: RuleFormType.cloudAlerting,
|
||||||
dataSourceName: ruleSourceName,
|
dataSourceName: ruleSourceName,
|
||||||
namespace,
|
namespace,
|
||||||
group: group.name,
|
group: group.name,
|
||||||
};
|
};
|
||||||
} else if (rulerRuleType.dataSource.recordingRule(rule)) {
|
} else if (rulerRuleType.dataSource.recordingRule(normalizedRule)) {
|
||||||
const datasourceUid = getDataSourceSrv().getInstanceSettings(ruleSourceName)?.uid ?? '';
|
const datasourceUid = getDataSourceSrv().getInstanceSettings(ruleSourceName)?.uid ?? '';
|
||||||
|
|
||||||
const defaultQuery = {
|
const defaultQuery = {
|
||||||
@@ -374,15 +378,15 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
datasourceUid,
|
datasourceUid,
|
||||||
queryType: '',
|
queryType: '',
|
||||||
relativeTimeRange: getDefaultRelativeTimeRange(),
|
relativeTimeRange: getDefaultRelativeTimeRange(),
|
||||||
expr: rule.expr,
|
expr: normalizedRule.expr,
|
||||||
model: {
|
model: {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
hide: false,
|
hide: false,
|
||||||
expr: rule.expr,
|
expr: normalizedRule.expr,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const recordingRuleValues = recordingRulerRuleToRuleForm(rule);
|
const recordingRuleValues = recordingRulerRuleToRuleForm(normalizedRule);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...defaultFormValues,
|
...defaultFormValues,
|
||||||
@@ -399,6 +403,23 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function isn't supposed to be needed, but we've noticed some customers are creating rules via Provisioning or
|
||||||
|
* other interfaces where they aren't including the RefId in the "model" of the expression so copy the refId from the query definition.
|
||||||
|
*/
|
||||||
|
export function fixMissingRefIdsInExpressionModel<T extends RulerRuleDTO>(rule: T): T {
|
||||||
|
// non-Grafana managed rules don't use expression nodes so we return the rule as-is
|
||||||
|
if (!rulerRuleType.grafana.rule(rule)) {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
return produce(rule, (draft) => {
|
||||||
|
draft.grafana_alert.data.forEach((query) => {
|
||||||
|
query.model.refId = query.model.refId ?? query.refId;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function grafanaRuleDtoToFormValues(rule: RulerGrafanaRuleDTO, namespace: string): RuleFormValues {
|
export function grafanaRuleDtoToFormValues(rule: RulerGrafanaRuleDTO, namespace: string): RuleFormValues {
|
||||||
const isGrafanaRecordingRule = rulerRuleType.grafana.recordingRule(rule);
|
const isGrafanaRecordingRule = rulerRuleType.grafana.recordingRule(rule);
|
||||||
const defaultFormValues = getDefaultFormValues(isGrafanaRecordingRule ? RuleFormType.grafanaRecording : undefined);
|
const defaultFormValues = getDefaultFormValues(isGrafanaRecordingRule ? RuleFormType.grafanaRecording : undefined);
|
||||||
|
|||||||
Reference in New Issue
Block a user