From c9d4689e0b943b9cd6984844e88c4c7abcac175d Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:54:31 +0200 Subject: [PATCH] relabeling: Fix labelmap action validation with legacy metric name scheme Fixes #17370 In Prometheus v3.7.0, using labelmap actions with replacement patterns containing regex variables (e.g., `$1`, `${1}`) would fail validation when `metric_name_validation_scheme` was set to `legacy`, causing Prometheus to fail at startup with: "$1" is invalid 'replacement' for labelmap action This was a regression as the same configuration worked in v3.6.0. The issue was in the validation logic: while UTF-8 validation correctly allowed `$` characters, legacy validation incorrectly used `IsValidLabelName` which rejects `$` characters. The fix ensures legacy validation uses `relabelTargetLegacy` regex which explicitly supports regex template variables. Added test cases to verify labelmap validation works with both `$1` and `${1}` replacement patterns under legacy validation scheme. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- model/relabel/relabel.go | 8 +++++++- model/relabel/relabel_test.go | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/model/relabel/relabel.go b/model/relabel/relabel.go index c7c5439d54..c15049b2b0 100644 --- a/model/relabel/relabel.go +++ b/model/relabel/relabel.go @@ -145,7 +145,13 @@ func (c *Config) Validate(nameValidationScheme model.ValidationScheme) error { // UTF-8 allows ${} characters, so standard validation allow $variables by default. // TODO(bwplotka): Relabelling users cannot put $ and ${<...>} characters in metric names or values. // Design escaping mechanism to allow that, once valid use case appears. - return c.NameValidationScheme.IsValidLabelName(value) + switch c.NameValidationScheme { + case model.UTF8Validation: + return c.NameValidationScheme.IsValidLabelName(value) + default: + // For legacy validation, use the legacy regex that allows $variables. + return relabelTargetLegacy.MatchString(value) + } } if c.Action == Replace && varInRegexTemplate(c.TargetLabel) && !isValidLabelNameWithRegexVarFn(c.TargetLabel) { return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) diff --git a/model/relabel/relabel_test.go b/model/relabel/relabel_test.go index 79730055cb..99a4e09f56 100644 --- a/model/relabel/relabel_test.go +++ b/model/relabel/relabel_test.go @@ -831,6 +831,22 @@ func TestRelabelValidate(t *testing.T) { NameValidationScheme: model.UTF8Validation, }, }, + { + config: Config{ + Regex: MustNewRegexp("__meta_kubernetes_pod_label_(strimzi_io_.+)"), + Action: LabelMap, + Replacement: "$1", + NameValidationScheme: model.LegacyValidation, + }, + }, + { + config: Config{ + Regex: MustNewRegexp("__meta_(.+)"), + Action: LabelMap, + Replacement: "${1}", + NameValidationScheme: model.LegacyValidation, + }, + }, } for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) {