| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-27 15:55:47 +08:00
										 |  |  | 	"github.com/go-openapi/strfmt" | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 	alertingNotify "github.com/grafana/alerting/notify" | 
					
						
							| 
									
										
										
										
											2022-10-18 03:43:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/response" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2022-04-01 21:39:59 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | 	contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" | 
					
						
							| 
									
										
										
										
											2021-04-20 02:26:04 +08:00
										 |  |  | 	apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/notifier" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/store" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	defaultTestReceiversTimeout = 15 * time.Second | 
					
						
							|  |  |  | 	maxTestReceiversTimeout     = 30 * time.Second | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | type AlertmanagerSrv struct { | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	log    log.Logger | 
					
						
							|  |  |  | 	ac     accesscontrol.AccessControl | 
					
						
							|  |  |  | 	mam    *notifier.MultiOrgAlertmanager | 
					
						
							|  |  |  | 	crypto notifier.Crypto | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | type UnknownReceiverError struct { | 
					
						
							|  |  |  | 	UID string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e UnknownReceiverError) Error() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("unknown receiver: %s", e.UID) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAMStatus(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, am.GetStatus()) | 
					
						
							| 
									
										
										
										
											2021-06-16 00:14:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteCreateSilence(c *contextmodel.ReqContext, postableSilence apimodels.PostableSilence) response.Response { | 
					
						
							| 
									
										
										
										
											2022-04-27 15:55:47 +08:00
										 |  |  | 	err := postableSilence.Validate(strfmt.Default) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-09-05 00:46:34 +08:00
										 |  |  | 		srv.log.Error("Silence failed validation", "error", err) | 
					
						
							| 
									
										
										
										
											2022-04-27 15:55:47 +08:00
										 |  |  | 		return ErrResp(http.StatusBadRequest, err, "silence failed validation") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 21:39:59 +08:00
										 |  |  | 	action := accesscontrol.ActionAlertingInstanceUpdate | 
					
						
							|  |  |  | 	if postableSilence.ID == "" { | 
					
						
							|  |  |  | 		action = accesscontrol.ActionAlertingInstanceCreate | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-30 21:39:09 +08:00
										 |  |  | 	if !accesscontrol.HasAccess(srv.ac, c)(accesscontrol.EvalPermission(action)) { | 
					
						
							| 
									
										
										
										
											2022-04-01 21:39:59 +08:00
										 |  |  | 		errAction := "update" | 
					
						
							|  |  |  | 		if postableSilence.ID == "" { | 
					
						
							|  |  |  | 			errAction = "create" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return ErrResp(http.StatusUnauthorized, fmt.Errorf("user is not authorized to %s silences", errAction), "") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 18:36:11 +08:00
										 |  |  | 	silenceID, err := am.CreateSilence(c.Req.Context(), &postableSilence) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrSilenceNotFound) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusNotFound, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrCreateSilenceBadPayload) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to create silence") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-18 03:43:37 +08:00
										 |  |  | 	return response.JSON(http.StatusAccepted, apimodels.PostSilencesOKBody{ | 
					
						
							|  |  |  | 		SilenceID: silenceID, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteDeleteAlertingConfig(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 17:22:09 +08:00
										 |  |  | 	if err := am.SaveAndApplyDefaultConfig(c.Req.Context()); err != nil { | 
					
						
							| 
									
										
										
										
											2023-09-05 00:46:34 +08:00
										 |  |  | 		srv.log.Error("Unable to save and apply default alertmanager configuration", "error", err) | 
					
						
							| 
									
										
										
										
											2021-07-17 01:07:31 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to save and apply default Alertmanager configuration") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration deleted; the default is applied"}) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteDeleteSilence(c *contextmodel.ReqContext, silenceID string) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 18:36:11 +08:00
										 |  |  | 	if err := am.DeleteSilence(c.Req.Context(), silenceID); err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrSilenceNotFound) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusNotFound, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, util.DynMap{"message": "silence deleted"}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAlertingConfig(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	config, err := srv.mam.GetAlertmanagerConfiguration(c.Req.Context(), c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-04-05 22:03:00 +08:00
										 |  |  | 		if errors.Is(err, store.ErrNoAlertmanagerConfiguration) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusNotFound, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-05 22:03:00 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, err.Error()) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	return response.JSON(http.StatusOK, config) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-01 04:43:04 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAlertingConfigHistory(c *contextmodel.ReqContext) response.Response { | 
					
						
							|  |  |  | 	limit := c.QueryInt("limit") | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	configs, err := srv.mam.GetAppliedAlertmanagerConfigurations(c.Req.Context(), c.SignedInUser.GetOrgID(), limit) | 
					
						
							| 
									
										
										
										
											2023-04-01 04:43:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusInternalServerError, err, err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, configs) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAMAlertGroups(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	groups, err := am.GetAlertGroups( | 
					
						
							| 
									
										
										
										
											2023-10-19 17:27:37 +08:00
										 |  |  | 		c.Req.Context(), | 
					
						
							| 
									
										
										
										
											2021-04-21 18:34:42 +08:00
										 |  |  | 		c.QueryBoolWithDefault("active", true), | 
					
						
							|  |  |  | 		c.QueryBoolWithDefault("silenced", true), | 
					
						
							|  |  |  | 		c.QueryBoolWithDefault("inhibited", true), | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		c.QueryStrings("filter"), | 
					
						
							|  |  |  | 		c.Query("receiver"), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrGetAlertGroupsBadPayload) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// any other error here should be an unexpected failure and thus an internal error
 | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, groups) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAMAlerts(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	alerts, err := am.GetAlerts( | 
					
						
							| 
									
										
										
										
											2023-10-19 17:27:37 +08:00
										 |  |  | 		c.Req.Context(), | 
					
						
							| 
									
										
										
										
											2021-04-21 18:34:42 +08:00
										 |  |  | 		c.QueryBoolWithDefault("active", true), | 
					
						
							|  |  |  | 		c.QueryBoolWithDefault("silenced", true), | 
					
						
							|  |  |  | 		c.QueryBoolWithDefault("inhibited", true), | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		c.QueryStrings("filter"), | 
					
						
							|  |  |  | 		c.Query("receiver"), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrGetAlertsBadPayload) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrGetAlertsUnavailable) { | 
					
						
							| 
									
										
										
										
											2021-07-12 13:45:16 +08:00
										 |  |  | 			return ErrResp(http.StatusServiceUnavailable, err, "") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		// any other error here should be an unexpected failure and thus an internal error
 | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, alerts) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetSilence(c *contextmodel.ReqContext, silenceID string) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 18:36:11 +08:00
										 |  |  | 	gettableSilence, err := am.GetSilence(c.Req.Context(), silenceID) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrSilenceNotFound) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusNotFound, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// any other error here should be an unexpected failure and thus an internal error
 | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, gettableSilence) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetSilences(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 18:36:11 +08:00
										 |  |  | 	gettableSilences, err := am.ListSilences(c.Req.Context(), c.QueryStrings("filter")) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrListSilencesBadPayload) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// any other error here should be an unexpected failure and thus an internal error
 | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, gettableSilences) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-06 02:10:03 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostGrafanaAlertingConfigHistoryActivate(c *contextmodel.ReqContext, id string) response.Response { | 
					
						
							|  |  |  | 	confId, err := strconv.ParseInt(id, 10, 64) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusBadRequest, err, "failed to parse config id") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	err = srv.mam.ActivateHistoricalConfiguration(c.Req.Context(), c.SignedInUser.GetOrgID(), confId) | 
					
						
							| 
									
										
										
										
											2023-04-06 02:10:03 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		var unknownReceiverError notifier.UnknownReceiverError | 
					
						
							|  |  |  | 		if errors.As(err, &unknownReceiverError) { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, unknownReceiverError, "") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var configRejectedError notifier.AlertmanagerConfigRejectedError | 
					
						
							|  |  |  | 		if errors.As(err, &configRejectedError) { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, configRejectedError, "") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if errors.Is(err, store.ErrNoAlertmanagerConfiguration) { | 
					
						
							|  |  |  | 			return response.Error(http.StatusNotFound, err.Error(), err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) { | 
					
						
							|  |  |  | 			return response.Error(http.StatusNotFound, err.Error(), err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.ErrAlertmanagerNotReady) { | 
					
						
							|  |  |  | 			return response.Error(http.StatusConflict, err.Error(), err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration activated"}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *contextmodel.ReqContext, body apimodels.PostableUserConfig) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	currentConfig, err := srv.mam.GetAlertmanagerConfiguration(c.Req.Context(), c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2022-06-04 20:55:46 +08:00
										 |  |  | 	// If a config is present and valid we proceed with the guard, otherwise we
 | 
					
						
							|  |  |  | 	// just bypass the guard which is okay as we are anyway in an invalid state.
 | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		if err := srv.provenanceGuard(currentConfig, body); err != nil { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	err = srv.mam.ApplyAlertmanagerConfiguration(c.Req.Context(), c.SignedInUser.GetOrgID(), body) | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration created"}) | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	var unknownReceiverError notifier.UnknownReceiverError | 
					
						
							|  |  |  | 	if errors.As(err, &unknownReceiverError) { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusBadRequest, unknownReceiverError, "") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	var configRejectedError notifier.AlertmanagerConfigRejectedError | 
					
						
							|  |  |  | 	if errors.As(err, &configRejectedError) { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusBadRequest, configRejectedError, "") | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusNotFound, err.Error(), err) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	if errors.Is(err, notifier.ErrAlertmanagerNotReady) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusConflict, err.Error(), err) | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-15 02:06:21 +08:00
										 |  |  | 	return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetReceivers(c *contextmodel.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2022-10-03 21:58:41 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rcvs := am.GetReceivers(c.Req.Context()) | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, rcvs) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostTestReceivers(c *contextmodel.ReqContext, body apimodels.TestReceiversConfigBodyParams) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	if err := srv.crypto.ProcessSecureSettings(c.Req.Context(), c.SignedInUser.GetOrgID(), body.Receivers); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		var unknownReceiverError UnknownReceiverError | 
					
						
							|  |  |  | 		if errors.As(err, &unknownReceiverError) { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to post process Alertmanager configuration") | 
					
						
							| 
									
										
										
										
											2021-05-10 20:30:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	ctx, cancelFunc, err := contextWithTimeoutFromRequest( | 
					
						
							|  |  |  | 		c.Req.Context(), | 
					
						
							| 
									
										
										
										
											2021-09-01 17:18:30 +08:00
										 |  |  | 		c.Req, | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		defaultTestReceiversTimeout, | 
					
						
							|  |  |  | 		maxTestReceiversTimeout) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	defer cancelFunc() | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, err := am.TestReceivers(ctx, body) | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-04 00:36:49 +08:00
										 |  |  | 		if errors.Is(err, alertingNotify.ErrNoReceivers) { | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 			return response.Error(http.StatusBadRequest, "", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return response.Error(http.StatusInternalServerError, "", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(statusForTestReceivers(result.Receivers), newTestReceiversResult(result)) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-28 22:56:59 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostTestTemplates(c *contextmodel.ReqContext, body apimodels.TestTemplatesConfigBodyParams) response.Response { | 
					
						
							| 
									
										
										
										
											2023-10-09 16:40:19 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.SignedInUser.GetOrgID()) | 
					
						
							| 
									
										
										
										
											2023-04-28 22:56:59 +08:00
										 |  |  | 	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)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | // contextWithTimeoutFromRequest returns a context with a deadline set from 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
 | 
					
						
							|  |  |  | // header cannot exceed the maximum timeout.
 | 
					
						
							|  |  |  | func contextWithTimeoutFromRequest(ctx context.Context, r *http.Request, defaultTimeout, maxTimeout time.Duration) (context.Context, context.CancelFunc, error) { | 
					
						
							|  |  |  | 	timeout := defaultTimeout | 
					
						
							|  |  |  | 	if s := strings.TrimSpace(r.Header.Get("Request-Timeout")); s != "" { | 
					
						
							|  |  |  | 		// the timeout is measured in seconds
 | 
					
						
							|  |  |  | 		v, err := strconv.ParseInt(s, 10, 16) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if d := time.Duration(v) * time.Second; d < maxTimeout { | 
					
						
							|  |  |  | 			timeout = d | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return nil, nil, fmt.Errorf("exceeded maximum timeout of %d seconds", maxTimeout) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ctx, cancelFunc := context.WithTimeout(ctx, timeout) | 
					
						
							|  |  |  | 	return ctx, cancelFunc, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newTestReceiversResult(r *notifier.TestReceiversResult) apimodels.TestReceiversResult { | 
					
						
							|  |  |  | 	v := apimodels.TestReceiversResult{ | 
					
						
							| 
									
										
										
										
											2021-10-21 20:47:06 +08:00
										 |  |  | 		Alert: apimodels.TestReceiversConfigAlertParams{ | 
					
						
							|  |  |  | 			Annotations: r.Alert.Annotations, | 
					
						
							|  |  |  | 			Labels:      r.Alert.Labels, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Receivers:  make([]apimodels.TestReceiverResult, len(r.Receivers)), | 
					
						
							|  |  |  | 		NotifiedAt: r.NotifedAt, | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for ix, next := range r.Receivers { | 
					
						
							|  |  |  | 		configs := make([]apimodels.TestReceiverConfigResult, len(next.Configs)) | 
					
						
							|  |  |  | 		for jx, config := range next.Configs { | 
					
						
							|  |  |  | 			configs[jx].Name = config.Name | 
					
						
							|  |  |  | 			configs[jx].UID = config.UID | 
					
						
							|  |  |  | 			configs[jx].Status = config.Status | 
					
						
							|  |  |  | 			if config.Error != nil { | 
					
						
							|  |  |  | 				configs[jx].Error = config.Error.Error() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		v.Receivers[ix].Configs = configs | 
					
						
							|  |  |  | 		v.Receivers[ix].Name = next.Name | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // statusForTestReceivers returns the appropriate status code for the response
 | 
					
						
							|  |  |  | // for the results.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // It returns an HTTP 200 OK status code if notifications were sent to all receivers,
 | 
					
						
							|  |  |  | // an HTTP 400 Bad Request status code if all receivers contain invalid configuration,
 | 
					
						
							|  |  |  | // an HTTP 408 Request Timeout status code if all receivers timed out when sending
 | 
					
						
							|  |  |  | // a test notification or an HTTP 207 Multi Status.
 | 
					
						
							|  |  |  | func statusForTestReceivers(v []notifier.TestReceiverResult) int { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		numBadRequests   int | 
					
						
							|  |  |  | 		numTimeouts      int | 
					
						
							|  |  |  | 		numUnknownErrors int | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	for _, receiver := range v { | 
					
						
							|  |  |  | 		for _, next := range receiver.Configs { | 
					
						
							|  |  |  | 			if next.Error != nil { | 
					
						
							|  |  |  | 				var ( | 
					
						
							| 
									
										
										
										
											2023-04-26 01:39:46 +08:00
										 |  |  | 					invalidReceiverErr alertingNotify.IntegrationValidationError | 
					
						
							|  |  |  | 					receiverTimeoutErr alertingNotify.IntegrationTimeoutError | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 				) | 
					
						
							|  |  |  | 				if errors.As(next.Error, &invalidReceiverErr) { | 
					
						
							|  |  |  | 					numBadRequests += 1 | 
					
						
							|  |  |  | 				} else if errors.As(next.Error, &receiverTimeoutErr) { | 
					
						
							|  |  |  | 					numTimeouts += 1 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					numUnknownErrors += 1 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if numBadRequests == len(v) { | 
					
						
							|  |  |  | 		// if all receivers contain invalid configuration
 | 
					
						
							|  |  |  | 		return http.StatusBadRequest | 
					
						
							|  |  |  | 	} else if numTimeouts == len(v) { | 
					
						
							|  |  |  | 		// if all receivers contain valid configuration but timed out
 | 
					
						
							|  |  |  | 		return http.StatusRequestTimeout | 
					
						
							|  |  |  | 	} else if numBadRequests+numTimeouts+numUnknownErrors > 0 { | 
					
						
							|  |  |  | 		return http.StatusMultiStatus | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// all receivers were sent a notification without error
 | 
					
						
							|  |  |  | 		return http.StatusOK | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-28 22:56:59 +08:00
										 |  |  | 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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-06 18:59:29 +08:00
										 |  |  | func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (notifier.Alertmanager, *response.NormalResponse) { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, err := srv.mam.AlertmanagerFor(orgID) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return am, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) { | 
					
						
							| 
									
										
										
										
											2021-12-28 07:01:17 +08:00
										 |  |  | 		return nil, response.Error(http.StatusNotFound, err.Error(), err) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if errors.Is(err, notifier.ErrAlertmanagerNotReady) { | 
					
						
							| 
									
										
										
										
											2021-12-28 07:01:17 +08:00
										 |  |  | 		return am, response.Error(http.StatusConflict, err.Error(), err) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-05 00:46:34 +08:00
										 |  |  | 	srv.log.Error("Unable to obtain the org's Alertmanager", "error", err) | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	return nil, response.Error(http.StatusInternalServerError, "unable to obtain org's Alertmanager", err) | 
					
						
							|  |  |  | } |