Merge pull request #17 from grafana/single-routing-tree
Single routing tree
This commit is contained in:
@@ -5,7 +5,7 @@ GO_PKG_FILES = $(shell find $(PKG_DIR) -name *.go -print)
|
||||
|
||||
|
||||
spec.json: $(GO_PKG_FILES)
|
||||
swagger generate spec -m -w $(PKG_DIR) | jq 'del(.definitions.ApiAlertingConfig.properties.route)' > $@
|
||||
swagger generate spec -m -w $(PKG_DIR) -o $@
|
||||
|
||||
|
||||
.PHONY: openapi
|
||||
|
||||
@@ -11,4 +11,3 @@ This repo aims to define the unified alerting API as code. It generates OpenAPI
|
||||
|
||||
## Requires
|
||||
- [go-swagger](https://github.com/go-swagger/go-swagger)
|
||||
- [jq](https://stedolan.github.io/jq/)
|
||||
|
||||
+15
-25
@@ -180,12 +180,6 @@ type AlertingConfigResponse struct {
|
||||
type ApiAlertingConfig struct {
|
||||
config.Config
|
||||
|
||||
// TODO: PR a followup to https://github.com/go-swagger/go-swagger/pull/1527 in order to allow
|
||||
// explicitly ignoring embedded fields. In the meantime, these are hackily removed in our make targets via `jq`
|
||||
|
||||
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"`
|
||||
}
|
||||
@@ -201,32 +195,28 @@ func (c *ApiAlertingConfig) UnmarshalJSON(b []byte) error {
|
||||
|
||||
// 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))
|
||||
receivers := make(map[string]struct{}, len(c.Receivers))
|
||||
|
||||
var hasGrafReceivers, hasAMReceivers bool
|
||||
for _, r := range c.Receivers {
|
||||
receivers[r.Name] = r.Type()
|
||||
receivers[r.Name] = struct{}{}
|
||||
switch r.Type() {
|
||||
case GrafanaReceiverType:
|
||||
hasGrafReceivers = true
|
||||
case AlertmanagerReceiverType:
|
||||
hasAMReceivers = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, receiver := range AllReceivers(c.GrafanaManagedRoute) {
|
||||
t, ok := receivers[receiver]
|
||||
if hasGrafReceivers && hasAMReceivers {
|
||||
return fmt.Errorf("cannot mix Alertmanager & Grafana receiver types")
|
||||
}
|
||||
|
||||
for _, receiver := range AllReceivers(c.Route) {
|
||||
_, 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
|
||||
|
||||
+39
-135
@@ -92,22 +92,15 @@ func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
desc: "success am",
|
||||
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",
|
||||
Config: config.Config{
|
||||
Route: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -118,6 +111,23 @@ func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "success graf",
|
||||
input: ApiAlertingConfig{
|
||||
Config: config.Config{
|
||||
Route: &config.Route{
|
||||
Receiver: "graf",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "graf",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Receivers: []*ApiReceiver{
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
@@ -132,20 +142,13 @@ func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
{
|
||||
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",
|
||||
Config: config.Config{
|
||||
Route: &config.Route{
|
||||
Receiver: "am",
|
||||
Routes: []*config.Route{
|
||||
{
|
||||
Receiver: "unmentioned",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -156,14 +159,6 @@ func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
EmailConfigs: []*config.EmailConfig{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
Receiver: config.Receiver{
|
||||
Name: "graf",
|
||||
},
|
||||
GrafanaReceivers: GrafanaReceivers{
|
||||
GrafanaManagedReceivers: []*GrafanaReceiver{{}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
@@ -171,108 +166,17 @@ func Test_ApiAlertingConfig_Marshaling(t *testing.T) {
|
||||
{
|
||||
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",
|
||||
Config: config.Config{
|
||||
Route: &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",
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"github.com/grafana/alerting-api/pkg/api"
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
)
|
||||
|
||||
// GrafanaAlertingConfig contains only the Grafana managed alerting configurations.
|
||||
type GrafanaAlertingConfig struct {
|
||||
Route *config.Route `yaml:"route,omitempty" json:"route,omitempty"`
|
||||
Templates []string `yaml:"templates" json:"templates"`
|
||||
Receivers []*GrafanaReceiver `yaml:"receivers,omitempty" json:"receivers,omitempty"`
|
||||
}
|
||||
|
||||
type GrafanaReceiver struct {
|
||||
// A unique identifier for this receiver.
|
||||
Name string `yaml:"name" json:"name"`
|
||||
api.GrafanaReceivers
|
||||
}
|
||||
|
||||
func SplitAlertingConfig(apiConf api.ApiAlertingConfig) (amConfig config.Config, gConfig GrafanaAlertingConfig, err error) {
|
||||
|
||||
var gReceivers []*GrafanaReceiver
|
||||
var amReceivers []*config.Receiver
|
||||
for _, r := range apiConf.Receivers {
|
||||
t := r.Type()
|
||||
if t == api.GrafanaReceiverType {
|
||||
gReceivers = append(gReceivers, &GrafanaReceiver{
|
||||
Name: r.Name,
|
||||
GrafanaReceivers: r.GrafanaReceivers,
|
||||
})
|
||||
} else {
|
||||
amReceivers = append(amReceivers, &r.Receiver)
|
||||
}
|
||||
}
|
||||
|
||||
// Create Grafana specific config
|
||||
gConfig.Templates = apiConf.Templates
|
||||
gConfig.Route = apiConf.GrafanaManagedRoute
|
||||
gConfig.Receivers = gReceivers
|
||||
|
||||
// Create AM specific config
|
||||
amConfig = apiConf.Config
|
||||
amConfig.Route = apiConf.AlertManagerRoute
|
||||
amConfig.Receivers = amReceivers
|
||||
|
||||
return amConfig, gConfig, nil
|
||||
}
|
||||
@@ -1021,15 +1021,9 @@
|
||||
"ApiAlertingConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"alertmanager_route": {
|
||||
"$ref": "#/definitions/Route"
|
||||
},
|
||||
"global": {
|
||||
"$ref": "#/definitions/GlobalConfig"
|
||||
},
|
||||
"grafana_managed_route": {
|
||||
"$ref": "#/definitions/Route"
|
||||
},
|
||||
"inhibit_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -1045,6 +1039,9 @@
|
||||
},
|
||||
"x-go-name": "Receivers"
|
||||
},
|
||||
"route": {
|
||||
"$ref": "#/definitions/Route"
|
||||
},
|
||||
"templates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -1736,7 +1733,7 @@
|
||||
"properties": {
|
||||
"Expr": {
|
||||
"type": "string",
|
||||
"example": "(node_filesystem_avail_bytes{fstype!=\"\",job=\"integrations/node_exporter\"} node_filesystem_size_bytes{fstype!=\"\",job=\"integrations/node_exporter\"} * 100 < 5 and node_filesystem_readonly{fstype!=\"\",job=\"integrations/node_exporter\"} == 0)"
|
||||
"example": "(node_filesystem_avail_bytes{fstype!=\"\",job=\"integrations/node_exporter\"} node_filesystem_size_bytes{fstype!=\"\",job=\"integrations/node_exporter\"} * 100 \u003c 5 and node_filesystem_readonly{fstype!=\"\",job=\"integrations/node_exporter\"} == 0)"
|
||||
},
|
||||
"datasourceUid": {
|
||||
"description": "DatasourceUID is required if the query will be sent to grafana to be executed",
|
||||
@@ -3561,4 +3558,4 @@
|
||||
"type": "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user