diff --git a/config/config.go b/config/config.go index 890592ca90..f3d1f58733 100644 --- a/config/config.go +++ b/config/config.go @@ -942,7 +942,11 @@ type InhibitRule struct { TargetMatchers Matchers `yaml:"target_matchers,omitempty" json:"target_matchers,omitempty"` // A set of labels that must be equal between the source and target alert // for them to be a match. - Equal model.LabelNames `yaml:"equal,omitempty" json:"equal,omitempty"` + Equal model.LabelNames `yaml:"-" json:"-"` + // EqualStr allows us to validate the label depending on whether UTF-8 is + // enabled or disabled. It should be removed when Alertmanager is updated + // to use the switchable validation in recent versions of prometheus/common. + EqualStr []string `yaml:"equal,omitempty" json:"equal,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for InhibitRule. @@ -964,6 +968,14 @@ func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error { } } + for _, l := range r.EqualStr { + labelName := model.LabelName(l) + if !compat.IsValidLabelName(labelName) { + return fmt.Errorf("invalid label name %q in equal list", l) + } + r.Equal = append(r.Equal, labelName) + } + return nil } diff --git a/config/config_test.go b/config/config_test.go index 15edfeed2d..9cf6f5cfa2 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -25,8 +25,12 @@ import ( commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" + "github.com/prometheus/common/promslog" "github.com/stretchr/testify/require" "gopkg.in/yaml.v2" + + "github.com/prometheus/alertmanager/featurecontrol" + "github.com/prometheus/alertmanager/matcher/compat" ) func TestLoadEmptyString(t *testing.T) { @@ -1387,3 +1391,39 @@ func TestNilRegexp(t *testing.T) { }) } } + +func TestInhibitRuleEqual(t *testing.T) { + _, err := LoadFile("testdata/conf.inhibit-equal.yml") + if err != nil { + t.Errorf("Error parsing %s: %s", "testdata/conf.inhibit-equal.yml", err) + } + // Should not be able to load configuration with UTF-8 in equals + _, err = LoadFile("testdata/conf.inhibit-equal-utf8.yml") + if err == nil { + t.Errorf("Expected error parsing %s, got nil", "testdata/conf.inhibit-equal-utf8.yml") + } + expected := "invalid label name \"qux🙂\" in equal list" + if err.Error() != expected { + t.Errorf("Expected error \n%s, got \n%s", expected, err) + } + + // Change the mode to UTF-8 mode. + ff, err := featurecontrol.NewFlags(promslog.NewNopLogger(), featurecontrol.FeatureUTF8StrictMode) + require.NoError(t, err) + compat.InitFromFlags(promslog.NewNopLogger(), ff) + + // Restore the mode to classic at the end of the test. + ff, err = featurecontrol.NewFlags(promslog.NewNopLogger(), featurecontrol.FeatureClassicMode) + require.NoError(t, err) + defer compat.InitFromFlags(promslog.NewNopLogger(), ff) + + _, err = LoadFile("testdata/conf.inhibit-equal.yml") + if err != nil { + t.Errorf("Error parsing %s: %s", "testdata/conf.inhibit-equal.yml", err) + } + // Should also be able to load configuration with UTF-8 in equals + _, err = LoadFile("testdata/conf.inhibit-equal-utf8.yml") + if err != nil { + t.Errorf("Error parsing %s: %s", "testdata/conf.inhibit-equal-utf8.yml", err) + } +} diff --git a/config/testdata/conf.inhibit-equal-utf8.yml b/config/testdata/conf.inhibit-equal-utf8.yml new file mode 100644 index 0000000000..4755243e2f --- /dev/null +++ b/config/testdata/conf.inhibit-equal-utf8.yml @@ -0,0 +1,10 @@ +route: + receiver: test +receivers: + - name: test +inhibit_rules: + - source_matchers: + - foo=bar + target_matchers: + - bar=baz + equal: ['qux🙂'] \ No newline at end of file diff --git a/config/testdata/conf.inhibit-equal.yml b/config/testdata/conf.inhibit-equal.yml new file mode 100644 index 0000000000..1b6d51c099 --- /dev/null +++ b/config/testdata/conf.inhibit-equal.yml @@ -0,0 +1,10 @@ +route: + receiver: test +receivers: + - name: test +inhibit_rules: + - source_matchers: + - foo=bar + target_matchers: + - bar=baz + equal: ['qux'] \ No newline at end of file