Repository: prometheus/prometheus
File: model/relabel/relabel.go (Go)

Code before:
		return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action)
	}

	// Relabel config validation scheme matches global if left blank.
	switch c.NameValidationScheme {
	case model.LegacyValidation, model.UTF8Validation:
	case model.UnsetValidation:
		c.NameValidationScheme = nameValidationScheme
	default:
		return fmt.Errorf("unknown relabel config name validation method specified, must be either '', 'legacy' or 'utf8', got %s", c.NameValidationScheme)
	}

	if c.Action == Replace && !varInRegexTemplate(c.TargetLabel) && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}

	isValidLabelNameWithRegexVarFn := func(value string) bool {
		// 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.
		switch c.NameValidationScheme {
		case model.UTF8Validation:
			return c.NameValidationScheme.IsValidLabelName(value)
		default:
			// For legacy validation, use the legacy regex that allows $variables.
			return relabelTargetLegacy.Match([]byte(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)
	}
	if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}
	if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.Replacement != DefaultRelabelConfig.Replacement {
		return fmt.Errorf("'replacement' can not be set for %s action", c.Action)
	}
	if c.Action == LabelMap && !isValidLabelNameWithRegexVarFn(c.Replacement) {
		return fmt.Errorf("%q is invalid 'replacement' for %s action", c.Replacement, c.Action)
	}
	if c.Action == HashMod && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}

	if c.Action == DropEqual || c.Action == KeepEqual {
		if c.Regex != DefaultRelabelConfig.Regex ||
			c.Modulus != DefaultRelabelConfig.Modulus ||
			c.Separator != DefaultRelabelConfig.Separator ||
			c.Replacement != DefaultRelabelConfig.Replacement {
			return fmt.Errorf("%s action requires only 'source_labels' and `target_label`, and no other fields", c.Action)
		}

Review comment (suggestion):
[Nit]
```suggestion
			return relabelTargetLegacy.MatchString(value)
```

Code after:
		return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action)
	}

	// Relabel config validation scheme matches global if left blank.
	switch c.NameValidationScheme {
	case model.LegacyValidation, model.UTF8Validation:
	case model.UnsetValidation:
		c.NameValidationScheme = nameValidationScheme
	default:
		return fmt.Errorf("unknown relabel config name validation method specified, must be either '', 'legacy' or 'utf8', got %s", c.NameValidationScheme)
	}

	if c.Action == Replace && !varInRegexTemplate(c.TargetLabel) && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}

	isValidLabelNameWithRegexVarFn := func(value string) bool {
		// 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.
		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)
	}
	if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}
	if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.Replacement != DefaultRelabelConfig.Replacement {
		return fmt.Errorf("'replacement' can not be set for %s action", c.Action)
	}
	if c.Action == LabelMap && !isValidLabelNameWithRegexVarFn(c.Replacement) {
		return fmt.Errorf("%q is invalid 'replacement' for %s action", c.Replacement, c.Action)
	}
	if c.Action == HashMod && !c.NameValidationScheme.IsValidLabelName(c.TargetLabel) {
		return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
	}

	if c.Action == DropEqual || c.Action == KeepEqual {
		if c.Regex != DefaultRelabelConfig.Regex ||
			c.Modulus != DefaultRelabelConfig.Modulus ||
			c.Separator != DefaultRelabelConfig.Separator ||
			c.Replacement != DefaultRelabelConfig.Replacement {
			return fmt.Errorf("%s action requires only 'source_labels' and `target_label`, and no other fields", c.Action)
		}