Alerting: send alerts to external, internal, or both alertmanagers (#40341)

* (WIP) send alerts to external, internal, or both alertmanagers

* Modify admin configuration endpoint, update swagger docs

* Integration test for admin config updated

* Code review changes

* Fix alertmanagers choice not changing bug, add unit test

* Add AlertmanagersChoice as enum in swagger, code review changes

* Fix API and tests errors

* Change enum from int to string, use 'SendAlertsTo' instead of 'AlertmanagerChoice' where necessary

* Fix tests to reflect last changes

* Keep senders running when alerts are handled just internally

* Check if any external AM has been discovered before sending alerts, update tests

* remove duplicate data from logs

* update comment

* represent alertmanagers choice as an int instead of a string

* default alertmanagers choice to all alertmanagers, test cases

* update definitions and generate spec
This commit is contained in:
Santiago
2022-02-01 20:36:55 -03:00
committed by GitHub
parent 21796c61ba
commit 04d93751b8
10 changed files with 388 additions and 84 deletions
+12 -1
View File
@@ -55,7 +55,8 @@ func (srv AdminSrv) RouteGetNGalertConfig(c *models.ReqContext) response.Respons
}
resp := apimodels.GettableNGalertConfig{
Alertmanagers: cfg.Alertmanagers,
Alertmanagers: cfg.Alertmanagers,
AlertmanagersChoice: apimodels.AlertmanagersChoice(cfg.SendAlertsTo.String()),
}
return response.JSON(http.StatusOK, resp)
}
@@ -65,8 +66,18 @@ func (srv AdminSrv) RoutePostNGalertConfig(c *models.ReqContext, body apimodels.
return accessForbiddenResp()
}
sendAlertsTo, err := ngmodels.StringToAlertmanagersChoice(string(body.AlertmanagersChoice))
if err != nil {
return response.Error(400, "Invalid alertmanager choice specified", nil)
}
if sendAlertsTo == ngmodels.ExternalAlertmanagers && len(body.Alertmanagers) == 0 {
return response.Error(400, "At least one Alertmanager must be provided to choose this option", nil)
}
cfg := &ngmodels.AdminConfiguration{
Alertmanagers: body.Alertmanagers,
SendAlertsTo: sendAlertsTo,
OrgID: c.OrgId,
}
@@ -1,6 +1,8 @@
package definitions
import v1 "github.com/prometheus/client_golang/api/prometheus/v1"
import (
v1 "github.com/prometheus/client_golang/api/prometheus/v1"
)
// swagger:route GET /api/v1/ngalert/alertmanagers configuration RouteGetAlertmanagers
//
@@ -26,7 +28,7 @@ import v1 "github.com/prometheus/client_golang/api/prometheus/v1"
// swagger:route POST /api/v1/ngalert/admin_config configuration RoutePostNGalertConfig
//
// Creates or updates the NGalert configuration of the user's organization.
// Creates or updates the NGalert configuration of the user's organization. If no value is sent for alertmanagersChoice, it defaults to "all".
//
// Consumes:
// - application/json
@@ -52,14 +54,25 @@ type NGalertConfig struct {
Body PostableNGalertConfig
}
// swagger:enum AlertmanagersChoice
type AlertmanagersChoice string
const (
AllAlertmanagers AlertmanagersChoice = "all"
InternalAlertmanager AlertmanagersChoice = "internal"
ExternalAlertmanagers AlertmanagersChoice = "external"
)
// swagger:model
type PostableNGalertConfig struct {
Alertmanagers []string `json:"alertmanagers"`
Alertmanagers []string `json:"alertmanagers"`
AlertmanagersChoice AlertmanagersChoice `json:"alertmanagersChoice"`
}
// swagger:model
type GettableNGalertConfig struct {
Alertmanagers []string `json:"alertmanagers"`
Alertmanagers []string `json:"alertmanagers"`
AlertmanagersChoice AlertmanagersChoice `json:"alertmanagersChoice"`
}
// swagger:model
+39 -16
View File
@@ -769,6 +769,7 @@
"Alerting"
],
"type": "string",
"x-go-enum-desc": "Alerting AlertingErrState",
"x-go-name": "ExecErrState"
},
"id": {
@@ -797,6 +798,7 @@
"OK"
],
"type": "string",
"x-go-enum-desc": "Alerting Alerting\nNoData NoData\nOK OK",
"x-go-name": "NoDataState"
},
"orgId": {
@@ -838,6 +840,16 @@
},
"type": "array",
"x-go-name": "Alertmanagers"
},
"alertmanagersChoice": {
"enum": [
"all",
"internal",
"external"
],
"type": "string",
"x-go-enum-desc": "all AllAlertmanagers\ninternal InternalAlertmanager\nexternal ExternalAlertmanagers",
"x-go-name": "AlertmanagersChoice"
}
},
"type": "object",
@@ -1718,6 +1730,7 @@
"Alerting"
],
"type": "string",
"x-go-enum-desc": "Alerting AlertingErrState",
"x-go-name": "ExecErrState"
},
"no_data_state": {
@@ -1727,6 +1740,7 @@
"OK"
],
"type": "string",
"x-go-enum-desc": "Alerting Alerting\nNoData NoData\nOK OK",
"x-go-name": "NoDataState"
},
"title": {
@@ -1749,6 +1763,16 @@
},
"type": "array",
"x-go-name": "Alertmanagers"
},
"alertmanagersChoice": {
"enum": [
"all",
"internal",
"external"
],
"type": "string",
"x-go-enum-desc": "all AllAlertmanagers\ninternal InternalAlertmanager\nexternal ExternalAlertmanagers",
"x-go-name": "AlertmanagersChoice"
}
},
"type": "object",
@@ -2884,6 +2908,7 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@@ -2905,16 +2930,15 @@
"labels",
"receiver"
],
"type": "object",
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
"type": "object"
},
"alertGroups": {
"description": "AlertGroups alert groups",
"items": {
"$ref": "#/definitions/alertGroup"
},
"type": "array"
"type": "array",
"x-go-name": "AlertGroups",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertStatus": {
"description": "AlertStatus alert status",
@@ -3096,13 +3120,15 @@
"type": "object"
},
"gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"items": {
"$ref": "#/definitions/gettableAlert"
},
"type": "array"
"type": "array",
"x-go-name": "GettableAlerts",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"properties": {
"comment": {
"description": "comment",
@@ -3154,9 +3180,7 @@
"status",
"updatedAt"
],
"type": "object",
"x-go-name": "GettableSilence",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
@@ -3335,6 +3359,7 @@
"type": "object"
},
"receiver": {
"description": "Receiver receiver",
"properties": {
"name": {
"description": "name",
@@ -3345,9 +3370,7 @@
"required": [
"name"
],
"type": "object",
"x-go-name": "Receiver",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
"type": "object"
},
"silence": {
"description": "Silence silence",
@@ -3456,8 +3479,8 @@
}
},
"info": {
"description": "Package definitions includes the types required for generating or consuming an OpenAPI\nspec for the Grafana 8 Alerts API.",
"title": "Grafana 8 Alerts API.",
"description": "Package definitions includes the types required for generating or consuming an OpenAPI\nspec for the Grafana Alerting API.",
"title": "Grafana Alerting API.",
"version": "1.1.0"
},
"paths": {
@@ -4400,7 +4423,7 @@
}
}
},
"summary": "Creates or updates the NGalert configuration of the user's organization.",
"summary": "Creates or updates the NGalert configuration of the user's organization. If no value is sent for alertmanagersChoice, it defaults to \"all\".",
"tags": [
"configuration"
]
+28 -11
View File
@@ -911,7 +911,7 @@
"tags": [
"configuration"
],
"summary": "Creates or updates the NGalert configuration of the user's organization.",
"summary": "Creates or updates the NGalert configuration of the user's organization. If no value is sent for alertmanagersChoice, it defaults to \"all\".",
"operationId": "RoutePostNGalertConfig",
"parameters": [
{
@@ -1863,6 +1863,16 @@
"type": "string"
},
"x-go-name": "Alertmanagers"
},
"alertmanagersChoice": {
"type": "string",
"enum": [
"all",
"internal",
"external"
],
"x-go-enum-desc": "all AllAlertmanagers\ninternal InternalAlertmanager\nexternal ExternalAlertmanagers",
"x-go-name": "AlertmanagersChoice"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
@@ -2777,6 +2787,16 @@
"type": "string"
},
"x-go-name": "Alertmanagers"
},
"alertmanagersChoice": {
"type": "string",
"enum": [
"all",
"internal",
"external"
],
"x-go-enum-desc": "all AllAlertmanagers\ninternal InternalAlertmanager\nexternal ExternalAlertmanagers",
"x-go-name": "AlertmanagersChoice"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
@@ -3680,9 +3700,8 @@
"x-go-package": "github.com/prometheus/alertmanager/timeinterval"
},
"URL": {
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
"type": "object",
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"properties": {
"ForceQuery": {
"type": "boolean"
@@ -3715,7 +3734,7 @@
"$ref": "#/definitions/Userinfo"
}
},
"x-go-package": "net/url"
"x-go-package": "github.com/prometheus/common/config"
},
"Userinfo": {
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
@@ -3912,6 +3931,7 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"type": "object",
"required": [
"alerts",
@@ -3934,8 +3954,6 @@
"$ref": "#/definitions/receiver"
}
},
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/alertGroup"
},
"alertGroups": {
@@ -4128,11 +4146,12 @@
"$ref": "#/definitions/gettableAlert"
},
"gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"type": "array",
"items": {
"$ref": "#/definitions/gettableAlert"
},
"x-go-name": "GettableAlerts",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/gettableAlerts"
},
"gettableSilence": {
@@ -4192,12 +4211,11 @@
"$ref": "#/definitions/gettableSilence"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"x-go-name": "GettableSilences",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/gettableSilences"
},
"labelSet": {
@@ -4371,6 +4389,7 @@
"$ref": "#/definitions/postableSilence"
},
"receiver": {
"description": "Receiver receiver",
"type": "object",
"required": [
"name"
@@ -4382,8 +4401,6 @@
"x-go-name": "Name"
}
},
"x-go-name": "Receiver",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/receiver"
},
"silence": {