[Alerting] Ensure upstream validations are run (#34333)

* use embedded validations via noop yaml unmarshaler

* lint

* fixes integration tests now that groupings are handled
This commit is contained in:
Owen Diehl
2021-05-19 06:22:44 -04:00
committed by GitHub
parent aed1c013c0
commit d6c4c2fcd5
5 changed files with 85 additions and 14 deletions

View File

@@ -413,6 +413,17 @@ func (c *GettableApiAlertingConfig) UnmarshalJSON(b []byte) error {
return err
}
// Since Config implements json.Unmarshaler, we must handle _all_ other fields independently.
// Otherwise, the json decoder will detect this and only use the embedded type.
// Additionally, we'll use pointers to slices in order to reference the intended target.
type overrides struct {
Receivers *[]*GettableApiReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
}
if err := json.Unmarshal(b, &overrides{Receivers: &c.Receivers}); err != nil {
return err
}
return c.validate()
}
@@ -452,10 +463,42 @@ type Config struct {
Global *config.GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"`
Route *config.Route `yaml:"route,omitempty" json:"route,omitempty"`
InhibitRules []*config.InhibitRule `yaml:"inhibit_rules,omitempty" json:"inhibit_rules,omitempty"`
Receivers []*config.Receiver `yaml:"-" json:"receivers,omitempty"`
Templates []string `yaml:"templates" json:"templates"`
}
// Config is the entrypoint for the embedded Alertmanager config with the exception of receivers.
// Prometheus historically uses yaml files as the method of configuration and thus some
// post-validation is included in the UnmarshalYAML method. Here we simply run this with
// a noop unmarshaling function in order to benefit from said validation.
func (c *Config) UnmarshalJSON(b []byte) error {
type plain Config
if err := json.Unmarshal(b, (*plain)(c)); err != nil {
return err
}
noopUnmarshal := func(_ interface{}) error { return nil }
if c.Global != nil {
if err := c.Global.UnmarshalYAML(noopUnmarshal); err != nil {
return err
}
}
if c.Route != nil {
if err := c.Route.UnmarshalYAML(noopUnmarshal); err != nil {
return err
}
}
for _, r := range c.InhibitRules {
if err := r.UnmarshalYAML(noopUnmarshal); err != nil {
return err
}
}
return nil
}
type PostableApiAlertingConfig struct {
Config `yaml:",inline"`
@@ -469,6 +512,17 @@ func (c *PostableApiAlertingConfig) UnmarshalJSON(b []byte) error {
return err
}
// Since Config implements json.Unmarshaler, we must handle _all_ other fields independently.
// Otherwise, the json decoder will detect this and only use the embedded type.
// Additionally, we'll use pointers to slices in order to reference the intended target.
type overrides struct {
Receivers *[]*PostableApiReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
}
if err := json.Unmarshal(b, &overrides{Receivers: &c.Receivers}); err != nil {
return err
}
return c.validate()
}

View File

@@ -7,6 +7,7 @@ import (
"testing"
"github.com/prometheus/alertmanager/config"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
@@ -563,3 +564,14 @@ func Test_ReceiverMatchesBackend(t *testing.T) {
})
}
}
func Test_Marshaling_Validation(t *testing.T) {
jsonEncoded, err := ioutil.ReadFile("alertmanager_test_artifact.json")
require.Nil(t, err)
var tmp GettableUserConfig
require.Nil(t, json.Unmarshal(jsonEncoded, &tmp))
expected := []model.LabelName{"alertname"}
require.Equal(t, expected, tmp.AlertmanagerConfig.Config.Route.GroupBy)
}

View File

@@ -23,6 +23,9 @@
],
"route": {
"continue": false,
"group_by": [
"alertname"
],
"receiver": "am",
"routes": [
{

View File

@@ -14,6 +14,8 @@ alertmanager_config: |
name: am
route:
continue: false
group_by:
- alertname
receiver: am
routes:
- continue: false