From 28a28a686df1deeb21c037298063371cedf71f67 Mon Sep 17 00:00:00 2001 From: Gilles De Mey Date: Mon, 3 Mar 2025 10:19:01 +0100 Subject: [PATCH] Alerting: Fix crash when invalid matcher is used in silence query params (#101500) --- .../alerting/unified/utils/matchers.test.ts | 8 ++++++++ .../features/alerting/unified/utils/matchers.ts | 17 +++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/public/app/features/alerting/unified/utils/matchers.test.ts b/public/app/features/alerting/unified/utils/matchers.test.ts index f89e3fa8230..fdf9511c7fa 100644 --- a/public/app/features/alerting/unified/utils/matchers.test.ts +++ b/public/app/features/alerting/unified/utils/matchers.test.ts @@ -49,6 +49,14 @@ describe('Unified Alerting matchers', () => { expect(matchers[0].name).toBe('alertname'); expect(matchers[0].value).toBe('TestData 1'); }); + + it('should not crash when matcher is not valid', () => { + expect(() => { + parseQueryParamMatchers(['alertname']); + }).not.toThrow(); + + expect(parseQueryParamMatchers(['alertname'])).toHaveLength(0); + }); }); describe('normalizeMatchers', () => { diff --git a/public/app/features/alerting/unified/utils/matchers.ts b/public/app/features/alerting/unified/utils/matchers.ts index f5f5476e208..32e0f08555a 100644 --- a/public/app/features/alerting/unified/utils/matchers.ts +++ b/public/app/features/alerting/unified/utils/matchers.ts @@ -5,7 +5,7 @@ * Please keep the references to other files here to a minimum, if we reference a file that uses GrafanaBootData from `window` the worker will fail to load. */ -import { compact, uniqBy } from 'lodash'; +import { chain, compact } from 'lodash'; import { parseFlags } from '@grafana/data'; import { Matcher, MatcherOperator, ObjectMatcher, Route } from 'app/plugins/datasource/alertmanager/types'; @@ -110,11 +110,16 @@ export function parsePromQLStyleMatcherLooseSafe(matcher: string): Matcher[] { // Parses a list of entries like like "['foo=bar', 'baz=~bad*']" into SilenceMatcher[] export function parseQueryParamMatchers(matcherPairs: string[]): Matcher[] { - const parsedMatchers = matcherPairs.filter((x) => !!x.trim()).map((x) => parseMatcher(x)); - - // Due to migration, old alert rules might have a duplicated alertname label - // To handle that case want to filter out duplicates and make sure there are only unique labels - return uniqBy(parsedMatchers, (matcher) => matcher.name); + return ( + chain(matcherPairs) + .map((m) => m.trim()) // trim spaces + .compact() // remove empty strings + .flatMap(parsePromQLStyleMatcherLooseSafe) + // Due to migration, old alert rules might have a duplicated alertname label + // To handle that case want to filter out duplicates and make sure there are only unique labels + .uniqBy('name') + .value() + ); } export const getMatcherQueryParams = (labels: Labels) => {