api marshaling & validation
This commit is contained in:
@@ -174,10 +174,68 @@ type AlertingConfigResponse struct {
|
||||
type ApiAlertingConfig struct {
|
||||
config.Config
|
||||
|
||||
// Override/eliminate Routes tree in AM config - we'll set it via new fields
|
||||
Route struct{} `yaml:"route,omitempty" json:"route,omitempty"`
|
||||
|
||||
AlertManagerRoute *config.Route `yaml:"alertmanager_route,omitempty" json:"alertmanager_route,omitempty"`
|
||||
GrafanaManagedRoute *config.Route `yaml:"grafana_managed_route,omitempty" json:"grafana_managed_route,omitempty"`
|
||||
|
||||
// Override with our superset receiver type
|
||||
Receivers []*ApiReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ApiAlertingConfig) UnmarshalJSON(b []byte) error {
|
||||
type plain ApiAlertingConfig
|
||||
if err := json.Unmarshal(b, (*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.validate()
|
||||
}
|
||||
|
||||
// validate ensures that the two routing trees use the correct receiver types.
|
||||
func (c *ApiAlertingConfig) validate() error {
|
||||
receivers := make(map[string]ReceiverType, len(c.Receivers))
|
||||
|
||||
for _, r := range c.Receivers {
|
||||
receivers[r.Name] = r.Type()
|
||||
}
|
||||
|
||||
for _, receiver := range AllReceivers(c.GrafanaManagedRoute) {
|
||||
t, ok := receivers[receiver]
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected receiver (%s) is undefined", receiver)
|
||||
}
|
||||
if t != GrafanaReceiverType {
|
||||
return fmt.Errorf("unexpected receiver (%s): cannot use Alertmanager receiver types in Grafana managed routes", receiver)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for _, receiver := range AllReceivers(c.AlertManagerRoute) {
|
||||
t, ok := receivers[receiver]
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected receiver (%s) is undefined", receiver)
|
||||
}
|
||||
if t != AlertmanagerReceiverType {
|
||||
return fmt.Errorf("unexpected receiver (%s): cannot use Grafana receiver types in non-Grafana managed routes", receiver)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllReceivers will recursively walk a routing tree and return a list of all the
|
||||
// referenced receiver names.
|
||||
func AllReceivers(route *config.Route) (res []string) {
|
||||
res = append(res, route.Receiver)
|
||||
for _, subRoute := range route.Routes {
|
||||
res = append(res, AllReceivers(subRoute)...)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
type GrafanaReceiver models.CreateAlertNotificationCommand
|
||||
|
||||
type ReceiverType int
|
||||
@@ -227,6 +285,7 @@ func (r *ApiReceiver) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@@ -63,3 +63,241 @@ func Test_ApiReceiver_Marshaling(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_AllReceivers(t *testing.T) {
|
||||
input := &config.Route{
|
||||
Receiver: "foo",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "bar",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "bazz",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: "buzz",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
require.Equal(t, []string{"foo", "bar", "bazz", "buzz"}, AllReceivers(input))
|
||||
}
|
||||
|
||||
func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
input ApiAlertingConfig
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{},
|
||||
AlertManagerRoute: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
GrafanaManagedRoute: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "graf",
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "am",
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "failure undefined am receiver",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{},
|
||||
AlertManagerRoute: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "unmentioned",
|
||||
},
|
||||
},
|
||||
},
|
||||
GrafanaManagedRoute: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "graf",
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "am",
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
desc: "failure undefined graf receiver",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{},
|
||||
AlertManagerRoute: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
GrafanaManagedRoute: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "unmentioned",
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "am",
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
desc: "failure mixed AM in Grafana",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{},
|
||||
AlertManagerRoute: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
GrafanaManagedRoute: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "am",
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
desc: "failure mixed Grafana in AM",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{},
|
||||
AlertManagerRoute: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "graf",
|
||||
},
|
||||
},
|
||||
},
|
||||
GrafanaManagedRoute: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "graf",
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "am",
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
encoded, err := json.Marshal(tc.input)
|
||||
require.Nil(t, err)
|
||||
|
||||
var out ApiAlertingConfig
|
||||
err = json.Unmarshal(encoded, &out)
|
||||
|
||||
if tc.err {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.Equal(t, tc.input, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user