| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-10-07 22:33:50 +08:00
										 |  |  | 	"encoding/base64" | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/api/response" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/notifier" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/store" | 
					
						
							| 
									
										
										
										
											2021-11-05 00:47:21 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/secrets" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/web" | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2021-11-05 00:47:21 +08:00
										 |  |  | 	mam     *notifier.MultiOrgAlertmanager | 
					
						
							|  |  |  | 	secrets secrets.Service | 
					
						
							|  |  |  | 	store   store.AlertingStore | 
					
						
							|  |  |  | 	log     log.Logger | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) loadSecureSettings(orgId int64, receivers []*apimodels.PostableApiReceiver) error { | 
					
						
							|  |  |  | 	// Get the last known working configuration
 | 
					
						
							|  |  |  | 	query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: orgId} | 
					
						
							|  |  |  | 	if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil { | 
					
						
							|  |  |  | 		// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one
 | 
					
						
							|  |  |  | 		if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) { | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to get latest configuration: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	currentReceiverMap := make(map[string]*apimodels.PostableGrafanaReceiver) | 
					
						
							|  |  |  | 	if query.Result != nil { | 
					
						
							|  |  |  | 		currentConfig, err := notifier.Load([]byte(query.Result.AlertmanagerConfiguration)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to load latest configuration: %w", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		currentReceiverMap = currentConfig.GetGrafanaReceiverMap() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Copy the previously known secure settings
 | 
					
						
							|  |  |  | 	for i, r := range receivers { | 
					
						
							|  |  |  | 		for j, gr := range r.PostableGrafanaReceivers.GrafanaManagedReceivers { | 
					
						
							|  |  |  | 			if gr.UID == "" { // new receiver
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cgmr, ok := currentReceiverMap[gr.UID] | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				// it tries to update a receiver that didn't previously exist
 | 
					
						
							|  |  |  | 				return UnknownReceiverError{UID: gr.UID} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// frontend sends only the secure settings that have to be updated
 | 
					
						
							|  |  |  | 			// therefore we have to copy from the last configuration only those secure settings not included in the request
 | 
					
						
							|  |  |  | 			for key := range cgmr.SecureSettings { | 
					
						
							|  |  |  | 				_, ok := gr.SecureSettings[key] | 
					
						
							|  |  |  | 				if !ok { | 
					
						
							| 
									
										
										
										
											2021-10-07 22:33:50 +08:00
										 |  |  | 					decryptedValue, err := srv.getDecryptedSecret(cgmr, key) | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 					if err != nil { | 
					
						
							|  |  |  | 						return fmt.Errorf("failed to decrypt stored secure setting: %s: %w", key, err) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings == nil { | 
					
						
							|  |  |  | 						receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings = make(map[string]string, len(cgmr.SecureSettings)) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings[key] = decryptedValue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 22:33:50 +08:00
										 |  |  | func (srv AlertmanagerSrv) getDecryptedSecret(r *apimodels.PostableGrafanaReceiver, key string) (string, error) { | 
					
						
							|  |  |  | 	storedValue, ok := r.SecureSettings[key] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return "", nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	decodeValue, err := base64.StdEncoding.DecodeString(storedValue) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 00:47:21 +08:00
										 |  |  | 	decryptedValue, err := srv.secrets.Decrypt(context.Background(), decodeValue) | 
					
						
							| 
									
										
										
										
											2021-10-07 22:33:50 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return string(decryptedValue), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-16 00:14:02 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteGetAMStatus(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, am.GetStatus()) | 
					
						
							| 
									
										
										
										
											2021-06-16 00:14:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | func (srv AlertmanagerSrv) RouteCreateSilence(c *models.ReqContext, postableSilence apimodels.PostableSilence) response.Response { | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusForbidden, errors.New("permission denied"), "") | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	silenceID, err := am.CreateSilence(&postableSilence) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.ErrSilenceNotFound) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusNotFound, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.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
										 |  |  | 	} | 
					
						
							|  |  |  | 	return response.JSON(http.StatusAccepted, util.DynMap{"message": "silence created", "id": silenceID}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteDeleteAlertingConfig(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-07-17 01:07:31 +08:00
										 |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusForbidden, errors.New("permission denied"), "") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := am.SaveAndApplyDefaultConfig(); err != nil { | 
					
						
							| 
									
										
										
										
											2021-07-17 01:07:31 +08:00
										 |  |  | 		srv.log.Error("unable to save and apply default alertmanager configuration", "err", err) | 
					
						
							|  |  |  | 		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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteDeleteSilence(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusForbidden, errors.New("permission denied"), "") | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | 	silenceID := web.Params(c.Req)[":SilenceId"] | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	if err := am.DeleteSilence(silenceID); err != nil { | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 		if errors.Is(err, notifier.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"}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteGetAlertingConfig(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-07-07 21:29:18 +08:00
										 |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							|  |  |  | 		return ErrResp(http.StatusForbidden, errors.New("permission denied"), "") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-12 21:04:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId} | 
					
						
							| 
									
										
										
										
											2021-04-05 22:03:00 +08:00
										 |  |  | 	if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil { | 
					
						
							|  |  |  | 		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
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to get latest configuration") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-13 20:02:44 +08:00
										 |  |  | 	cfg, err := notifier.Load([]byte(query.Result.AlertmanagerConfiguration)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to unmarshal alertmanager configuration") | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 23:18:19 +08:00
										 |  |  | 	result := apimodels.GettableUserConfig{ | 
					
						
							|  |  |  | 		TemplateFiles: cfg.TemplateFiles, | 
					
						
							|  |  |  | 		AlertmanagerConfig: apimodels.GettableApiAlertingConfig{ | 
					
						
							|  |  |  | 			Config: cfg.AlertmanagerConfig.Config, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, recv := range cfg.AlertmanagerConfig.Receivers { | 
					
						
							|  |  |  | 		receivers := make([]*apimodels.GettableGrafanaReceiver, 0, len(recv.PostableGrafanaReceivers.GrafanaManagedReceivers)) | 
					
						
							|  |  |  | 		for _, pr := range recv.PostableGrafanaReceivers.GrafanaManagedReceivers { | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 			secureFields := make(map[string]bool, len(pr.SecureSettings)) | 
					
						
							|  |  |  | 			for k := range pr.SecureSettings { | 
					
						
							| 
									
										
										
										
											2021-10-07 22:33:50 +08:00
										 |  |  | 				decryptedValue, err := srv.getDecryptedSecret(pr, k) | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 					return ErrResp(http.StatusInternalServerError, err, "failed to decrypt stored secure setting: %s", k) | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				if decryptedValue == "" { | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 				secureFields[k] = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			gr := apimodels.GettableGrafanaReceiver{ | 
					
						
							| 
									
										
										
										
											2021-05-18 16:04:47 +08:00
										 |  |  | 				UID:                   pr.UID, | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 				Name:                  pr.Name, | 
					
						
							|  |  |  | 				Type:                  pr.Type, | 
					
						
							|  |  |  | 				DisableResolveMessage: pr.DisableResolveMessage, | 
					
						
							|  |  |  | 				Settings:              pr.Settings, | 
					
						
							|  |  |  | 				SecureFields:          secureFields, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			receivers = append(receivers, &gr) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-04-27 23:18:19 +08:00
										 |  |  | 		gettableApiReceiver := apimodels.GettableApiReceiver{ | 
					
						
							|  |  |  | 			GettableGrafanaReceivers: apimodels.GettableGrafanaReceivers{ | 
					
						
							|  |  |  | 				GrafanaManagedReceivers: receivers, | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2021-04-27 23:18:19 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		gettableApiReceiver.Name = recv.Name | 
					
						
							|  |  |  | 		result.AlertmanagerConfig.Receivers = append(result.AlertmanagerConfig.Receivers, &gettableApiReceiver) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(http.StatusOK, result) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteGetAMAlertGroups(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	groups, err := am.GetAlertGroups( | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteGetAMAlerts(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	alerts, err := am.GetAlerts( | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.ErrGetAlertsBadPayload) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-04-08 19:27:59 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-12 13:45:16 +08:00
										 |  |  | 		if errors.Is(err, notifier.ErrGetAlertsUnavailable) { | 
					
						
							|  |  |  | 			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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteGetSilence(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 20:30:59 +08:00
										 |  |  | 	silenceID := web.Params(c.Req)[":SilenceId"] | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	gettableSilence, err := am.GetSilence(silenceID) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RouteGetSilences(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gettableSilences, err := am.ListSilences(c.QueryStrings("filter")) | 
					
						
							| 
									
										
										
										
											2021-04-01 04:00:56 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *models.ReqContext, body apimodels.PostableUserConfig) response.Response { | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 		return ErrResp(http.StatusForbidden, errors.New("permission denied"), "") | 
					
						
							| 
									
										
										
										
											2021-05-11 16:31:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Get the last known working configuration
 | 
					
						
							| 
									
										
										
										
											2021-08-12 21:04:09 +08:00
										 |  |  | 	query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId} | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil { | 
					
						
							|  |  |  | 		// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one
 | 
					
						
							|  |  |  | 		if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) { | 
					
						
							| 
									
										
										
										
											2021-05-28 23:55:03 +08:00
										 |  |  | 			return ErrResp(http.StatusInternalServerError, err, "failed to get latest configuration") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	if err := srv.loadSecureSettings(c.OrgId, body.AlertmanagerConfig.Receivers); err != nil { | 
					
						
							|  |  |  | 		var unknownReceiverError UnknownReceiverError | 
					
						
							|  |  |  | 		if errors.As(err, &unknownReceiverError) { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-06-04 20:52:41 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 00:47:21 +08:00
										 |  |  | 	if err := body.ProcessConfig(srv.secrets.Encrypt); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "failed to post process Alertmanager configuration") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := am.SaveAndApplyConfig(&body); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		srv.log.Error("unable to save and apply alertmanager configuration", "err", err) | 
					
						
							|  |  |  | 		return ErrResp(http.StatusBadRequest, err, "failed to save and apply Alertmanager configuration") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration created"}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostAMAlerts(_ *models.ReqContext, _ apimodels.PostableAlerts) response.Response { | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	return NotImplementedResp | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-18 22:31:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | func (srv AlertmanagerSrv) RoutePostTestReceivers(c *models.ReqContext, body apimodels.TestReceiversConfigParams) response.Response { | 
					
						
							|  |  |  | 	if !c.HasUserRole(models.ROLE_EDITOR) { | 
					
						
							|  |  |  | 		return accessForbiddenResp() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := srv.loadSecureSettings(c.OrgId, body.Receivers); err != nil { | 
					
						
							|  |  |  | 		var unknownReceiverError UnknownReceiverError | 
					
						
							|  |  |  | 		if errors.As(err, &unknownReceiverError) { | 
					
						
							|  |  |  | 			return ErrResp(http.StatusBadRequest, err, "") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 		return ErrResp(http.StatusInternalServerError, err, "") | 
					
						
							| 
									
										
										
										
											2021-05-15 02:49:54 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 00:47:21 +08:00
										 |  |  | 	if err := body.ProcessConfig(srv.secrets.Encrypt); err != nil { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 18:28:09 +08:00
										 |  |  | 	am, errResp := srv.AlertmanagerFor(c.OrgId) | 
					
						
							|  |  |  | 	if errResp != nil { | 
					
						
							|  |  |  | 		return errResp | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, err := am.TestReceivers(ctx, body) | 
					
						
							| 
									
										
										
										
											2021-08-17 20:49:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if errors.Is(err, notifier.ErrNoReceivers) { | 
					
						
							|  |  |  | 			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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 					invalidReceiverErr notifier.InvalidReceiverError | 
					
						
							|  |  |  | 					receiverTimeoutErr notifier.ReceiverTimeoutError | 
					
						
							|  |  |  | 				) | 
					
						
							|  |  |  | 				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
										 |  |  | 
 | 
					
						
							|  |  |  | func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (Alertmanager, *response.NormalResponse) { | 
					
						
							|  |  |  | 	am, err := srv.mam.AlertmanagerFor(orgID) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return am, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) { | 
					
						
							|  |  |  | 		return nil, response.Error(http.StatusNotFound, err.Error(), nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if errors.Is(err, notifier.ErrAlertmanagerNotReady) { | 
					
						
							|  |  |  | 		return nil, response.Error(http.StatusConflict, err.Error(), nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	srv.log.Error("unable to obtain the org's Alertmanager", "err", err) | 
					
						
							|  |  |  | 	return nil, response.Error(http.StatusInternalServerError, "unable to obtain org's Alertmanager", err) | 
					
						
							|  |  |  | } |