Alerting: Allow linking to silence form with __alert_rule_uid__ value preset (#93526)

This commit is contained in:
Tom Ratcliffe 2024-09-30 09:20:53 +01:00 committed by GitHub
parent e4698d9c52
commit 0b2478859a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 28 additions and 2 deletions

View File

@ -77,6 +77,8 @@ export function getAlertingRoutes(cfg = config): RouteDescriptor[] {
roles: evaluateAccess([ roles: evaluateAccess([
AccessControlAction.AlertingInstanceCreate, AccessControlAction.AlertingInstanceCreate,
AccessControlAction.AlertingInstancesExternalWrite, AccessControlAction.AlertingInstancesExternalWrite,
AccessControlAction.AlertingSilenceCreate,
AccessControlAction.AlertingSilenceUpdate,
]), ]),
component: importAlertingComponent( component: importAlertingComponent(
() => import(/* webpackChunkName: "AlertSilences" */ 'app/features/alerting/unified/Silences') () => import(/* webpackChunkName: "AlertSilences" */ 'app/features/alerting/unified/Silences')

View File

@ -12,6 +12,7 @@ import {
} from 'app/features/alerting/unified/mocks/server/handlers/datasources'; } from 'app/features/alerting/unified/mocks/server/handlers/datasources';
import { MOCK_GRAFANA_ALERT_RULE_TITLE } from 'app/features/alerting/unified/mocks/server/handlers/grafanaRuler'; import { MOCK_GRAFANA_ALERT_RULE_TITLE } from 'app/features/alerting/unified/mocks/server/handlers/grafanaRuler';
import { silenceCreateHandler } from 'app/features/alerting/unified/mocks/server/handlers/silences'; import { silenceCreateHandler } from 'app/features/alerting/unified/mocks/server/handlers/silences';
import { MATCHER_ALERT_RULE_UID } from 'app/features/alerting/unified/utils/constants';
import { MatcherOperator, SilenceState } from 'app/plugins/datasource/alertmanager/types'; import { MatcherOperator, SilenceState } from 'app/plugins/datasource/alertmanager/types';
import { AccessControlAction } from 'app/types'; import { AccessControlAction } from 'app/types';
@ -339,6 +340,11 @@ describe('Silence create/edit', () => {
expect(await screen.findByLabelText(/alert rule/i)).toHaveValue(grafanaRulerRule.grafana_alert.title); expect(await screen.findByLabelText(/alert rule/i)).toHaveValue(grafanaRulerRule.grafana_alert.title);
}); });
it('populates form with information when specifying alert rule UID in matchers', async () => {
renderSilences(`/alerting/silence/new?matcher=${MATCHER_ALERT_RULE_UID}%3D${grafanaRulerRule.grafana_alert.uid}`);
expect(await screen.findByLabelText(/alert rule/i)).toHaveValue(grafanaRulerRule.grafana_alert.title);
});
it( it(
'silences page should contain alertmanager parameter after creating a silence', 'silences page should contain alertmanager parameter after creating a silence',
async () => { async () => {

View File

@ -5,6 +5,8 @@ import {
defaultsFromQuery, defaultsFromQuery,
getDefaultSilenceFormValues, getDefaultSilenceFormValues,
} from 'app/features/alerting/unified/components/silences/utils'; } from 'app/features/alerting/unified/components/silences/utils';
import { MATCHER_ALERT_RULE_UID } from 'app/features/alerting/unified/utils/constants';
import { parseQueryParamMatchers } from 'app/features/alerting/unified/utils/matchers';
import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper'; import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning'; import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
@ -30,9 +32,22 @@ const Silences = () => {
<Route exact path="/alerting/silence/new"> <Route exact path="/alerting/silence/new">
{({ location }) => { {({ location }) => {
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
const potentialAlertRuleMatcher = parseQueryParamMatchers(queryParams.getAll('matcher')).find(
(m) => m.name === MATCHER_ALERT_RULE_UID
);
const potentialRuleUid = potentialAlertRuleMatcher?.value;
const formValues = getDefaultSilenceFormValues(defaultsFromQuery(queryParams)); const formValues = getDefaultSilenceFormValues(defaultsFromQuery(queryParams));
return <SilencesEditor formValues={formValues} alertManagerSourceName={selectedAlertmanager} />; return (
<SilencesEditor
formValues={formValues}
alertManagerSourceName={selectedAlertmanager}
ruleUid={potentialRuleUid}
/>
);
}} }}
</Route> </Route>
<Route exact path="/alerting/silence/:id/edit"> <Route exact path="/alerting/silence/:id/edit">

View File

@ -2,6 +2,7 @@ import { DefaultTimeZone, addDurationToDate, dateTime, intervalToAbbreviatedDura
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { SilenceFormFields } from 'app/features/alerting/unified/types/silence-form'; import { SilenceFormFields } from 'app/features/alerting/unified/types/silence-form';
import { matcherToMatcherField } from 'app/features/alerting/unified/utils/alertmanager'; import { matcherToMatcherField } from 'app/features/alerting/unified/utils/alertmanager';
import { MATCHER_ALERT_RULE_UID } from 'app/features/alerting/unified/utils/constants';
import { parseQueryParamMatchers } from 'app/features/alerting/unified/utils/matchers'; import { parseQueryParamMatchers } from 'app/features/alerting/unified/utils/matchers';
import { MatcherOperator, Silence } from 'app/plugins/datasource/alertmanager/types'; import { MatcherOperator, Silence } from 'app/plugins/datasource/alertmanager/types';
@ -14,7 +15,9 @@ export const defaultsFromQuery = (searchParams: URLSearchParams): Partial<Silenc
const comment = searchParams.get('comment'); const comment = searchParams.get('comment');
const matchers = searchParams.getAll('matcher'); const matchers = searchParams.getAll('matcher');
const formMatchers = parseQueryParamMatchers(matchers); const strippedMatchers = matchers.filter((m) => !m.startsWith(MATCHER_ALERT_RULE_UID));
const formMatchers = parseQueryParamMatchers(strippedMatchers);
if (formMatchers.length) { if (formMatchers.length) {
defaults.matchers = formMatchers.map(matcherToMatcherField); defaults.matchers = formMatchers.map(matcherToMatcherField);
} }