mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Template Testing API (#67450)
This commit is contained in:
parent
9eb10bee1f
commit
91471ac7ae
2
go.mod
2
go.mod
@ -57,7 +57,7 @@ require (
|
|||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/google/wire v0.5.0
|
github.com/google/wire v0.5.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/grafana/alerting v0.0.0-20230426193323-4f09f516596b
|
github.com/grafana/alerting v0.0.0-20230428095912-33c5aa68a5ba
|
||||||
github.com/grafana/grafana-aws-sdk v0.12.0
|
github.com/grafana/grafana-aws-sdk v0.12.0
|
||||||
github.com/grafana/grafana-azure-sdk-go v1.6.0
|
github.com/grafana/grafana-azure-sdk-go v1.6.0
|
||||||
github.com/grafana/grafana-plugin-sdk-go v0.160.0
|
github.com/grafana/grafana-plugin-sdk-go v0.160.0
|
||||||
|
8
go.sum
8
go.sum
@ -1275,8 +1275,12 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grafana/alerting v0.0.0-20230426193323-4f09f516596b h1:dAHlNtW62HcSh+XmhV7kmcWqnOSnYsw/pGHiEyix544=
|
github.com/grafana/alerting v0.0.0-20230427200804-f8565cd8b74b h1:SyatotlHGK+05AxICctry09ZEawhE0AasWpOifljH4M=
|
||||||
github.com/grafana/alerting v0.0.0-20230426193323-4f09f516596b/go.mod h1:5edgy6tQY4+W2wuJdi8g2GjbVmpJufguy7QGIRl2q4o=
|
github.com/grafana/alerting v0.0.0-20230427200804-f8565cd8b74b/go.mod h1:nHfrSTdV7/l74N5/ezqlQ+JwSvIChhN3G5+PjCfwG/E=
|
||||||
|
github.com/grafana/alerting v0.0.0-20230428094731-e067f119be06 h1:g+J4UGslzpi9Kt+846NDAjGtVyt8K9Lgjj/vUh61yK0=
|
||||||
|
github.com/grafana/alerting v0.0.0-20230428094731-e067f119be06/go.mod h1:5edgy6tQY4+W2wuJdi8g2GjbVmpJufguy7QGIRl2q4o=
|
||||||
|
github.com/grafana/alerting v0.0.0-20230428095912-33c5aa68a5ba h1:aNTu22ojw4XY24DYNAuvw8v/5iFUNk2bkdTeeWQ5+0o=
|
||||||
|
github.com/grafana/alerting v0.0.0-20230428095912-33c5aa68a5ba/go.mod h1:5edgy6tQY4+W2wuJdi8g2GjbVmpJufguy7QGIRl2q4o=
|
||||||
github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw=
|
github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw=
|
||||||
github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
|
github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s=
|
||||||
github.com/grafana/cuetsy v0.1.8 h1:l0AKXfHr0clu6qPirirDzNC/W5mqq5gG7iruOVolG34=
|
github.com/grafana/cuetsy v0.1.8 h1:l0AKXfHr0clu6qPirirDzNC/W5mqq5gG7iruOVolG34=
|
||||||
|
@ -52,6 +52,7 @@ type Alertmanager interface {
|
|||||||
// Receivers
|
// Receivers
|
||||||
GetReceivers(ctx context.Context) []apimodels.Receiver
|
GetReceivers(ctx context.Context) []apimodels.Receiver
|
||||||
TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*notifier.TestReceiversResult, error)
|
TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*notifier.TestReceiversResult, error)
|
||||||
|
TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*notifier.TestTemplatesResults, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertingStore interface {
|
type AlertingStore interface {
|
||||||
|
@ -342,6 +342,20 @@ func (srv AlertmanagerSrv) RoutePostTestReceivers(c *contextmodel.ReqContext, bo
|
|||||||
return response.JSON(statusForTestReceivers(result.Receivers), newTestReceiversResult(result))
|
return response.JSON(statusForTestReceivers(result.Receivers), newTestReceiversResult(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (srv AlertmanagerSrv) RoutePostTestTemplates(c *contextmodel.ReqContext, body apimodels.TestTemplatesConfigBodyParams) response.Response {
|
||||||
|
am, errResp := srv.AlertmanagerFor(c.OrgID)
|
||||||
|
if errResp != nil {
|
||||||
|
return errResp
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := am.TestTemplate(c.Req.Context(), body)
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusInternalServerError, "", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.JSON(http.StatusOK, newTestTemplateResult(res))
|
||||||
|
}
|
||||||
|
|
||||||
// contextWithTimeoutFromRequest returns a context with a deadline set from the
|
// contextWithTimeoutFromRequest returns a context with a deadline set from the
|
||||||
// Request-Timeout header in the HTTP request. If the header is absent then the
|
// Request-Timeout header in the HTTP request. If the header is absent then the
|
||||||
// context will use the default timeout. The timeout in the Request-Timeout
|
// context will use the default timeout. The timeout in the Request-Timeout
|
||||||
@ -433,6 +447,24 @@ func statusForTestReceivers(v []notifier.TestReceiverResult) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTestTemplateResult(res *notifier.TestTemplatesResults) apimodels.TestTemplatesResults {
|
||||||
|
apiRes := apimodels.TestTemplatesResults{}
|
||||||
|
for _, r := range res.Results {
|
||||||
|
apiRes.Results = append(apiRes.Results, apimodels.TestTemplatesResult{
|
||||||
|
Name: r.Name,
|
||||||
|
Text: r.Text,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, e := range res.Errors {
|
||||||
|
apiRes.Errors = append(apiRes.Errors, apimodels.TestTemplatesErrorResult{
|
||||||
|
Name: e.Name,
|
||||||
|
Kind: apimodels.TemplateErrorKind(e.Kind),
|
||||||
|
Message: e.Error.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return apiRes
|
||||||
|
}
|
||||||
|
|
||||||
func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (Alertmanager, *response.NormalResponse) {
|
func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (Alertmanager, *response.NormalResponse) {
|
||||||
am, err := srv.mam.AlertmanagerFor(orgID)
|
am, err := srv.mam.AlertmanagerFor(orgID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -421,6 +421,46 @@ func TestRoutePostGrafanaAlertingConfigHistoryActivate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRoutePostTestTemplates(t *testing.T) {
|
||||||
|
sut := createSut(t, nil)
|
||||||
|
|
||||||
|
t.Run("assert 404 when no alertmanager found", func(tt *testing.T) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil)
|
||||||
|
require.NoError(tt, err)
|
||||||
|
q := req.URL.Query()
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
rc := createRequestCtxInOrg(10)
|
||||||
|
|
||||||
|
response := sut.RoutePostTestTemplates(rc, apimodels.TestTemplatesConfigBodyParams{})
|
||||||
|
require.Equal(tt, 404, response.Status())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("assert 409 when alertmanager not ready", func(tt *testing.T) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil)
|
||||||
|
require.NoError(tt, err)
|
||||||
|
q := req.URL.Query()
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
rc := createRequestCtxInOrg(3)
|
||||||
|
|
||||||
|
response := sut.RoutePostTestTemplates(rc, apimodels.TestTemplatesConfigBodyParams{})
|
||||||
|
require.Equal(tt, 409, response.Status())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("assert 200 for a valid alertmanager", func(tt *testing.T) {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil)
|
||||||
|
require.NoError(tt, err)
|
||||||
|
q := req.URL.Query()
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
rc := createRequestCtxInOrg(1)
|
||||||
|
|
||||||
|
response := sut.RoutePostTestTemplates(rc, apimodels.TestTemplatesConfigBodyParams{})
|
||||||
|
require.Equal(tt, 200, response.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSilenceCreate(t *testing.T) {
|
func TestSilenceCreate(t *testing.T) {
|
||||||
makeSilence := func(comment string, createdBy string,
|
makeSilence := func(comment string, createdBy string,
|
||||||
startsAt, endsAt strfmt.DateTime, matchers amv2.Matchers) amv2.Silence {
|
startsAt, endsAt strfmt.DateTime, matchers amv2.Matchers) amv2.Silence {
|
||||||
|
@ -173,6 +173,9 @@ func (api *API) authorize(method, path string) web.Handler {
|
|||||||
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test":
|
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test":
|
||||||
fallback = middleware.ReqEditorRole
|
fallback = middleware.ReqEditorRole
|
||||||
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
|
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
|
||||||
|
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/templates/test":
|
||||||
|
fallback = middleware.ReqSignedIn
|
||||||
|
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
|
||||||
|
|
||||||
// External Alertmanager Paths
|
// External Alertmanager Paths
|
||||||
case http.MethodDelete + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts":
|
case http.MethodDelete + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts":
|
||||||
|
@ -49,7 +49,7 @@ func TestAuthorize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
paths[p] = methods
|
paths[p] = methods
|
||||||
}
|
}
|
||||||
require.Len(t, paths, 47)
|
require.Len(t, paths, 48)
|
||||||
|
|
||||||
ac := acmock.New()
|
ac := acmock.New()
|
||||||
api := &API{AccessControl: ac}
|
api := &API{AccessControl: ac}
|
||||||
|
@ -189,3 +189,7 @@ func (f *AlertmanagerApiHandler) handleRouteGetGrafanaReceivers(ctx *contextmode
|
|||||||
func (f *AlertmanagerApiHandler) handleRoutePostTestGrafanaReceivers(ctx *contextmodel.ReqContext, conf apimodels.TestReceiversConfigBodyParams) response.Response {
|
func (f *AlertmanagerApiHandler) handleRoutePostTestGrafanaReceivers(ctx *contextmodel.ReqContext, conf apimodels.TestReceiversConfigBodyParams) response.Response {
|
||||||
return f.GrafanaSvc.RoutePostTestReceivers(ctx, conf)
|
return f.GrafanaSvc.RoutePostTestReceivers(ctx, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *AlertmanagerApiHandler) handleRoutePostTestGrafanaTemplates(ctx *contextmodel.ReqContext, conf apimodels.TestTemplatesConfigBodyParams) response.Response {
|
||||||
|
return f.GrafanaSvc.RoutePostTestTemplates(ctx, conf)
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@ type AlertmanagerApi interface {
|
|||||||
RoutePostGrafanaAlertingConfig(*contextmodel.ReqContext) response.Response
|
RoutePostGrafanaAlertingConfig(*contextmodel.ReqContext) response.Response
|
||||||
RoutePostGrafanaAlertingConfigHistoryActivate(*contextmodel.ReqContext) response.Response
|
RoutePostGrafanaAlertingConfigHistoryActivate(*contextmodel.ReqContext) response.Response
|
||||||
RoutePostTestGrafanaReceivers(*contextmodel.ReqContext) response.Response
|
RoutePostTestGrafanaReceivers(*contextmodel.ReqContext) response.Response
|
||||||
|
RoutePostTestGrafanaTemplates(*contextmodel.ReqContext) response.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *AlertmanagerApiHandler) RouteCreateGrafanaSilence(ctx *contextmodel.ReqContext) response.Response {
|
func (f *AlertmanagerApiHandler) RouteCreateGrafanaSilence(ctx *contextmodel.ReqContext) response.Response {
|
||||||
@ -181,6 +182,14 @@ func (f *AlertmanagerApiHandler) RoutePostTestGrafanaReceivers(ctx *contextmodel
|
|||||||
}
|
}
|
||||||
return f.handleRoutePostTestGrafanaReceivers(ctx, conf)
|
return f.handleRoutePostTestGrafanaReceivers(ctx, conf)
|
||||||
}
|
}
|
||||||
|
func (f *AlertmanagerApiHandler) RoutePostTestGrafanaTemplates(ctx *contextmodel.ReqContext) response.Response {
|
||||||
|
// Parse Request Body
|
||||||
|
conf := apimodels.TestTemplatesConfigBodyParams{}
|
||||||
|
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||||
|
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||||
|
}
|
||||||
|
return f.handleRoutePostTestGrafanaTemplates(ctx, conf)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics.API) {
|
func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics.API) {
|
||||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||||
@ -434,5 +443,15 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics
|
|||||||
m,
|
m,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
group.Post(
|
||||||
|
toMacaronPath("/api/alertmanager/grafana/config/api/v1/templates/test"),
|
||||||
|
api.authorize(http.MethodPost, "/api/alertmanager/grafana/config/api/v1/templates/test"),
|
||||||
|
metrics.Instrument(
|
||||||
|
http.MethodPost,
|
||||||
|
"/api/alertmanager/grafana/config/api/v1/templates/test",
|
||||||
|
api.Hooks.Wrap(srv.RoutePostTestGrafanaTemplates),
|
||||||
|
m,
|
||||||
|
),
|
||||||
|
)
|
||||||
}, middleware.ReqSignedIn)
|
}, middleware.ReqSignedIn)
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,10 @@
|
|||||||
"AlertingRule": {
|
"AlertingRule": {
|
||||||
"description": "adapted from cortex",
|
"description": "adapted from cortex",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"activeAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Alert"
|
"$ref": "#/definitions/Alert"
|
||||||
@ -339,6 +343,20 @@
|
|||||||
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"totalsFiltered": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/definitions/RuleType"
|
"$ref": "#/definitions/RuleType"
|
||||||
}
|
}
|
||||||
@ -350,7 +368,7 @@
|
|||||||
"type",
|
"type",
|
||||||
"state",
|
"state",
|
||||||
"annotations",
|
"annotations",
|
||||||
"alerts"
|
"activeAt"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@ -2845,6 +2863,13 @@
|
|||||||
"$ref": "#/definitions/RuleGroup"
|
"$ref": "#/definitions/RuleGroup"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -2878,6 +2903,13 @@
|
|||||||
"$ref": "#/definitions/AlertingRule"
|
"$ref": "#/definitions/AlertingRule"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -3343,6 +3375,77 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"TestTemplatesConfigBodyParams": {
|
||||||
|
"properties": {
|
||||||
|
"alerts": {
|
||||||
|
"description": "Alerts to use as data when testing the template.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/postableAlert"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the template file.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"description": "Template string to test.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesErrorResult": {
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"description": "Kind of template error that occurred.",
|
||||||
|
"enum": [
|
||||||
|
"invalid_template",
|
||||||
|
"execution_error"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"description": "Error message.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template for this error. Will be empty if the Kind is \"invalid_template\".",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesResult": {
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template definition for this result.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"description": "Interpolated value of the template.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesResults": {
|
||||||
|
"properties": {
|
||||||
|
"errors": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesErrorResult"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesResult"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Threshold": {
|
"Threshold": {
|
||||||
"description": "Threshold a single step on the threshold list",
|
"description": "Threshold a single step on the threshold list",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -3644,7 +3747,6 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"alertGroup": {
|
"alertGroup": {
|
||||||
"description": "AlertGroup alert group",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"description": "alerts",
|
"description": "alerts",
|
||||||
@ -3829,13 +3931,13 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"gettableAlerts": {
|
"gettableAlerts": {
|
||||||
|
"description": "GettableAlerts gettable alerts",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/gettableAlert"
|
"$ref": "#/definitions/gettableAlert"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"gettableSilence": {
|
"gettableSilence": {
|
||||||
"description": "GettableSilence gettable silence",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"comment": {
|
"comment": {
|
||||||
"description": "comment",
|
"description": "comment",
|
||||||
@ -3891,7 +3993,6 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
"description": "Integration integration",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"lastNotifyAttempt": {
|
"lastNotifyAttempt": {
|
||||||
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
|
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
|
||||||
@ -4035,7 +4136,6 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"postableSilence": {
|
"postableSilence": {
|
||||||
"description": "PostableSilence postable silence",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"comment": {
|
"comment": {
|
||||||
"description": "comment",
|
"description": "comment",
|
||||||
@ -4073,6 +4173,7 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"receiver": {
|
"receiver": {
|
||||||
|
"description": "Receiver receiver",
|
||||||
"properties": {
|
"properties": {
|
||||||
"active": {
|
"active": {
|
||||||
"description": "active",
|
"description": "active",
|
||||||
|
@ -168,6 +168,19 @@ import (
|
|||||||
// 408: Failure
|
// 408: Failure
|
||||||
// 409: AlertManagerNotReady
|
// 409: AlertManagerNotReady
|
||||||
|
|
||||||
|
// swagger:route POST /api/alertmanager/grafana/config/api/v1/templates/test alertmanager RoutePostTestGrafanaTemplates
|
||||||
|
//
|
||||||
|
// Test Grafana managed templates without saving them.
|
||||||
|
// Produces:
|
||||||
|
// - application/json
|
||||||
|
//
|
||||||
|
// Responses:
|
||||||
|
//
|
||||||
|
// 200: TestTemplatesResults
|
||||||
|
// 400: ValidationError
|
||||||
|
// 403: PermissionDenied
|
||||||
|
// 409: AlertManagerNotReady
|
||||||
|
|
||||||
// swagger:route GET /api/alertmanager/grafana/api/v2/silences alertmanager RouteGetGrafanaSilences
|
// swagger:route GET /api/alertmanager/grafana/api/v2/silences alertmanager RouteGetGrafanaSilences
|
||||||
//
|
//
|
||||||
// get silences
|
// get silences
|
||||||
@ -293,6 +306,56 @@ type TestReceiverConfigResult struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swagger:parameters RoutePostTestGrafanaTemplates
|
||||||
|
type TestTemplatesConfigParams struct {
|
||||||
|
// in:body
|
||||||
|
Body TestTemplatesConfigBodyParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestTemplatesConfigBodyParams struct {
|
||||||
|
// Alerts to use as data when testing the template.
|
||||||
|
Alerts []*amv2.PostableAlert `json:"alerts"`
|
||||||
|
|
||||||
|
// Template string to test.
|
||||||
|
Template string `json:"template"`
|
||||||
|
|
||||||
|
// Name of the template file.
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// swagger:model
|
||||||
|
type TestTemplatesResults struct {
|
||||||
|
Results []TestTemplatesResult `json:"results,omitempty"`
|
||||||
|
Errors []TestTemplatesErrorResult `json:"errors,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestTemplatesResult struct {
|
||||||
|
// Name of the associated template definition for this result.
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Interpolated value of the template.
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestTemplatesErrorResult struct {
|
||||||
|
// Name of the associated template for this error. Will be empty if the Kind is "invalid_template".
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
|
// Kind of template error that occurred.
|
||||||
|
Kind TemplateErrorKind `json:"kind"`
|
||||||
|
|
||||||
|
// Error message.
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// swagger:enum TemplateErrorKind
|
||||||
|
type TemplateErrorKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
InvalidTemplate TemplateErrorKind = "invalid_template"
|
||||||
|
ExecutionError TemplateErrorKind = "execution_error"
|
||||||
|
)
|
||||||
|
|
||||||
// swagger:parameters RouteCreateSilence RouteCreateGrafanaSilence
|
// swagger:parameters RouteCreateSilence RouteCreateGrafanaSilence
|
||||||
type CreateSilenceParams struct {
|
type CreateSilenceParams struct {
|
||||||
// in:body
|
// in:body
|
||||||
|
@ -299,6 +299,10 @@
|
|||||||
"AlertingRule": {
|
"AlertingRule": {
|
||||||
"description": "adapted from cortex",
|
"description": "adapted from cortex",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"activeAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/Alert"
|
"$ref": "#/definitions/Alert"
|
||||||
@ -339,6 +343,20 @@
|
|||||||
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"totalsFiltered": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/definitions/RuleType"
|
"$ref": "#/definitions/RuleType"
|
||||||
}
|
}
|
||||||
@ -350,7 +368,7 @@
|
|||||||
"type",
|
"type",
|
||||||
"state",
|
"state",
|
||||||
"annotations",
|
"annotations",
|
||||||
"alerts"
|
"activeAt"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@ -2845,6 +2863,13 @@
|
|||||||
"$ref": "#/definitions/RuleGroup"
|
"$ref": "#/definitions/RuleGroup"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -2878,6 +2903,13 @@
|
|||||||
"$ref": "#/definitions/AlertingRule"
|
"$ref": "#/definitions/AlertingRule"
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"additionalProperties": {
|
||||||
|
"format": "int64",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@ -3343,6 +3375,77 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"TestTemplatesConfigBodyParams": {
|
||||||
|
"properties": {
|
||||||
|
"alerts": {
|
||||||
|
"description": "Alerts to use as data when testing the template.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/postableAlert"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the template file.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"description": "Template string to test.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesErrorResult": {
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"description": "Kind of template error that occurred.",
|
||||||
|
"enum": [
|
||||||
|
"invalid_template",
|
||||||
|
"execution_error"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"description": "Error message.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template for this error. Will be empty if the Kind is \"invalid_template\".",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesResult": {
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template definition for this result.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"description": "Interpolated value of the template.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"TestTemplatesResults": {
|
||||||
|
"properties": {
|
||||||
|
"errors": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesErrorResult"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesResult"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Threshold": {
|
"Threshold": {
|
||||||
"description": "Threshold a single step on the threshold list",
|
"description": "Threshold a single step on the threshold list",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -3668,6 +3771,7 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"alertGroups": {
|
"alertGroups": {
|
||||||
|
"description": "AlertGroups alert groups",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/alertGroup"
|
"$ref": "#/definitions/alertGroup"
|
||||||
},
|
},
|
||||||
@ -3888,6 +3992,7 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
|
"description": "Integration integration",
|
||||||
"properties": {
|
"properties": {
|
||||||
"lastNotifyAttempt": {
|
"lastNotifyAttempt": {
|
||||||
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
|
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
|
||||||
@ -4031,7 +4136,6 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"postableSilence": {
|
"postableSilence": {
|
||||||
"description": "PostableSilence postable silence",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"comment": {
|
"comment": {
|
||||||
"description": "comment",
|
"description": "comment",
|
||||||
@ -4606,6 +4710,53 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/alertmanager/grafana/config/api/v1/templates/test": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "RoutePostTestGrafanaTemplates",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "Body",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesConfigBodyParams"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "TestTemplatesResults",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesResults"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "ValidationError",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ValidationError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "PermissionDenied",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/PermissionDenied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "AlertManagerNotReady",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/AlertManagerNotReady"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Test Grafana managed templates without saving them.",
|
||||||
|
"tags": [
|
||||||
|
"alertmanager"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/alertmanager/grafana/config/history": {
|
"/api/alertmanager/grafana/config/history": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "gets Alerting configurations that were successfully applied in the past",
|
"description": "gets Alerting configurations that were successfully applied in the past",
|
||||||
|
@ -435,6 +435,53 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/alertmanager/grafana/config/api/v1/templates/test": {
|
||||||
|
"post": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"alertmanager"
|
||||||
|
],
|
||||||
|
"summary": "Test Grafana managed templates without saving them.",
|
||||||
|
"operationId": "RoutePostTestGrafanaTemplates",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "Body",
|
||||||
|
"in": "body",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesConfigBodyParams"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "TestTemplatesResults",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesResults"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "ValidationError",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ValidationError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "PermissionDenied",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/PermissionDenied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"409": {
|
||||||
|
"description": "AlertManagerNotReady",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/AlertManagerNotReady"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/alertmanager/grafana/config/history": {
|
"/api/alertmanager/grafana/config/history": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "gets Alerting configurations that were successfully applied in the past",
|
"description": "gets Alerting configurations that were successfully applied in the past",
|
||||||
@ -3016,9 +3063,13 @@
|
|||||||
"type",
|
"type",
|
||||||
"state",
|
"state",
|
||||||
"annotations",
|
"annotations",
|
||||||
"alerts"
|
"activeAt"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"activeAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
"alerts": {
|
"alerts": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
@ -3059,6 +3110,20 @@
|
|||||||
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
"description": "State can be \"pending\", \"firing\", \"inactive\".",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"totalsFiltered": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/definitions/RuleType"
|
"$ref": "#/definitions/RuleType"
|
||||||
}
|
}
|
||||||
@ -5563,6 +5628,13 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/RuleGroup"
|
"$ref": "#/definitions/RuleGroup"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -5599,6 +5671,13 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/AlertingRule"
|
"$ref": "#/definitions/AlertingRule"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -6057,6 +6136,77 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"TestTemplatesConfigBodyParams": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"alerts": {
|
||||||
|
"description": "Alerts to use as data when testing the template.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/postableAlert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the template file.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"description": "Template string to test.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TestTemplatesErrorResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"description": "Kind of template error that occurred.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"invalid_template",
|
||||||
|
"execution_error"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"description": "Error message.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template for this error. Will be empty if the Kind is \"invalid_template\".",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TestTemplatesResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "Name of the associated template definition for this result.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"description": "Interpolated value of the template.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TestTemplatesResults": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"errors": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesErrorResult"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/TestTemplatesResult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Threshold": {
|
"Threshold": {
|
||||||
"description": "Threshold a single step on the threshold list",
|
"description": "Threshold a single step on the threshold list",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -6383,6 +6533,7 @@
|
|||||||
"$ref": "#/definitions/alertGroup"
|
"$ref": "#/definitions/alertGroup"
|
||||||
},
|
},
|
||||||
"alertGroups": {
|
"alertGroups": {
|
||||||
|
"description": "AlertGroups alert groups",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/alertGroup"
|
"$ref": "#/definitions/alertGroup"
|
||||||
@ -6608,6 +6759,7 @@
|
|||||||
"$ref": "#/definitions/gettableSilences"
|
"$ref": "#/definitions/gettableSilences"
|
||||||
},
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
|
"description": "Integration integration",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"name",
|
"name",
|
||||||
@ -6752,7 +6904,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postableSilence": {
|
"postableSilence": {
|
||||||
"description": "PostableSilence postable silence",
|
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"comment",
|
"comment",
|
||||||
|
@ -117,7 +117,8 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
|
|||||||
}
|
}
|
||||||
|
|
||||||
amcfg := &alertingNotify.GrafanaAlertmanagerConfig{
|
amcfg := &alertingNotify.GrafanaAlertmanagerConfig{
|
||||||
WorkingDirectory: workingDir,
|
WorkingDirectory: filepath.Join(cfg.DataPath, workingDir, strconv.Itoa(int(orgID))),
|
||||||
|
ExternalURL: cfg.AppURL,
|
||||||
AlertStoreCallback: nil,
|
AlertStoreCallback: nil,
|
||||||
PeerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
PeerTimeout: cfg.UnifiedAlerting.HAPeerTimeout,
|
||||||
Silences: silencesOptions,
|
Silences: silencesOptions,
|
||||||
@ -259,9 +260,10 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
|||||||
cfg.TemplateFiles = map[string]string{}
|
cfg.TemplateFiles = map[string]string{}
|
||||||
}
|
}
|
||||||
cfg.TemplateFiles["__default__.tmpl"] = alertingTemplates.DefaultTemplateString
|
cfg.TemplateFiles["__default__.tmpl"] = alertingTemplates.DefaultTemplateString
|
||||||
|
cfg.AlertmanagerConfig.Templates = append(cfg.AlertmanagerConfig.Templates, "__default__.tmpl")
|
||||||
|
|
||||||
// next, we need to make sure we persist the templates to disk.
|
// next, we need to make sure we persist the templates to disk.
|
||||||
paths, templatesChanged, err := PersistTemplates(cfg, am.WorkingDirPath())
|
_, templatesChanged, err := PersistTemplates(cfg, am.Base.WorkingDirectory())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -272,18 +274,11 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the templates persisted, create the template list using the paths.
|
|
||||||
tmpl, err := am.Base.TemplateFromPaths(am.Settings.AppURL, paths...)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = am.Base.ApplyConfig(AlertingConfiguration{
|
err = am.Base.ApplyConfig(AlertingConfiguration{
|
||||||
RawAlertmanagerConfig: rawConfig,
|
rawAlertmanagerConfig: rawConfig,
|
||||||
AlertmanagerConfig: cfg.AlertmanagerConfig,
|
alertmanagerConfig: cfg.AlertmanagerConfig,
|
||||||
AlertmanagerTemplates: tmpl,
|
receivers: PostableApiAlertingConfigToApiReceivers(cfg.AlertmanagerConfig),
|
||||||
IntegrationsFunc: am.buildIntegrationsMap,
|
receiverIntegrationsFunc: am.buildReceiverIntegrations,
|
||||||
ReceiverIntegrationsFunc: am.buildReceiverIntegration,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -310,22 +305,8 @@ func (am *Alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) WorkingDirPath() string {
|
func (am *Alertmanager) AppURL() string {
|
||||||
return filepath.Join(am.Settings.DataPath, workingDir, strconv.Itoa(int(am.orgID)))
|
return am.Settings.AppURL
|
||||||
}
|
|
||||||
|
|
||||||
// buildIntegrationsMap builds a map of name to the list of Grafana integration notifiers off of a list of receiver config.
|
|
||||||
func (am *Alertmanager) buildIntegrationsMap(receivers []*alertingNotify.APIReceiver, templates *alertingTemplates.Template) (map[string][]*alertingNotify.Integration, error) {
|
|
||||||
integrationsMap := make(map[string][]*alertingNotify.Integration, len(receivers))
|
|
||||||
for _, receiver := range receivers {
|
|
||||||
integrations, err := am.buildReceiverIntegrations(receiver, templates)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
integrationsMap[receiver.Name] = integrations
|
|
||||||
}
|
|
||||||
|
|
||||||
return integrationsMap, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
|
// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
|
||||||
@ -356,23 +337,6 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIRe
|
|||||||
return integrations, nil
|
return integrations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) buildReceiverIntegration(r *alertingNotify.GrafanaIntegrationConfig, tmpl *alertingTemplates.Template) (*alertingNotify.Integration, error) {
|
|
||||||
apiReceiver := &alertingNotify.APIReceiver{
|
|
||||||
GrafanaIntegrations: alertingNotify.GrafanaIntegrations{
|
|
||||||
Integrations: []*alertingNotify.GrafanaIntegrationConfig{r},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
integrations, err := am.buildReceiverIntegrations(apiReceiver, tmpl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(integrations) == 0 {
|
|
||||||
// This should not happen, but it is better to return some error rather than having a panic.
|
|
||||||
return nil, fmt.Errorf("failed to build integration")
|
|
||||||
}
|
|
||||||
return integrations[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutAlerts receives the alerts and then sends them through the corresponding route based on whenever the alert has a receiver embedded or not
|
// PutAlerts receives the alerts and then sends them through the corresponding route based on whenever the alert has a receiver embedded or not
|
||||||
func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error {
|
func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error {
|
||||||
alerts := make(alertingNotify.PostableAlerts, 0, len(postableAlerts.PostableAlerts))
|
alerts := make(alertingNotify.PostableAlerts, 0, len(postableAlerts.PostableAlerts))
|
||||||
|
@ -22,6 +22,7 @@ func setupAMTest(t *testing.T) *Alertmanager {
|
|||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
cfg := &setting.Cfg{
|
cfg := &setting.Cfg{
|
||||||
DataPath: dir,
|
DataPath: dir,
|
||||||
|
AppURL: "http://localhost:9093",
|
||||||
}
|
}
|
||||||
|
|
||||||
m := metrics.NewAlertmanagerMetrics(prometheus.NewRegistry())
|
m := metrics.NewAlertmanagerMetrics(prometheus.NewRegistry())
|
||||||
|
@ -92,18 +92,16 @@ func Load(rawConfig []byte) (*api.PostableUserConfig, error) {
|
|||||||
// AlertingConfiguration provides configuration for an Alertmanager.
|
// AlertingConfiguration provides configuration for an Alertmanager.
|
||||||
// It implements the notify.Configuration interface.
|
// It implements the notify.Configuration interface.
|
||||||
type AlertingConfiguration struct {
|
type AlertingConfiguration struct {
|
||||||
AlertmanagerConfig api.PostableApiAlertingConfig
|
alertmanagerConfig api.PostableApiAlertingConfig
|
||||||
RawAlertmanagerConfig []byte
|
rawAlertmanagerConfig []byte
|
||||||
|
|
||||||
AlertmanagerTemplates *alertingTemplates.Template
|
receivers []*alertingNotify.APIReceiver
|
||||||
|
receiverIntegrationsFunc func(r *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error)
|
||||||
IntegrationsFunc func(receivers []*alertingNotify.APIReceiver, templates *alertingTemplates.Template) (map[string][]*alertingNotify.Integration, error)
|
|
||||||
ReceiverIntegrationsFunc func(r *alertingNotify.GrafanaIntegrationConfig, tmpl *alertingTemplates.Template) (*alertingNotify.Integration, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) BuildReceiverIntegrationsFunc() func(next *alertingNotify.GrafanaIntegrationConfig, tmpl *alertingTemplates.Template) (alertingNotify.Notifier, error) {
|
func (a AlertingConfiguration) BuildReceiverIntegrationsFunc() func(next *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) {
|
||||||
return func(next *alertingNotify.GrafanaIntegrationConfig, tmpl *alertingTemplates.Template) (alertingNotify.Notifier, error) {
|
return func(next *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) {
|
||||||
return a.ReceiverIntegrationsFunc(next, tmpl)
|
return a.receiverIntegrationsFunc(next, tmpl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,29 +110,29 @@ func (a AlertingConfiguration) DispatcherLimits() alertingNotify.DispatcherLimit
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) InhibitRules() []alertingNotify.InhibitRule {
|
func (a AlertingConfiguration) InhibitRules() []alertingNotify.InhibitRule {
|
||||||
return a.AlertmanagerConfig.InhibitRules
|
return a.alertmanagerConfig.InhibitRules
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) MuteTimeIntervals() []alertingNotify.MuteTimeInterval {
|
func (a AlertingConfiguration) MuteTimeIntervals() []alertingNotify.MuteTimeInterval {
|
||||||
return a.AlertmanagerConfig.MuteTimeIntervals
|
return a.alertmanagerConfig.MuteTimeIntervals
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) ReceiverIntegrations() (map[string][]*alertingNotify.Integration, error) {
|
func (a AlertingConfiguration) Receivers() []*alertingNotify.APIReceiver {
|
||||||
return a.IntegrationsFunc(PostableApiAlertingConfigToApiReceivers(a.AlertmanagerConfig), a.AlertmanagerTemplates)
|
return a.receivers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) RoutingTree() *alertingNotify.Route {
|
func (a AlertingConfiguration) RoutingTree() *alertingNotify.Route {
|
||||||
return a.AlertmanagerConfig.Route.AsAMRoute()
|
return a.alertmanagerConfig.Route.AsAMRoute()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) Templates() *alertingTemplates.Template {
|
func (a AlertingConfiguration) Templates() []string {
|
||||||
return a.AlertmanagerTemplates
|
return a.alertmanagerConfig.Templates
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) Hash() [16]byte {
|
func (a AlertingConfiguration) Hash() [16]byte {
|
||||||
return md5.Sum(a.RawAlertmanagerConfig)
|
return md5.Sum(a.rawAlertmanagerConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) Raw() []byte {
|
func (a AlertingConfiguration) Raw() []byte {
|
||||||
return a.RawAlertmanagerConfig
|
return a.rawAlertmanagerConfig
|
||||||
}
|
}
|
||||||
|
63
pkg/services/ngalert/notifier/templates.go
Normal file
63
pkg/services/ngalert/notifier/templates.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
alertingModels "github.com/grafana/alerting/models"
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
amv2 "github.com/prometheus/alertmanager/api/v2/models"
|
||||||
|
prometheusModel "github.com/prometheus/common/model"
|
||||||
|
|
||||||
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestTemplatesResults = alertingNotify.TestTemplatesResults
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultLabels = map[string]string{
|
||||||
|
prometheusModel.AlertNameLabel: `alert title`,
|
||||||
|
alertingModels.FolderTitleLabel: `folder title`,
|
||||||
|
}
|
||||||
|
DefaultAnnotations = map[string]string{
|
||||||
|
alertingModels.ValuesAnnotation: `{"B":22,"C":1}`,
|
||||||
|
alertingModels.ValueStringAnnotation: `[ var='B' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=22 ], [ var='C' labels={__name__=go_threads, instance=host.docker.internal:3000, job=grafana} value=1 ]`,
|
||||||
|
alertingModels.OrgIDAnnotation: `1`,
|
||||||
|
alertingModels.DashboardUIDAnnotation: `dashboard_uid`,
|
||||||
|
alertingModels.PanelIDAnnotation: `1`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestTemplate tests the given template string against the given alerts. Existing templates are used to provide context for the test.
|
||||||
|
// If an existing template of the same filename as the one being tested is found, it will not be used as context.
|
||||||
|
func (am *Alertmanager) TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*TestTemplatesResults, error) {
|
||||||
|
for _, alert := range c.Alerts {
|
||||||
|
addDefaultLabelsAndAnnotations(alert)
|
||||||
|
}
|
||||||
|
|
||||||
|
return am.Base.TestTemplate(ctx, alertingNotify.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: c.Alerts,
|
||||||
|
Template: c.Template,
|
||||||
|
Name: c.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// addDefaultLabelsAndAnnotations is a slimmed down version of schedule.stateToPostableAlert and schedule.getRuleExtraLabels using default values.
|
||||||
|
func addDefaultLabelsAndAnnotations(alert *amv2.PostableAlert) {
|
||||||
|
if alert.Labels == nil {
|
||||||
|
alert.Labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
for k, v := range DefaultLabels {
|
||||||
|
if _, ok := alert.Labels[k]; !ok {
|
||||||
|
alert.Labels[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if alert.Annotations == nil {
|
||||||
|
alert.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
for k, v := range DefaultAnnotations {
|
||||||
|
if _, ok := alert.Annotations[k]; !ok {
|
||||||
|
alert.Annotations[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
174
pkg/services/ngalert/notifier/templates_test.go
Normal file
174
pkg/services/ngalert/notifier/templates_test.go
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-openapi/strfmt"
|
||||||
|
alertingModels "github.com/grafana/alerting/models"
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
amv2 "github.com/prometheus/alertmanager/api/v2/models"
|
||||||
|
prometheusModel "github.com/prometheus/common/model"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
simpleAlert = amv2.PostableAlert{
|
||||||
|
Alert: amv2.Alert{
|
||||||
|
Labels: amv2.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"},
|
||||||
|
},
|
||||||
|
Annotations: amv2.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh", "__alertImageToken__": "test-image-1"},
|
||||||
|
StartsAt: strfmt.DateTime{},
|
||||||
|
EndsAt: strfmt.DateTime{},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTemplateDefaultData(t *testing.T) {
|
||||||
|
am := setupAMTest(t)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input apimodels.TestTemplatesConfigBodyParams
|
||||||
|
expected TestTemplatesResults
|
||||||
|
}{{
|
||||||
|
name: "check various extended data",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{&simpleAlert},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}
|
||||||
|
Receiver: {{ .Receiver }}
|
||||||
|
Status: {{ .Status }}
|
||||||
|
ExternalURL: {{ .ExternalURL }}
|
||||||
|
Alerts: {{ len .Alerts }}
|
||||||
|
Firing Alerts: {{ len .Alerts.Firing }}
|
||||||
|
Resolved Alerts: {{ len .Alerts.Resolved }}
|
||||||
|
GroupLabels: {{ range .GroupLabels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
|
||||||
|
CommonLabels: {{ range .CommonLabels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
|
||||||
|
CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
|
||||||
|
{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: "\nReceiver: TestReceiver\nStatus: firing\nExternalURL: http://localhost:9093\nAlerts: 1\nFiring Alerts: 1\nResolved Alerts: 0\nGroupLabels: group_label=group_label_value \nCommonLabels: alertname=alert1 grafana_folder=folder title lbl1=val1 \nCommonAnnotations: ann1=annv1 \n",
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "AlertNameLabel",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: fmt.Sprintf(`{{ define "slack.title" }}{{ index (index .Alerts 0 ).Labels "%s" }}{{ end }}`, prometheusModel.AlertNameLabel),
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: DefaultLabels[prometheusModel.AlertNameLabel],
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "FolderTitleLabel",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: fmt.Sprintf(`{{ define "slack.title" }}{{ index (index .Alerts 0 ).Labels "%s" }}{{ end }}`, alertingModels.FolderTitleLabel),
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: DefaultLabels[alertingModels.FolderTitleLabel],
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "ValuesAnnotation",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}{{ range $key, $value := (index .Alerts 0 ).Values }}{{ $key }}={{ $value }} {{ end }}{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: "B=22 C=1 ",
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "ValueStringAnnotation",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).ValueString }}{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: DefaultAnnotations[alertingModels.ValueStringAnnotation],
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "DashboardURL generation contains DashboardUIDAnnotation and OrgIDAnnotation ",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).DashboardURL }}{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: fmt.Sprintf("http://localhost:9093/d/%s?orgId=%s",
|
||||||
|
DefaultAnnotations[alertingModels.DashboardUIDAnnotation],
|
||||||
|
DefaultAnnotations[alertingModels.OrgIDAnnotation]),
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "PanelURL generation contains DashboardUIDAnnotation, PanelIDAnnotation, and OrgIDAnnotation ",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).PanelURL }}{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: fmt.Sprintf("http://localhost:9093/d/%s?orgId=%s&viewPanel=%s",
|
||||||
|
DefaultAnnotations[alertingModels.DashboardUIDAnnotation],
|
||||||
|
DefaultAnnotations[alertingModels.OrgIDAnnotation],
|
||||||
|
DefaultAnnotations[alertingModels.PanelIDAnnotation]),
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "GeneratorURL generation ",
|
||||||
|
input: apimodels.TestTemplatesConfigBodyParams{
|
||||||
|
Alerts: []*amv2.PostableAlert{{Alert: amv2.Alert{GeneratorURL: "http://localhost:3000"}}},
|
||||||
|
Name: "slack.title",
|
||||||
|
Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).GeneratorURL }}{{ end }}`,
|
||||||
|
},
|
||||||
|
expected: TestTemplatesResults{
|
||||||
|
Results: []alertingNotify.TestTemplatesResult{{
|
||||||
|
Name: "slack.title",
|
||||||
|
Text: fmt.Sprintf("http://localhost:3000?orgId=%s", DefaultAnnotations[alertingModels.OrgIDAnnotation]),
|
||||||
|
}},
|
||||||
|
Errors: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
res, err := am.TestTemplate(context.Background(), test.input)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expected, *res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -102,7 +102,7 @@ func TestIntegrationAlertmanagerConfigurationIsTransactional(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
var res map[string]interface{}
|
var res map[string]interface{}
|
||||||
require.NoError(t, json.Unmarshal(b, &res))
|
require.NoError(t, json.Unmarshal(b, &res))
|
||||||
require.Regexp(t, `^failed to save and apply Alertmanager configuration: failed to build integration map: failed to validate integration "slack.receiver" \(UID [^\)]+\) of type "slack": token must be specified when using the Slack chat API`, res["message"])
|
require.Regexp(t, `^failed to save and apply Alertmanager configuration: failed to validate integration "slack.receiver" \(UID [^\)]+\) of type "slack": token must be specified when using the Slack chat API`, res["message"])
|
||||||
resp = getRequest(t, alertConfigURL, http.StatusOK) // nolint
|
resp = getRequest(t, alertConfigURL, http.StatusOK) // nolint
|
||||||
|
|
||||||
require.JSONEq(t, defaultAlertmanagerConfigJSON, getBody(t, resp.Body))
|
require.JSONEq(t, defaultAlertmanagerConfigJSON, getBody(t, resp.Body))
|
||||||
|
Loading…
Reference in New Issue
Block a user