Alerting: Fix potential panic in Alertmanager when starting up (#36562)

* Alerting: Fix potential panic in Alertmanager when starting up

Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>

* Fix reviews

Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>
This commit is contained in:
Ganesh Vernekar 2021-07-12 11:15:16 +05:30 committed by GitHub
parent afff7f24fc
commit e19c690426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 1 deletions

View File

@ -153,6 +153,9 @@ func (srv AlertmanagerSrv) RouteGetAMAlerts(c *models.ReqContext) response.Respo
if errors.Is(err, notifier.ErrGetAlertsBadPayload) {
return ErrResp(http.StatusBadRequest, err, "")
}
if errors.Is(err, notifier.ErrGetAlertsUnavailable) {
return ErrResp(http.StatusServiceUnavailable, err, "")
}
// any other error here should be an unexpected failure and thus an internal error
return ErrResp(http.StatusInternalServerError, err, "")
}

View File

@ -104,6 +104,8 @@ type Alertmanager struct {
reloadConfigMtx sync.RWMutex
config []byte
initialised bool
}
func New(cfg *setting.Cfg, store store.AlertingStore, m *metrics.Metrics) (*Alertmanager, error) {
@ -269,7 +271,15 @@ func (am *Alertmanager) SyncAndApplyConfigFromDatabase() error {
// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
// It is not safe to call concurrently.
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) error {
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (err error) {
defer func() {
if err == nil {
// We consider AM as initialised only when the config has been
// applied at least once successfully. Until then, some objects
// can still be nil.
am.initialised = true
}
}()
// First, let's make sure this config is not already loaded
var configChanged bool
if rawConfig == nil {

View File

@ -16,6 +16,7 @@ import (
var (
ErrGetAlertsInternal = fmt.Errorf("unable to retrieve alerts(s) due to an internal error")
ErrGetAlertsUnavailable = fmt.Errorf("unable to retrieve alerts(s) as alertmanager is not initialised yet")
ErrGetAlertsBadPayload = fmt.Errorf("unable to retrieve alerts")
ErrGetAlertGroupsBadPayload = fmt.Errorf("unable to retrieve alerts groups")
)
@ -27,6 +28,10 @@ func (am *Alertmanager) GetAlerts(active, silenced, inhibited bool, filter []str
res = apimodels.GettableAlerts{}
)
if !am.initialised {
return res, ErrGetAlertsUnavailable
}
matchers, err := parseFilter(filter)
if err != nil {
am.logger.Error("failed to parse matchers", "err", err)